This patch series does following:
- Remove unused member from extcon palmas structure.
- Fix to support of detecting cable properly with multiple insert/removal.
- Add support for suspend/resume functionlaity and wakup from suspend.
- Option to select/de-select the ID or VBUS detection.
Laxman Dewangan (4):
extcon: palmas: remove unused member from palams_usb structure
extcon: palmas: enable ID_GND and ID_FLOAT detection always
extcon: palams: add support for suspend/resume
extcon: palmas: Option to disable ID/VBUS detection based on platform
.../devicetree/bindings/extcon/extcon-palmas.txt | 2 +
drivers/extcon/extcon-palmas.c | 111 ++++++++++++++------
include/linux/mfd/palmas.h | 9 +-
3 files changed, 86 insertions(+), 36 deletions(-)
Remove unused member vbus_enable and set_vbus_work from palmas_usb
as these members are not used in drivers.
Signed-off-by: Laxman Dewangan <[email protected]>
---
include/linux/mfd/palmas.h | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index 1a8dd7a..03c22ca 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -371,16 +371,11 @@ struct palmas_usb {
struct extcon_dev edev;
- /* used to set vbus, in atomic path */
- struct work_struct set_vbus_work;
-
int id_otg_irq;
int id_irq;
int vbus_otg_irq;
int vbus_irq;
- int vbus_enable;
-
enum palmas_usb_state linkstat;
};
--
1.7.1.1
Based on system design, platform needs to detect the VBUS or ID or
both. Provide option to select this through platform data to
disable part of cable detection through palmas-usb.
Signed-off-by: Laxman Dewangan <[email protected]>
---
.../devicetree/bindings/extcon/extcon-palmas.txt | 2 +
drivers/extcon/extcon-palmas.c | 65 +++++++++++++-------
include/linux/mfd/palmas.h | 4 +
3 files changed, 48 insertions(+), 23 deletions(-)
diff --git a/Documentation/devicetree/bindings/extcon/extcon-palmas.txt b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
index f110e75..8e593ec 100644
--- a/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
+++ b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
@@ -6,6 +6,8 @@ Required Properties:
Optional Properties:
- ti,wakeup : To enable the wakeup comparator in probe
+ - ti,disable-id-detection: Do not perform ID detection.
+ - ti,disable-vbus-detection: Do not pwerform VBUS detection.
palmas-usb {
compatible = "ti,twl6035-usb", "ti,palmas-usb";
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index b2d64d4..e42046b 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -122,11 +122,14 @@ static void palmas_enable_irq(struct palmas_usb *palmas_usb)
PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
- palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
+ if (palmas_usb->enable_vbus_detection)
+ palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
/* cold plug for host mode needs this delay */
- msleep(30);
- palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb);
+ if (palmas_usb->enable_id_detection) {
+ msleep(30);
+ palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb);
+ }
}
static int palmas_usb_probe(struct platform_device *pdev)
@@ -144,6 +147,10 @@ static int palmas_usb_probe(struct platform_device *pdev)
return -ENOMEM;
pdata->wakeup = of_property_read_bool(node, "ti,wakeup");
+ pdata->disable_id_detection = of_property_read_bool(node,
+ "ti,disable-id-detection");
+ pdata->disable_vbus_detection = of_property_read_bool(node,
+ "ti,disable-vbus-detection");
} else if (!pdata) {
return -EINVAL;
}
@@ -154,6 +161,8 @@ static int palmas_usb_probe(struct platform_device *pdev)
palmas->usb = palmas_usb;
palmas_usb->palmas = palmas;
+ palmas_usb->enable_vbus_detection = !pdata->disable_vbus_detection;
+ palmas_usb->enable_id_detection = !pdata->disable_id_detection;
palmas_usb->dev = &pdev->dev;
@@ -180,26 +189,32 @@ static int palmas_usb_probe(struct platform_device *pdev)
return status;
}
- status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_irq,
- NULL, palmas_id_irq_handler,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
- IRQF_ONESHOT | IRQF_EARLY_RESUME,
- "palmas_usb_id", palmas_usb);
- if (status < 0) {
- dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+ if (palmas_usb->enable_id_detection) {
+ status = devm_request_threaded_irq(palmas_usb->dev,
+ palmas_usb->id_irq,
+ NULL, palmas_id_irq_handler,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT | IRQF_EARLY_RESUME,
+ "palmas_usb_id", palmas_usb);
+ if (status < 0) {
+ dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
palmas_usb->id_irq, status);
- goto fail_extcon;
+ goto fail_extcon;
+ }
}
- status = devm_request_threaded_irq(palmas_usb->dev,
- palmas_usb->vbus_irq, NULL, palmas_vbus_irq_handler,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
- IRQF_ONESHOT | IRQF_EARLY_RESUME,
- "palmas_usb_vbus", palmas_usb);
- if (status < 0) {
- dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+ if (palmas_usb->enable_vbus_detection) {
+ status = devm_request_threaded_irq(palmas_usb->dev,
+ palmas_usb->vbus_irq, NULL,
+ palmas_vbus_irq_handler,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT | IRQF_EARLY_RESUME,
+ "palmas_usb_vbus", palmas_usb);
+ if (status < 0) {
+ dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
palmas_usb->vbus_irq, status);
- goto fail_extcon;
+ goto fail_extcon;
+ }
}
palmas_enable_irq(palmas_usb);
@@ -227,8 +242,10 @@ static int palmas_usb_suspend(struct device *dev)
struct palmas_usb *palmas_usb = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
- enable_irq_wake(palmas_usb->vbus_irq);
- enable_irq_wake(palmas_usb->id_irq);
+ if (palmas_usb->enable_vbus_detection)
+ enable_irq_wake(palmas_usb->vbus_irq);
+ if (palmas_usb->enable_id_detection)
+ enable_irq_wake(palmas_usb->id_irq);
}
return 0;
}
@@ -238,8 +255,10 @@ static int palmas_usb_resume(struct device *dev)
struct palmas_usb *palmas_usb = dev_get_drvdata(dev);
if (device_may_wakeup(dev)) {
- disable_irq_wake(palmas_usb->vbus_irq);
- disable_irq_wake(palmas_usb->id_irq);
+ if (palmas_usb->enable_vbus_detection)
+ disable_irq_wake(palmas_usb->vbus_irq);
+ if (palmas_usb->enable_id_detection)
+ disable_irq_wake(palmas_usb->id_irq);
}
return 0;
};
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index 03c22ca..d9ef94c 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -204,6 +204,8 @@ struct palmas_pmic_platform_data {
struct palmas_usb_platform_data {
/* Do we enable the wakeup comparator on probe */
int wakeup;
+ bool disable_vbus_detection;
+ bool disable_id_detection;
};
struct palmas_resource_platform_data {
@@ -377,6 +379,8 @@ struct palmas_usb {
int vbus_irq;
enum palmas_usb_state linkstat;
+ bool enable_vbus_detection;
+ bool enable_id_detection;
};
#define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
--
1.7.1.1
Add suspend/resume callbacks and support for wakeup from
suspend on USB HOST or USB Device cable insertion or removal.
Signed-off-by: Laxman Dewangan <[email protected]>
---
drivers/extcon/extcon-palmas.c | 38 +++++++++++++++++++++++++++++++++++---
1 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index 587034b..b2d64d4 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -182,7 +182,8 @@ static int palmas_usb_probe(struct platform_device *pdev)
status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_irq,
NULL, palmas_id_irq_handler,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT | IRQF_EARLY_RESUME,
"palmas_usb_id", palmas_usb);
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
@@ -192,7 +193,8 @@ static int palmas_usb_probe(struct platform_device *pdev)
status = devm_request_threaded_irq(palmas_usb->dev,
palmas_usb->vbus_irq, NULL, palmas_vbus_irq_handler,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT | IRQF_EARLY_RESUME,
"palmas_usb_vbus", palmas_usb);
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
@@ -201,7 +203,7 @@ static int palmas_usb_probe(struct platform_device *pdev)
}
palmas_enable_irq(palmas_usb);
-
+ device_set_wakeup_capable(&pdev->dev, true);
return 0;
fail_extcon:
@@ -219,6 +221,35 @@ static int palmas_usb_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int palmas_usb_suspend(struct device *dev)
+{
+ struct palmas_usb *palmas_usb = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(palmas_usb->vbus_irq);
+ enable_irq_wake(palmas_usb->id_irq);
+ }
+ return 0;
+}
+
+static int palmas_usb_resume(struct device *dev)
+{
+ struct palmas_usb *palmas_usb = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(palmas_usb->vbus_irq);
+ disable_irq_wake(palmas_usb->id_irq);
+ }
+ return 0;
+};
+#endif
+
+static const struct dev_pm_ops palmas_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(palmas_usb_suspend,
+ palmas_usb_resume)
+};
+
static struct of_device_id of_palmas_match_tbl[] = {
{ .compatible = "ti,palmas-usb", },
{ .compatible = "ti,twl6035-usb", },
@@ -232,6 +263,7 @@ static struct platform_driver palmas_usb_driver = {
.name = "palmas-usb",
.of_match_table = of_palmas_match_tbl,
.owner = THIS_MODULE,
+ .pm = &palmas_pm_ops,
},
};
--
1.7.1.1
When integrating driver with Tegra platform, it is found that
the ID pins get detected only once after booting system and
further removal and re-insert does not detect the ID pin.
Fixing this issue with enabling interrupt on ID_GND and ID_FLOAT
always and clearing the status on LATCH register which actually
occurred.
Also if interrupt occurs with line status as zero then based on
previous status, set the cable state.
Add debug prints to display the cable state when any cable
insertion/removal happen.
Signed-off-by: Laxman Dewangan <[email protected]>
---
drivers/extcon/extcon-palmas.c | 24 +++++++++++-------------
1 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index b752a0a..587034b 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -57,6 +57,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) {
palmas_usb->linkstat = PALMAS_USB_STATE_VBUS;
extcon_set_cable_state(&palmas_usb->edev, "USB", true);
+ dev_info(palmas_usb->dev, "USB cable state: TRUE\n");
} else {
dev_dbg(palmas_usb->dev,
"Spurious connect event detected\n");
@@ -65,6 +66,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) {
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
extcon_set_cable_state(&palmas_usb->edev, "USB", false);
+ dev_info(palmas_usb->dev, "USB cable state: FALSE\n");
} else {
dev_dbg(palmas_usb->dev,
"Spurious disconnect event detected\n");
@@ -84,28 +86,23 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
if (set & PALMAS_USB_ID_INT_SRC_ID_GND) {
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
- PALMAS_USB_ID_INT_EN_HI_SET,
- PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
- palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
- PALMAS_USB_ID_INT_EN_HI_CLR,
- PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
- palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_LATCH_CLR,
PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
palmas_usb->linkstat = PALMAS_USB_STATE_ID;
extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true);
+ dev_info(palmas_usb->dev, "HOST cable state: TRUE\n");
} else if (set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) {
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
- PALMAS_USB_ID_INT_EN_HI_SET,
- PALMAS_USB_ID_INT_EN_HI_SET_ID_GND);
- palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
- PALMAS_USB_ID_INT_EN_HI_CLR,
- PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
- palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_LATCH_CLR,
PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
+ dev_info(palmas_usb->dev, "HOST cable state: FALSE\n");
+ } else if ((palmas_usb->linkstat == PALMAS_USB_STATE_ID) &&
+ (!(set & PALMAS_USB_ID_INT_SRC_ID_GND))) {
+ palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
+ extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
+ dev_info(palmas_usb->dev, "HOST cable state: FALSE\n");
}
return IRQ_HANDLED;
@@ -122,7 +119,8 @@ static void palmas_enable_irq(struct palmas_usb *palmas_usb)
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_ID_INT_EN_HI_SET,
- PALMAS_USB_ID_INT_EN_HI_SET_ID_GND);
+ PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
+ PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
--
1.7.1.1
Whole series looks good to me.
Acked-by: Graeme Gregory <[email protected]>
On Tue, Jul 09, 2013 at 06:34:20PM +0530, Laxman Dewangan wrote:
> This patch series does following:
> - Remove unused member from extcon palmas structure.
> - Fix to support of detecting cable properly with multiple insert/removal.
> - Add support for suspend/resume functionlaity and wakup from suspend.
> - Option to select/de-select the ID or VBUS detection.
>
> Laxman Dewangan (4):
> extcon: palmas: remove unused member from palams_usb structure
> extcon: palmas: enable ID_GND and ID_FLOAT detection always
> extcon: palams: add support for suspend/resume
> extcon: palmas: Option to disable ID/VBUS detection based on platform
>
> .../devicetree/bindings/extcon/extcon-palmas.txt | 2 +
> drivers/extcon/extcon-palmas.c | 111 ++++++++++++++------
> include/linux/mfd/palmas.h | 9 +-
> 3 files changed, 86 insertions(+), 36 deletions(-)
>
Hi Laxman,
On 07/09/2013 10:04 PM, Laxman Dewangan wrote:
> When integrating driver with Tegra platform, it is found that
> the ID pins get detected only once after booting system and
> further removal and re-insert does not detect the ID pin.
>
> Fixing this issue with enabling interrupt on ID_GND and ID_FLOAT
> always and clearing the status on LATCH register which actually
> occurred.
>
> Also if interrupt occurs with line status as zero then based on
> previous status, set the cable state.
>
> Add debug prints to display the cable state when any cable
> insertion/removal happen.
>
> Signed-off-by: Laxman Dewangan <[email protected]>
> ---
> drivers/extcon/extcon-palmas.c | 24 +++++++++++-------------
> 1 files changed, 11 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
> index b752a0a..587034b 100644
> --- a/drivers/extcon/extcon-palmas.c
> +++ b/drivers/extcon/extcon-palmas.c
> @@ -57,6 +57,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
> if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) {
> palmas_usb->linkstat = PALMAS_USB_STATE_VBUS;
> extcon_set_cable_state(&palmas_usb->edev, "USB", true);
> + dev_info(palmas_usb->dev, "USB cable state: TRUE\n");
I prfer following info message when USB cable is inserted.
dev_info(palmas_usb->dev, "USB cable is attached\n");
> } else {
> dev_dbg(palmas_usb->dev,
> "Spurious connect event detected\n");
> @@ -65,6 +66,7 @@ static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
> if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) {
> palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
> extcon_set_cable_state(&palmas_usb->edev, "USB", false);
> + dev_info(palmas_usb->dev, "USB cable state: FALSE\n");
ditto.
dev_info(palmas_usb->dev, "USB cable is detached\n");
> } else {
> dev_dbg(palmas_usb->dev,
> "Spurious disconnect event detected\n");
> @@ -84,28 +86,23 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
>
> if (set & PALMAS_USB_ID_INT_SRC_ID_GND) {
> palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
> - PALMAS_USB_ID_INT_EN_HI_SET,
> - PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
> - palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
> - PALMAS_USB_ID_INT_EN_HI_CLR,
> - PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
> - palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
> PALMAS_USB_ID_INT_LATCH_CLR,
> PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
> palmas_usb->linkstat = PALMAS_USB_STATE_ID;
> extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true);
> + dev_info(palmas_usb->dev, "HOST cable state: TRUE\n");
ditto.
dev_info(palmas_usb->dev, "USB-HOST cable is attached\n");
> } else if (set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) {
> palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
> - PALMAS_USB_ID_INT_EN_HI_SET,
> - PALMAS_USB_ID_INT_EN_HI_SET_ID_GND);
> - palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
> - PALMAS_USB_ID_INT_EN_HI_CLR,
> - PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
> - palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
> PALMAS_USB_ID_INT_LATCH_CLR,
> PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
> palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
> extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
> + dev_info(palmas_usb->dev, "HOST cable state: FALSE\n");
ditto.
dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
> + } else if ((palmas_usb->linkstat == PALMAS_USB_STATE_ID) &&
> + (!(set & PALMAS_USB_ID_INT_SRC_ID_GND))) {
> + palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
> + extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
> + dev_info(palmas_usb->dev, "HOST cable state: FALSE\n");
dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
> }
>
> return IRQ_HANDLED;
> @@ -122,7 +119,8 @@ static void palmas_enable_irq(struct palmas_usb *palmas_usb)
>
> palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
> PALMAS_USB_ID_INT_EN_HI_SET,
> - PALMAS_USB_ID_INT_EN_HI_SET_ID_GND);
> + PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
> + PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
>
> palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
>
>
I you would modify info message, anything else is good.
Thanks,
Chanwoo Choi