diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2013-03-25 21:42:42 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 13:06:59 -0700 |
commit | 78088047854bbb8513094da697bfe0c597707c06 (patch) | |
tree | 2af4db68fb44bbf76b53ad0b44728309b7b774aa /drivers/extcon | |
parent | 826613cf7f76c19319596e939fd6d0064e8fff77 (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.c | 134 |
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 |