hwmon: pm8921-adc: Add sysfs interface

-Add sysfs interface to read PM8921 HK/XOADC
and thermistor temperature measurements mapped
through MPP's.
-Move PM8921 ADC from directory /drivers/mfd to
/drivers/hwmon for userspace clients to read ADC
through hwmon.

CRs-Fixed: 302365
Signed-off-by: Siddartha Mohanadoss <smohanad@codeaurora.org>

Conflicts:

	drivers/mfd/Kconfig
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index ef3cb2e..f9d671e 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -788,6 +788,15 @@
 	  internally uses an array of LTC2499 and EPM ADCs in a differential
 	  configuration to provide a flat set of channels that can be addressed.
 
+config SENSORS_PM8921_ADC
+	tristate "Support for Qualcomm PM8921 ADC"
+	depends on MFD_PM8921_CORE
+	help
+	  This is the ADC arbiter driver for Qualcomm PM8921 Chip.
+
+	  The driver supports reading the HKADC, XOADC and support to set and receive
+	  temperature threshold notifications using the Battery temperature module.
+
 config SENSORS_PC87360
 	tristate "National Semiconductor PC87360 family"
 	select HWMON_VID
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index eacfcb5..c25ffcb 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -120,6 +120,7 @@
 obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
 obj-$(CONFIG_SENSORS_WPCE775X)	+= wpce775x.o
 obj-$(CONFIG_SENSORS_MSM_ADC)	+= msm_adc.o m_adcproc.o
+obj-$(CONFIG_SENSORS_PM8921_ADC)	+= pm8921-adc.o msmproc_adc.o
 
 # PMBus drivers
 obj-$(CONFIG_PMBUS)		+= pmbus_core.o
diff --git a/drivers/mfd/msmproc_adc.c b/drivers/hwmon/msmproc_adc.c
similarity index 99%
rename from drivers/mfd/msmproc_adc.c
rename to drivers/hwmon/msmproc_adc.c
index 5f2f975..a0ee748 100644
--- a/drivers/mfd/msmproc_adc.c
+++ b/drivers/hwmon/msmproc_adc.c
@@ -14,7 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/module.h>
-#include <linux/mfd/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/pm8921-adc.h>
 #define KELVINMIL_DEGMIL	273160
 
 static const struct pm8921_adc_map_pt adcmap_batttherm[] = {
diff --git a/drivers/mfd/pm8921-adc.c b/drivers/hwmon/pm8921-adc.c
similarity index 92%
rename from drivers/mfd/pm8921-adc.c
rename to drivers/hwmon/pm8921-adc.c
index b545fa5..5ab6296 100644
--- a/drivers/mfd/pm8921-adc.c
+++ b/drivers/hwmon/pm8921-adc.c
@@ -26,9 +26,11 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/mfd/pm8xxx/mpp.h>
-#include <linux/mfd/pm8921-adc.h>
 #include <linux/debugfs.h>
 #include <linux/regulator/consumer.h>
+#include <linux/mfd/pm8xxx/pm8921-adc.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 
 /* User Bank register set */
 #define PM8921_ADC_ARB_USRP_CNTRL1			0x197
@@ -127,6 +129,7 @@
 	struct mutex				mpp_adc_lock;
 	spinlock_t				btm_lock;
 	uint32_t				adc_num_channel;
+	uint32_t				adc_num_board_channel;
 	struct completion			adc_rslt_completion;
 	struct pm8921_adc_amux			*adc_channel;
 	struct pm8921_adc_amux_properties	*conv;
@@ -137,6 +140,8 @@
 	struct work_struct			warm_work;
 	struct work_struct			cool_work;
 	uint32_t				mpp_base;
+	struct sensor_device_attribute		*sens_attr;
+	struct device				*hwmon;
 };
 
 struct pm8921_adc_amux_properties {
@@ -763,7 +768,7 @@
 
 	mutex_lock(&adc_pmic->mpp_adc_lock);
 
-	rc = pm8xxx_mpp_config((mpp_num + adc_pmic->mpp_base),
+	rc = pm8xxx_mpp_config(((mpp_num - 1) + adc_pmic->mpp_base),
 					&pm8921_adc_mpp_config);
 	if (rc < 0) {
 		pr_err("pm8921 adc mpp config error with %d\n", rc);
@@ -777,7 +782,7 @@
 	if (rc < 0)
 		pr_err("pm8921 adc read error with %d\n", rc);
 
-	rc = pm8xxx_mpp_config((mpp_num + adc_pmic->mpp_base),
+	rc = pm8xxx_mpp_config(((mpp_num - 1) + adc_pmic->mpp_base),
 					&pm8921_adc_mpp_unconfig);
 	if (rc < 0)
 		pr_err("pm8921 adc mpp config error with %d\n", rc);
@@ -978,6 +983,25 @@
 }
 EXPORT_SYMBOL_GPL(pm8921_adc_btm_end);
 
+static ssize_t pm8921_adc_show(struct device *dev,
+			struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pm8921_adc *adc_pmic = pmic_adc;
+	struct pm8921_adc_chan_result result;
+	int rc = -1;
+
+	if (attr->index < adc_pmic->adc_num_channel)
+		rc = pm8921_adc_read(attr->index, &result);
+
+	if (rc)
+		return 0;
+
+	return snprintf(buf, sizeof(struct pm8921_adc_chan_result),
+				"Result:%lld Raw:%d\n",
+				result.physical, result.adc_code);
+}
+
 static int get_adc(void *data, u64 *val)
 {
 	struct pm8921_adc_chan_result result;
@@ -1000,8 +1024,8 @@
 	int i = (int)data;
 	int rc;
 
-	rc = pm8921_adc_mpp_config_read(PM8921_AMUX_MPP_8,
-		i, &result);
+	rc = pm8921_adc_mpp_config_read(i,
+		ADC_MPP_1_AMUX6, &result);
 	if (!rc)
 		pr_info("ADC MPP value raw:%x physical:%lld\n",
 			result.adc_code, result.physical);
@@ -1047,22 +1071,62 @@
 			    (void *)CHANNEL_ICHG, &reg_fops);
 	debugfs_create_file("ibat", 0644, pmic_adc->dent,
 			    (void *)CHANNEL_IBAT, &reg_fops);
-	debugfs_create_file("pa_therm", 0644, pmic_adc->dent,
+	debugfs_create_file("pa_therm1", 0644, pmic_adc->dent,
 			    (void *)ADC_MPP_1_AMUX8, &reg_fops);
 	debugfs_create_file("xo_therm", 0644, pmic_adc->dent,
 			    (void *)CHANNEL_MUXOFF, &reg_fops);
+	debugfs_create_file("pa_therm0", 0644, pmic_adc->dent,
+			    (void *)ADC_MPP_1_AMUX3, &reg_fops);
 }
 #else
 static inline void create_debugfs_entries(void)
 {
 }
 #endif
+static struct sensor_device_attribute pm8921_adc_attr =
+	SENSOR_ATTR(NULL, S_IRUGO, pm8921_adc_show, NULL, 0);
+
+static int32_t pm8921_adc_init_hwmon(struct platform_device *pdev)
+{
+	struct pm8921_adc *adc_pmic = pmic_adc;
+	int rc = 0, i;
+
+	adc_pmic->sens_attr = kzalloc(pmic_adc->adc_num_board_channel *
+		sizeof(struct sensor_device_attribute), GFP_KERNEL);
+
+	if (!adc_pmic->sens_attr) {
+		dev_err(&pdev->dev, "Unable to allocate memory\n");
+		rc = -ENOMEM;
+		goto hwmon_err_sens;
+	}
+
+	for (i = 0; i < pmic_adc->adc_num_board_channel; i++) {
+		pm8921_adc_attr.index = adc_pmic->adc_channel[i].channel_name;
+		pm8921_adc_attr.dev_attr.attr.name =
+						adc_pmic->adc_channel[i].name;
+		memcpy(&adc_pmic->sens_attr[i], &pm8921_adc_attr,
+						sizeof(pm8921_adc_attr));
+		rc = device_create_file(&pdev->dev,
+				&adc_pmic->sens_attr[i].dev_attr);
+		if (rc) {
+			dev_err(&pdev->dev, "device_create_file failed for "
+					    "dev %s\n",
+					    adc_pmic->adc_channel[i].name);
+			goto hwmon_err_sens;
+		}
+	}
+	return 0;
+
+hwmon_err_sens:
+	pr_info("Init HWMON failed for pm8921_adc with %d\n", rc);
+	return rc;
+}
 
 static int __devexit pm8921_adc_teardown(struct platform_device *pdev)
 {
 	struct pm8921_adc *adc_pmic = pmic_adc;
+	int i;
 
-	device_init_wakeup(&pdev->dev, 0);
 	free_irq(adc_pmic->adc_irq, adc_pmic);
 	free_irq(adc_pmic->btm_warm_irq, adc_pmic);
 	free_irq(adc_pmic->btm_cool_irq, adc_pmic);
@@ -1071,6 +1135,10 @@
 	kfree(adc_pmic->conv->chan_prop);
 	kfree(adc_pmic->adc_channel);
 	kfree(adc_pmic->batt);
+	for (i = 0; i < adc_pmic->adc_num_board_channel; i++)
+		device_remove_file(adc_pmic->dev,
+				&adc_pmic->sens_attr[i].dev_attr);
+	kfree(adc_pmic->sens_attr);
 	kfree(adc_pmic);
 	pm8921_adc_initialized = false;
 
@@ -1127,6 +1195,7 @@
 
 	init_completion(&adc_pmic->adc_rslt_completion);
 	adc_pmic->adc_channel = pdata->adc_channel;
+	adc_pmic->adc_num_board_channel = pdata->adc_num_board_channel;
 	adc_pmic->adc_num_channel = ADC_MPP_2_CHANNEL_NONE;
 	adc_pmic->mpp_base = pdata->adc_mpp_base;
 
@@ -1188,7 +1257,6 @@
 	}
 
 	disable_irq_nosync(adc_pmic->btm_cool_irq);
-	device_init_wakeup(&pdev->dev, pdata->adc_wakeup);
 	platform_set_drvdata(pdev, adc_pmic);
 	pmic_adc = adc_pmic;
 
@@ -1198,6 +1266,13 @@
 	pm8921_adc_calib_first_adc = false;
 	pm8921_adc_calib_device_init = false;
 	pm8921_adc_initialized = true;
+
+	rc = pm8921_adc_init_hwmon(pdev);
+	if (rc) {
+		pr_err("pm8921 adc init hwmon failed with %d\n", rc);
+		goto err_cleanup;
+	}
+	adc_pmic->hwmon = hwmon_device_register(adc_pmic->dev);
 	return 0;
 
 err_cleanup:
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b17495f..d291baa 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -827,15 +827,6 @@
 config TPS65911_COMPARATOR
 	tristate
 
-config MFD_PM8921_ADC
-	tristate "Support for Qualcomm PM8921 ADC"
-	depends on MFD_PM8921_CORE
-	help
-	  This is the ADC arbiter driver for Qualcomm PM8921 Chip.
-
-	  The driver supports reading the HKADC, XOADC and support to set and receive
-	  temperature threshold notifications using the Battery temperature module.
-
 config MFD_PM8XXX_DEBUG
 	tristate "Qualcomm PM8xxx debugfs support"
 	depends on MFD_PM8XXX && DEBUG_FS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b15e09a..5813b86 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -122,4 +122,3 @@
 obj-$(CONFIG_MFD_PM8XXX_PWM) 	+= pm8xxx-pwm.o
 obj-$(CONFIG_MFD_PM8XXX_MISC) 	+= pm8xxx-misc.o
 obj-$(CONFIG_MFD_PM8XXX_BATT_ALARM) 	+= pm8xxx-batt-alarm.o
-obj-$(CONFIG_MFD_PM8921_ADC)	+= pm8921-adc.o msmproc_adc.o
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 79124f7..1307da4 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -18,7 +18,7 @@
 #include <linux/errno.h>
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
 #include <linux/mfd/pm8xxx/core.h>
-#include <linux/mfd/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/pm8921-adc.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/debugfs.h>
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 84e5ef3..fba714e 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -18,7 +18,7 @@
 #include <linux/errno.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
-#include <linux/mfd/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/pm8921-adc.h>
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/interrupt.h>
 #include <linux/power_supply.h>
diff --git a/drivers/thermal/pm8xxx-tm.c b/drivers/thermal/pm8xxx-tm.c
index a094aed..d9f9c9e 100644
--- a/drivers/thermal/pm8xxx-tm.c
+++ b/drivers/thermal/pm8xxx-tm.c
@@ -29,7 +29,7 @@
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/mfd/pm8xxx/tm.h>
 #include <linux/completion.h>
-#include <linux/mfd/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/pm8921-adc.h>
 
 /* Register TEMP_ALARM_CTRL bits */
 #define	TEMP_ALARM_CTRL_ST3_SD		0x80