diff --git a/arch/arm/mach-exynos4/include/mach/thermal_interface.h b/arch/arm/mach-exynos4/include/mach/thermal_interface.h
new file mode 100644
index 0000000..b228033
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/thermal_interface.h
@@ -0,0 +1,26 @@
+/* linux/drivers/staging/thermal_exynos4/thermal_interface.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef THERMAL_INTERFACE_H
+#define THERMAL_INTERFACE_H
+/* CPU Zone information */
+#define PANIC_ZONE      4
+#define WARN_ZONE       3
+#define MONITOR_ZONE    2
+#define SAFE_ZONE       1
+#define NO_ACTION       0
+
+#define EXYNOS_PANIC_TEMP 110
+#define EXYNOS_WARN_TEMP 100
+#define EXYNOS_MONITOR_TEMP 85
+
+extern void exynos4_report_trigger(void);
+extern int (*exynos4_read_sensor)(int *temp);
+#endif
diff --git a/drivers/staging/thermal_exynos4/Kconfig b/drivers/staging/thermal_exynos4/Kconfig
new file mode 100644
index 0000000..85c6f5d
--- /dev/null
+++ b/drivers/staging/thermal_exynos4/Kconfig
@@ -0,0 +1,12 @@
+#
+# Generic Thermal Framework drivers configuration
+#
+
+menuconfig SAMSUNG_THERMAL_INTERFACE
+	bool "Samsung Thermal support"
+	help
+	  This is a samsung thermal interface which will be used as
+	  a link between sensors and cooling devices with linux thermal
+	  framework.
+
+source "drivers/staging/thermal_exynos4/sensor/Kconfig"
diff --git a/drivers/staging/thermal_exynos4/Makefile b/drivers/staging/thermal_exynos4/Makefile
new file mode 100644
index 0000000..daf393c
--- /dev/null
+++ b/drivers/staging/thermal_exynos4/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for sensor chip drivers.
+#
+obj-$(CONFIG_SAMSUNG_THERMAL_INTERFACE)	+= thermal_interface.o \
+				   sensor/
diff --git a/drivers/staging/thermal_exynos4/thermal_interface.c b/drivers/staging/thermal_exynos4/thermal_interface.c
new file mode 100644
index 0000000..da15f13
--- /dev/null
+++ b/drivers/staging/thermal_exynos4/thermal_interface.c
@@ -0,0 +1,382 @@
+/* linux/drivers/staging/thermal_exynos4/thermal_interface.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define pr_fmt(fmt) "exynos4: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/thermal.h>
+#include <linux/platform_device.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <mach/thermal_interface.h>
+
+#define INITIAL_COOLING_LEVEL 0
+#define MAX_COOLING_LEVEL 2
+
+static unsigned int idle_interval = 50;
+static unsigned int active_interval = 1;
+static unsigned int verbose;
+static int exynos4_thermal_level;
+static struct thermal_zone_device *therm_dev;
+static struct thermal_cooling_device *cool_dev;
+static struct platform_device *exynos4_dev;
+int (*exynos4_read_sensor)(int *);
+
+static int exynos4_get_mode(struct thermal_zone_device *thermal,
+			    enum thermal_device_mode *mode)
+{
+	if (!exynos4_read_sensor) {
+		pr_info("Temperature sensor not initialised\n");
+		*mode = THERMAL_DEVICE_DISABLED;
+	} else
+		*mode = THERMAL_DEVICE_ENABLED;
+	return 0;
+}
+
+/*
+ * set operation mode;
+ * enabled: the thermal layer of the kernel takes care about
+ *          the temperature.
+ * disabled: temperature sensor is not enabled.
+ */
+static int exynos4_set_mode(struct thermal_zone_device *thermal,
+			    enum thermal_device_mode mode)
+{
+	if (!therm_dev) {
+		pr_notice("thermal zone not registered\n");
+		return 0;
+	}
+	if (mode == THERMAL_DEVICE_ENABLED)
+		therm_dev->polling_delay = active_interval*1000;
+	else
+		therm_dev->polling_delay = idle_interval*1000;
+
+	thermal_zone_device_update(therm_dev);
+	pr_info("thermal polling set for duration=%d sec\n",
+					therm_dev->polling_delay/1000);
+	return 0;
+}
+
+/*This may be called from interrupt based temperature sensor*/
+void exynos4_report_trigger(void)
+{
+	therm_dev->polling_delay = active_interval*1000;
+	thermal_zone_device_update(therm_dev);
+}
+
+static int exynos4_get_trip_type(struct thermal_zone_device *thermal, int trip,
+				 enum thermal_trip_type *type)
+{
+	if (trip == 0 || trip == 1)
+		*type = THERMAL_TRIP_ACTIVE;
+	else if (trip == 2)
+		*type = THERMAL_TRIP_CRITICAL;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int exynos4_get_trip_temp(struct thermal_zone_device *thermal, int trip,
+				 unsigned long *temp)
+{
+	if (trip == 0)
+		*temp = EXYNOS_MONITOR_TEMP;
+	else if (trip == 1)
+		*temp = EXYNOS_WARN_TEMP;
+	else if (trip == 2)
+		*temp = EXYNOS_PANIC_TEMP;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int exynos4_get_crit_temp(struct thermal_zone_device *thermal,
+				 unsigned long *temperature)
+{
+	*temperature = EXYNOS_PANIC_TEMP;
+	return 0;
+}
+
+static int exynos4_bind(struct thermal_zone_device *thermal,
+			struct thermal_cooling_device *cdev)
+{
+	/* if the cooling device is the one from exynos4 bind it */
+	if (cdev != cool_dev)
+		return 0;
+	if (thermal_zone_bind_cooling_device(thermal, 0, cdev)) {
+		pr_err("error binding cooling dev\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int exynos4_unbind(struct thermal_zone_device *thermal,
+			  struct thermal_cooling_device *cdev)
+{
+	if (cdev != cool_dev)
+		return 0;
+	if (thermal_zone_unbind_cooling_device(thermal, 0, cdev)) {
+		pr_err("error unbinding cooling dev\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int exynos4_get_temp(struct thermal_zone_device *thermal,
+			       unsigned long *t)
+{
+	int temp, err = 0;
+	if (!exynos4_read_sensor) {
+		pr_info("Temperature sensor not initialised\n");
+		return -EINVAL;
+	}
+
+	err = exynos4_read_sensor(&temp);
+	if (err)
+		return err;
+
+	if (verbose)
+		pr_notice("temp %d\n", temp);
+
+	*t = temp;
+	return 0;
+}
+
+/* bind callback functions to thermalzone */
+static struct thermal_zone_device_ops exynos4_dev_ops = {
+	.bind = exynos4_bind,
+	.unbind = exynos4_unbind,
+	.get_temp = exynos4_get_temp,
+	.get_mode = exynos4_get_mode,
+	.set_mode = exynos4_set_mode,
+	.get_trip_type = exynos4_get_trip_type,
+	.get_trip_temp = exynos4_get_trip_temp,
+	.get_crit_temp = exynos4_get_crit_temp,
+};
+
+/*Below codes defines functions to be used for cpufreq as cooling device*/
+static bool is_cpufreq_valid(void)
+{
+	struct cpufreq_policy policy;
+	if (!cpufreq_get_policy(&policy, 0))
+		return true;
+	return false;
+}
+
+static int exynos4_cpufreq_apply_cooling(int cooling_level)
+{
+	if (verbose)
+		pr_info("%s: %d cooling_level=%d\n", __func__, __LINE__,
+			cooling_level);
+	if (!is_cpufreq_valid())
+		return 0;
+	exynos4_thermal_level = cooling_level;
+	cpufreq_update_policy(0);
+	if (cooling_level == INITIAL_COOLING_LEVEL)
+		therm_dev->polling_delay = idle_interval*1000;
+	return 0;
+}
+
+static int exynos4_thermal_cpufreq_notifier(struct notifier_block *nb,
+						unsigned long event, void *data)
+{
+	struct cpufreq_policy *policy = data;
+	unsigned long max_freq = 0;
+	if (event != CPUFREQ_ADJUST)
+		return 0;
+
+	max_freq =
+	(policy->cpuinfo.max_freq * (100 - (exynos4_thermal_level*48))) / 100;
+	cpufreq_verify_within_limits(policy, 0, max_freq);
+
+	return 0;
+}
+
+static struct notifier_block exynos4_thermal_cpufreq_notifier_block = {
+	.notifier_call = exynos4_thermal_cpufreq_notifier,
+};
+
+/*
+ * cooling device callback functions
+ */
+static int exynos4_get_max_state(struct thermal_cooling_device *cdev,
+				 unsigned long *state)
+{
+	*state = MAX_COOLING_LEVEL;
+	return 0;
+}
+
+static int exynos4_get_cur_state(struct thermal_cooling_device *cdev,
+				 unsigned long *state)
+{
+	*state = exynos4_thermal_level;
+	return 0;
+}
+
+static int exynos4_set_cur_state(struct thermal_cooling_device *cdev,
+				 unsigned long state)
+{
+	int zone, err = 0;
+	unsigned long cur_temp;
+
+	err = exynos4_get_temp(therm_dev, &cur_temp);
+	if (err) {
+		pr_err("error reading temperature\n");
+		return -EINVAL;
+	}
+
+	if (cur_temp < EXYNOS_MONITOR_TEMP)
+		zone = SAFE_ZONE;
+	else if (cur_temp >= EXYNOS_MONITOR_TEMP && cur_temp < EXYNOS_WARN_TEMP)
+		zone = MONITOR_ZONE;
+	else if (cur_temp >= EXYNOS_WARN_TEMP)
+		zone = WARN_ZONE;
+
+	if ((zone == SAFE_ZONE) && (state == INITIAL_COOLING_LEVEL))
+		exynos4_cpufreq_apply_cooling(INITIAL_COOLING_LEVEL);
+	else if ((zone == MONITOR_ZONE) && (state > INITIAL_COOLING_LEVEL))
+		exynos4_cpufreq_apply_cooling(INITIAL_COOLING_LEVEL + 1);
+	else if ((zone == WARN_ZONE) && (state > INITIAL_COOLING_LEVEL))
+		exynos4_cpufreq_apply_cooling(INITIAL_COOLING_LEVEL + 2);
+
+	return 0;
+}
+
+/* bind cpufreq callbacks to cpufreq cooling device */
+static struct thermal_cooling_device_ops exynos4_cooling_ops = {
+	.get_max_state = exynos4_get_max_state,
+	.get_cur_state = exynos4_get_cur_state,
+	.set_cur_state = exynos4_set_cur_state,
+};
+
+static int __devinit exynos4_probe(struct platform_device *device)
+{
+	return 0;
+}
+
+static int exynos4_remove(struct platform_device *device)
+{
+	return 0;
+}
+
+static struct platform_driver exynos4_driver = {
+	.driver = {
+		.name  = "exynos4",
+		.owner = THIS_MODULE,
+	},
+	.probe = exynos4_probe,
+	.remove = exynos4_remove,
+};
+
+static int exynos4_register_platform(void)
+{
+	int err = 0;
+
+	err = platform_driver_register(&exynos4_driver);
+	if (err)
+		return err;
+
+	exynos4_dev = platform_device_alloc("exynos4", -1);
+	if (!exynos4_dev) {
+		err = -ENOMEM;
+		goto err_device_alloc;
+	}
+	err = platform_device_add(exynos4_dev);
+	if (err)
+		goto err_device_add;
+
+	return 0;
+
+err_device_add:
+	platform_device_put(exynos4_dev);
+err_device_alloc:
+	platform_driver_unregister(&exynos4_driver);
+	return err;
+}
+
+static void exynos4_unregister_platform(void)
+{
+	platform_device_unregister(exynos4_dev);
+	platform_driver_unregister(&exynos4_driver);
+}
+
+static int exynos4_register_thermal(void)
+{
+	cool_dev = thermal_cooling_device_register("exynos4-cpufreq", NULL,
+						 &exynos4_cooling_ops);
+
+	if (IS_ERR(cool_dev))
+		return -EINVAL;
+
+	therm_dev = thermal_zone_device_register("exynos4-therm", 3, NULL,
+					      &exynos4_dev_ops, 0, 0, 0,
+					      1000);
+	if (IS_ERR(therm_dev))
+		return -EINVAL;
+
+	exynos4_set_mode(therm_dev, THERMAL_DEVICE_DISABLED);
+
+	cpufreq_register_notifier(&exynos4_thermal_cpufreq_notifier_block,
+				CPUFREQ_POLICY_NOTIFIER);
+
+	return 0;
+}
+
+static void exynos4_unregister_thermal(void)
+{
+	if (cool_dev) {
+		thermal_cooling_device_unregister(cool_dev);
+		cool_dev = NULL;
+	}
+
+	if (therm_dev) {
+		thermal_zone_device_unregister(therm_dev);
+		therm_dev = NULL;
+	}
+}
+
+static int __init exynos4_init(void)
+{
+	int err = 0;
+
+	err = exynos4_register_platform();
+	if (err)
+		goto out_err;
+
+	err = exynos4_register_thermal();
+	if (err)
+		goto err_unreg;
+
+	return 0;
+
+err_unreg:
+	exynos4_unregister_thermal();
+	exynos4_unregister_platform();
+
+out_err:
+	return err;
+}
+
+static void __exit exynos4_exit(void)
+{
+	exynos4_unregister_thermal();
+	exynos4_unregister_platform();
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Amit Daniel <amit.kachhap@linaro.org>");
+MODULE_DESCRIPTION("Exynos4 thermal monitor driver");
+
+module_init(exynos4_init);
+module_exit(exynos4_exit);
