driver: max77665: fix multiple issues in charger driver
Syed Rafiuddin [Fri, 28 Sep 2012 11:37:27 +0000 (16:37 +0530)]
- fix probe issue.
- differentiate between E1236 and E1587
- use late_initcall
- init charger values correctly

Change-Id: Iab11261dab084bd707dcd9d24d236d3c1b438b0e
Signed-off-by: Syed Rafiuddin <srafiuddin@nvidia.com>
Reviewed-on: http://git-master/r/135174
(cherry picked from commit 7360d8753133ef15cd59264fd02613c42cacbd93)
Signed-off-by: Gaurav Batra <gbatra@nvidia.com>
Reviewed-on: http://git-master/r/146695
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

drivers/extcon/extcon-max77665.c
drivers/power/max77665-charger.c
include/linux/max77665-charger.h

index cfbe635..193b66d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/kobject.h>
 #include <linux/extcon.h>
 #include <linux/mfd/max77665.h>
+#include <linux/max77665-charger.h>
 
 #define        DEV_NAME        "max77665-muic"
 
@@ -85,13 +86,9 @@ enum max77665_muic_charger_type {
        MAX77665_CHARGER_TYPE_1A,
 };
 
-struct max77665_muic_platform_data {
-       int irq_base;
-};
-
 struct max77665_muic {
        struct device *dev;
-       struct max77665_muic_platform_data *muic_pdata;
+       struct max77665_muic_platform_data *pdata;
 
        int irq;
        struct work_struct irq_work;
@@ -126,19 +123,6 @@ static int max77665_read_reg(struct max77665_muic *muic,
        return 0;
 }
 
-static int max77665_bulk_read(struct max77665_muic *muic,
-               uint8_t reg, int count, uint8_t *buf)
-{
-       int ret;
-       struct device *dev = muic->dev;
-
-       ret = max77665_read(dev->parent, MAX77665_I2C_SLAVE_MUIC, reg, buf);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
 static int max77665_update_reg(struct max77665_muic *muic,
                                uint8_t reg, uint8_t value, uint8_t mask)
 {
@@ -258,7 +242,7 @@ static int max77665_muic_handle_charger_type(struct max77665_muic *muic,
                                enum max77665_muic_charger_type charger_type)
 {
        uint8_t adc;
-       int ret;
+       int ret = 0;
 
        ret = max77665_read_reg(muic, MAX77665_MUIC_REG_STATUS1, &adc);
        if (ret) {
@@ -309,7 +293,8 @@ static void max77665_muic_irq_work(struct work_struct *work)
 
        mutex_lock(&muic->mutex);
 
-       ret = max77665_bulk_read(muic, MAX77665_MUIC_REG_STATUS1,
+       ret = max77665_bulk_read(muic->dev->parent, MAX77665_I2C_SLAVE_MUIC,
+                               MAX77665_MUIC_REG_STATUS1,
                                2, status);
        if (ret) {
                dev_err(muic->dev, "failed to read muic register\n");
@@ -326,7 +311,6 @@ static void max77665_muic_irq_work(struct work_struct *work)
        chg_type = status[1] & STATUS2_CHGTYP_MASK;
        chg_type >>= STATUS2_CHGTYP_SHIFT;
 
-       max77665_muic_handle_adc(muic, adc);
        max77665_muic_handle_charger_type(muic, chg_type);
 
        mutex_unlock(&muic->mutex);
@@ -351,7 +335,8 @@ static void max77665_muic_detect_dev(struct max77665_muic *muic)
        int ret;
        uint8_t status[2], adc, chg_type;
 
-       ret = max77665_bulk_read(muic, MAX77665_MUIC_REG_STATUS1,
+       ret = max77665_bulk_read(muic->dev->parent, MAX77665_I2C_SLAVE_MUIC,
+                               MAX77665_MUIC_REG_STATUS1,
                                2, status);
        if (ret) {
                dev_err(muic->dev, "failed to read muic register\n");
@@ -367,21 +352,13 @@ static void max77665_muic_detect_dev(struct max77665_muic *muic)
        chg_type = status[1] & STATUS2_CHGTYP_MASK;
        chg_type >>= STATUS2_CHGTYP_SHIFT;
 
-       max77665_muic_handle_adc(muic, adc);
        max77665_muic_handle_charger_type(muic, chg_type);
 }
 
 static int __devinit max77665_muic_probe(struct platform_device *pdev)
 {
+       int ret = 0;
        struct max77665_muic *muic;
-       struct max77665_muic_platform_data *pdata;
-       int ret;
-
-       pdata = dev_get_platdata(pdev->dev.parent);
-       if (!pdata) {
-               dev_err(&pdev->dev, "no platform data available\n");
-               return -ENODEV;
-       }
 
        muic = devm_kzalloc(&pdev->dev, sizeof(struct max77665_muic),
                        GFP_KERNEL);
@@ -391,39 +368,52 @@ static int __devinit max77665_muic_probe(struct platform_device *pdev)
        }
 
        muic->dev = &pdev->dev;
+       muic->pdata = pdev->dev.platform_data;
+       if (!muic->pdata) {
+               dev_err(&pdev->dev, "no platform data available\n");
+               return -ENODEV;
+       }
 
-       platform_set_drvdata(pdev, muic);
+       dev_set_drvdata(&pdev->dev, muic);
        mutex_init(&muic->mutex);
        INIT_WORK(&muic->irq_work, max77665_muic_irq_work);
 
-       ret = request_threaded_irq(pdata->irq_base, NULL,
-                               max77665_muic_irq_handler,
-                               0, "muic_irq",
-                               muic);
-       if (ret) {
-               dev_err(&pdev->dev,
-                       "failed: irq request error :%d)\n", ret);
-               return ret;
+       if (muic->pdata->irq_base) {
+               ret = request_threaded_irq(muic->pdata->irq_base +
+                                       MAX77665_IRQ_MUIC, NULL,
+                                       max77665_muic_irq_handler,
+                                       0, "muic_irq",
+                                       muic);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "failed: irq request error :%d)\n", ret);
+                       return ret;
+               }
        }
-
        /* External connector */
-       muic->edev = devm_kzalloc(&pdev->dev, sizeof(struct extcon_dev),
+       muic->edev = kzalloc(sizeof(struct extcon_dev),
                        GFP_KERNEL);
        if (!muic->edev) {
                dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto error;
        }
        muic->edev->name = DEV_NAME;
        muic->edev->supported_cable = max77665_extcon_cable;
        ret = extcon_dev_register(muic->edev, NULL);
        if (ret) {
                dev_err(&pdev->dev, "failed to register extcon device\n");
-               return ret;
+               goto error1;
        }
        /* Initial device detection */
        max77665_muic_detect_dev(muic);
 
        return 0;
+error1:
+       kfree(muic->edev);
+error:
+       free_irq(muic->pdata->irq_base + MAX77665_IRQ_MUIC, muic);
+       return ret;
 }
 
 static int __devexit max77665_muic_remove(struct platform_device *pdev)
index b20e21e..cda63b0 100644 (file)
 #include <linux/power_supply.h>
 #include <linux/mfd/max77665.h>
 #include <linux/max77665-charger.h>
+#include <linux/power/max17042_battery.h>
+
+#define MAX_TEMP 70
+#define MIN_TEMP -70
 
 /* fast charge current in mA */
 static const uint32_t chg_cc[]  = {
@@ -68,22 +72,11 @@ struct max77665_charger {
        struct extcon_dev *edev;
 };
 
-struct max77665_charger_cable {
-       const char *extcon_name;
-       const char *name;
-       struct notifier_block nb;
-       struct max77665_charger *charger;
-       struct extcon_specific_cable_nb *extcon_dev;
-};
-
-
 static enum power_supply_property max77665_ac_props[] = {
-       POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_ONLINE,
 };
 
 static enum power_supply_property max77665_usb_props[] = {
-       POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_ONLINE,
 };
 
@@ -242,6 +235,7 @@ static int max77665_charger_enable(struct max77665_charger *charger,
 static int max77665_charger_init(struct max77665_charger *charger)
 {
        int ret = 0;
+       uint8_t read_val;
 
        ret = max77665_enable_write(charger, true);
        if (ret < 0) {
@@ -249,6 +243,13 @@ static int max77665_charger_init(struct max77665_charger *charger)
                goto error;
        }
 
+       ret = max77665_update_reg(charger, MAX77665_CHG_CNFG_01, 0xa4);
+       if (ret < 0) {
+               dev_err(charger->dev, "Failed in writing to register 0x%x\n",
+                       MAX77665_CHG_CNFG_01);
+               goto error;
+       }
+
        if (charger->plat_data->fast_chg_cc) {
                ret = convert_to_reg(chg_cc, ARRAY_SIZE(chg_cc),
                                        charger->plat_data->fast_chg_cc);
@@ -269,9 +270,10 @@ static int max77665_charger_init(struct max77665_charger *charger)
                if (ret < 0)
                        goto error;
 
-               ret = max77665_update_reg(charger, MAX77665_CHG_CNFG_04, ret+1);
+               ret = max77665_update_reg(charger,
+                               MAX77665_CHG_CNFG_04, ret+1);
                if (ret < 0) {
-                       dev_err(charger->dev, "Failed in writing to register 0x%x\n",
+                       dev_err(charger->dev, "Failed writing to reg:0x%x\n",
                                MAX77665_CHG_CNFG_04);
                        goto error;
                }
@@ -283,9 +285,10 @@ static int max77665_charger_init(struct max77665_charger *charger)
                if (ret < 0)
                        goto error;
 
-               ret = max77665_update_reg(charger, MAX77665_CHG_CNFG_09, ret+5);
+               ret = max77665_update_reg(charger,
+                               MAX77665_CHG_CNFG_09, (ret-1)*5);
                if (ret < 0) {
-                       dev_err(charger->dev, "Failed in writing to register 0x%x\n",
+                       dev_err(charger->dev, "Failed writing to reg:0x%x\n",
                                MAX77665_CHG_CNFG_09);
                        goto error;
                }
@@ -299,61 +302,43 @@ error:
        return ret;
 }
 
-static int charger_extcon_notifier(struct notifier_block *self,
-               unsigned long event, void *ptr)
+static int max77665_enable_charger(struct max77665_charger *charger)
 {
-       int ret;
-       struct max77665_charger_cable *cable =
-               container_of(self, struct max77665_charger_cable, nb);
+       int ret = 0;
 
-       cable->charger->ac_online = 0;
-       cable->charger->usb_online = 0;
+       if (extcon_get_cable_state(charger->edev, "USB")) {
 
-       if (extcon_get_cable_state(cable->charger->edev, "0")) {
-               ret = max77665_charger_enable(cable->charger, CHARGER);
+               ret = max77665_charger_enable(charger, CHARGER);
                if (ret < 0)
                        goto error;
 
-               cable->charger->usb_online = 1;
-               power_supply_changed(&cable->charger->usb);
+               charger->usb_online = 1;
+               power_supply_changed(&charger->usb);
        }
 
-       if (extcon_get_cable_state(cable->charger->edev, "1")) {
-               ret = max77665_charger_enable(cable->charger, OTG);
+       if (extcon_get_cable_state(charger->edev, "USB-Host")) {
+               ret = max77665_charger_enable(charger, OTG);
                if (ret < 0)
                        goto error;
        }
 
-       if (extcon_get_cable_state(cable->charger->edev, "2")) {
-               ret = max77665_charger_enable(cable->charger, CHARGER);
+       if (extcon_get_cable_state(charger->edev, "TA")) {
+               ret = max77665_charger_enable(charger, CHARGER);
                if (ret < 0)
                        goto error;
 
-               cable->charger->ac_online = 1;
-               power_supply_changed(&cable->charger->ac);
+               charger->ac_online = 1;
+               power_supply_changed(&charger->ac);
        }
-
+       return 0;
 error:
-       return NOTIFY_DONE;
+       return ret;
 }
 
-static int max77665_extcon_init(struct max77665_charger *charger,
-               struct max77665_charger_cable *cable)
+static int charger_extcon_notifier(struct notifier_block *self,
+               unsigned long event, void *ptr)
 {
-       int ret = 0;
-
-       cable->nb.notifier_call = charger_extcon_notifier;
-
-       ret = extcon_register_interest(cable->extcon_dev,
-               cable->extcon_name, cable->name, &cable->nb);
-       if (ret < 0) {
-               dev_err(charger->dev, "Cannot register for %s(cable: %s).\n",
-                       cable->extcon_name, cable->name);
-
-               ret = -EINVAL;
-       }
-
-       return ret;
+       return NOTIFY_DONE;
 }
 
 static __devinit int max77665_battery_probe(struct platform_device *pdev)
@@ -362,13 +347,6 @@ static __devinit int max77665_battery_probe(struct platform_device *pdev)
        uint8_t j;
        uint32_t read_val;
        struct max77665_charger *charger;
-       struct max77665_charger_plat_data *pdata;
-
-       pdata = dev_get_platdata(pdev->dev.parent);
-       if (!pdata) {
-               dev_err(&pdev->dev, "no platform data available\n");
-               return -ENODEV;
-       }
 
        charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
        if (!charger) {
@@ -376,10 +354,11 @@ static __devinit int max77665_battery_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       dev_set_drvdata(&pdev->dev, charger);
-
        charger->dev = &pdev->dev;
 
+       charger->plat_data = pdev->dev.platform_data;
+       dev_set_drvdata(&pdev->dev, charger);
+
        /* check for battery presence */
        ret = max77665_read_reg(charger, MAX77665_CHG_DTLS_01, &read_val);
        if (ret < 0) {
@@ -391,9 +370,15 @@ static __devinit int max77665_battery_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       charger->plat_data->fast_chg_cc = pdata->fast_chg_cc;
-       charger->plat_data->term_volt = pdata->term_volt;
-       charger->plat_data->curr_lim = pdata->curr_lim;
+       /* differentiate between E1236 and E1587*/
+       ret = maxim_get_temp();
+       if (ret == 0xff) {
+               dev_err(&pdev->dev, "failed in reading temperaure\n");
+               return -ENODEV;
+       } else if ((ret < MIN_TEMP) || (ret > MAX_TEMP)) {
+                       dev_err(&pdev->dev, "E1236 detected exiting driver....\n");
+                       return -ENODEV;
+       }
 
        charger->ac.name                = "ac";
        charger->ac.type                = POWER_SUPPLY_TYPE_MAINS;
@@ -419,14 +404,18 @@ static __devinit int max77665_battery_probe(struct platform_device *pdev)
                goto pwr_sply_error;
        }
 
-       for (j = 0 ; j < charger->num_cables ; j++) {
+       for (j = 0 ; j < charger->plat_data->num_cables; j++) {
                struct max77665_charger_cable *cable =
                                &charger->plat_data->cables[j];
 
-               ret = max77665_extcon_init(charger, cable);
-                       if (ret < 0) {
-                               dev_err(&pdev->dev, "Cannot initialize extcon");
-                       goto chrg_error;
+               cable->nb.notifier_call = charger_extcon_notifier;
+               ret = extcon_register_interest(&cable->extcon_dev,
+                               "max77665-muic", cable->name, &cable->nb);
+
+               if (ret < 0) {
+                       dev_err(charger->dev, "Cannot register for cable: %s\n",
+                               cable->name);
+                       ret = -EINVAL;
                }
        }
 
@@ -436,6 +425,23 @@ static __devinit int max77665_battery_probe(struct platform_device *pdev)
                goto chrg_error;
        }
 
+       charger->edev = extcon_get_extcon_dev("max77665-muic");
+       if (!charger->edev)
+               return -ENODEV;
+
+       ret = max77665_enable_charger(charger);
+       if (ret < 0) {
+               dev_err(charger->dev, "failed to initialize charger\n");
+               goto chrg_error;
+       }
+
+       ret = max77665_read_reg(charger, MAX77665_CHG_DTLS_01, &read_val);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "error in reading register 0x%x\n",
+                               MAX77665_CHG_DTLS_01);
+               return -ENODEV;
+       }
+
        return 0;
 
 chrg_error:
@@ -456,21 +462,28 @@ static int __devexit max77665_battery_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct platform_device_id max77665_battery_id[] = {
-       { "max77665-battery", 0 },
-};
-
 static struct platform_driver max77665_battery_driver = {
        .driver = {
-               .name = "max77665-battery",
+               .name = "max77665-charger",
                .owner = THIS_MODULE,
        },
        .probe = max77665_battery_probe,
        .remove = __devexit_p(max77665_battery_remove),
-       .id_table = max77665_battery_id,
+
 };
 
-module_platform_driver(max77665_battery_driver);
+static int __init max77665_battery_init(void)
+{
+       return platform_driver_register(&max77665_battery_driver);
+}
+
+static void __exit max77665_battery_exit(void)
+{
+       platform_driver_unregister(&max77665_battery_driver);
+}
+
+late_initcall(max77665_battery_init);
+module_exit(max77665_battery_exit);
 
 MODULE_DESCRIPTION("MAXIM MAX77665 battery charging driver");
 MODULE_AUTHOR("Syed Rafiuddin <srafiuddin@nvidia.com>");
index 7ddb75b..af1ac7b 100644 (file)
 #define MAX77665_CHG_CNFG_14    0xc5
 #define MAX77665_SAFEOUTCTRL    0xc6
 
-#define MAX_CABLES     3
+#define MAX_CABLES     6
 
 enum max77665_mode {
        CHARGER,
        OTG,
 };
 
+struct max77665_muic_platform_data {
+       int irq_base;
+};
+
+struct max77665_charger_cable {
+       const char *extcon_name;
+       const char *name;
+       struct notifier_block nb;
+       struct max77665_charger *charger;
+       struct extcon_specific_cable_nb *extcon_dev;
+};
+
 struct max77665_charger_plat_data {
-       uint8_t fast_chg_cc; /* fast charger current*/
-       uint8_t term_volt; /* charger termination voltage */
-       uint8_t curr_lim; /* input current limit */
+       uint32_t fast_chg_cc; /* fast charger current*/
+       uint32_t term_volt; /* charger termination voltage */
+       uint32_t curr_lim; /* input current limit */
+       uint8_t num_cables;
        struct max77665_charger_cable *cables;
 };
 #endif