From: Rajkumar Kasirajan <rajkumar.kasira...@stericsson.com>

In L9540, turn_on_status register is not updated correctly if
the device is rebooted with AC/USB charger connected. Due to
this, the device boots android instead of entering into charge
only mode. Read the AC/USB status register to detect the charger
presence and update the turn on status manually.

Signed-off-by: Rajkumar Kasirajan <rajkumar.kasira...@stericsson.com>
Signed-off-by: Per Forlin <per.for...@stericsson.com>
Signed-off-by: Lee Jones <lee.jo...@linaro.org>
Reviewed-by: Rupesh KUMAR <rupesh.ku...@stericsson.com>
Reviewed-by: Philippe LANGLAIS <philippe.langl...@stericsson.com>
Tested-by: Rupesh KUMAR <rupesh.ku...@stericsson.com>
Tested-by: Philippe LANGLAIS <philippe.langl...@stericsson.com>
---
 drivers/mfd/ab8500-core.c         |   39 +++++++++++++++++++++++++++++++++++++
 drivers/mfd/ab8500-sysctrl.c      |    2 +-
 include/linux/mfd/abx500/ab8500.h |   11 +++++++++++
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index f5ceb2e..bbbd6e4 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -113,6 +113,13 @@
 
 #define AB8500_TURN_ON_STATUS          0x00
 
+#define AB8500_CH_USBCH_STAT1_REG      0x02
+#define VBUS_DET_DBNC100               0x02
+#define VBUS_DET_DBNC1                 0x01
+
+static DEFINE_SPINLOCK(on_stat_lock);
+static u8 turn_on_stat_mask = 0xFF;
+static u8 turn_on_stat_set;
 static bool no_bm; /* No battery management */
 module_param(no_bm, bool, S_IRUGO);
 
@@ -1329,6 +1336,15 @@ static ssize_t show_switch_off_status(struct device *dev,
        return sprintf(buf, "%#x\n", value);
 }
 
+/* use mask and set to override the register turn_on_stat value */
+void ab8500_override_turn_on_stat(u8 mask, u8 set)
+{
+       spin_lock(&on_stat_lock);
+       turn_on_stat_mask = mask;
+       turn_on_stat_set = set;
+       spin_unlock(&on_stat_lock);
+}
+
 /*
  * ab8500 has turned on due to (TURN_ON_STATUS):
  * 0x01 PORnVbat
@@ -1352,6 +1368,20 @@ static ssize_t show_turn_on_status(struct device *dev,
                AB8500_TURN_ON_STATUS, &value);
        if (ret < 0)
                return ret;
+
+       /*
+        * In L9540, turn_on_status register is not updated correctly if
+        * the device is rebooted with AC/USB charger connected. Due to
+        * this, the device boots android instead of entering into charge
+        * only mode. Read the AC/USB status register to detect the charger
+        * presence and update the turn on status manually.
+        */
+       if (is_ab9540(ab8500)) {
+               spin_lock(&on_stat_lock);
+               value = (value & turn_on_stat_mask) | turn_on_stat_set;
+               spin_unlock(&on_stat_lock);
+       }
+
        return sprintf(buf, "%#x\n", value);
 }
 
@@ -1564,6 +1594,15 @@ static int ab8500_probe(struct platform_device *pdev)
 
        if (plat && plat->init)
                plat->init(ab8500);
+       if (is_ab9540(ab8500)) {
+               ret = get_register_interruptible(ab8500, AB8500_CHARGER,
+                       AB8500_CH_USBCH_STAT1_REG, &value);
+               if (ret < 0)
+                       return ret;
+               if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
+                       ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
+                                                    AB8500_VBUS_DET);
+       }
 
        /* Clear and mask all interrupts */
        for (i = 0; i < ab8500->mask_size; i++) {
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index ab6bfd3..6ac63a0 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -21,7 +21,7 @@ void ab8500_power_off(void)
 {
        sigset_t old;
        sigset_t all;
-       static char *pss[] = {"ab8500_ac", "ab8500_usb"};
+       static char *pss[] = {"ab8500_ac", "pm2301", "ab8500_usb"};
        int i;
        bool charger_present = false;
        union power_supply_propval val;
diff --git a/include/linux/mfd/abx500/ab8500.h 
b/include/linux/mfd/abx500/ab8500.h
index 06a8292..6748129 100644
--- a/include/linux/mfd/abx500/ab8500.h
+++ b/include/linux/mfd/abx500/ab8500.h
@@ -308,6 +308,15 @@ enum ab8500_version {
 #define AB9540_NUM_IRQ_REGS            20
 #define AB8540_NUM_IRQ_REGS            27
 
+/* Turn On Status Event */
+#define AB8500_POR_ON_VBAT             0x01
+#define AB8500_POW_KEY_1_ON            0x02
+#define AB8500_POW_KEY_2_ON            0x04
+#define AB8500_RTC_ALARM               0x08
+#define AB8500_MAIN_CH_DET             0x10
+#define AB8500_VBUS_DET                        0x20
+#define AB8500_USB_ID_DET              0x40
+
 /**
  * struct ab8500 - ab8500 internal structure
  * @dev: parent device
@@ -468,6 +477,8 @@ static inline int is_ab8540_2p0(struct ab8500 *ab)
        return is_ab8540(ab) && (ab->chip_id == AB8500_CUT2P0);
 }
 
+void ab8500_override_turn_on_stat(u8 mask, u8 set);
+
 #ifdef CONFIG_AB8500_DEBUG
 void ab8500_dump_all_banks(struct device *dev);
 void ab8500_debug_register_interrupt(int line);
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to