mfd: pm8xxx: provide api to read restart reason

The BMS driver needs to know the restart reason of the pmic. Add
an api in the pm8xxx design to provide the restart reason.

Change-Id: I0bbad22c5fed8c32dd7de387194e94c8d4b9ad75
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
diff --git a/drivers/mfd/pm8018-core.c b/drivers/mfd/pm8018-core.c
index b1b64cb..a91152f 100644
--- a/drivers/mfd/pm8018-core.c
+++ b/drivers/mfd/pm8018-core.c
@@ -45,7 +45,6 @@
 #define PM8018_REVISION_MASK	0x000F
 
 #define REG_PM8018_PON_CNTRL_3	0x01D
-#define PM8018_RESTART_REASON_MASK	0x07
 
 #define SINGLE_IRQ_RESOURCE(_name, _irq) \
 { \
@@ -61,6 +60,7 @@
 	struct mfd_cell					*mfd_regulators;
 	struct pm8xxx_regulator_core_platform_data	*regulator_cdata;
 	u32						rev_registers;
+	u8						restart_reason;
 };
 
 static int pm8018_readb(const struct device *dev, u16 addr, u8 *val)
@@ -125,6 +125,14 @@
 	return pmic->rev_registers & PM8018_REVISION_MASK;
 }
 
+static u8 pm8018_restart_reason(const struct device *dev)
+{
+	const struct pm8xxx_drvdata *pm8018_drvdata = dev_get_drvdata(dev);
+	const struct pm8018 *pmic = pm8018_drvdata->pm_chip_data;
+
+	return pmic->restart_reason;
+}
+
 static struct pm8xxx_drvdata pm8018_drvdata = {
 	.pmic_readb		= pm8018_readb,
 	.pmic_writeb		= pm8018_writeb,
@@ -133,6 +141,7 @@
 	.pmic_read_irq_stat	= pm8018_read_irq_stat,
 	.pmic_get_version	= pm8018_get_version,
 	.pmic_get_revision	= pm8018_get_revision,
+	.pmic_restart_reason	= pm8018_restart_reason,
 };
 
 static const struct resource gpio_cell_resources[] __devinitconst = {
@@ -516,17 +525,6 @@
 	return ret;
 }
 
-static const char * const pm8018_restart_reason[] = {
-	[0] = "Unknown",
-	[1] = "Triggered from CBL (external charger)",
-	[2] = "Triggered from KPD (power key press)",
-	[3] = "Triggered from CHG (usb charger insertion)",
-	[4] = "Triggered from SMPL (sudden momentary power loss)",
-	[5] = "Triggered from RTC (real time clock)",
-	[6] = "Triggered by Hard Reset",
-	[7] = "Triggered by General Purpose Trigger",
-};
-
 static const char * const pm8018_rev_names[] = {
 	[PM8XXX_REVISION_8018_TEST]	= "test",
 	[PM8XXX_REVISION_8018_1p0]	= "1.0",
@@ -594,8 +592,9 @@
 		pr_err("Cannot read restart reason rc=%d\n", rc);
 		goto err_read_rev;
 	}
-	val &= PM8018_RESTART_REASON_MASK;
-	pr_info("PMIC Restart Reason: %s\n", pm8018_restart_reason[val]);
+	val &= PM8XXX_RESTART_REASON_MASK;
+	pr_info("PMIC Restart Reason: %s\n", pm8xxx_restart_reason_str[val]);
+	pmic->restart_reason = val;
 
 	rc = pm8018_add_subdevices(pdata, pmic);
 	if (rc) {
diff --git a/drivers/mfd/pm8038-core.c b/drivers/mfd/pm8038-core.c
index b32932b..712a772 100644
--- a/drivers/mfd/pm8038-core.c
+++ b/drivers/mfd/pm8038-core.c
@@ -44,7 +44,6 @@
 #define PM8038_REVISION_MASK	0x000F
 
 #define REG_PM8038_PON_CNTRL_3	0x01D
-#define PM8038_RESTART_REASON_MASK	0x07
 
 #define SINGLE_IRQ_RESOURCE(_name, _irq) \
 { \
@@ -60,6 +59,7 @@
 	struct mfd_cell					*mfd_regulators;
 	struct pm8xxx_regulator_core_platform_data	*regulator_cdata;
 	u32						rev_registers;
+	u8						restart_reason;
 };
 
 static int pm8038_readb(const struct device *dev, u16 addr, u8 *val)
@@ -124,6 +124,14 @@
 	return pmic->rev_registers & PM8038_REVISION_MASK;
 }
 
+static u8 pm8038_restart_reason(const struct device *dev)
+{
+	const struct pm8xxx_drvdata *pm8038_drvdata = dev_get_drvdata(dev);
+	const struct pm8038 *pmic = pm8038_drvdata->pm_chip_data;
+
+	return pmic->restart_reason;
+}
+
 static struct pm8xxx_drvdata pm8038_drvdata = {
 	.pmic_readb		= pm8038_readb,
 	.pmic_writeb		= pm8038_writeb,
@@ -132,6 +140,7 @@
 	.pmic_read_irq_stat	= pm8038_read_irq_stat,
 	.pmic_get_version	= pm8038_get_version,
 	.pmic_get_revision	= pm8038_get_revision,
+	.pmic_restart_reason	= pm8038_restart_reason,
 };
 
 static const struct resource gpio_cell_resources[] __devinitconst = {
@@ -674,17 +683,6 @@
 	return ret;
 }
 
-static const char * const pm8038_restart_reason[] = {
-	[0] = "Unknown",
-	[1] = "Triggered from CBL (external charger)",
-	[2] = "Triggered from KPD (power key press)",
-	[3] = "Triggered from CHG (usb charger insertion)",
-	[4] = "Triggered from SMPL (sudden momentary power loss)",
-	[5] = "Triggered from RTC (real time clock)",
-	[6] = "Triggered by Hard Reset",
-	[7] = "Triggered by General Purpose Trigger",
-};
-
 static const char * const pm8038_rev_names[] = {
 	[PM8XXX_REVISION_8038_TEST]	= "test",
 	[PM8XXX_REVISION_8038_1p0]	= "1.0",
@@ -753,8 +751,9 @@
 		pr_err("Cannot read restart reason rc=%d\n", rc);
 		goto err_read_rev;
 	}
-	val &= PM8038_RESTART_REASON_MASK;
-	pr_info("PMIC Restart Reason: %s\n", pm8038_restart_reason[val]);
+	val &= PM8XXX_RESTART_REASON_MASK;
+	pr_info("PMIC Restart Reason: %s\n", pm8xxx_restart_reason_str[val]);
+	pmic->restart_reason = val;
 
 	rc = pm8038_add_subdevices(pdata, pmic);
 	if (rc) {
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index f39a19f..7d63129 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -63,6 +63,7 @@
 	struct mfd_cell					*mfd_regulators;
 	struct pm8xxx_regulator_core_platform_data	*regulator_cdata;
 	u32						rev_registers;
+	u8						restart_reason;
 };
 
 static int pm8921_readb(const struct device *dev, u16 addr, u8 *val)
@@ -133,6 +134,14 @@
 	return pmic->rev_registers & PM8921_REVISION_MASK;
 }
 
+static u8 pm8921_restart_reason(const struct device *dev)
+{
+	const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
+	const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
+
+	return pmic->restart_reason;
+}
+
 static struct pm8xxx_drvdata pm8921_drvdata = {
 	.pmic_readb		= pm8921_readb,
 	.pmic_writeb		= pm8921_writeb,
@@ -141,6 +150,7 @@
 	.pmic_read_irq_stat	= pm8921_read_irq_stat,
 	.pmic_get_version	= pm8921_get_version,
 	.pmic_get_revision	= pm8921_get_revision,
+	.pmic_restart_reason	= pm8921_restart_reason,
 };
 
 static struct resource gpio_cell_resources[] = {
@@ -815,17 +825,6 @@
 	return ret;
 }
 
-static const char * const pm8921_restart_reason[] = {
-	[0] = "Unknown",
-	[1] = "Triggered from CBL (external charger)",
-	[2] = "Triggered from KPD (power key press)",
-	[3] = "Triggered from CHG (usb charger insertion)",
-	[4] = "Triggered from SMPL (sudden momentary power loss)",
-	[5] = "Triggered from RTC (real time clock)",
-	[6] = "Triggered by Hard Reset",
-	[7] = "Triggered by General Purpose Trigger",
-};
-
 static const char * const pm8921_rev_names[] = {
 	[PM8XXX_REVISION_8921_TEST]	= "test",
 	[PM8XXX_REVISION_8921_1p0]	= "1.0",
@@ -918,8 +917,9 @@
 		pr_err("Cannot read restart reason rc=%d\n", rc);
 		goto err_read_rev;
 	}
-	val &= PM8921_RESTART_REASON_MASK;
-	pr_info("PMIC Restart Reason: %s\n", pm8921_restart_reason[val]);
+	val &= PM8XXX_RESTART_REASON_MASK;
+	pr_info("PMIC Restart Reason: %s\n", pm8xxx_restart_reason_str[val]);
+	pmic->restart_reason = val;
 
 	rc = pm8921_add_subdevices(pdata, pmic);
 	if (rc) {
diff --git a/include/linux/mfd/pm8xxx/core.h b/include/linux/mfd/pm8xxx/core.h
index 08e9014..38c589d 100644
--- a/include/linux/mfd/pm8xxx/core.h
+++ b/include/linux/mfd/pm8xxx/core.h
@@ -75,6 +75,27 @@
 #define PM8XXX_REVISION_8917_TEST	0
 #define PM8XXX_REVISION_8917_1p0	1
 
+#define PM8XXX_RESTART_UNKNOWN		0
+#define PM8XXX_RESTART_CBL		1
+#define PM8XXX_RESTART_KPD		2
+#define PM8XXX_RESTART_CHG		3
+#define PM8XXX_RESTART_SMPL		4
+#define PM8XXX_RESTART_RTC		5
+#define PM8XXX_RESTART_HARD_RESET	6
+#define PM8XXX_RESTART_GEN_PURPOSE	7
+#define PM8XXX_RESTART_REASON_MASK	0x07
+
+static const char * const pm8xxx_restart_reason_str[] = {
+	[0] = "Unknown",
+	[1] = "Triggered from CBL (external charger)",
+	[2] = "Triggered from KPD (power key press)",
+	[3] = "Triggered from CHG (usb charger insertion)",
+	[4] = "Triggered from SMPL (sudden momentary power loss)",
+	[5] = "Triggered from RTC (real time clock)",
+	[6] = "Triggered by Hard Reset",
+	[7] = "Triggered by General Purpose Trigger",
+};
+
 struct pm8xxx_drvdata {
 	int			(*pmic_readb) (const struct device *dev,
 						u16 addr, u8 *val);
@@ -88,6 +109,8 @@
 						int irq);
 	enum pm8xxx_version	(*pmic_get_version) (const struct device *dev);
 	int			(*pmic_get_revision) (const struct device *dev);
+	u8			(*pmic_restart_reason)
+						(const struct device *dev);
 	void			*pm_chip_data;
 };
 
@@ -156,4 +179,12 @@
 	return dd->pmic_get_revision(dev);
 }
 
+static inline u8 pm8xxx_restart_reason(const struct device *dev)
+{
+	struct pm8xxx_drvdata *dd = dev_get_drvdata(dev);
+
+	if (!dd)
+		return -EINVAL;
+	return dd->pmic_restart_reason(dev);
+}
 #endif