Index: ac_kernel/kernel/drivers/hwmon/Kconfig
===================================================================
--- ac_kernel.orig/kernel/drivers/hwmon/Kconfig
+++ ac_kernel/kernel/drivers/hwmon/Kconfig
@@ -1182,7 +1182,7 @@ config SENSORS_MRST_ANALOG_ACCEL
 
 config SENSORS_THERMAL_MFLD
         tristate "Thermal driver for Intel Medfield platform"
-        depends on INTEL_SCU_IPC
+        depends on INTEL_SCU_IPC && THERMAL
         help
           Say Y here to enable thermal driver on Intel Medfield
           platform.
Index: ac_kernel/kernel/drivers/hwmon/intel_mid_thermal.c
===================================================================
--- /dev/null
+++ ac_kernel/kernel/drivers/hwmon/intel_mid_thermal.c
@@ -0,0 +1,657 @@
+/*
+ * intel_mid_thermal.c - Intel MID platform thermal driver
+ *
+ * Copyright (C) 2010 Intel Corporation
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Author: Ananth Krishna <ananth.krishna.r@intel.com>
+ * Author: Durgadoss <durgadoss.r@intel.com>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/param.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/thermal.h>
+
+#include <asm/intel_scu_ipc.h>
+
+MODULE_AUTHOR("Ananth Krishna <ananth.krishna.r@intel.com>");
+MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
+MODULE_LICENSE("GPL");
+
+#define DRIVER_NAME "msic_sensor"
+#define PREFIX "intel_mid_thermal:"
+
+/*No of Thermal sensors */
+#define MSIC_THERMAL_SENSORS	4
+
+/*No of trip_points used by the MSIC thermal sensors */
+#define TRIP_POINTS	3
+
+/* ADC1 - thermal registers */
+#define MSIC_THERM_ADC1CNTL1	0x1C0
+#define MSIC_ADC_ENBL		0x18
+#define MSIC_THERM_ADC1CNTL3	0x1C2
+#define MSIC_ADCTHERM_ENBL	0x04
+#define MSIC_ADCRRDATA_ENBL	0x05
+#define MSIC_CHANL_MASK_VAL	0x0F
+
+#define MSIC_STOPBIT_MASK	16
+#define MSIC_ADCTHERM_MASK	4
+#define ADC_CHANLS_MAX		15 /*no of adc channels*/
+#define ADC_LOOP_MAX		(ADC_CHANLS_MAX - MSIC_THERMAL_SENSORS)
+
+#define MSIC_VAUDA		0x0DB
+#define MSIC_VAUDA_VAL		0xFF
+
+/* adc channel code values */
+#define SKIN_SENSOR0_CODE		0x08
+#define SKIN_SENSOR1_CODE		0x09
+#define SYS_SENSOR_CODE			0x0A
+#define MSIC_DIE_SENSOR_CODE		0x03
+
+#define SKIN_THERM_SENSOR0	0
+#define SKIN_THERM_SENSOR1	1
+#define SYS_THERM_SENSOR2	2
+#define MSIC_DIE_THERM_SENSOR3	3
+
+/* ADC code range */
+#define ADC_MAX		977
+#define ADC_MIN		162
+#define ADC_VAL1	887
+#define ADC_VAL2	720
+#define ADC_VAL3	508
+#define ADC_VAL4	315
+
+/* ADC base addresses */
+#define ADC_CHNL_START_ADDR	0x1C5	/* increments by 1 */
+#define ADC_DATA_START_ADDR     0x1D4   /* increments by 2 */
+
+/*MSIC die attributes*/
+#define MSIC_DIE_ADC_MIN		488
+#define MSIC_DIE_ADC_MAX		1004
+
+/*convert adc_val to die temperature */
+#define TO_MSIC_DIE_TEMP(adc_val)	((368 * (adc_val) / 1000) - 220)
+
+
+
+#define TEMP_CONST1  0
+#define TEMP_CONST2  0
+#define PASSIVE_FREQ 2000
+#define POLLING_FREQ 2000
+
+static int channel_index;
+
+struct platform_info {
+	struct platform_device *pdev;
+	struct thermal_zone_device *tzd[MSIC_THERMAL_SENSORS];
+};
+
+struct thermal_device_info {
+	unsigned int chnl_addr;
+	int curr_temp;
+	unsigned int trip_temp[TRIP_POINTS];
+	u64 event_timer[TRIP_POINTS];
+};
+
+static int write_trip_temp(struct thermal_zone_device *, int, long);
+static int read_trip_temp(struct thermal_zone_device *, int, long *);
+static int read_curr_temp(struct thermal_zone_device *, long *);
+static int read_trip_type(struct thermal_zone_device *, int,
+					enum thermal_trip_type *);
+
+struct thermal_zone_device_ops tzd_ops = {
+	.get_trip_type = read_trip_type,
+	.get_trip_temp = read_trip_temp,
+	.set_trip_temp = write_trip_temp,
+	.get_temp = read_curr_temp,
+};
+
+static char *name[MSIC_THERMAL_SENSORS] = {"skin0", "skin1",
+					"sys", "msicdie"};
+
+/* default temperatures for all sensors in milli degree celsius
+ * row order(sensors): skin1,skin2,sys,msic_die
+ * column order(thresholds): min,max,crit
+ */
+static uint32_t default_temp[][TRIP_POINTS] = {   { 0, 35000, 45000},
+						{ 0, 35000, 45000},
+						{ 0, 45000, 55000},
+						{ 0, 50000, 60000}
+						};
+/**
+ * is_valid_adc - checks whether the adc code is within the defined range
+ * @min: minimum value for the sensor
+ * @max: maximum value for the sensor
+ * context: can sleep
+ */
+static int is_valid_adc(uint16_t adc_val, uint16_t min, uint16_t max)
+{
+	return (adc_val >= min) && (adc_val <= max);
+}
+
+/**
+ * adc_to_temp - converts the ADC code to temperature in C
+ * @adc_val: the adc_val needs to be converted
+ *
+ * Linear approximation is used to covert the skin adc value into temperature.
+ * This technique is used to avoid very long look-up table to get
+ * the appropriate temp value from ADC value.
+ * The adc code vs sensor temp curve is split into five parts
+ * to achieve very close approximate temp value with less than
+ * 0.5C error
+ */
+static int adc_to_temp(char *type, uint16_t adc_val)
+{
+	int temp;
+
+	/* direct conversion for die temperature*/
+	if (!strcmp(type, name[MSIC_DIE_THERM_SENSOR3])) {
+		if (is_valid_adc(adc_val, MSIC_DIE_ADC_MIN, MSIC_DIE_ADC_MAX))
+			return  (int)(TO_MSIC_DIE_TEMP(adc_val) * 1000);
+		else
+			return -ERANGE;
+	}
+
+	if (!is_valid_adc(adc_val, ADC_MIN, ADC_MAX))
+		return -ERANGE;
+
+	/* linear approximation for skin temperature*/
+	if (adc_val > ADC_VAL1) /* -20 to 0C */
+		temp = 177 - (adc_val/5);
+	else if ((adc_val <= ADC_VAL1) && (adc_val > ADC_VAL2)) /* 0C to 20C */
+		temp = 111 - (adc_val/8);
+	else if ((adc_val <= ADC_VAL2) && (adc_val > ADC_VAL3)) /* 20C to 40C */
+		temp = 92 - (adc_val/10);
+	else if ((adc_val <= ADC_VAL3) && (adc_val > ADC_VAL4)) /* 40C to 60C */
+		temp = 91 - (adc_val/10);
+	else
+		temp = 112 - (adc_val/6); /* 60C to 85C */
+
+	/*convert tempertaure in celsius to milli degree celsius*/
+	return temp * 1000;
+}
+
+/**
+ * mid_read_temp - read sensors for temperature
+ * @temp: holds the current temperature for the sensor after reading
+ * Context: can sleep
+ *
+ * reads the adc_code from the channel and converts it to real
+ * temperature. The converted value is stored in temp.
+ */
+static int mid_read_temp(struct thermal_zone_device *tzd, long *temp)
+{
+	uint16_t adc_val, addr;
+	uint8_t data = 0;
+	int ret;
+
+	struct thermal_device_info *td_info =
+				(struct thermal_device_info *)tzd->devdata;
+
+	addr = td_info->chnl_addr;
+
+	/* enable the msic for conversion before reading */
+	ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL3, MSIC_ADCRRDATA_ENBL);
+	if (ret) {
+		dev_warn(&tzd->device, PREFIX "%s:ipc write failed", __func__);
+		return ret;
+	}
+	/* re-toggle the RRDATARD bit
+	 * temporary workaround */
+	ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL3, MSIC_ADCTHERM_ENBL);
+	if (ret) {
+		dev_warn(&tzd->device, PREFIX "%s:ipc write failed", __func__);
+		return ret;
+	}
+	/* reading the higher bits of data */
+	ret = intel_scu_ipc_ioread8(addr, &data);
+	if (ret) {
+		dev_warn(&tzd->device, PREFIX "%s:ipc read failed", __func__);
+		return ret;
+	}
+	/* shifting bits to accomodate the lower two data bits */
+	adc_val = (data << 2);
+	addr++;
+	ret = intel_scu_ipc_ioread8(addr, &data);/* reading lower bits */
+	if (ret) {
+		dev_warn(&tzd->device, PREFIX "%s:ipc read failed", __func__);
+		return ret;
+	}
+	/*adding lower two bits to the higher bits*/
+	data &= 03;
+	adc_val += data;
+	/*convert adc value to temperature*/
+	ret = adc_to_temp(tzd->type, adc_val);
+	if (ret == -ERANGE) {
+		dev_err(&tzd->device, PREFIX
+			"%s:invalid adc_code:%d", __func__, adc_val);
+		return ret;
+	}
+	*temp = td_info->curr_temp = ret;
+	return 0;
+}
+
+/**
+ * set_up_therm_chnl - enable thermal channel for conversion
+ * @base_addr: index of free msic adc channel
+ * Context: can sleep
+ *
+ * Enable all the three channels for conversion
+ */
+static int set_up_therm_chnl(u16 base_addr, struct device *dev)
+{
+	int ret;
+
+	/* enabling all the sensor channels */
+	ret = intel_scu_ipc_iowrite8(base_addr, SKIN_SENSOR0_CODE);
+	if (ret) {
+		dev_warn(dev, PREFIX "%s:enabling skin0 failed", __func__);
+		return ret;
+	}
+
+	ret = intel_scu_ipc_iowrite8(base_addr + 1, SKIN_SENSOR1_CODE);
+	if (ret) {
+		dev_warn(dev, PREFIX "%s:enabling skin1 failed", __func__);
+		return ret;
+	}
+
+	ret = intel_scu_ipc_iowrite8(base_addr + 2, SYS_SENSOR_CODE);
+	if (ret) {
+		dev_warn(dev, PREFIX "%s:enabling sys_sens failed", __func__);
+		return ret;
+	}
+
+	/*since this is the last channel, set the stop bit
+	to 1 by ORing the DIE_SENSOR_CODE with 0x10*/
+	ret = intel_scu_ipc_iowrite8(base_addr + 3,
+					(MSIC_DIE_SENSOR_CODE | 0x10));
+	if (ret) {
+		dev_warn(dev, PREFIX "%s:enabling msic_die failed", __func__);
+		return ret;
+	}
+
+	/* enable VAUDA line: temporary workaround for MSIC issue */
+	ret = intel_scu_ipc_iowrite8(MSIC_VAUDA, MSIC_VAUDA_VAL);
+	if (ret) {
+		dev_warn(dev, PREFIX "%s:VAUDA:ipc write failed", __func__);
+		return ret;
+	}
+
+	ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL1, MSIC_ADC_ENBL);
+	if (ret)
+		dev_warn(dev, PREFIX "%s:adc enabling failed", __func__);
+	else
+		dev_info(dev, PREFIX "%s:thrm_chnl set up success", __func__);
+
+	return ret;
+}
+
+/**
+ * reset_stopbit - sets the stop bit to 0 on the given channel
+ * @addr: address of the channel
+ * context: can sleep
+ */
+static int reset_stopbit(uint16_t addr)
+{
+	int ret;
+	uint8_t data;
+	ret = intel_scu_ipc_ioread8(addr, &data);
+	if (ret)
+		return ret;
+	/*setting the stop bit to zero*/
+	ret = intel_scu_ipc_iowrite8(addr, (data & 0xEF));
+	return ret;
+}
+
+/**
+ * find_free_channel - finds an empty channel for conversion
+ * Context: can sleep
+ *
+ * If adc is not enabled then start using 0th channel
+ * itself. Otherwise find an empty channel by looking for a
+ * channel in which the stopbit is set to 1. returns the index
+ * of the first free channel if succeeds,-EINVAL otherwise
+ */
+static int find_free_channel(struct device *dev)
+{
+	int ret;
+	int i;
+	uint8_t data;
+
+	/*check whether ADC is enabled */
+	ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL1, &data);
+	if (ret) {
+		dev_warn(dev, PREFIX "%s:ipc read failed", __func__);
+		return ret;
+	}
+
+	if ((data & 0x10) == 0) {
+		/*ADC not enabled.so enable it here */
+		ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL1,
+						(data | 0x10));
+		if (ret) {
+			dev_warn(dev, PREFIX "%s:ipc write failed", __func__);
+			return ret;
+		}
+		return 0;
+	}
+
+	/*ADC is already enabled; Looping for empty channel */
+	for (i = 0; i < ADC_CHANLS_MAX; i++) {
+		ret = intel_scu_ipc_ioread8(ADC_CHNL_START_ADDR + i, &data);
+		if (ret) {
+			dev_warn(dev, PREFIX "%s:ipc read failed\n", __func__);
+			return ret;
+		}
+		if (data & MSIC_STOPBIT_MASK) {
+			ret = i;
+			break;
+		}
+	}
+
+	if (ret > ADC_LOOP_MAX) {
+		dev_warn(dev, PREFIX "%s:No free channels", __func__);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/**
+ * mid_initialize_adc - initializing the adc
+ * Context: can sleep
+ *
+ * Initialize the adc for reading thermistor values
+ */
+static int mid_initialize_adc(struct device *dev)
+{
+	u8  data = 0;
+	int ret;
+	int offset;
+
+	/* ensure that adctherm is disabled before we
+	 * initialize the adc and map the channels
+	 */
+	ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL3, &data);
+	if (ret) {
+		dev_warn(dev, PREFIX "%s:ipc read failed", __func__);
+		return ret;
+	}
+
+	if (data & MSIC_ADCTHERM_MASK)
+		dev_warn(dev, PREFIX "%s:ADCTHERM already set", __func__);
+
+	ret = find_free_channel(dev);
+	if (ret == -EINVAL)
+		return ret;
+
+	/*assign free channel index to global variable*/
+	channel_index = ret;
+
+	offset = (ret == 0 || ret == ADC_LOOP_MAX) ? 0 : 1;
+
+	/* base address of the free channel*/
+	ret = set_up_therm_chnl(ADC_CHNL_START_ADDR + channel_index + offset,
+				dev);
+	if (ret)
+		return ret;
+
+	if (offset) {	/*no need to reset for channels 0 and 12*/
+		ret = reset_stopbit(ADC_CHNL_START_ADDR + channel_index);
+		if (ret) {
+			dev_err(dev, PREFIX "%s:ipc r/w failed", __func__);
+			return ret;
+		}
+	}
+	channel_index += offset;
+	dev_info(dev, PREFIX "adc initialization successfull");
+	return ret;
+}
+
+/**
+ * initialize_sensor - sets default temp and timer ranges
+ * @index: index of the sensor
+ * Context: can sleep
+ */
+static struct thermal_device_info *initialize_sensor(int index)
+{
+	int i;
+	struct thermal_device_info *td_info =
+		kzalloc(sizeof(struct thermal_device_info), GFP_KERNEL);
+	u64 now = get_jiffies_64();
+
+	/* setting default temp limits for msic thermal sensors */
+	for (i = 0; i < TRIP_POINTS; i++) {
+		td_info->trip_temp[i] = default_temp[index][i];
+		td_info->event_timer[i] = now;
+	}
+	/*setting the base addr of the channel for this sensor*/
+	td_info->chnl_addr = ADC_DATA_START_ADDR+2*(channel_index+index);
+
+	return td_info;
+}
+
+/**
+ * mid_thermal_resume - resume routine
+ * @pdev: platform device structure
+ * Context: can sleep
+ *
+ * mid thermal resume re-initialize the thermal monitoring
+ * of system by starting the polling
+ */
+static int mid_thermal_resume(struct platform_device *pdev)
+{
+	int i;
+	struct platform_info *pinfo = platform_get_drvdata(pdev);
+
+	for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+		mutex_lock(&pinfo->tzd[i]->lock);
+		thermal_zone_device_set_polling(pinfo->tzd[i],
+					pinfo->tzd[i]->polling_delay);
+		mutex_unlock(&pinfo->tzd[i]->lock);
+	}
+	return 0;
+}
+
+/**
+ * mid_thermal_suspend - suspend routine
+ * @pdev: platform device structure
+ * Context: can sleep
+ *
+ * mid thermal suspend implements the suspend functionality
+ * by setting the polling delay to 0 and cancelling the delayed
+ * work.
+ */
+static int mid_thermal_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	int i;
+	struct platform_info *pinfo = platform_get_drvdata(pdev);
+
+	for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+		mutex_lock(&pinfo->tzd[i]->lock);
+		thermal_zone_device_set_polling(pinfo->tzd[i], 0);
+		mutex_unlock(&pinfo->tzd[i]->lock);
+	}
+	return 0;
+}
+
+/**
+ * write_trip_temp - sets the trip point temperature
+ * @trip: index of the trip point
+ * @temp: holds the temperature of the trip point
+ * context: can sleep
+ */
+static int write_trip_temp(struct thermal_zone_device *tzd, int trip,
+			long temp)
+{
+	struct thermal_device_info *td_info =
+			(struct thermal_device_info *)tzd->devdata;
+
+	WARN_ON(td_info == NULL);
+
+	td_info->trip_temp[trip] = temp;
+	return 0;
+}
+
+/**
+ * read_trip_temp - reads the trip point temperature
+ * @trip: index of the trip point
+ * @temperature: holds the trip_point_temperature after reading
+ * context: can sleep
+ */
+static int read_trip_temp(struct thermal_zone_device *tzd, int trip,
+						long *temperature)
+{
+	struct thermal_device_info *td_info =
+		(struct thermal_device_info *)tzd->devdata;
+
+	WARN_ON(td_info == NULL);
+
+	*temperature = td_info->trip_temp[trip];
+	return 0;
+}
+
+/**
+ * read_trip_type - stores the trip_type in trip_value
+ * @trip_value: holds the trip_type for the sensor
+ * context: can sleep
+ *
+ * Since we are not doing any active handling, all trip types
+ * are PASSIVE by default.
+ */
+static int read_trip_type(struct thermal_zone_device *tzd, int trip,
+			enum thermal_trip_type *trip_value)
+{
+	*trip_value = THERMAL_TRIP_PASSIVE;
+	return 0;
+}
+
+/**
+ * read_curr_temp - reads the current temperature and stores in temp
+ * @temp: holds the current temperature value after reading
+ * context: can sleep
+ */
+static int read_curr_temp(struct thermal_zone_device *tzd, long *temp)
+{
+	int ret;
+
+	WARN_ON(tzd == NULL);
+
+	ret = mid_read_temp(tzd, temp);
+
+	return (ret == 0) ? 0 : ret;
+}
+
+/**
+ * mid_thermal_probe - mfld thermal initialize
+ * @pdev: platform device structure
+ * Context: can sleep
+ *
+ * mid thermal probe initializes the hardware and registers
+ * all the sensors with the generic thermal framework.
+ */
+static int mid_thermal_probe(struct platform_device *pdev)
+{
+	int ret;
+	int i;
+	struct platform_info *pinfo;
+
+	pinfo = kzalloc(sizeof(struct platform_info), GFP_KERNEL);
+	if (!pinfo)
+		return -ENOMEM;
+
+	/* Initializing the hardware */
+	ret = mid_initialize_adc(&pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, PREFIX "%s: adc init failed", __func__);
+		return ret;
+	}
+
+	/* register each sensor with the generic thermal framework*/
+	for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+		pinfo->tzd[i] = thermal_zone_device_register(name[i],
+					TRIP_POINTS, initialize_sensor(i),
+					&tzd_ops, TEMP_CONST1, TEMP_CONST2,
+					PASSIVE_FREQ, POLLING_FREQ);
+		pinfo->tzd[i]->passive = true;
+	}
+
+	pinfo->pdev = pdev;
+	platform_set_drvdata(pdev, pinfo);
+
+	return ret;
+}
+
+/**
+ * mid_thermal_remove - mfld thermal finalize
+ * @dev: platform device structure
+ * Context: can sleep
+ *
+ * MLFD thermal remove unregisters all the sensors from the generic
+ * thermal framework.
+ */
+static int mid_thermal_remove(struct platform_device *pdev)
+{
+	int i;
+	struct platform_info *pinfo = platform_get_drvdata(pdev);
+
+	for (i = 0; i < MSIC_THERMAL_SENSORS; i++)
+		thermal_zone_device_unregister(pinfo->tzd[i]);
+
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+/*********************************************************************
+ *		Driver initialisation and finalization
+ *********************************************************************/
+static const struct platform_device_id therm_id_table[] = {
+	{ DRIVER_NAME, 1 },
+};
+
+
+static struct platform_driver mid_thermal_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = mid_thermal_probe,
+	.suspend = mid_thermal_suspend,
+	.resume = mid_thermal_resume,
+	.remove = __devexit_p(mid_thermal_remove),
+	.id_table = therm_id_table,
+};
+
+static int __init mid_thermal_module_init(void)
+{
+	return platform_driver_register(&mid_thermal_driver);
+}
+
+static void __exit mid_thermal_module_exit(void)
+{
+	platform_driver_unregister(&mid_thermal_driver);
+}
+
+module_init(mid_thermal_module_init);
+module_exit(mid_thermal_module_exit);
