Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux

Pull thermal management updates from Zhang Rui:
 "There are not too many changes this time, except two new platform
  thermal drivers, ti-soc-thermal driver and x86_pkg_temp_thermal
  driver, and a couple of small fixes.

  Highlights:

   - move the ti-soc-thermal driver out of the staging tree to the
     thermal tree.

   - introduce the x86_pkg_temp_thermal driver.  This driver registers
     CPU digital temperature package level sensor as a thermal zone.

   - small fixes/cleanups including removing redundant use of
     platform_set_drvdata() and of_match_ptr for all platform thermal
     drivers"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (34 commits)
  thermal: cpu_cooling: fix stub function
  thermal: ti-soc-thermal: use standard GPIO DT bindings
  thermal: MAINTAINERS: Add git tree path for SoC specific updates
  thermal: fix x86_pkg_temp_thermal.c build and Kconfig
  Thermal: Documentation for x86 package temperature thermal driver
  Thermal: CPU Package temperature thermal
  thermal: consider emul_temperature while computing trend
  thermal: ti-soc-thermal: add DT example for DRA752 chip
  thermal: ti-soc-thermal: add dra752 chip to device table
  thermal: ti-soc-thermal: add thermal data for DRA752 chips
  thermal: ti-soc-thermal: remove usage of IS_ERR_OR_NULL
  thermal: ti-soc-thermal: freeze FSM while computing trend
  thermal: ti-soc-thermal: remove external heat while extrapolating hotspot
  thermal: ti-soc-thermal: update DT reference for OMAP5430
  x86, mcheck, therm_throt: Process package thresholds
  thermal: cpu_cooling: fix 'descend' check in get_property()
  Thermal: spear: Remove redundant use of of_match_ptr
  Thermal: kirkwood: Remove redundant use of of_match_ptr
  Thermal: dove: Remove redundant use of of_match_ptr
  Thermal: armada: Remove redundant use of of_match_ptr
  ...
diff --git a/drivers/staging/ti-soc-thermal/ti_soc_thermal.txt b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt
similarity index 78%
rename from drivers/staging/ti-soc-thermal/ti_soc_thermal.txt
rename to Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt
index 1629652..0c9222d 100644
--- a/drivers/staging/ti-soc-thermal/ti_soc_thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt
@@ -17,8 +17,9 @@
 - interrupts : this entry should indicate which interrupt line
 the talert signal is routed to;
 Specific:
-- ti,tshut-gpio : this entry should be used to inform which GPIO
-line the tshut signal is routed to;
+- gpios : this entry should be used to inform which GPIO
+line the tshut signal is routed to. The informed GPIO will
+be treated as an IRQ;
 - regs : this entry must also be specified and it is specific
 to each bandgap version, because the mapping may change from
 soc to soc, apart of depending on available features.
@@ -37,7 +38,7 @@
 		0x4a002378 0x18>;
 	compatible = "ti,omap4460-bandgap";
 	interrupts = <0 126 4>; /* talert */
-	ti,tshut-gpio = <86>;
+	gpios = <&gpio3 22 0>; /* tshut */
 };
 
 OMAP4470:
@@ -47,7 +48,7 @@
 		0x4a002378 0x18>;
 	compatible = "ti,omap4470-bandgap";
 	interrupts = <0 126 4>; /* talert */
-	ti,tshut-gpio = <86>;
+	gpios = <&gpio3 22 0>; /* tshut */
 };
 
 OMAP5430:
@@ -59,3 +60,15 @@
 	compatible = "ti,omap5430-bandgap";
 	interrupts = <0 126 4>; /* talert */
 };
+
+DRA752:
+bandgap {
+	reg = <0x4a0021e0 0xc
+		0x4a00232c 0xc
+		0x4a002380 0x2c
+		0x4a0023C0 0x3c
+		0x4a002564 0x8
+		0x4a002574 0x50>;
+	compatible = "ti,dra752-bandgap";
+	interrupts = <0 126 4>; /* talert */
+};
diff --git a/Documentation/thermal/x86_pkg_temperature_thermal b/Documentation/thermal/x86_pkg_temperature_thermal
new file mode 100644
index 0000000..17a3a4c
--- /dev/null
+++ b/Documentation/thermal/x86_pkg_temperature_thermal
@@ -0,0 +1,47 @@
+Kernel driver: x86_pkg_temp_thermal
+===================
+
+Supported chips:
+* x86: with package level thermal management
+(Verify using: CPUID.06H:EAX[bit 6] =1)
+
+Authors: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+
+Reference
+---
+Intel® 64 and IA-32 Architectures Software Developer’s Manual (Jan, 2013):
+Chapter 14.6: PACKAGE LEVEL THERMAL MANAGEMENT
+
+Description
+---------
+
+This driver register CPU digital temperature package level sensor as a thermal
+zone with maximum two user mode configurable trip points. Number of trip points
+depends on the capability of the package. Once the trip point is violated,
+user mode can receive notification via thermal notification mechanism and can
+take any action to control temperature.
+
+
+Threshold management
+--------------------
+Each package will register as a thermal zone under /sys/class/thermal.
+Example:
+/sys/class/thermal/thermal_zone1
+
+This contains two trip points:
+- trip_point_0_temp
+- trip_point_1_temp
+
+User can set any temperature between 0 to TJ-Max temperature. Temperature units
+are in milli-degree Celsius. Refer to "Documentation/thermal/sysfs-api.txt" for
+thermal sys-fs details.
+
+Any value other than 0 in these trip points, can trigger thermal notifications.
+Setting 0, stops sending thermal notifications.
+
+Thermal notifications: To get kobject-uevent notifications, set the thermal zone
+policy to "user_space". For example: echo -n "user_space" > policy
+
+
+
+
diff --git a/MAINTAINERS b/MAINTAINERS
index cbd4f66..3a81b6d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8159,6 +8159,7 @@
 M:      Eduardo Valentin <eduardo.valentin@ti.com>
 L:      linux-pm@vger.kernel.org
 T:      git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
+T:      git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
 Q:      https://patchwork.kernel.org/project/linux-pm/list/
 S:      Supported
 F:      drivers/thermal/
@@ -8183,8 +8184,8 @@
 TI BANDGAP AND THERMAL DRIVER
 M:	Eduardo Valentin <eduardo.valentin@ti.com>
 L:	linux-pm@vger.kernel.org
-S:	Maintained
-F:	drivers/staging/omap-thermal/
+S:	Supported
+F:	drivers/thermal/ti-soc-thermal/
 
 TI FLASH MEDIA INTERFACE DRIVER
 M:	Alex Dubov <oakad@yahoo.com>
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 6b52980..29e3093 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -214,6 +214,13 @@
 /* Interrupt Handler for core thermal thresholds */
 extern int (*platform_thermal_notify)(__u64 msr_val);
 
+/* Interrupt Handler for package thermal thresholds */
+extern int (*platform_thermal_package_notify)(__u64 msr_val);
+
+/* Callback support of rate control, return true, if
+ * callback has rate control */
+extern bool (*platform_thermal_package_rate_control)(void);
+
 #ifdef CONFIG_X86_THERMAL_VECTOR
 extern void mcheck_intel_therm_init(void);
 #else
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 98f2083..41e8e00 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -55,12 +55,24 @@
 	struct _thermal_state package_power_limit;
 	struct _thermal_state core_thresh0;
 	struct _thermal_state core_thresh1;
+	struct _thermal_state pkg_thresh0;
+	struct _thermal_state pkg_thresh1;
 };
 
 /* Callback to handle core threshold interrupts */
 int (*platform_thermal_notify)(__u64 msr_val);
 EXPORT_SYMBOL(platform_thermal_notify);
 
+/* Callback to handle core package threshold_interrupts */
+int (*platform_thermal_package_notify)(__u64 msr_val);
+EXPORT_SYMBOL_GPL(platform_thermal_package_notify);
+
+/* Callback support of rate control, return true, if
+ * callback has rate control */
+bool (*platform_thermal_package_rate_control)(void);
+EXPORT_SYMBOL_GPL(platform_thermal_package_rate_control);
+
+
 static DEFINE_PER_CPU(struct thermal_state, thermal_state);
 
 static atomic_t therm_throt_en	= ATOMIC_INIT(0);
@@ -195,19 +207,25 @@
 	return 0;
 }
 
-static int thresh_event_valid(int event)
+static int thresh_event_valid(int level, int event)
 {
 	struct _thermal_state *state;
 	unsigned int this_cpu = smp_processor_id();
 	struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
 	u64 now = get_jiffies_64();
 
-	state = (event == 0) ? &pstate->core_thresh0 : &pstate->core_thresh1;
+	if (level == PACKAGE_LEVEL)
+		state = (event == 0) ? &pstate->pkg_thresh0 :
+						&pstate->pkg_thresh1;
+	else
+		state = (event == 0) ? &pstate->core_thresh0 :
+						&pstate->core_thresh1;
 
 	if (time_before64(now, state->next_check))
 		return 0;
 
 	state->next_check = now + CHECK_INTERVAL;
+
 	return 1;
 }
 
@@ -322,6 +340,39 @@
 
 #endif /* CONFIG_SYSFS */
 
+static void notify_package_thresholds(__u64 msr_val)
+{
+	bool notify_thres_0 = false;
+	bool notify_thres_1 = false;
+
+	if (!platform_thermal_package_notify)
+		return;
+
+	/* lower threshold check */
+	if (msr_val & THERM_LOG_THRESHOLD0)
+		notify_thres_0 = true;
+	/* higher threshold check */
+	if (msr_val & THERM_LOG_THRESHOLD1)
+		notify_thres_1 = true;
+
+	if (!notify_thres_0 && !notify_thres_1)
+		return;
+
+	if (platform_thermal_package_rate_control &&
+		platform_thermal_package_rate_control()) {
+		/* Rate control is implemented in callback */
+		platform_thermal_package_notify(msr_val);
+		return;
+	}
+
+	/* lower threshold reached */
+	if (notify_thres_0 && thresh_event_valid(PACKAGE_LEVEL, 0))
+		platform_thermal_package_notify(msr_val);
+	/* higher threshold reached */
+	if (notify_thres_1 && thresh_event_valid(PACKAGE_LEVEL, 1))
+		platform_thermal_package_notify(msr_val);
+}
+
 static void notify_thresholds(__u64 msr_val)
 {
 	/* check whether the interrupt handler is defined;
@@ -331,10 +382,12 @@
 		return;
 
 	/* lower threshold reached */
-	if ((msr_val & THERM_LOG_THRESHOLD0) &&	thresh_event_valid(0))
+	if ((msr_val & THERM_LOG_THRESHOLD0) &&
+			thresh_event_valid(CORE_LEVEL, 0))
 		platform_thermal_notify(msr_val);
 	/* higher threshold reached */
-	if ((msr_val & THERM_LOG_THRESHOLD1) && thresh_event_valid(1))
+	if ((msr_val & THERM_LOG_THRESHOLD1) &&
+			thresh_event_valid(CORE_LEVEL, 1))
 		platform_thermal_notify(msr_val);
 }
 
@@ -360,6 +413,8 @@
 
 	if (this_cpu_has(X86_FEATURE_PTS)) {
 		rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
+		/* check violations of package thermal thresholds */
+		notify_package_thresholds(msr_val);
 		therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT,
 					THERMAL_THROTTLING_EVENT,
 					PACKAGE_LEVEL);
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index f64b662..3227ebe 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -120,8 +120,6 @@
 
 source "drivers/staging/csr/Kconfig"
 
-source "drivers/staging/ti-soc-thermal/Kconfig"
-
 source "drivers/staging/silicom/Kconfig"
 
 source "drivers/staging/ced1401/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 1fb58a1..4d79ebe 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -53,7 +53,6 @@
 obj-$(CONFIG_USB_WPAN_HCD)	+= ozwpan/
 obj-$(CONFIG_WIMAX_GDM72XX)	+= gdm72xx/
 obj-$(CONFIG_CSR_WIFI)		+= csr/
-obj-$(CONFIG_TI_SOC_THERMAL)	+= ti-soc-thermal/
 obj-$(CONFIG_NET_VENDOR_SILICOM)	+= silicom/
 obj-$(CONFIG_CED1401)		+= ced1401/
 obj-$(CONFIG_DRM_IMX)		+= imx-drm/
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 5e3c025..e988c81 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -169,4 +169,19 @@
 	  enforce idle time which results in more package C-state residency. The
 	  user interface is exposed via generic thermal framework.
 
+config X86_PKG_TEMP_THERMAL
+	tristate "X86 package temperature thermal driver"
+	depends on X86_THERMAL_VECTOR
+	select THERMAL_GOV_USER_SPACE
+	default m
+	help
+	  Enable this to register CPU digital sensor for package temperature as
+	  thermal zone. Each package will have its own thermal zone. There are
+	  two trip points which can be set by user to get notifications via thermal
+	  notification methods.
+
+menu "Texas Instruments thermal drivers"
+source "drivers/thermal/ti-soc-thermal/Kconfig"
+endmenu
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index c054d41..67184a2 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -23,4 +23,5 @@
 obj-$(CONFIG_ARMADA_THERMAL)	+= armada_thermal.o
 obj-$(CONFIG_DB8500_CPUFREQ_COOLING)	+= db8500_cpufreq_cooling.o
 obj-$(CONFIG_INTEL_POWERCLAMP)	+= intel_powerclamp.o
-
+obj-$(CONFIG_X86_PKG_TEMP_THERMAL)	+= x86_pkg_temp_thermal.o
+obj-$(CONFIG_TI_SOC_THERMAL)	+= ti-soc-thermal/
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index 54ffd64..5e53212 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -200,7 +200,6 @@
 		platform_get_drvdata(pdev);
 
 	thermal_zone_device_unregister(armada_thermal);
-	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
@@ -211,7 +210,7 @@
 	.driver = {
 		.name = "armada_thermal",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(armada_thermal_id_table),
+		.of_match_table = armada_thermal_id_table,
 	},
 };
 
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index c94bf2e..82e15db 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -167,7 +167,7 @@
 			continue;
 
 		/* get the frequency order */
-		if (freq != CPUFREQ_ENTRY_INVALID && descend != -1)
+		if (freq != CPUFREQ_ENTRY_INVALID && descend == -1)
 			descend = !!(freq > table[i].frequency);
 
 		freq = table[i].frequency;
diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c
index a088d13..828f5e3 100644
--- a/drivers/thermal/dove_thermal.c
+++ b/drivers/thermal/dove_thermal.c
@@ -134,16 +134,11 @@
 	struct resource *res;
 	int ret;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "Failed to get platform resource\n");
-		return -ENODEV;
-	}
-
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	priv->sensor = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(priv->sensor))
 		return PTR_ERR(priv->sensor);
@@ -178,7 +173,6 @@
 		platform_get_drvdata(pdev);
 
 	thermal_zone_device_unregister(dove_thermal);
-	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
@@ -191,7 +185,7 @@
 	.driver = {
 		.name = "dove_thermal",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(dove_thermal_id_table),
+		.of_match_table = dove_thermal_id_table,
 	},
 };
 
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c
index 4cbe3ee..9af4b93 100644
--- a/drivers/thermal/exynos_thermal.c
+++ b/drivers/thermal/exynos_thermal.c
@@ -997,7 +997,6 @@
 
 	return 0;
 err_clk:
-	platform_set_drvdata(pdev, NULL);
 	clk_unprepare(data->clk);
 	return ret;
 }
@@ -1012,8 +1011,6 @@
 
 	clk_unprepare(data->clk);
 
-	platform_set_drvdata(pdev, NULL);
-
 	return 0;
 }
 
diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c
index dfeceaf..3b034a0 100644
--- a/drivers/thermal/kirkwood_thermal.c
+++ b/drivers/thermal/kirkwood_thermal.c
@@ -75,16 +75,11 @@
 	struct kirkwood_thermal_priv *priv;
 	struct resource *res;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "Failed to get platform resource\n");
-		return -ENODEV;
-	}
-
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	priv->sensor = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(priv->sensor))
 		return PTR_ERR(priv->sensor);
@@ -108,7 +103,6 @@
 		platform_get_drvdata(pdev);
 
 	thermal_zone_device_unregister(kirkwood_thermal);
-	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
@@ -121,7 +115,7 @@
 	.driver = {
 		.name = "kirkwood_thermal",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(kirkwood_thermal_id_table),
+		.of_match_table = kirkwood_thermal_id_table,
 	},
 };
 
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index 8d7edd4..88f92e1 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -389,11 +389,6 @@
 		 * platform has IRQ support.
 		 * Then, drier use common register
 		 */
-		res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
-		if (!res) {
-			dev_err(dev, "Could not get platform resource\n");
-			return -ENODEV;
-		}
 
 		ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0,
 				       dev_name(dev), common);
@@ -405,6 +400,7 @@
 		/*
 		 * rcar_has_irq_support() will be enabled
 		 */
+		res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
 		common->base = devm_ioremap_resource(dev, res);
 		if (IS_ERR(common->base))
 			return PTR_ERR(common->base);
@@ -458,7 +454,7 @@
 
 	platform_set_drvdata(pdev, common);
 
-	dev_info(dev, "%d sensor proved\n", i);
+	dev_info(dev, "%d sensor probed\n", i);
 
 	return 0;
 
@@ -487,8 +483,6 @@
 			rcar_thermal_irq_disable(priv);
 	}
 
-	platform_set_drvdata(pdev, NULL);
-
 	pm_runtime_put_sync(dev);
 	pm_runtime_disable(dev);
 
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index 3c5ee56..ab79ea4 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -104,7 +104,7 @@
 	struct thermal_zone_device *spear_thermal = NULL;
 	struct spear_thermal_dev *stdev;
 	struct device_node *np = pdev->dev.of_node;
-	struct resource *stres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *res;
 	int ret = 0, val;
 
 	if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) {
@@ -112,11 +112,6 @@
 		return -EINVAL;
 	}
 
-	if (!stres) {
-		dev_err(&pdev->dev, "memory resource missing\n");
-		return -ENODEV;
-	}
-
 	stdev = devm_kzalloc(&pdev->dev, sizeof(*stdev), GFP_KERNEL);
 	if (!stdev) {
 		dev_err(&pdev->dev, "kzalloc fail\n");
@@ -124,12 +119,10 @@
 	}
 
 	/* Enable thermal sensor */
-	stdev->thermal_base = devm_ioremap(&pdev->dev, stres->start,
-			resource_size(stres));
-	if (!stdev->thermal_base) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		return -ENOMEM;
-	}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	stdev->thermal_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(stdev->thermal_base))
+		return PTR_ERR(stdev->thermal_base);
 
 	stdev->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(stdev->clk)) {
@@ -174,7 +167,6 @@
 	struct spear_thermal_dev *stdev = spear_thermal->devdata;
 
 	thermal_zone_device_unregister(spear_thermal);
-	platform_set_drvdata(pdev, NULL);
 
 	/* Disable SPEAr Thermal Sensor */
 	actual_mask = readl_relaxed(stdev->thermal_base);
@@ -198,7 +190,7 @@
 		.name = "spear_thermal",
 		.owner = THIS_MODULE,
 		.pm = &spear_thermal_pm_ops,
-		.of_match_table = of_match_ptr(spear_thermal_id_table),
+		.of_match_table = spear_thermal_id_table,
 	},
 };
 
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index d755440..1f02e8e 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -33,6 +33,7 @@
 #include <linux/idr.h>
 #include <linux/thermal.h>
 #include <linux/reboot.h>
+#include <linux/string.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
 
@@ -155,7 +156,8 @@
 {
 	enum thermal_trend trend;
 
-	if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) {
+	if (tz->emul_temperature || !tz->ops->get_trend ||
+	    tz->ops->get_trend(tz, trip, &trend)) {
 		if (tz->temperature > tz->last_temperature)
 			trend = THERMAL_TREND_RAISING;
 		else if (tz->temperature < tz->last_temperature)
@@ -713,10 +715,13 @@
 	int ret = -EINVAL;
 	struct thermal_zone_device *tz = to_thermal_zone(dev);
 	struct thermal_governor *gov;
+	char name[THERMAL_NAME_LENGTH];
+
+	snprintf(name, sizeof(name), "%s", buf);
 
 	mutex_lock(&thermal_governor_lock);
 
-	gov = __find_governor(buf);
+	gov = __find_governor(strim(name));
 	if (!gov)
 		goto exit;
 
@@ -1624,7 +1629,7 @@
 	if (!ops || !ops->get_temp)
 		return ERR_PTR(-EINVAL);
 
-	if (trips > 0 && !ops->get_trip_type)
+	if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp))
 		return ERR_PTR(-EINVAL);
 
 	tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL);
diff --git a/drivers/staging/ti-soc-thermal/Kconfig b/drivers/thermal/ti-soc-thermal/Kconfig
similarity index 80%
rename from drivers/staging/ti-soc-thermal/Kconfig
rename to drivers/thermal/ti-soc-thermal/Kconfig
index e81375f..bd4c7be 100644
--- a/drivers/staging/ti-soc-thermal/Kconfig
+++ b/drivers/thermal/ti-soc-thermal/Kconfig
@@ -46,3 +46,15 @@
 
 	  This includes alert interrupts generation and also the TSHUT
 	  support.
+
+config DRA752_THERMAL
+	bool "Texas Instruments DRA752 thermal support"
+	depends on TI_SOC_THERMAL
+	depends on SOC_DRA7XX
+	help
+	  If you say yes here you get thermal support for the Texas Instruments
+	  DRA752 SoC family. The current chip supported are:
+	   - DRA752
+
+	  This includes alert interrupts generation and also the TSHUT
+	  support.
diff --git a/drivers/staging/ti-soc-thermal/Makefile b/drivers/thermal/ti-soc-thermal/Makefile
similarity index 80%
rename from drivers/staging/ti-soc-thermal/Makefile
rename to drivers/thermal/ti-soc-thermal/Makefile
index 0ca034f..1226b24 100644
--- a/drivers/staging/ti-soc-thermal/Makefile
+++ b/drivers/thermal/ti-soc-thermal/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_TI_SOC_THERMAL)		+= ti-soc-thermal.o
 ti-soc-thermal-y			:= ti-bandgap.o
 ti-soc-thermal-$(CONFIG_TI_THERMAL)	+= ti-thermal-common.o
+ti-soc-thermal-$(CONFIG_DRA752_THERMAL)	+= dra752-thermal-data.o
 ti-soc-thermal-$(CONFIG_OMAP4_THERMAL)	+= omap4-thermal-data.o
 ti-soc-thermal-$(CONFIG_OMAP5_THERMAL)	+= omap5-thermal-data.o
diff --git a/drivers/staging/ti-soc-thermal/TODO b/drivers/thermal/ti-soc-thermal/TODO
similarity index 100%
rename from drivers/staging/ti-soc-thermal/TODO
rename to drivers/thermal/ti-soc-thermal/TODO
diff --git a/drivers/thermal/ti-soc-thermal/dra752-bandgap.h b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h
new file mode 100644
index 0000000..6b0f2b1
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h
@@ -0,0 +1,280 @@
+/*
+ * DRA752 bandgap registers, bitfields and temperature definitions
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Contact:
+ *   Eduardo Valentin <eduardo.valentin@ti.com>
+ *   Tero Kristo <t-kristo@ti.com>
+ *
+ * This is an auto generated file.
+ *
+ * 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.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifndef __DRA752_BANDGAP_H
+#define __DRA752_BANDGAP_H
+
+/**
+ * *** DRA752 ***
+ *
+ * Below, in sequence, are the Register definitions,
+ * the bitfields and the temperature definitions for DRA752.
+ */
+
+/**
+ * DRA752 register definitions
+ *
+ * Registers are defined as offsets. The offsets are
+ * relative to FUSE_OPP_BGAP_GPU on DRA752.
+ * DRA752_BANDGAP_BASE		0x4a0021e0
+ *
+ * Register below are grouped by domain (not necessarily in offset order)
+ */
+
+
+/* DRA752.common register offsets */
+#define DRA752_BANDGAP_CTRL_1_OFFSET		0x1a0
+#define DRA752_BANDGAP_STATUS_1_OFFSET		0x1c8
+#define DRA752_BANDGAP_CTRL_2_OFFSET		0x39c
+#define DRA752_BANDGAP_STATUS_2_OFFSET		0x3b8
+
+/* DRA752.core register offsets */
+#define DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET		0x8
+#define DRA752_TEMP_SENSOR_CORE_OFFSET			0x154
+#define DRA752_BANDGAP_THRESHOLD_CORE_OFFSET		0x1ac
+#define DRA752_BANDGAP_TSHUT_CORE_OFFSET		0x1b8
+#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET		0x1c4
+#define DRA752_DTEMP_CORE_0_OFFSET			0x208
+#define DRA752_DTEMP_CORE_1_OFFSET			0x20c
+#define DRA752_DTEMP_CORE_2_OFFSET			0x210
+#define DRA752_DTEMP_CORE_3_OFFSET			0x214
+#define DRA752_DTEMP_CORE_4_OFFSET			0x218
+
+/* DRA752.iva register offsets */
+#define DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET		0x388
+#define DRA752_TEMP_SENSOR_IVA_OFFSET			0x398
+#define DRA752_BANDGAP_THRESHOLD_IVA_OFFSET		0x3a4
+#define DRA752_BANDGAP_TSHUT_IVA_OFFSET			0x3ac
+#define DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET		0x3b4
+#define DRA752_DTEMP_IVA_0_OFFSET			0x3d0
+#define DRA752_DTEMP_IVA_1_OFFSET			0x3d4
+#define DRA752_DTEMP_IVA_2_OFFSET			0x3d8
+#define DRA752_DTEMP_IVA_3_OFFSET			0x3dc
+#define DRA752_DTEMP_IVA_4_OFFSET			0x3e0
+
+/* DRA752.mpu register offsets */
+#define DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET		0x4
+#define DRA752_TEMP_SENSOR_MPU_OFFSET			0x14c
+#define DRA752_BANDGAP_THRESHOLD_MPU_OFFSET		0x1a4
+#define DRA752_BANDGAP_TSHUT_MPU_OFFSET			0x1b0
+#define DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET		0x1bc
+#define DRA752_DTEMP_MPU_0_OFFSET			0x1e0
+#define DRA752_DTEMP_MPU_1_OFFSET			0x1e4
+#define DRA752_DTEMP_MPU_2_OFFSET			0x1e8
+#define DRA752_DTEMP_MPU_3_OFFSET			0x1ec
+#define DRA752_DTEMP_MPU_4_OFFSET			0x1f0
+
+/* DRA752.dspeve register offsets */
+#define DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET			0x384
+#define DRA752_TEMP_SENSOR_DSPEVE_OFFSET			0x394
+#define DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET			0x3a0
+#define DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET			0x3a8
+#define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET		0x3b0
+#define DRA752_DTEMP_DSPEVE_0_OFFSET				0x3bc
+#define DRA752_DTEMP_DSPEVE_1_OFFSET				0x3c0
+#define DRA752_DTEMP_DSPEVE_2_OFFSET				0x3c4
+#define DRA752_DTEMP_DSPEVE_3_OFFSET				0x3c8
+#define DRA752_DTEMP_DSPEVE_4_OFFSET				0x3cc
+
+/* DRA752.gpu register offsets */
+#define DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET		0x0
+#define DRA752_TEMP_SENSOR_GPU_OFFSET			0x150
+#define DRA752_BANDGAP_THRESHOLD_GPU_OFFSET		0x1a8
+#define DRA752_BANDGAP_TSHUT_GPU_OFFSET			0x1b4
+#define DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET		0x1c0
+#define DRA752_DTEMP_GPU_0_OFFSET			0x1f4
+#define DRA752_DTEMP_GPU_1_OFFSET			0x1f8
+#define DRA752_DTEMP_GPU_2_OFFSET			0x1fc
+#define DRA752_DTEMP_GPU_3_OFFSET			0x200
+#define DRA752_DTEMP_GPU_4_OFFSET			0x204
+
+/**
+ * Register bitfields for DRA752
+ *
+ * All the macros bellow define the required bits for
+ * controlling temperature on DRA752. Bit defines are
+ * grouped by register.
+ */
+
+/* DRA752.BANDGAP_STATUS_1 */
+#define DRA752_BANDGAP_STATUS_1_ALERT_MASK		BIT(31)
+#define DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK		BIT(5)
+#define DRA752_BANDGAP_STATUS_1_COLD_CORE_MASK		BIT(4)
+#define DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK		BIT(3)
+#define DRA752_BANDGAP_STATUS_1_COLD_GPU_MASK		BIT(2)
+#define DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK		BIT(1)
+#define DRA752_BANDGAP_STATUS_1_COLD_MPU_MASK		BIT(0)
+
+/* DRA752.BANDGAP_CTRL_2 */
+#define DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK			BIT(22)
+#define DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK		BIT(21)
+#define DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK			BIT(19)
+#define DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK			BIT(18)
+#define DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK		BIT(16)
+#define DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK		BIT(15)
+#define DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK			BIT(3)
+#define DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK		BIT(2)
+#define DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK		BIT(1)
+#define DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK		BIT(0)
+
+/* DRA752.BANDGAP_STATUS_2 */
+#define DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK			BIT(3)
+#define DRA752_BANDGAP_STATUS_2_COLD_IVA_MASK			BIT(2)
+#define DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK			BIT(1)
+#define DRA752_BANDGAP_STATUS_2_COLD_DSPEVE_MASK		BIT(0)
+
+/* DRA752.BANDGAP_CTRL_1 */
+#define DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK			(0x3 << 30)
+#define DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK		(0x7 << 27)
+#define DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK			BIT(23)
+#define DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK			BIT(22)
+#define DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK			BIT(21)
+#define DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK			BIT(20)
+#define DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK			BIT(19)
+#define DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK			BIT(18)
+#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK		BIT(17)
+#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK		BIT(16)
+#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK		BIT(15)
+#define DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK		BIT(5)
+#define DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK		BIT(4)
+#define DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK			BIT(3)
+#define DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK		BIT(2)
+#define DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK			BIT(1)
+#define DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK		BIT(0)
+
+/* DRA752.TEMP_SENSOR */
+#define DRA752_TEMP_SENSOR_TMPSOFF_MASK		BIT(11)
+#define DRA752_TEMP_SENSOR_EOCZ_MASK		BIT(10)
+#define DRA752_TEMP_SENSOR_DTEMP_MASK		(0x3ff << 0)
+
+/* DRA752.BANDGAP_THRESHOLD */
+#define DRA752_BANDGAP_THRESHOLD_HOT_MASK		(0x3ff << 16)
+#define DRA752_BANDGAP_THRESHOLD_COLD_MASK		(0x3ff << 0)
+
+/* DRA752.TSHUT_THRESHOLD */
+#define DRA752_TSHUT_THRESHOLD_MUXCTRL_MASK		BIT(31)
+#define DRA752_TSHUT_THRESHOLD_HOT_MASK			(0x3ff << 16)
+#define DRA752_TSHUT_THRESHOLD_COLD_MASK		(0x3ff << 0)
+
+/* DRA752.BANDGAP_CUMUL_DTEMP_CORE */
+#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_MASK		(0xffffffff << 0)
+
+/* DRA752.BANDGAP_CUMUL_DTEMP_IVA */
+#define DRA752_BANDGAP_CUMUL_DTEMP_IVA_MASK		(0xffffffff << 0)
+
+/* DRA752.BANDGAP_CUMUL_DTEMP_MPU */
+#define DRA752_BANDGAP_CUMUL_DTEMP_MPU_MASK		(0xffffffff << 0)
+
+/* DRA752.BANDGAP_CUMUL_DTEMP_DSPEVE */
+#define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_MASK		(0xffffffff << 0)
+
+/* DRA752.BANDGAP_CUMUL_DTEMP_GPU */
+#define DRA752_BANDGAP_CUMUL_DTEMP_GPU_MASK		(0xffffffff << 0)
+
+/**
+ * Temperature limits and thresholds for DRA752
+ *
+ * All the macros bellow are definitions for handling the
+ * ADC conversions and representation of temperature limits
+ * and thresholds for DRA752. Definitions are grouped
+ * by temperature domain.
+ */
+
+/* DRA752.common temperature definitions */
+/* ADC conversion table limits */
+#define DRA752_ADC_START_VALUE		540
+#define DRA752_ADC_END_VALUE		945
+
+/* DRA752.GPU temperature definitions */
+/* bandgap clock limits */
+#define DRA752_GPU_MAX_FREQ				1500000
+#define DRA752_GPU_MIN_FREQ				1000000
+/* sensor limits */
+#define DRA752_GPU_MIN_TEMP				-40000
+#define DRA752_GPU_MAX_TEMP				125000
+#define DRA752_GPU_HYST_VAL				5000
+/* interrupts thresholds */
+#define DRA752_GPU_TSHUT_HOT				915
+#define DRA752_GPU_TSHUT_COLD				900
+#define DRA752_GPU_T_HOT				800
+#define DRA752_GPU_T_COLD				795
+
+/* DRA752.MPU temperature definitions */
+/* bandgap clock limits */
+#define DRA752_MPU_MAX_FREQ				1500000
+#define DRA752_MPU_MIN_FREQ				1000000
+/* sensor limits */
+#define DRA752_MPU_MIN_TEMP				-40000
+#define DRA752_MPU_MAX_TEMP				125000
+#define DRA752_MPU_HYST_VAL				5000
+/* interrupts thresholds */
+#define DRA752_MPU_TSHUT_HOT				915
+#define DRA752_MPU_TSHUT_COLD				900
+#define DRA752_MPU_T_HOT				800
+#define DRA752_MPU_T_COLD				795
+
+/* DRA752.CORE temperature definitions */
+/* bandgap clock limits */
+#define DRA752_CORE_MAX_FREQ				1500000
+#define DRA752_CORE_MIN_FREQ				1000000
+/* sensor limits */
+#define DRA752_CORE_MIN_TEMP				-40000
+#define DRA752_CORE_MAX_TEMP				125000
+#define DRA752_CORE_HYST_VAL				5000
+/* interrupts thresholds */
+#define DRA752_CORE_TSHUT_HOT				915
+#define DRA752_CORE_TSHUT_COLD				900
+#define DRA752_CORE_T_HOT				800
+#define DRA752_CORE_T_COLD				795
+
+/* DRA752.DSPEVE temperature definitions */
+/* bandgap clock limits */
+#define DRA752_DSPEVE_MAX_FREQ				1500000
+#define DRA752_DSPEVE_MIN_FREQ				1000000
+/* sensor limits */
+#define DRA752_DSPEVE_MIN_TEMP				-40000
+#define DRA752_DSPEVE_MAX_TEMP				125000
+#define DRA752_DSPEVE_HYST_VAL				5000
+/* interrupts thresholds */
+#define DRA752_DSPEVE_TSHUT_HOT				915
+#define DRA752_DSPEVE_TSHUT_COLD			900
+#define DRA752_DSPEVE_T_HOT				800
+#define DRA752_DSPEVE_T_COLD				795
+
+/* DRA752.IVA temperature definitions */
+/* bandgap clock limits */
+#define DRA752_IVA_MAX_FREQ				1500000
+#define DRA752_IVA_MIN_FREQ				1000000
+/* sensor limits */
+#define DRA752_IVA_MIN_TEMP				-40000
+#define DRA752_IVA_MAX_TEMP				125000
+#define DRA752_IVA_HYST_VAL				5000
+/* interrupts thresholds */
+#define DRA752_IVA_TSHUT_HOT				915
+#define DRA752_IVA_TSHUT_COLD				900
+#define DRA752_IVA_T_HOT				800
+#define DRA752_IVA_T_COLD				795
+
+#endif /* __DRA752_BANDGAP_H */
diff --git a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
new file mode 100644
index 0000000..e5d8326
--- /dev/null
+++ b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
@@ -0,0 +1,476 @@
+/*
+ * DRA752 thermal data.
+ *
+ * Copyright (C) 2013 Texas Instruments Inc.
+ * Contact:
+ *	Eduardo Valentin <eduardo.valentin@ti.com>
+ *	Tero Kristo <t-kristo@ti.com>
+ *
+ * This file is partially autogenerated.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include "ti-thermal.h"
+#include "ti-bandgap.h"
+#include "dra752-bandgap.h"
+
+/*
+ * DRA752 has five instances of thermal sensor: MPU, GPU, CORE,
+ * IVA and DSPEVE need to describe the individual registers and
+ * bit fields.
+ */
+
+/*
+ * DRA752 CORE thermal sensor register offsets and bit-fields
+ */
+static struct temp_sensor_registers
+dra752_core_temp_sensor_registers = {
+	.temp_sensor_ctrl = DRA752_TEMP_SENSOR_CORE_OFFSET,
+	.bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK,
+	.bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK,
+	.bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET,
+	.mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK,
+	.mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK,
+	.mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
+	.mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK,
+	.mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK,
+	.mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK,
+	.bgap_threshold = DRA752_BANDGAP_THRESHOLD_CORE_OFFSET,
+	.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
+	.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
+	.tshut_threshold = DRA752_BANDGAP_TSHUT_CORE_OFFSET,
+	.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
+	.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
+	.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
+	.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
+	.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK,
+	.status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_CORE_MASK,
+	.bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET,
+	.ctrl_dtemp_0 = DRA752_DTEMP_CORE_0_OFFSET,
+	.ctrl_dtemp_1 = DRA752_DTEMP_CORE_1_OFFSET,
+	.ctrl_dtemp_2 = DRA752_DTEMP_CORE_2_OFFSET,
+	.ctrl_dtemp_3 = DRA752_DTEMP_CORE_3_OFFSET,
+	.ctrl_dtemp_4 = DRA752_DTEMP_CORE_4_OFFSET,
+	.bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET,
+};
+
+/*
+ * DRA752 IVA thermal sensor register offsets and bit-fields
+ */
+static struct temp_sensor_registers
+dra752_iva_temp_sensor_registers = {
+	.temp_sensor_ctrl = DRA752_TEMP_SENSOR_IVA_OFFSET,
+	.bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK,
+	.bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK,
+	.bgap_mask_ctrl = DRA752_BANDGAP_CTRL_2_OFFSET,
+	.mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK,
+	.mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK,
+	.mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
+	.mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK,
+	.mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK,
+	.mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK,
+	.bgap_threshold = DRA752_BANDGAP_THRESHOLD_IVA_OFFSET,
+	.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
+	.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
+	.tshut_threshold = DRA752_BANDGAP_TSHUT_IVA_OFFSET,
+	.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
+	.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
+	.bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET,
+	.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
+	.status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK,
+	.status_cold_mask = DRA752_BANDGAP_STATUS_2_COLD_IVA_MASK,
+	.bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET,
+	.ctrl_dtemp_0 = DRA752_DTEMP_IVA_0_OFFSET,
+	.ctrl_dtemp_1 = DRA752_DTEMP_IVA_1_OFFSET,
+	.ctrl_dtemp_2 = DRA752_DTEMP_IVA_2_OFFSET,
+	.ctrl_dtemp_3 = DRA752_DTEMP_IVA_3_OFFSET,
+	.ctrl_dtemp_4 = DRA752_DTEMP_IVA_4_OFFSET,
+	.bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET,
+};
+
+/*
+ * DRA752 MPU thermal sensor register offsets and bit-fields
+ */
+static struct temp_sensor_registers
+dra752_mpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = DRA752_TEMP_SENSOR_MPU_OFFSET,
+	.bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK,
+	.bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK,
+	.bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET,
+	.mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK,
+	.mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK,
+	.mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
+	.mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK,
+	.mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK,
+	.mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK,
+	.bgap_threshold = DRA752_BANDGAP_THRESHOLD_MPU_OFFSET,
+	.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
+	.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
+	.tshut_threshold = DRA752_BANDGAP_TSHUT_MPU_OFFSET,
+	.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
+	.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
+	.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
+	.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
+	.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK,
+	.status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_MPU_MASK,
+	.bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET,
+	.ctrl_dtemp_0 = DRA752_DTEMP_MPU_0_OFFSET,
+	.ctrl_dtemp_1 = DRA752_DTEMP_MPU_1_OFFSET,
+	.ctrl_dtemp_2 = DRA752_DTEMP_MPU_2_OFFSET,
+	.ctrl_dtemp_3 = DRA752_DTEMP_MPU_3_OFFSET,
+	.ctrl_dtemp_4 = DRA752_DTEMP_MPU_4_OFFSET,
+	.bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET,
+};
+
+/*
+ * DRA752 DSPEVE thermal sensor register offsets and bit-fields
+ */
+static struct temp_sensor_registers
+dra752_dspeve_temp_sensor_registers = {
+	.temp_sensor_ctrl = DRA752_TEMP_SENSOR_DSPEVE_OFFSET,
+	.bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK,
+	.bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK,
+	.bgap_mask_ctrl = DRA752_BANDGAP_CTRL_2_OFFSET,
+	.mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK,
+	.mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK,
+	.mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
+	.mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK,
+	.mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK,
+	.mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK,
+	.bgap_threshold = DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET,
+	.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
+	.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
+	.tshut_threshold = DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET,
+	.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
+	.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
+	.bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET,
+	.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
+	.status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK,
+	.status_cold_mask = DRA752_BANDGAP_STATUS_2_COLD_DSPEVE_MASK,
+	.bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET,
+	.ctrl_dtemp_0 = DRA752_DTEMP_DSPEVE_0_OFFSET,
+	.ctrl_dtemp_1 = DRA752_DTEMP_DSPEVE_1_OFFSET,
+	.ctrl_dtemp_2 = DRA752_DTEMP_DSPEVE_2_OFFSET,
+	.ctrl_dtemp_3 = DRA752_DTEMP_DSPEVE_3_OFFSET,
+	.ctrl_dtemp_4 = DRA752_DTEMP_DSPEVE_4_OFFSET,
+	.bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET,
+};
+
+/*
+ * DRA752 GPU thermal sensor register offsets and bit-fields
+ */
+static struct temp_sensor_registers
+dra752_gpu_temp_sensor_registers = {
+	.temp_sensor_ctrl = DRA752_TEMP_SENSOR_GPU_OFFSET,
+	.bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK,
+	.bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK,
+	.bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK,
+	.bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET,
+	.mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK,
+	.mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK,
+	.mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK,
+	.mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK,
+	.mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK,
+	.mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK,
+	.bgap_threshold = DRA752_BANDGAP_THRESHOLD_GPU_OFFSET,
+	.threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK,
+	.threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK,
+	.tshut_threshold = DRA752_BANDGAP_TSHUT_GPU_OFFSET,
+	.tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK,
+	.tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK,
+	.bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET,
+	.status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK,
+	.status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK,
+	.status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_GPU_MASK,
+	.bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET,
+	.ctrl_dtemp_0 = DRA752_DTEMP_GPU_0_OFFSET,
+	.ctrl_dtemp_1 = DRA752_DTEMP_GPU_1_OFFSET,
+	.ctrl_dtemp_2 = DRA752_DTEMP_GPU_2_OFFSET,
+	.ctrl_dtemp_3 = DRA752_DTEMP_GPU_3_OFFSET,
+	.ctrl_dtemp_4 = DRA752_DTEMP_GPU_4_OFFSET,
+	.bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET,
+};
+
+/* Thresholds and limits for DRA752 MPU temperature sensor */
+static struct temp_sensor_data dra752_mpu_temp_sensor_data = {
+	.tshut_hot = DRA752_MPU_TSHUT_HOT,
+	.tshut_cold = DRA752_MPU_TSHUT_COLD,
+	.t_hot = DRA752_MPU_T_HOT,
+	.t_cold = DRA752_MPU_T_COLD,
+	.min_freq = DRA752_MPU_MIN_FREQ,
+	.max_freq = DRA752_MPU_MAX_FREQ,
+	.max_temp = DRA752_MPU_MAX_TEMP,
+	.min_temp = DRA752_MPU_MIN_TEMP,
+	.hyst_val = DRA752_MPU_HYST_VAL,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for DRA752 GPU temperature sensor */
+static struct temp_sensor_data dra752_gpu_temp_sensor_data = {
+	.tshut_hot = DRA752_GPU_TSHUT_HOT,
+	.tshut_cold = DRA752_GPU_TSHUT_COLD,
+	.t_hot = DRA752_GPU_T_HOT,
+	.t_cold = DRA752_GPU_T_COLD,
+	.min_freq = DRA752_GPU_MIN_FREQ,
+	.max_freq = DRA752_GPU_MAX_FREQ,
+	.max_temp = DRA752_GPU_MAX_TEMP,
+	.min_temp = DRA752_GPU_MIN_TEMP,
+	.hyst_val = DRA752_GPU_HYST_VAL,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for DRA752 CORE temperature sensor */
+static struct temp_sensor_data dra752_core_temp_sensor_data = {
+	.tshut_hot = DRA752_CORE_TSHUT_HOT,
+	.tshut_cold = DRA752_CORE_TSHUT_COLD,
+	.t_hot = DRA752_CORE_T_HOT,
+	.t_cold = DRA752_CORE_T_COLD,
+	.min_freq = DRA752_CORE_MIN_FREQ,
+	.max_freq = DRA752_CORE_MAX_FREQ,
+	.max_temp = DRA752_CORE_MAX_TEMP,
+	.min_temp = DRA752_CORE_MIN_TEMP,
+	.hyst_val = DRA752_CORE_HYST_VAL,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for DRA752 DSPEVE temperature sensor */
+static struct temp_sensor_data dra752_dspeve_temp_sensor_data = {
+	.tshut_hot = DRA752_DSPEVE_TSHUT_HOT,
+	.tshut_cold = DRA752_DSPEVE_TSHUT_COLD,
+	.t_hot = DRA752_DSPEVE_T_HOT,
+	.t_cold = DRA752_DSPEVE_T_COLD,
+	.min_freq = DRA752_DSPEVE_MIN_FREQ,
+	.max_freq = DRA752_DSPEVE_MAX_FREQ,
+	.max_temp = DRA752_DSPEVE_MAX_TEMP,
+	.min_temp = DRA752_DSPEVE_MIN_TEMP,
+	.hyst_val = DRA752_DSPEVE_HYST_VAL,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/* Thresholds and limits for DRA752 IVA temperature sensor */
+static struct temp_sensor_data dra752_iva_temp_sensor_data = {
+	.tshut_hot = DRA752_IVA_TSHUT_HOT,
+	.tshut_cold = DRA752_IVA_TSHUT_COLD,
+	.t_hot = DRA752_IVA_T_HOT,
+	.t_cold = DRA752_IVA_T_COLD,
+	.min_freq = DRA752_IVA_MIN_FREQ,
+	.max_freq = DRA752_IVA_MAX_FREQ,
+	.max_temp = DRA752_IVA_MAX_TEMP,
+	.min_temp = DRA752_IVA_MIN_TEMP,
+	.hyst_val = DRA752_IVA_HYST_VAL,
+	.update_int1 = 1000,
+	.update_int2 = 2000,
+};
+
+/*
+ * DRA752 : Temperature values in milli degree celsius
+ * ADC code values from 540 to 945
+ */
+static
+int dra752_adc_to_temp[DRA752_ADC_END_VALUE - DRA752_ADC_START_VALUE + 1] = {
+	/* Index 540 - 549 */
+	-40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
+	-37800,
+	/* Index 550 - 559 */
+	-37400, -37000, -36600, -36200, -35800, -35300, -34700, -34200, -33800,
+	-33400,
+	/* Index 560 - 569 */
+	-33000, -32600, -32200, -31800, -31400, -31000, -30600, -30200, -29800,
+	-29400,
+	/* Index 570 - 579 */
+	-29000, -28600, -28200, -27700, -27100, -26600, -26200, -25800, -25400,
+	-25000,
+	/* Index 580 - 589 */
+	-24600, -24200, -23800, -23400, -23000, -22600, -22200, -21800, -21400,
+	-21000,
+	/* Index 590 - 599 */
+	-20500, -19900, -19400, -19000, -18600, -18200, -17800, -17400, -17000,
+	-16600,
+	/* Index 600 - 609 */
+	-16200, -15800, -15400, -15000, -14600, -14200, -13800, -13400, -13000,
+	-12500,
+	/* Index 610 - 619 */
+	-11900, -11400, -11000, -10600, -10200, -9800, -9400, -9000, -8600,
+	-8200,
+	/* Index 620 - 629 */
+	-7800, -7400, -7000, -6600, -6200, -5800, -5400, -5000, -4500,
+	-3900,
+	/* Index 630 - 639 */
+	-3400, -3000, -2600, -2200, -1800, -1400, -1000, -600, -200,
+	200,
+	/* Index 640 - 649 */
+	600, 1000, 1400, 1800, 2200, 2600, 3000, 3400, 3900,
+	4500,
+	/* Index 650 - 659 */
+	5000, 5400, 5800, 6200, 6600, 7000, 7400, 7800, 8200,
+	8600,
+	/* Index 660 - 669 */
+	9000, 9400, 9800, 10200, 10600, 11000, 11400, 11800, 12200,
+	12700,
+	/* Index 670 - 679 */
+	13300, 13800, 14200, 14600, 15000, 15400, 15800, 16200, 16600,
+	17000,
+	/* Index 680 - 689 */
+	17400, 17800, 18200, 18600, 19000, 19400, 19800, 20200, 20600,
+	21000,
+	/* Index 690 - 699 */
+	21400, 21900, 22500, 23000, 23400, 23800, 24200, 24600, 25000,
+	25400,
+	/* Index 700 - 709 */
+	25800, 26200, 26600, 27000, 27400, 27800, 28200, 28600, 29000,
+	29400,
+	/* Index 710 - 719 */
+	29800, 30200, 30600, 31000, 31400, 31900, 32500, 33000, 33400,
+	33800,
+	/* Index 720 - 729 */
+	34200, 34600, 35000, 35400, 35800, 36200, 36600, 37000, 37400,
+	37800,
+	/* Index 730 - 739 */
+	38200, 38600, 39000, 39400, 39800, 40200, 40600, 41000, 41400,
+	41800,
+	/* Index 740 - 749 */
+	42200, 42600, 43100, 43700, 44200, 44600, 45000, 45400, 45800,
+	46200,
+	/* Index 750 - 759 */
+	46600, 47000, 47400, 47800, 48200, 48600, 49000, 49400, 49800,
+	50200,
+	/* Index 760 - 769 */
+	50600, 51000, 51400, 51800, 52200, 52600, 53000, 53400, 53800,
+	54200,
+	/* Index 770 - 779 */
+	54600, 55000, 55400, 55900, 56500, 57000, 57400, 57800, 58200,
+	58600,
+	/* Index 780 - 789 */
+	59000, 59400, 59800, 60200, 60600, 61000, 61400, 61800, 62200,
+	62600,
+	/* Index 790 - 799 */
+	63000, 63400, 63800, 64200, 64600, 65000, 65400, 65800, 66200,
+	66600,
+	/* Index 800 - 809 */
+	67000, 67400, 67800, 68200, 68600, 69000, 69400, 69800, 70200,
+	70600,
+	/* Index 810 - 819 */
+	71000, 71500, 72100, 72600, 73000, 73400, 73800, 74200, 74600,
+	75000,
+	/* Index 820 - 829 */
+	75400, 75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600,
+	79000,
+	/* Index 830 - 839 */
+	79400, 79800, 80200, 80600, 81000, 81400, 81800, 82200, 82600,
+	83000,
+	/* Index 840 - 849 */
+	83400, 83800, 84200, 84600, 85000, 85400, 85800, 86200, 86600,
+	87000,
+	/* Index 850 - 859 */
+	87400, 87800, 88200, 88600, 89000, 89400, 89800, 90200, 90600,
+	91000,
+	/* Index 860 - 869 */
+	91400, 91800, 92200, 92600, 93000, 93400, 93800, 94200, 94600,
+	95000,
+	/* Index 870 - 879 */
+	95400, 95800, 96200, 96600, 97000, 97500, 98100, 98600, 99000,
+	99400,
+	/* Index 880 - 889 */
+	99800, 100200, 100600, 101000, 101400, 101800, 102200, 102600, 103000,
+	103400,
+	/* Index 890 - 899 */
+	103800, 104200, 104600, 105000, 105400, 105800, 106200, 106600, 107000,
+	107400,
+	/* Index 900 - 909 */
+	107800, 108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000,
+	111400,
+	/* Index 910 - 919 */
+	111800, 112200, 112600, 113000, 113400, 113800, 114200, 114600, 115000,
+	115400,
+	/* Index 920 - 929 */
+	115800, 116200, 116600, 117000, 117400, 117800, 118200, 118600, 119000,
+	119400,
+	/* Index 930 - 939 */
+	119800, 120200, 120600, 121000, 121400, 121800, 122200, 122600, 123000,
+	123400,
+	/* Index 940 - 945 */
+	123800, 124200, 124600, 124900, 125000, 125000,
+};
+
+/* DRA752 data */
+const struct ti_bandgap_data dra752_data = {
+	.features = TI_BANDGAP_FEATURE_TSHUT_CONFIG |
+			TI_BANDGAP_FEATURE_FREEZE_BIT |
+			TI_BANDGAP_FEATURE_TALERT |
+			TI_BANDGAP_FEATURE_COUNTER_DELAY |
+			TI_BANDGAP_FEATURE_HISTORY_BUFFER,
+	.fclock_name = "l3instr_ts_gclk_div",
+	.div_ck_name = "l3instr_ts_gclk_div",
+	.conv_table = dra752_adc_to_temp,
+	.adc_start_val = DRA752_ADC_START_VALUE,
+	.adc_end_val = DRA752_ADC_END_VALUE,
+	.expose_sensor = ti_thermal_expose_sensor,
+	.remove_sensor = ti_thermal_remove_sensor,
+	.sensors = {
+		{
+		.registers = &dra752_mpu_temp_sensor_registers,
+		.ts_data = &dra752_mpu_temp_sensor_data,
+		.domain = "cpu",
+		.register_cooling = ti_thermal_register_cpu_cooling,
+		.unregister_cooling = ti_thermal_unregister_cpu_cooling,
+		.slope = DRA752_GRADIENT_SLOPE,
+		.constant = DRA752_GRADIENT_CONST,
+		.slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
+		.constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
+		},
+		{
+		.registers = &dra752_gpu_temp_sensor_registers,
+		.ts_data = &dra752_gpu_temp_sensor_data,
+		.domain = "gpu",
+		.slope = DRA752_GRADIENT_SLOPE,
+		.constant = DRA752_GRADIENT_CONST,
+		.slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
+		.constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
+		},
+		{
+		.registers = &dra752_core_temp_sensor_registers,
+		.ts_data = &dra752_core_temp_sensor_data,
+		.domain = "core",
+		.slope = DRA752_GRADIENT_SLOPE,
+		.constant = DRA752_GRADIENT_CONST,
+		.slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
+		.constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
+		},
+		{
+		.registers = &dra752_dspeve_temp_sensor_registers,
+		.ts_data = &dra752_dspeve_temp_sensor_data,
+		.domain = "dspeve",
+		.slope = DRA752_GRADIENT_SLOPE,
+		.constant = DRA752_GRADIENT_CONST,
+		.slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
+		.constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
+		},
+		{
+		.registers = &dra752_iva_temp_sensor_registers,
+		.ts_data = &dra752_iva_temp_sensor_data,
+		.domain = "iva",
+		.slope = DRA752_GRADIENT_SLOPE,
+		.constant = DRA752_GRADIENT_CONST,
+		.slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
+		.constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
+		},
+	},
+	.sensor_count = 5,
+};
diff --git a/drivers/staging/ti-soc-thermal/omap4-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
similarity index 100%
rename from drivers/staging/ti-soc-thermal/omap4-thermal-data.c
rename to drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
diff --git a/drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h
similarity index 100%
rename from drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h
rename to drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h
diff --git a/drivers/staging/ti-soc-thermal/omap5-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
similarity index 100%
rename from drivers/staging/ti-soc-thermal/omap5-thermal-data.c
rename to drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
diff --git a/drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h
similarity index 100%
rename from drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h
rename to drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h
diff --git a/drivers/staging/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
similarity index 98%
rename from drivers/staging/ti-soc-thermal/ti-bandgap.c
rename to drivers/thermal/ti-soc-thermal/ti-bandgap.c
index f20c1cf..9dfd471 100644
--- a/drivers/staging/ti-soc-thermal/ti-bandgap.c
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
@@ -38,6 +38,7 @@
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
+#include <linux/of_gpio.h>
 #include <linux/io.h>
 
 #include "ti-bandgap.h"
@@ -469,7 +470,7 @@
 {
 	int ret = 0;
 
-	if (IS_ERR_OR_NULL(bgp)) {
+	if (!bgp || IS_ERR(bgp)) {
 		pr_err("%s: invalid bandgap pointer\n", __func__);
 		ret = -EINVAL;
 		goto exit;
@@ -992,9 +993,12 @@
 		goto exit;
 	}
 
+	spin_lock(&bgp->lock);
+
 	tsr = bgp->conf->sensors[id].registers;
 
 	/* Freeze and read the last 2 valid readings */
+	RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1);
 	reg1 = tsr->ctrl_dtemp_1;
 	reg2 = tsr->ctrl_dtemp_2;
 
@@ -1008,22 +1012,25 @@
 	/* Convert from adc values to mCelsius temperature */
 	ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1);
 	if (ret)
-		goto exit;
+		goto unfreeze;
 
 	ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2);
 	if (ret)
-		goto exit;
+		goto unfreeze;
 
 	/* Fetch the update interval */
 	ret = ti_bandgap_read_update_interval(bgp, id, &interval);
 	if (ret || !interval)
-		goto exit;
+		goto unfreeze;
 
 	*trend = (t1 - t2) / interval;
 
 	dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n",
 		t1, t2, *trend);
 
+unfreeze:
+	RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0);
+	spin_unlock(&bgp->lock);
 exit:
 	return ret;
 }
@@ -1123,7 +1130,6 @@
 	const struct of_device_id *of_id;
 	struct ti_bandgap *bgp;
 	struct resource *res;
-	u32 prop;
 	int i;
 
 	/* just for the sake */
@@ -1167,11 +1173,7 @@
 	} while (res);
 
 	if (TI_BANDGAP_HAS(bgp, TSHUT)) {
-		if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) {
-			dev_err(&pdev->dev, "missing tshut gpio in device tree\n");
-			return ERR_PTR(-EINVAL);
-		}
-		bgp->tshut_gpio = prop;
+		bgp->tshut_gpio = of_get_gpio(node, 0);
 		if (!gpio_is_valid(bgp->tshut_gpio)) {
 			dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
 				bgp->tshut_gpio);
@@ -1191,7 +1193,7 @@
 	int clk_rate, ret = 0, i;
 
 	bgp = ti_bandgap_build(pdev);
-	if (IS_ERR_OR_NULL(bgp)) {
+	if (IS_ERR(bgp)) {
 		dev_err(&pdev->dev, "failed to fetch platform data\n");
 		return PTR_ERR(bgp);
 	}
@@ -1207,17 +1209,19 @@
 	}
 
 	bgp->fclock = clk_get(NULL, bgp->conf->fclock_name);
-	ret = IS_ERR_OR_NULL(bgp->fclock);
+	ret = IS_ERR(bgp->fclock);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to request fclock reference\n");
+		ret = PTR_ERR(bgp->fclock);
 		goto free_irqs;
 	}
 
 	bgp->div_clk = clk_get(NULL,  bgp->conf->div_ck_name);
-	ret = IS_ERR_OR_NULL(bgp->div_clk);
+	ret = IS_ERR(bgp->div_clk);
 	if (ret) {
 		dev_err(&pdev->dev,
 			"failed to request div_ts_ck clock ref\n");
+		ret = PTR_ERR(bgp->div_clk);
 		goto free_irqs;
 	}
 
@@ -1523,6 +1527,12 @@
 		.data = (void *)&omap5430_data,
 	},
 #endif
+#ifdef CONFIG_DRA752_THERMAL
+	{
+		.compatible = "ti,dra752-bandgap",
+		.data = (void *)&dra752_data,
+	},
+#endif
 	/* Sentinel */
 	{ },
 };
diff --git a/drivers/staging/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
similarity index 98%
rename from drivers/staging/ti-soc-thermal/ti-bandgap.h
rename to drivers/thermal/ti-soc-thermal/ti-bandgap.h
index 5f4794a..b3adf72 100644
--- a/drivers/staging/ti-soc-thermal/ti-bandgap.h
+++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h
@@ -400,4 +400,9 @@
 #define omap5430_data					NULL
 #endif
 
+#ifdef CONFIG_DRA752_THERMAL
+extern const struct ti_bandgap_data dra752_data;
+#else
+#define dra752_data					NULL
+#endif
 #endif
diff --git a/drivers/staging/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
similarity index 97%
rename from drivers/staging/ti-soc-thermal/ti-thermal-common.c
rename to drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 8e67ebf..4c5f55c37 100644
--- a/drivers/staging/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -101,7 +101,7 @@
 
 	pcb_tz = data->pcb_tz;
 	/* In case pcb zone is available, use the extrapolation rule with it */
-	if (!IS_ERR_OR_NULL(pcb_tz)) {
+	if (!IS_ERR(pcb_tz)) {
 		ret = thermal_zone_get_temp(pcb_tz, &pcb_temp);
 		if (!ret) {
 			tmp -= pcb_temp; /* got a valid PCB temp */
@@ -124,7 +124,7 @@
 	struct ti_thermal_data *data = thermal->devdata;
 	int id;
 
-	if (IS_ERR_OR_NULL(data))
+	if (!data || IS_ERR(data))
 		return -ENODEV;
 
 	/* check if this is the cooling device we registered */
@@ -146,7 +146,7 @@
 {
 	struct ti_thermal_data *data = thermal->devdata;
 
-	if (IS_ERR_OR_NULL(data))
+	if (!data || IS_ERR(data))
 		return -ENODEV;
 
 	/* check if this is the cooling device we registered */
@@ -282,6 +282,7 @@
 	data->sensor_id = id;
 	data->bgp = bgp;
 	data->mode = THERMAL_DEVICE_ENABLED;
+	/* pcb_tz will be either valid or PTR_ERR() */
 	data->pcb_tz = thermal_zone_get_zone_by_name("pcb");
 	INIT_WORK(&data->thermal_wq, ti_thermal_work);
 
@@ -295,7 +296,7 @@
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
 
-	if (IS_ERR_OR_NULL(data))
+	if (!data || IS_ERR(data))
 		data = ti_thermal_build_data(bgp, id);
 
 	if (!data)
@@ -306,7 +307,7 @@
 				OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
 				NULL, FAST_TEMP_MONITORING_RATE,
 				FAST_TEMP_MONITORING_RATE);
-	if (IS_ERR_OR_NULL(data->ti_thermal)) {
+	if (IS_ERR(data->ti_thermal)) {
 		dev_err(bgp->dev, "thermal zone device is NULL\n");
 		return PTR_ERR(data->ti_thermal);
 	}
@@ -343,7 +344,7 @@
 	struct ti_thermal_data *data;
 
 	data = ti_bandgap_get_sensor_data(bgp, id);
-	if (IS_ERR_OR_NULL(data))
+	if (!data || IS_ERR(data))
 		data = ti_thermal_build_data(bgp, id);
 
 	if (!data)
@@ -356,7 +357,7 @@
 
 	/* Register cooling device */
 	data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
-	if (IS_ERR_OR_NULL(data->cool_dev)) {
+	if (IS_ERR(data->cool_dev)) {
 		dev_err(bgp->dev,
 			"Failed to register cpufreq cooling device\n");
 		return PTR_ERR(data->cool_dev);
diff --git a/drivers/staging/ti-soc-thermal/ti-thermal.h b/drivers/thermal/ti-soc-thermal/ti-thermal.h
similarity index 95%
rename from drivers/staging/ti-soc-thermal/ti-thermal.h
rename to drivers/thermal/ti-soc-thermal/ti-thermal.h
index 5055777..f8b7ffe 100644
--- a/drivers/staging/ti-soc-thermal/ti-thermal.h
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal.h
@@ -38,6 +38,9 @@
 #define OMAP_GRADIENT_SLOPE_5430_GPU				117
 #define OMAP_GRADIENT_CONST_5430_GPU				-2992
 
+#define DRA752_GRADIENT_SLOPE					0
+#define DRA752_GRADIENT_CONST					2000
+
 /* PCB sensor calculation constants */
 #define OMAP_GRADIENT_SLOPE_W_PCB_4430				0
 #define OMAP_GRADIENT_CONST_W_PCB_4430				20000
@@ -51,6 +54,9 @@
 #define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU			464
 #define OMAP_GRADIENT_CONST_W_PCB_5430_GPU			-5102
 
+#define DRA752_GRADIENT_SLOPE_W_PCB				0
+#define DRA752_GRADIENT_CONST_W_PCB				2000
+
 /* trip points of interest in milicelsius (at hotspot level) */
 #define OMAP_TRIP_COLD						100000
 #define OMAP_TRIP_HOT						110000
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
new file mode 100644
index 0000000..5de56f6
--- /dev/null
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -0,0 +1,642 @@
+/*
+ * x86_pkg_temp_thermal driver
+ * Copyright (c) 2013, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#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/cpu.h>
+#include <linux/smp.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/thermal.h>
+#include <linux/debugfs.h>
+#include <asm/cpu_device_id.h>
+#include <asm/mce.h>
+
+/*
+* Rate control delay: Idea is to introduce denounce effect
+* This should be long enough to avoid reduce events, when
+* threshold is set to a temperature, which is constantly
+* violated, but at the short enough to take any action.
+* The action can be remove threshold or change it to next
+* interesting setting. Based on experiments, in around
+* every 5 seconds under load will give us a significant
+* temperature change.
+*/
+#define PKG_TEMP_THERMAL_NOTIFY_DELAY	5000
+static int notify_delay_ms = PKG_TEMP_THERMAL_NOTIFY_DELAY;
+module_param(notify_delay_ms, int, 0644);
+MODULE_PARM_DESC(notify_delay_ms,
+	"User space notification delay in milli seconds.");
+
+/* Number of trip points in thermal zone. Currently it can't
+* be more than 2. MSR can allow setting and getting notifications
+* for only 2 thresholds. This define enforces this, if there
+* is some wrong values returned by cpuid for number of thresholds.
+*/
+#define MAX_NUMBER_OF_TRIPS	2
+
+struct phy_dev_entry {
+	struct list_head list;
+	u16 phys_proc_id;
+	u16 first_cpu;
+	u32 tj_max;
+	int ref_cnt;
+	u32 start_pkg_therm_low;
+	u32 start_pkg_therm_high;
+	struct thermal_zone_device *tzone;
+};
+
+/* List maintaining number of package instances */
+static LIST_HEAD(phy_dev_list);
+static DEFINE_MUTEX(phy_dev_list_mutex);
+
+/* Interrupt to work function schedule queue */
+static DEFINE_PER_CPU(struct delayed_work, pkg_temp_thermal_threshold_work);
+
+/* To track if the work is already scheduled on a package */
+static u8 *pkg_work_scheduled;
+
+/* Spin lock to prevent races with pkg_work_scheduled */
+static spinlock_t pkg_work_lock;
+static u16 max_phy_id;
+
+/* Debug counters to show using debugfs */
+static struct dentry *debugfs;
+static unsigned int pkg_interrupt_cnt;
+static unsigned int pkg_work_cnt;
+
+static int pkg_temp_debugfs_init(void)
+{
+	struct dentry *d;
+
+	debugfs = debugfs_create_dir("pkg_temp_thermal", NULL);
+	if (!debugfs)
+		return -ENOENT;
+
+	d = debugfs_create_u32("pkg_thres_interrupt", S_IRUGO, debugfs,
+				(u32 *)&pkg_interrupt_cnt);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("pkg_thres_work", S_IRUGO, debugfs,
+				(u32 *)&pkg_work_cnt);
+	if (!d)
+		goto err_out;
+
+	return 0;
+
+err_out:
+	debugfs_remove_recursive(debugfs);
+	return -ENOENT;
+}
+
+static struct phy_dev_entry
+			*pkg_temp_thermal_get_phy_entry(unsigned int cpu)
+{
+	u16 phys_proc_id = topology_physical_package_id(cpu);
+	struct phy_dev_entry *phy_ptr;
+
+	mutex_lock(&phy_dev_list_mutex);
+
+	list_for_each_entry(phy_ptr, &phy_dev_list, list)
+		if (phy_ptr->phys_proc_id == phys_proc_id) {
+			mutex_unlock(&phy_dev_list_mutex);
+			return phy_ptr;
+		}
+
+	mutex_unlock(&phy_dev_list_mutex);
+
+	return NULL;
+}
+
+/*
+* tj-max is is interesting because threshold is set relative to this
+* temperature.
+*/
+static int get_tj_max(int cpu, u32 *tj_max)
+{
+	u32 eax, edx;
+	u32 val;
+	int err;
+
+	err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
+	if (err)
+		goto err_ret;
+	else {
+		val = (eax >> 16) & 0xff;
+		if (val)
+			*tj_max = val * 1000;
+		else {
+			err = -EINVAL;
+			goto err_ret;
+		}
+	}
+
+	return 0;
+err_ret:
+	*tj_max = 0;
+	return err;
+}
+
+static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
+{
+	u32 eax, edx;
+	struct phy_dev_entry *phy_dev_entry;
+
+	phy_dev_entry = tzd->devdata;
+	rdmsr_on_cpu(phy_dev_entry->first_cpu, MSR_IA32_PACKAGE_THERM_STATUS,
+			&eax, &edx);
+	if (eax & 0x80000000) {
+		*temp = phy_dev_entry->tj_max -
+				((eax >> 16) & 0x7f) * 1000;
+		pr_debug("sys_get_curr_temp %ld\n", *temp);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int sys_get_trip_temp(struct thermal_zone_device *tzd,
+		int trip, unsigned long *temp)
+{
+	u32 eax, edx;
+	struct phy_dev_entry *phy_dev_entry;
+	u32 mask, shift;
+	unsigned long thres_reg_value;
+	int ret;
+
+	if (trip >= MAX_NUMBER_OF_TRIPS)
+		return -EINVAL;
+
+	phy_dev_entry = tzd->devdata;
+
+	if (trip) {
+		mask = THERM_MASK_THRESHOLD1;
+		shift = THERM_SHIFT_THRESHOLD1;
+	} else {
+		mask = THERM_MASK_THRESHOLD0;
+		shift = THERM_SHIFT_THRESHOLD0;
+	}
+
+	ret = rdmsr_on_cpu(phy_dev_entry->first_cpu,
+				MSR_IA32_PACKAGE_THERM_INTERRUPT, &eax, &edx);
+	if (ret < 0)
+		return -EINVAL;
+
+	thres_reg_value = (eax & mask) >> shift;
+	if (thres_reg_value)
+		*temp = phy_dev_entry->tj_max - thres_reg_value * 1000;
+	else
+		*temp = 0;
+	pr_debug("sys_get_trip_temp %ld\n", *temp);
+
+	return 0;
+}
+
+int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
+							unsigned long temp)
+{
+	u32 l, h;
+	struct phy_dev_entry *phy_dev_entry;
+	u32 mask, shift, intr;
+	int ret;
+
+	phy_dev_entry = tzd->devdata;
+
+	if (trip >= MAX_NUMBER_OF_TRIPS || temp >= phy_dev_entry->tj_max)
+		return -EINVAL;
+
+	ret = rdmsr_on_cpu(phy_dev_entry->first_cpu,
+					MSR_IA32_PACKAGE_THERM_INTERRUPT,
+					&l, &h);
+	if (ret < 0)
+		return -EINVAL;
+
+	if (trip) {
+		mask = THERM_MASK_THRESHOLD1;
+		shift = THERM_SHIFT_THRESHOLD1;
+		intr = THERM_INT_THRESHOLD1_ENABLE;
+	} else {
+		mask = THERM_MASK_THRESHOLD0;
+		shift = THERM_SHIFT_THRESHOLD0;
+		intr = THERM_INT_THRESHOLD0_ENABLE;
+	}
+	l &= ~mask;
+	/*
+	* When users space sets a trip temperature == 0, which is indication
+	* that, it is no longer interested in receiving notifications.
+	*/
+	if (!temp)
+		l &= ~intr;
+	else {
+		l |= (phy_dev_entry->tj_max - temp)/1000 << shift;
+		l |= intr;
+	}
+
+	return wrmsr_on_cpu(phy_dev_entry->first_cpu,
+					MSR_IA32_PACKAGE_THERM_INTERRUPT,
+					l, h);
+}
+
+static int sys_get_trip_type(struct thermal_zone_device *thermal,
+		int trip, enum thermal_trip_type *type)
+{
+
+	*type = THERMAL_TRIP_PASSIVE;
+
+	return 0;
+}
+
+/* Thermal zone callback registry */
+static struct thermal_zone_device_ops tzone_ops = {
+	.get_temp = sys_get_curr_temp,
+	.get_trip_temp = sys_get_trip_temp,
+	.get_trip_type = sys_get_trip_type,
+	.set_trip_temp = sys_set_trip_temp,
+};
+
+static bool pkg_temp_thermal_platform_thermal_rate_control(void)
+{
+	return true;
+}
+
+/* Enable threshold interrupt on local package/cpu */
+static inline void enable_pkg_thres_interrupt(void)
+{
+	u32 l, h;
+	u8 thres_0, thres_1;
+
+	rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+	/* only enable/disable if it had valid threshold value */
+	thres_0 = (l & THERM_MASK_THRESHOLD0) >> THERM_SHIFT_THRESHOLD0;
+	thres_1 = (l & THERM_MASK_THRESHOLD1) >> THERM_SHIFT_THRESHOLD1;
+	if (thres_0)
+		l |= THERM_INT_THRESHOLD0_ENABLE;
+	if (thres_1)
+		l |= THERM_INT_THRESHOLD1_ENABLE;
+	wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+}
+
+/* Disable threshold interrupt on local package/cpu */
+static inline void disable_pkg_thres_interrupt(void)
+{
+	u32 l, h;
+	rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+	wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT,
+			l & (~THERM_INT_THRESHOLD0_ENABLE) &
+				(~THERM_INT_THRESHOLD1_ENABLE), h);
+}
+
+static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
+{
+	__u64 msr_val;
+	int cpu = smp_processor_id();
+	int phy_id = topology_physical_package_id(cpu);
+	struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu);
+	bool notify = false;
+
+	if (!phdev)
+		return;
+
+	spin_lock(&pkg_work_lock);
+	++pkg_work_cnt;
+	if (unlikely(phy_id > max_phy_id)) {
+		spin_unlock(&pkg_work_lock);
+		return;
+	}
+	pkg_work_scheduled[phy_id] = 0;
+	spin_unlock(&pkg_work_lock);
+
+	enable_pkg_thres_interrupt();
+	rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
+	if (msr_val & THERM_LOG_THRESHOLD0) {
+		wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS,
+				msr_val & ~THERM_LOG_THRESHOLD0);
+		notify = true;
+	}
+	if (msr_val & THERM_LOG_THRESHOLD1) {
+		wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS,
+				msr_val & ~THERM_LOG_THRESHOLD1);
+		notify = true;
+	}
+	if (notify) {
+		pr_debug("thermal_zone_device_update\n");
+		thermal_zone_device_update(phdev->tzone);
+	}
+}
+
+static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val)
+{
+	unsigned long flags;
+	int cpu = smp_processor_id();
+	int phy_id = topology_physical_package_id(cpu);
+
+	/*
+	* When a package is in interrupted state, all CPU's in that package
+	* are in the same interrupt state. So scheduling on any one CPU in
+	* the package is enough and simply return for others.
+	*/
+	spin_lock_irqsave(&pkg_work_lock, flags);
+	++pkg_interrupt_cnt;
+	if (unlikely(phy_id > max_phy_id) || unlikely(!pkg_work_scheduled) ||
+			pkg_work_scheduled[phy_id]) {
+		disable_pkg_thres_interrupt();
+		spin_unlock_irqrestore(&pkg_work_lock, flags);
+		return -EINVAL;
+	}
+	pkg_work_scheduled[phy_id] = 1;
+	spin_unlock_irqrestore(&pkg_work_lock, flags);
+
+	disable_pkg_thres_interrupt();
+	schedule_delayed_work_on(cpu,
+				&per_cpu(pkg_temp_thermal_threshold_work, cpu),
+				msecs_to_jiffies(notify_delay_ms));
+	return 0;
+}
+
+static int find_siblings_cpu(int cpu)
+{
+	int i;
+	int id = topology_physical_package_id(cpu);
+
+	for_each_online_cpu(i)
+		if (i != cpu && topology_physical_package_id(i) == id)
+			return i;
+
+	return 0;
+}
+
+static int pkg_temp_thermal_device_add(unsigned int cpu)
+{
+	int err;
+	u32 tj_max;
+	struct phy_dev_entry *phy_dev_entry;
+	char buffer[30];
+	int thres_count;
+	u32 eax, ebx, ecx, edx;
+
+	cpuid(6, &eax, &ebx, &ecx, &edx);
+	thres_count = ebx & 0x07;
+	if (!thres_count)
+		return -ENODEV;
+
+	thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS);
+
+	err = get_tj_max(cpu, &tj_max);
+	if (err)
+		goto err_ret;
+
+	mutex_lock(&phy_dev_list_mutex);
+
+	phy_dev_entry = kzalloc(sizeof(*phy_dev_entry), GFP_KERNEL);
+	if (!phy_dev_entry) {
+		err = -ENOMEM;
+		goto err_ret_unlock;
+	}
+
+	spin_lock(&pkg_work_lock);
+	if (topology_physical_package_id(cpu) > max_phy_id)
+		max_phy_id = topology_physical_package_id(cpu);
+	pkg_work_scheduled = krealloc(pkg_work_scheduled,
+				(max_phy_id+1) * sizeof(u8), GFP_ATOMIC);
+	if (!pkg_work_scheduled) {
+		spin_unlock(&pkg_work_lock);
+		err = -ENOMEM;
+		goto err_ret_free;
+	}
+	pkg_work_scheduled[topology_physical_package_id(cpu)] = 0;
+	spin_unlock(&pkg_work_lock);
+
+	phy_dev_entry->phys_proc_id = topology_physical_package_id(cpu);
+	phy_dev_entry->first_cpu = cpu;
+	phy_dev_entry->tj_max = tj_max;
+	phy_dev_entry->ref_cnt = 1;
+	snprintf(buffer, sizeof(buffer), "pkg-temp-%d\n",
+					phy_dev_entry->phys_proc_id);
+	phy_dev_entry->tzone = thermal_zone_device_register(buffer,
+			thres_count,
+			(thres_count == MAX_NUMBER_OF_TRIPS) ?
+				0x03 : 0x01,
+			phy_dev_entry, &tzone_ops, NULL, 0, 0);
+	if (IS_ERR(phy_dev_entry->tzone)) {
+		err = PTR_ERR(phy_dev_entry->tzone);
+		goto err_ret_free;
+	}
+	/* Store MSR value for package thermal interrupt, to restore at exit */
+	rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
+				&phy_dev_entry->start_pkg_therm_low,
+				&phy_dev_entry->start_pkg_therm_high);
+
+	list_add_tail(&phy_dev_entry->list, &phy_dev_list);
+	pr_debug("pkg_temp_thermal_device_add :phy_id %d cpu %d\n",
+			phy_dev_entry->phys_proc_id, cpu);
+
+	mutex_unlock(&phy_dev_list_mutex);
+
+	return 0;
+
+err_ret_free:
+	kfree(phy_dev_entry);
+err_ret_unlock:
+	mutex_unlock(&phy_dev_list_mutex);
+
+err_ret:
+	return err;
+}
+
+static int pkg_temp_thermal_device_remove(unsigned int cpu)
+{
+	struct phy_dev_entry *n;
+	u16 phys_proc_id = topology_physical_package_id(cpu);
+	struct phy_dev_entry *phdev =
+			pkg_temp_thermal_get_phy_entry(cpu);
+
+	if (!phdev)
+		return -ENODEV;
+
+	mutex_lock(&phy_dev_list_mutex);
+	/* If we are loosing the first cpu for this package, we need change */
+	if (phdev->first_cpu == cpu) {
+		phdev->first_cpu = find_siblings_cpu(cpu);
+		pr_debug("thermal_device_remove: first cpu switched %d\n",
+					phdev->first_cpu);
+	}
+	/*
+	* It is possible that no siblings left as this was the last cpu
+	* going offline. We don't need to worry about this assignment
+	* as the phydev entry will be removed in this case and
+	* thermal zone is removed.
+	*/
+	--phdev->ref_cnt;
+	pr_debug("thermal_device_remove: pkg: %d cpu %d ref_cnt %d\n",
+					phys_proc_id, cpu, phdev->ref_cnt);
+	if (!phdev->ref_cnt)
+		list_for_each_entry_safe(phdev, n, &phy_dev_list, list) {
+			if (phdev->phys_proc_id == phys_proc_id) {
+				thermal_zone_device_unregister(phdev->tzone);
+				list_del(&phdev->list);
+				kfree(phdev);
+				break;
+			}
+		}
+	mutex_unlock(&phy_dev_list_mutex);
+
+	return 0;
+}
+
+static int get_core_online(unsigned int cpu)
+{
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu);
+
+	/* Check if there is already an instance for this package */
+	if (!phdev) {
+		if (!cpu_has(c, X86_FEATURE_DTHERM) &&
+					!cpu_has(c, X86_FEATURE_PTS))
+			return -ENODEV;
+		if (pkg_temp_thermal_device_add(cpu))
+			return -ENODEV;
+	} else {
+		mutex_lock(&phy_dev_list_mutex);
+		++phdev->ref_cnt;
+		pr_debug("get_core_online: cpu %d ref_cnt %d\n",
+						cpu, phdev->ref_cnt);
+		mutex_unlock(&phy_dev_list_mutex);
+	}
+	INIT_DELAYED_WORK(&per_cpu(pkg_temp_thermal_threshold_work, cpu),
+			pkg_temp_thermal_threshold_work_fn);
+
+	pr_debug("get_core_online: cpu %d successful\n", cpu);
+
+	return 0;
+}
+
+static void put_core_offline(unsigned int cpu)
+{
+	if (!pkg_temp_thermal_device_remove(cpu))
+		cancel_delayed_work_sync(
+			&per_cpu(pkg_temp_thermal_threshold_work, cpu));
+
+	pr_debug("put_core_offline: cpu %d\n", cpu);
+}
+
+static int pkg_temp_thermal_cpu_callback(struct notifier_block *nfb,
+				 unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long) hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_DOWN_FAILED:
+		get_core_online(cpu);
+		break;
+	case CPU_DOWN_PREPARE:
+		put_core_offline(cpu);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block pkg_temp_thermal_notifier __refdata = {
+	.notifier_call = pkg_temp_thermal_cpu_callback,
+};
+
+static const struct x86_cpu_id __initconst pkg_temp_thermal_ids[] = {
+	{ X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM },
+	{}
+};
+MODULE_DEVICE_TABLE(x86cpu, pkg_temp_thermal_ids);
+
+static int __init pkg_temp_thermal_init(void)
+{
+	int i;
+
+	if (!x86_match_cpu(pkg_temp_thermal_ids))
+		return -ENODEV;
+
+	spin_lock_init(&pkg_work_lock);
+	platform_thermal_package_notify =
+			pkg_temp_thermal_platform_thermal_notify;
+	platform_thermal_package_rate_control =
+			pkg_temp_thermal_platform_thermal_rate_control;
+
+	get_online_cpus();
+	for_each_online_cpu(i)
+		if (get_core_online(i))
+			goto err_ret;
+	register_hotcpu_notifier(&pkg_temp_thermal_notifier);
+	put_online_cpus();
+
+	pkg_temp_debugfs_init(); /* Don't care if fails */
+
+	return 0;
+
+err_ret:
+	get_online_cpus();
+	for_each_online_cpu(i)
+		put_core_offline(i);
+	put_online_cpus();
+	kfree(pkg_work_scheduled);
+	platform_thermal_package_notify = NULL;
+	platform_thermal_package_rate_control = NULL;
+
+	return -ENODEV;
+}
+
+static void __exit pkg_temp_thermal_exit(void)
+{
+	struct phy_dev_entry *phdev, *n;
+	int i;
+
+	get_online_cpus();
+	unregister_hotcpu_notifier(&pkg_temp_thermal_notifier);
+	mutex_lock(&phy_dev_list_mutex);
+	list_for_each_entry_safe(phdev, n, &phy_dev_list, list) {
+		/* Retore old MSR value for package thermal interrupt */
+		wrmsr_on_cpu(phdev->first_cpu,
+			MSR_IA32_PACKAGE_THERM_INTERRUPT,
+			phdev->start_pkg_therm_low,
+			phdev->start_pkg_therm_high);
+		thermal_zone_device_unregister(phdev->tzone);
+		list_del(&phdev->list);
+		kfree(phdev);
+	}
+	mutex_unlock(&phy_dev_list_mutex);
+	platform_thermal_package_notify = NULL;
+	platform_thermal_package_rate_control = NULL;
+	for_each_online_cpu(i)
+		cancel_delayed_work_sync(
+			&per_cpu(pkg_temp_thermal_threshold_work, i));
+	put_online_cpus();
+
+	kfree(pkg_work_scheduled);
+
+	debugfs_remove_recursive(debugfs);
+}
+
+module_init(pkg_temp_thermal_init)
+module_exit(pkg_temp_thermal_exit)
+
+MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver");
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h
index 282e270..a5d52ee 100644
--- a/include/linux/cpu_cooling.h
+++ b/include/linux/cpu_cooling.h
@@ -41,7 +41,7 @@
  */
 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev);
 
-unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int);
+unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq);
 #else /* !CONFIG_CPU_THERMAL */
 static inline struct thermal_cooling_device *
 cpufreq_cooling_register(const struct cpumask *clip_cpus)
@@ -54,7 +54,7 @@
 	return;
 }
 static inline
-unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int)
+unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
 {
 	return THERMAL_CSTATE_INVALID;
 }