summaryrefslogtreecommitdiff
path: root/drivers/extcon
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2013-03-25 21:42:42 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 13:06:59 -0700
commit78088047854bbb8513094da697bfe0c597707c06 (patch)
tree2af4db68fb44bbf76b53ad0b44728309b7b774aa /drivers/extcon
parent826613cf7f76c19319596e939fd6d0064e8fff77 (diff)
extcon: palmas: make vbus/ID cable detection to platform choice
Enable vbus/id pin detection only if it is enabled through platform data. Also provide the connection name through platform data. bug 1242273 Bug 1249130 Bug 1249783 Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/212609 (Cherry picked from commit de31f6b38ea1a96fb99c8f72db7029f23d693fb2) Change-Id: I06dbedb0462e77ef05a42b164b9d457254ed47e7 Signed-off-by: Sumit Sharma <sumsharma@nvidia.com> Reviewed-on: http://git-master/r/214920 Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Diffstat (limited to 'drivers/extcon')
-rw-r--r--drivers/extcon/extcon-palmas.c134
1 files changed, 108 insertions, 26 deletions
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index 5a91c34afd12..fd70f7809ec3 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -42,6 +42,8 @@ struct palmas_extcon {
int id_irq;
char vbus_irq_name[MAX_INT_NAME];
char id_irq_name[MAX_INT_NAME];
+ bool enable_vbus_detection;
+ bool enable_id_pin_detection;
};
const char *palmas_excon_cable[] = {
@@ -50,7 +52,7 @@ const char *palmas_excon_cable[] = {
NULL,
};
-static int palmas_extcon_cable_update(
+static int palmas_extcon_vbus_cable_update(
struct palmas_extcon *palma_econ)
{
int ret;
@@ -85,12 +87,40 @@ static int palmas_extcon_cable_update(
return 0;
}
+static int palmas_extcon_id_cable_update(
+ struct palmas_extcon *palma_econ)
+{
+ int ret;
+ unsigned int status;
+
+ ret = palmas_read(palma_econ->palmas, PALMAS_INTERRUPT_BASE,
+ PALMAS_INT3_LINE_STATE, &status);
+ if (ret < 0) {
+ dev_err(palma_econ->dev,
+ "INT3_LINE_STATE read failed: %d\n", ret);
+ return ret;
+ }
+
+ if (status & PALMAS_INT3_LINE_STATE_ID)
+ extcon_set_cable_state(palma_econ->edev, "USB-Host", true);
+ else
+ extcon_set_cable_state(palma_econ->edev, "USB-Host", false);
+
+ dev_info(palma_econ->dev, "ID %s status: 0x%02x\n",
+ (status & PALMAS_INT3_LINE_STATE_ID) ? "Valid" : "Invalid",
+ status);
+
+ return 0;
+}
+
static irqreturn_t palmas_extcon_irq(int irq, void *data)
{
struct palmas_extcon *palma_econ = data;
if (irq == palma_econ->vbus_irq)
- palmas_extcon_cable_update(palma_econ);
+ palmas_extcon_vbus_cable_update(palma_econ);
+ else if (irq == palma_econ->id_irq)
+ palmas_extcon_id_cable_update(palma_econ);
else
dev_err(palma_econ->dev, "Unknown interrupt %d\n", irq);
@@ -99,13 +129,23 @@ static irqreturn_t palmas_extcon_irq(int irq, void *data)
static int __devinit palmas_extcon_probe(struct platform_device *pdev)
{
+ struct palmas_platform_data *pdata;
+ struct palmas_extcon_platform_data *epdata = NULL;
struct palmas_extcon *palma_econ;
struct extcon_dev *edev;
int ret;
+ pdata = dev_get_platdata(pdev->dev.parent);
+ if (pdata)
+ epdata = pdata->extcon_pdata;
+ if (!epdata) {
+ dev_err(&pdev->dev, "No platform data\n");
+ return -EINVAL;
+ }
+
palma_econ = devm_kzalloc(&pdev->dev, sizeof(*palma_econ), GFP_KERNEL);
if (!palma_econ) {
- dev_err(&pdev->dev, "Memory allocation failed for palma_econ\n");
+ dev_err(&pdev->dev, "Memory alloc failed for palma_econ\n");
return -ENOMEM;
}
@@ -114,14 +154,18 @@ static int __devinit palmas_extcon_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Memory allocation failed for edev\n");
return -ENOMEM;
}
+
palma_econ->edev = edev;
- palma_econ->edev->name = dev_name(&pdev->dev);
+ palma_econ->edev->name = (epdata->connection_name) ?
+ epdata->connection_name : pdev->name;
palma_econ->edev->supported_cable = palmas_excon_cable;
palma_econ->dev = &pdev->dev;
palma_econ->palmas = dev_get_drvdata(pdev->dev.parent);
dev_set_drvdata(&pdev->dev, palma_econ);
+ palma_econ->enable_vbus_detection = epdata->enable_vbus_detection;
+ palma_econ->enable_id_pin_detection = epdata->enable_id_pin_detection;
palma_econ->vbus_irq = platform_get_irq(pdev, 0);
palma_econ->id_irq = platform_get_irq(pdev, 1);
@@ -132,24 +176,51 @@ static int __devinit palmas_extcon_probe(struct platform_device *pdev)
}
/* Set initial state */
- ret = palmas_extcon_cable_update(palma_econ);
- if (ret < 0) {
- dev_err(&pdev->dev, "Cable init failed: %d\n", ret);
- goto out;
+ if (epdata->enable_vbus_detection) {
+ ret = palmas_extcon_vbus_cable_update(palma_econ);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "VBUS Cable init failed: %d\n", ret);
+ goto out;
+ }
+ snprintf(palma_econ->vbus_irq_name, MAX_INT_NAME,
+ "vbus-%s\n", dev_name(palma_econ->dev));
+ ret = request_threaded_irq(palma_econ->vbus_irq, NULL,
+ palmas_extcon_irq, IRQF_ONESHOT | IRQF_EARLY_RESUME,
+ palma_econ->vbus_irq_name, palma_econ);
+ if (ret < 0) {
+ dev_err(palma_econ->dev, "request irq %d failed: %d\n",
+ palma_econ->vbus_irq, ret);
+ goto out;
+ }
}
- snprintf(palma_econ->vbus_irq_name, MAX_INT_NAME,
- "vbus-%s\n", dev_name(palma_econ->dev));
- snprintf(palma_econ->id_irq_name, MAX_INT_NAME,
+ if (epdata->enable_id_pin_detection) {
+ ret = palmas_update_bits(palma_econ->palmas,
+ PALMAS_USB_OTG_BASE,
+ PALMAS_USB_WAKEUP,
+ PALMAS_USB_WAKEUP_ID_WK_UP_COMP, 1);
+ if (ret < 0) {
+ dev_err(palma_econ->dev,
+ "USB_WAKEUP write failed: %d\n", ret);
+ goto out_free_vbus;
+ }
+
+ ret = palmas_extcon_id_cable_update(palma_econ);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "ID Cable init failed: %d\n", ret);
+ goto out;
+ }
+ snprintf(palma_econ->id_irq_name, MAX_INT_NAME,
"id-%s\n", dev_name(palma_econ->dev));
-
- ret = request_threaded_irq(palma_econ->vbus_irq, NULL,
- palmas_extcon_irq, IRQF_ONESHOT | IRQF_EARLY_RESUME,
- palma_econ->vbus_irq_name, palma_econ);
- if (ret < 0) {
- dev_err(palma_econ->dev, "request irq %d failed: %d\n",
- palma_econ->vbus_irq, ret);
- goto out;
+ ret = request_threaded_irq(palma_econ->id_irq, NULL,
+ palmas_extcon_irq, IRQF_ONESHOT | IRQF_EARLY_RESUME,
+ palma_econ->id_irq_name, palma_econ);
+ if (ret < 0) {
+ dev_err(palma_econ->dev, "request irq %d failed: %d\n",
+ palma_econ->id_irq, ret);
+ goto out_free_vbus;
+ }
}
ret = request_threaded_irq(palma_econ->id_irq, NULL,
@@ -164,7 +235,8 @@ static int __devinit palmas_extcon_probe(struct platform_device *pdev)
device_set_wakeup_capable(&pdev->dev, 1);
return 0;
out_free_vbus:
- free_irq(palma_econ->vbus_irq, palma_econ);
+ if (epdata->enable_vbus_detection)
+ free_irq(palma_econ->vbus_irq, palma_econ);
out:
extcon_dev_unregister(palma_econ->edev);
return ret;
@@ -175,8 +247,10 @@ static int __devexit palmas_extcon_remove(struct platform_device *pdev)
struct palmas_extcon *palma_econ = dev_get_drvdata(&pdev->dev);
extcon_dev_unregister(palma_econ->edev);
- free_irq(palma_econ->vbus_irq, palma_econ);
- free_irq(palma_econ->id_irq, palma_econ);
+ if (palma_econ->enable_vbus_detection)
+ free_irq(palma_econ->vbus_irq, palma_econ);
+ if (palma_econ->enable_id_pin_detection)
+ free_irq(palma_econ->id_irq, palma_econ);
return 0;
}
@@ -185,8 +259,12 @@ static int palmas_extcon_suspend(struct device *dev)
{
struct palmas_extcon *palma_econ = dev_get_drvdata(dev);
- if (device_may_wakeup(dev))
- enable_irq_wake(palma_econ->vbus_irq);
+ if (device_may_wakeup(dev)) {
+ if (palma_econ->enable_vbus_detection)
+ enable_irq_wake(palma_econ->vbus_irq);
+ if (palma_econ->enable_id_pin_detection)
+ enable_irq_wake(palma_econ->id_irq);
+ }
return 0;
}
@@ -194,8 +272,12 @@ static int palmas_extcon_resume(struct device *dev)
{
struct palmas_extcon *palma_econ = dev_get_drvdata(dev);
- if (device_may_wakeup(dev))
- disable_irq_wake(palma_econ->vbus_irq);
+ if (device_may_wakeup(dev)) {
+ if (palma_econ->enable_vbus_detection)
+ disable_irq_wake(palma_econ->vbus_irq);
+ if (palma_econ->enable_id_pin_detection)
+ disable_irq_wake(palma_econ->id_irq);
+ }
return 0;
};
#endif