Merge "msm: qpnp-revid: Add api to return pmic revision id"
diff --git a/drivers/platform/msm/qpnp-revid.c b/drivers/platform/msm/qpnp-revid.c
index 9471188..a2876e0 100644
--- a/drivers/platform/msm/qpnp-revid.c
+++ b/drivers/platform/msm/qpnp-revid.c
@@ -13,6 +13,8 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/spmi.h>
+#include <linux/err.h>
+#include <linux/qpnp-revid.h>
 
 #define REVID_REVISION1	0x0
 #define REVID_REVISION2	0x1
@@ -36,6 +38,15 @@
 	"PMD9635",
 };
 
+struct revid_chip {
+	struct list_head	link;
+	struct device_node	*dev_node;
+	struct pmic_revid_data	data;
+};
+
+static LIST_HEAD(revid_chips);
+static DEFINE_MUTEX(revid_chips_lock);
+
 static struct of_device_id qpnp_revid_match_table[] = {
 	{ .compatible = QPNP_REVID_DEV_NAME },
 	{}
@@ -54,6 +65,35 @@
 	return val;
 }
 
+/**
+ * get_revid_data - Return the revision information of PMIC
+ * @dev_node: Pointer to the revid peripheral of the PMIC for which
+ *		revision information is seeked
+ *
+ * CONTEXT: Should be called in non atomic context
+ *
+ * RETURNS: pointer to struct pmic_revid_data filled with the information
+ *		about the PMIC revision
+ */
+struct pmic_revid_data *get_revid_data(struct device_node *dev_node)
+{
+	struct revid_chip *revid_chip;
+
+	if (!dev_node)
+		return ERR_PTR(-EINVAL);
+
+	mutex_lock(&revid_chips_lock);
+	list_for_each_entry(revid_chip, &revid_chips, link) {
+		if (dev_node == revid_chip->dev_node) {
+			mutex_unlock(&revid_chips_lock);
+			return &revid_chip->data;
+		}
+	}
+	mutex_unlock(&revid_chips_lock);
+	return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL(get_revid_data);
+
 #define PM8941_PERIPHERAL_SUBTYPE	0x01
 #define PM8226_PERIPHERAL_SUBTYPE	0x04
 static size_t build_pmic_string(char *buf, size_t n, int sid,
@@ -94,6 +134,7 @@
 	u8 option1, option2, option3, option4;
 	struct resource *resource;
 	char pmic_string[PMIC_STRING_MAXLENGTH] = {'\0'};
+	struct revid_chip *revid_chip;
 
 	resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
 	if (!resource) {
@@ -114,6 +155,23 @@
 	pmic_subtype = qpnp_read_byte(spmi, resource->start + REVID_SUBTYPE);
 	pmic_status = qpnp_read_byte(spmi, resource->start + REVID_STATUS1);
 
+	revid_chip = devm_kzalloc(&spmi->dev, sizeof(struct revid_chip),
+						GFP_KERNEL);
+	if (!revid_chip)
+		return -ENOMEM;
+
+	revid_chip->dev_node = spmi->dev.of_node;
+	revid_chip->data.rev1 = rev1;
+	revid_chip->data.rev2 = rev2;
+	revid_chip->data.rev3 = rev3;
+	revid_chip->data.rev4 = rev4;
+	revid_chip->data.pmic_subtype = pmic_subtype;
+	revid_chip->data.pmic_type = pmic_type;
+
+	mutex_lock(&revid_chips_lock);
+	list_add(&revid_chip->link, &revid_chips);
+	mutex_unlock(&revid_chips_lock);
+
 	option1 = pmic_status & 0x3;
 	option2 = (pmic_status >> 2) & 0x3;
 	option3 = (pmic_status >> 4) & 0x3;
diff --git a/include/linux/qpnp-revid.h b/include/linux/qpnp-revid.h
new file mode 100644
index 0000000..3cf9f1c
--- /dev/null
+++ b/include/linux/qpnp-revid.h
@@ -0,0 +1,111 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __QPNP_REVID
+#define __QPNP_REVID
+
+#define PM8226_V2P1_REV1	0x00
+#define PM8226_V2P1_REV2	0x00
+#define PM8226_V2P1_REV3	0x01
+#define PM8226_V2P1_REV4	0x02
+#define PM8226_V2P1_TYPE	0x51
+#define PM8226_V2P1_SUBTYPE	0x04
+
+#define PM8226_V2P0_REV1	0x00
+#define PM8226_V2P0_REV2	0x00
+#define PM8226_V2P0_REV3	0x00
+#define PM8226_V2P0_REV4	0x02
+#define PM8226_V2P0_TYPE	0x51
+#define PM8226_V2P0_SUBTYPE	0x04
+
+#define PM8226_V1P0_REV1	0x00
+#define PM8226_V1P0_REV2	0x00
+#define PM8226_V1P0_REV3	0x00
+#define PM8226_V1P0_REV4	0x00
+#define PM8226_V1P0_TYPE	0x51
+#define PM8226_V1P0_SUBTYPE	0x04
+
+#define PM8941_V1P0_REV1	0x00
+#define PM8941_V1P0_REV2	0x00
+#define PM8941_V1P0_REV3	0x00
+#define PM8941_V1P0_REV4	0x01
+#define PM8941_V1P0_TYPE	0x51
+#define PM8941_V1P0_SUBTYPE	0x01
+
+#define PM8941_V2P0_REV1	0x00
+#define PM8941_V2P0_REV2	0x00
+#define PM8941_V2P0_REV3	0x00
+#define PM8941_V2P0_REV4	0x01
+#define PM8941_V2P0_TYPE	0x51
+#define PM8941_V2P0_SUBTYPE	0x01
+
+#define PM8941_V3P0_REV1	0x00
+#define PM8941_V3P0_REV2	0x00
+#define PM8941_V3P0_REV3	0x00
+#define PM8941_V3P0_REV4	0x03
+#define PM8941_V3P0_TYPE	0x51
+#define PM8941_V3P0_SUBTYPE	0x01
+
+#define PM8941_V3P1_REV1	0x00
+#define PM8941_V3P1_REV2	0x00
+#define PM8941_V3P1_REV3	0x01
+#define PM8941_V3P1_REV4	0x03
+#define PM8941_V3P1_TYPE	0x51
+#define PM8941_V3P1_SUBTYPE	0x01
+
+#define PM8110_V1P0_REV1	0x00
+#define PM8110_V1P0_REV2	0x00
+#define PM8110_V1P0_REV3	0x00
+#define PM8110_V1P0_REV4	0x01
+#define PM8110_V1P0_TYPE	0x51
+#define PM8110_V1P0_SUBTYPE	0x05
+
+#define PM8110_V1P1_REV1	0x00
+#define PM8110_V1P1_REV2	0x01
+#define PM8110_V1P1_REV3	0x00
+#define PM8110_V1P1_REV4	0x01
+#define PM8110_V1P1_TYPE	0x51
+#define PM8110_V1P1_SUBTYPE	0x05
+
+#define PM8110_V1P3_REV1	0x00
+#define PM8110_V1P3_REV2	0x03
+#define PM8110_V1P3_REV3	0x00
+#define PM8110_V1P3_REV4	0x01
+#define PM8110_V1P3_TYPE	0x51
+#define PM8110_V1P3_SUBTYPE	0x05
+
+#define PM8110_V2P0_REV1	0x00
+#define PM8110_V2P0_REV2	0x00
+#define PM8110_V2P0_REV3	0x00
+#define PM8110_V2P0_REV4	0x02
+#define PM8110_V2P0_TYPE	0x51
+#define PM8110_V2P0_SUBTYPE	0x05
+
+struct pmic_revid_data {
+	u8	rev1;
+	u8	rev2;
+	u8	rev3;
+	u8	rev4;
+	u8	pmic_type;
+	u8	pmic_subtype;
+};
+
+#ifdef CONFIG_QPNP_REVID
+struct pmic_revid_data *get_revid_data(struct device_node *dev_node);
+#else
+static inline
+struct pmic_revid_data *get_revid_data(struct device_node *dev_node)
+{
+	return NULL;
+}
+#endif
+#endif