extcon: palmas: make vbus/ID cable detection to platform choice
Laxman Dewangan [Mon, 25 Mar 2013 16:12:42 +0000 (21:12 +0530)]
Enable vbus/id pin detection only if it is enabled through
platform data. Also provide the connection name through platform
data.

bug 1242273

Change-Id: I6a95552c46e3c850549da656c6947f9bdcd7423f
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Sumit Sharma <sumsharma@nvidia.com>
Reviewed-on: http://git-master/r/212609
Tested-by: Yunfan Zhang <yunfanz@nvidia.com>
Reviewed-by: Yunfan Zhang <yunfanz@nvidia.com>
GVS: Gerrit_Virtual_Submit

arch/arm/mach-tegra/board-macallan-power.c
drivers/extcon/extcon-palmas.c
include/linux/mfd/palmas.h

index 46f0cf5..bc32daf 100644 (file)
@@ -356,12 +356,19 @@ static struct palmas_pinctrl_platform_data palmas_pinctrl_pdata = {
        .dvfs2_enable = false,
 };
 
+struct palmas_extcon_platform_data palmas_extcon_pdata = {
+       .connection_name = "palmas-extcon",
+       .enable_vbus_detection = true,
+       .enable_id_pin_detection = false,
+};
+
 static struct palmas_platform_data palmas_pdata = {
        .gpio_base = PALMAS_TEGRA_GPIO_BASE,
        .irq_base = PALMAS_TEGRA_IRQ_BASE,
        .pmic_pdata = &pmic_platform,
        .use_power_off = true,
        .pinctrl_pdata = &palmas_pinctrl_pdata,
+       .extcon_pdata = &palmas_extcon_pdata,
 };
 
 static struct i2c_board_info palma_device[] = {
index 38b26c9..cd00b72 100644 (file)
@@ -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;
@@ -73,13 +75,30 @@ static int palmas_extcon_cable_update(
                (status & PALMAS_INT3_LINE_STATE_VBUS) ? "Valid" : "Invalid",
                status);
 
+       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_VBUS) ? "Valid" : "Invalid",
+               (status & PALMAS_INT3_LINE_STATE_ID) ? "Valid" : "Invalid",
                status);
 
        return 0;
@@ -90,7 +109,9 @@ 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 +120,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 +145,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 = pdev->name;
+       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,39 +167,58 @@ 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;
-       }
-
-       snprintf(palma_econ->vbus_irq_name, MAX_INT_NAME,
+       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));
-       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->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;
+       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->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;
+               }
        }
 
        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 +229,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 +241,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 +254,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
index b58e178..c536453 100644 (file)
@@ -221,6 +221,12 @@ struct palmas_pinctrl_platform_data {
        bool dvfs2_enable;
 };
 
+struct palmas_extcon_platform_data {
+       const char *connection_name;
+       bool enable_vbus_detection;
+       bool enable_id_pin_detection;
+};
+
 struct palmas_platform_data {
        int gpio_base;
        int irq_base;
@@ -238,6 +244,7 @@ struct palmas_platform_data {
        bool use_power_off;
 
        struct palmas_pinctrl_platform_data *pinctrl_pdata;
+       struct palmas_extcon_platform_data *extcon_pdata;
 
        int watchdog_timer_initial_period;
 };