brintos

brintos / linux-shallow public Read only

0
0
Text · 23.6 KiB · b8e85a4 Raw
872 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Copyright 2013 Freescale Semiconductor, Inc.4 5#include <linux/clk.h>6#include <linux/cpufreq.h>7#include <linux/cpu_cooling.h>8#include <linux/delay.h>9#include <linux/interrupt.h>10#include <linux/io.h>11#include <linux/mfd/syscon.h>12#include <linux/module.h>13#include <linux/of.h>14#include <linux/platform_device.h>15#include <linux/regmap.h>16#include <linux/thermal.h>17#include <linux/nvmem-consumer.h>18#include <linux/pm_runtime.h>19 20#define REG_SET		0x421#define REG_CLR		0x822#define REG_TOG		0xc23 24/* i.MX6 specific */25#define IMX6_MISC0				0x015026#define IMX6_MISC0_REFTOP_SELBIASOFF		(1 << 3)27#define IMX6_MISC1				0x016028#define IMX6_MISC1_IRQ_TEMPHIGH			(1 << 29)29/* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */30#define IMX6_MISC1_IRQ_TEMPLOW			(1 << 28)31#define IMX6_MISC1_IRQ_TEMPPANIC		(1 << 27)32 33#define IMX6_TEMPSENSE0				0x018034#define IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT	2035#define IMX6_TEMPSENSE0_ALARM_VALUE_MASK	(0xfff << 20)36#define IMX6_TEMPSENSE0_TEMP_CNT_SHIFT		837#define IMX6_TEMPSENSE0_TEMP_CNT_MASK		(0xfff << 8)38#define IMX6_TEMPSENSE0_FINISHED		(1 << 2)39#define IMX6_TEMPSENSE0_MEASURE_TEMP		(1 << 1)40#define IMX6_TEMPSENSE0_POWER_DOWN		(1 << 0)41 42#define IMX6_TEMPSENSE1				0x019043#define IMX6_TEMPSENSE1_MEASURE_FREQ		0xffff44#define IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT	045 46#define OCOTP_MEM0			0x048047#define OCOTP_ANA1			0x04e048 49/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */50#define IMX6_TEMPSENSE2				0x029051#define IMX6_TEMPSENSE2_LOW_VALUE_SHIFT		052#define IMX6_TEMPSENSE2_LOW_VALUE_MASK		0xfff53#define IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT	1654#define IMX6_TEMPSENSE2_PANIC_VALUE_MASK	0xfff000055 56/* i.MX7 specific */57#define IMX7_ANADIG_DIGPROG			0x80058#define IMX7_TEMPSENSE0				0x30059#define IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT	1860#define IMX7_TEMPSENSE0_PANIC_ALARM_MASK	(0x1ff << 18)61#define IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT	962#define IMX7_TEMPSENSE0_HIGH_ALARM_MASK		(0x1ff << 9)63#define IMX7_TEMPSENSE0_LOW_ALARM_SHIFT		064#define IMX7_TEMPSENSE0_LOW_ALARM_MASK		0x1ff65 66#define IMX7_TEMPSENSE1				0x31067#define IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT	1668#define IMX7_TEMPSENSE1_MEASURE_FREQ_MASK	(0xffff << 16)69#define IMX7_TEMPSENSE1_FINISHED		(1 << 11)70#define IMX7_TEMPSENSE1_MEASURE_TEMP		(1 << 10)71#define IMX7_TEMPSENSE1_POWER_DOWN		(1 << 9)72#define IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT	073#define IMX7_TEMPSENSE1_TEMP_VALUE_MASK		0x1ff74 75/* The driver supports 1 passive trip point and 1 critical trip point */76enum imx_thermal_trip {77	IMX_TRIP_PASSIVE,78	IMX_TRIP_CRITICAL,79};80 81#define IMX_POLLING_DELAY		2000 /* millisecond */82#define IMX_PASSIVE_DELAY		100083 84#define TEMPMON_IMX6Q			185#define TEMPMON_IMX6SX			286#define TEMPMON_IMX7D			387 88struct thermal_soc_data {89	u32 version;90 91	u32 sensor_ctrl;92	u32 power_down_mask;93	u32 measure_temp_mask;94 95	u32 measure_freq_ctrl;96	u32 measure_freq_mask;97	u32 measure_freq_shift;98 99	u32 temp_data;100	u32 temp_value_mask;101	u32 temp_value_shift;102	u32 temp_valid_mask;103 104	u32 panic_alarm_ctrl;105	u32 panic_alarm_mask;106	u32 panic_alarm_shift;107 108	u32 high_alarm_ctrl;109	u32 high_alarm_mask;110	u32 high_alarm_shift;111 112	u32 low_alarm_ctrl;113	u32 low_alarm_mask;114	u32 low_alarm_shift;115};116 117static struct thermal_trip trips[] = {118	[IMX_TRIP_PASSIVE]  = { .type = THERMAL_TRIP_PASSIVE,119				.flags = THERMAL_TRIP_FLAG_RW_TEMP },120	[IMX_TRIP_CRITICAL] = { .type = THERMAL_TRIP_CRITICAL },121};122 123static struct thermal_soc_data thermal_imx6q_data = {124	.version = TEMPMON_IMX6Q,125 126	.sensor_ctrl = IMX6_TEMPSENSE0,127	.power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,128	.measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,129 130	.measure_freq_ctrl = IMX6_TEMPSENSE1,131	.measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,132	.measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,133 134	.temp_data = IMX6_TEMPSENSE0,135	.temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,136	.temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,137	.temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,138 139	.high_alarm_ctrl = IMX6_TEMPSENSE0,140	.high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,141	.high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,142};143 144static struct thermal_soc_data thermal_imx6sx_data = {145	.version = TEMPMON_IMX6SX,146 147	.sensor_ctrl = IMX6_TEMPSENSE0,148	.power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,149	.measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,150 151	.measure_freq_ctrl = IMX6_TEMPSENSE1,152	.measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,153	.measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,154 155	.temp_data = IMX6_TEMPSENSE0,156	.temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,157	.temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,158	.temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,159 160	.high_alarm_ctrl = IMX6_TEMPSENSE0,161	.high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,162	.high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,163 164	.panic_alarm_ctrl = IMX6_TEMPSENSE2,165	.panic_alarm_mask = IMX6_TEMPSENSE2_PANIC_VALUE_MASK,166	.panic_alarm_shift = IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT,167 168	.low_alarm_ctrl = IMX6_TEMPSENSE2,169	.low_alarm_mask = IMX6_TEMPSENSE2_LOW_VALUE_MASK,170	.low_alarm_shift = IMX6_TEMPSENSE2_LOW_VALUE_SHIFT,171};172 173static struct thermal_soc_data thermal_imx7d_data = {174	.version = TEMPMON_IMX7D,175 176	.sensor_ctrl = IMX7_TEMPSENSE1,177	.power_down_mask = IMX7_TEMPSENSE1_POWER_DOWN,178	.measure_temp_mask = IMX7_TEMPSENSE1_MEASURE_TEMP,179 180	.measure_freq_ctrl = IMX7_TEMPSENSE1,181	.measure_freq_shift = IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT,182	.measure_freq_mask = IMX7_TEMPSENSE1_MEASURE_FREQ_MASK,183 184	.temp_data = IMX7_TEMPSENSE1,185	.temp_value_mask = IMX7_TEMPSENSE1_TEMP_VALUE_MASK,186	.temp_value_shift = IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT,187	.temp_valid_mask = IMX7_TEMPSENSE1_FINISHED,188 189	.panic_alarm_ctrl = IMX7_TEMPSENSE1,190	.panic_alarm_mask = IMX7_TEMPSENSE0_PANIC_ALARM_MASK,191	.panic_alarm_shift = IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT,192 193	.high_alarm_ctrl = IMX7_TEMPSENSE0,194	.high_alarm_mask = IMX7_TEMPSENSE0_HIGH_ALARM_MASK,195	.high_alarm_shift = IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT,196 197	.low_alarm_ctrl = IMX7_TEMPSENSE0,198	.low_alarm_mask = IMX7_TEMPSENSE0_LOW_ALARM_MASK,199	.low_alarm_shift = IMX7_TEMPSENSE0_LOW_ALARM_SHIFT,200};201 202struct imx_thermal_data {203	struct device *dev;204	struct cpufreq_policy *policy;205	struct thermal_zone_device *tz;206	struct thermal_cooling_device *cdev;207	struct regmap *tempmon;208	u32 c1, c2; /* See formula in imx_init_calib() */209	int temp_max;210	int alarm_temp;211	int last_temp;212	bool irq_enabled;213	int irq;214	struct clk *thermal_clk;215	const struct thermal_soc_data *socdata;216	const char *temp_grade;217};218 219static void imx_set_panic_temp(struct imx_thermal_data *data,220			       int panic_temp)221{222	const struct thermal_soc_data *soc_data = data->socdata;223	struct regmap *map = data->tempmon;224	int critical_value;225 226	critical_value = (data->c2 - panic_temp) / data->c1;227 228	regmap_write(map, soc_data->panic_alarm_ctrl + REG_CLR,229		     soc_data->panic_alarm_mask);230	regmap_write(map, soc_data->panic_alarm_ctrl + REG_SET,231		     critical_value << soc_data->panic_alarm_shift);232}233 234static void imx_set_alarm_temp(struct imx_thermal_data *data,235			       int alarm_temp)236{237	struct regmap *map = data->tempmon;238	const struct thermal_soc_data *soc_data = data->socdata;239	int alarm_value;240 241	data->alarm_temp = alarm_temp;242 243	if (data->socdata->version == TEMPMON_IMX7D)244		alarm_value = alarm_temp / 1000 + data->c1 - 25;245	else246		alarm_value = (data->c2 - alarm_temp) / data->c1;247 248	regmap_write(map, soc_data->high_alarm_ctrl + REG_CLR,249		     soc_data->high_alarm_mask);250	regmap_write(map, soc_data->high_alarm_ctrl + REG_SET,251		     alarm_value << soc_data->high_alarm_shift);252}253 254static int imx_get_temp(struct thermal_zone_device *tz, int *temp)255{256	struct imx_thermal_data *data = thermal_zone_device_priv(tz);257	const struct thermal_soc_data *soc_data = data->socdata;258	struct regmap *map = data->tempmon;259	unsigned int n_meas;260	u32 val;261	int ret;262 263	ret = pm_runtime_resume_and_get(data->dev);264	if (ret < 0)265		return ret;266 267	regmap_read(map, soc_data->temp_data, &val);268 269	if ((val & soc_data->temp_valid_mask) == 0)270		return -EAGAIN;271 272	n_meas = (val & soc_data->temp_value_mask)273		>> soc_data->temp_value_shift;274 275	/* See imx_init_calib() for formula derivation */276	if (data->socdata->version == TEMPMON_IMX7D)277		*temp = (n_meas - data->c1 + 25) * 1000;278	else279		*temp = data->c2 - n_meas * data->c1;280 281	/* Update alarm value to next higher trip point for TEMPMON_IMX6Q */282	if (data->socdata->version == TEMPMON_IMX6Q) {283		if (data->alarm_temp == trips[IMX_TRIP_PASSIVE].temperature &&284			*temp >= trips[IMX_TRIP_PASSIVE].temperature)285			imx_set_alarm_temp(data, trips[IMX_TRIP_CRITICAL].temperature);286		if (data->alarm_temp == trips[IMX_TRIP_CRITICAL].temperature &&287			*temp < trips[IMX_TRIP_PASSIVE].temperature) {288			imx_set_alarm_temp(data, trips[IMX_TRIP_PASSIVE].temperature);289			dev_dbg(data->dev, "thermal alarm off: T < %d\n",290				data->alarm_temp / 1000);291		}292	}293 294	if (*temp != data->last_temp) {295		dev_dbg(data->dev, "millicelsius: %d\n", *temp);296		data->last_temp = *temp;297	}298 299	/* Reenable alarm IRQ if temperature below alarm temperature */300	if (!data->irq_enabled && *temp < data->alarm_temp) {301		data->irq_enabled = true;302		enable_irq(data->irq);303	}304 305	pm_runtime_put(data->dev);306 307	return 0;308}309 310static int imx_change_mode(struct thermal_zone_device *tz,311			   enum thermal_device_mode mode)312{313	struct imx_thermal_data *data = thermal_zone_device_priv(tz);314 315	if (mode == THERMAL_DEVICE_ENABLED) {316		pm_runtime_get(data->dev);317 318		if (!data->irq_enabled) {319			data->irq_enabled = true;320			enable_irq(data->irq);321		}322	} else {323		pm_runtime_put(data->dev);324 325		if (data->irq_enabled) {326			disable_irq(data->irq);327			data->irq_enabled = false;328		}329	}330 331	return 0;332}333 334static int imx_set_trip_temp(struct thermal_zone_device *tz,335			     const struct thermal_trip *trip, int temp)336{337	struct imx_thermal_data *data = thermal_zone_device_priv(tz);338	int ret;339 340	ret = pm_runtime_resume_and_get(data->dev);341	if (ret < 0)342		return ret;343 344	/* do not allow passive to be set higher than critical */345	if (temp < 0 || temp > trips[IMX_TRIP_CRITICAL].temperature)346		return -EINVAL;347 348	imx_set_alarm_temp(data, temp);349	trips[IMX_TRIP_PASSIVE].temperature = temp;350 351	pm_runtime_put(data->dev);352 353	return 0;354}355 356static bool imx_should_bind(struct thermal_zone_device *tz,357			    const struct thermal_trip *trip,358			    struct thermal_cooling_device *cdev,359			    struct cooling_spec *c)360{361	return trip->type == THERMAL_TRIP_PASSIVE;362}363 364static struct thermal_zone_device_ops imx_tz_ops = {365	.should_bind = imx_should_bind,366	.get_temp = imx_get_temp,367	.change_mode = imx_change_mode,368	.set_trip_temp = imx_set_trip_temp,369};370 371static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1)372{373	struct imx_thermal_data *data = platform_get_drvdata(pdev);374	int n1;375	u64 temp64;376 377	if (ocotp_ana1 == 0 || ocotp_ana1 == ~0) {378		dev_err(&pdev->dev, "invalid sensor calibration data\n");379		return -EINVAL;380	}381 382	/*383	 * On i.MX7D, we only use the calibration data at 25C to get the temp,384	 * Tmeas = ( Nmeas - n1) + 25; n1 is the fuse value for 25C.385	 */386	if (data->socdata->version == TEMPMON_IMX7D) {387		data->c1 = (ocotp_ana1 >> 9) & 0x1ff;388		return 0;389	}390 391	/*392	 * The sensor is calibrated at 25 °C (aka T1) and the value measured393	 * (aka N1) at this temperature is provided in bits [31:20] in the394	 * i.MX's OCOTP value ANA1.395	 * To find the actual temperature T, the following formula has to be used396	 * when reading value n from the sensor:397	 *398	 * T = T1 + (N - N1) / (0.4148468 - 0.0015423 * N1) °C + 3.580661 °C399	 *   = [T1' - N1 / (0.4148468 - 0.0015423 * N1) °C] + N / (0.4148468 - 0.0015423 * N1) °C400	 *   = [T1' + N1 / (0.0015423 * N1 - 0.4148468) °C] - N / (0.0015423 * N1 - 0.4148468) °C401	 *   = c2 - c1 * N402	 *403	 * with404	 *405	 *  T1' = 28.580661 °C406	 *   c1 = 1 / (0.0015423 * N1 - 0.4297157) °C407	 *   c2 = T1' + N1 / (0.0015423 * N1 - 0.4148468) °C408	 *      = T1' + N1 * c1409	 */410	n1 = ocotp_ana1 >> 20;411 412	temp64 = 10000000; /* use 10^7 as fixed point constant for values in formula */413	temp64 *= 1000; /* to get result in °mC */414	do_div(temp64, 15423 * n1 - 4148468);415	data->c1 = temp64;416	data->c2 = n1 * data->c1 + 28581;417 418	return 0;419}420 421static void imx_init_temp_grade(struct platform_device *pdev, u32 ocotp_mem0)422{423	struct imx_thermal_data *data = platform_get_drvdata(pdev);424 425	/* The maximum die temp is specified by the Temperature Grade */426	switch ((ocotp_mem0 >> 6) & 0x3) {427	case 0: /* Commercial (0 to 95 °C) */428		data->temp_grade = "Commercial";429		data->temp_max = 95000;430		break;431	case 1: /* Extended Commercial (-20 °C to 105 °C) */432		data->temp_grade = "Extended Commercial";433		data->temp_max = 105000;434		break;435	case 2: /* Industrial (-40 °C to 105 °C) */436		data->temp_grade = "Industrial";437		data->temp_max = 105000;438		break;439	case 3: /* Automotive (-40 °C to 125 °C) */440		data->temp_grade = "Automotive";441		data->temp_max = 125000;442		break;443	}444 445	/*446	 * Set the critical trip point at 5 °C under max447	 * Set the passive trip point at 10 °C under max (changeable via sysfs)448	 */449	trips[IMX_TRIP_PASSIVE].temperature = data->temp_max - (1000 * 10);450	trips[IMX_TRIP_CRITICAL].temperature = data->temp_max - (1000 * 5);451}452 453static int imx_init_from_tempmon_data(struct platform_device *pdev)454{455	struct regmap *map;456	int ret;457	u32 val;458 459	map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,460					      "fsl,tempmon-data");461	if (IS_ERR(map)) {462		ret = PTR_ERR(map);463		dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);464		return ret;465	}466 467	ret = regmap_read(map, OCOTP_ANA1, &val);468	if (ret) {469		dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);470		return ret;471	}472	ret = imx_init_calib(pdev, val);473	if (ret)474		return ret;475 476	ret = regmap_read(map, OCOTP_MEM0, &val);477	if (ret) {478		dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);479		return ret;480	}481	imx_init_temp_grade(pdev, val);482 483	return 0;484}485 486static int imx_init_from_nvmem_cells(struct platform_device *pdev)487{488	int ret;489	u32 val;490 491	ret = nvmem_cell_read_u32(&pdev->dev, "calib", &val);492	if (ret)493		return ret;494 495	ret = imx_init_calib(pdev, val);496	if (ret)497		return ret;498 499	ret = nvmem_cell_read_u32(&pdev->dev, "temp_grade", &val);500	if (ret)501		return ret;502	imx_init_temp_grade(pdev, val);503 504	return 0;505}506 507static irqreturn_t imx_thermal_alarm_irq(int irq, void *dev)508{509	struct imx_thermal_data *data = dev;510 511	disable_irq_nosync(irq);512	data->irq_enabled = false;513 514	return IRQ_WAKE_THREAD;515}516 517static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)518{519	struct imx_thermal_data *data = dev;520 521	dev_dbg(data->dev, "THERMAL ALARM: T > %d\n", data->alarm_temp / 1000);522 523	thermal_zone_device_update(data->tz, THERMAL_EVENT_UNSPECIFIED);524 525	return IRQ_HANDLED;526}527 528static const struct of_device_id of_imx_thermal_match[] = {529	{ .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, },530	{ .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, },531	{ .compatible = "fsl,imx7d-tempmon", .data = &thermal_imx7d_data, },532	{ /* end */ }533};534MODULE_DEVICE_TABLE(of, of_imx_thermal_match);535 536#ifdef CONFIG_CPU_FREQ537/*538 * Create cooling device in case no #cooling-cells property is available in539 * CPU node540 */541static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)542{543	struct device_node *np;544	int ret = 0;545 546	data->policy = cpufreq_cpu_get(0);547	if (!data->policy) {548		pr_debug("%s: CPUFreq policy not found\n", __func__);549		return -EPROBE_DEFER;550	}551 552	np = of_get_cpu_node(data->policy->cpu, NULL);553 554	if (!np || !of_property_present(np, "#cooling-cells")) {555		data->cdev = cpufreq_cooling_register(data->policy);556		if (IS_ERR(data->cdev)) {557			ret = PTR_ERR(data->cdev);558			cpufreq_cpu_put(data->policy);559		}560	}561 562	of_node_put(np);563 564	return ret;565}566 567static void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)568{569	cpufreq_cooling_unregister(data->cdev);570	cpufreq_cpu_put(data->policy);571}572 573#else574 575static inline int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)576{577	return 0;578}579 580static inline void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)581{582}583#endif584 585static int imx_thermal_probe(struct platform_device *pdev)586{587	struct device *dev = &pdev->dev;588	struct imx_thermal_data *data;589	struct regmap *map;590	int measure_freq;591	int ret;592 593	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);594	if (!data)595		return -ENOMEM;596 597	data->dev = dev;598 599	map = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,tempmon");600	if (IS_ERR(map)) {601		ret = PTR_ERR(map);602		dev_err(dev, "failed to get tempmon regmap: %d\n", ret);603		return ret;604	}605	data->tempmon = map;606 607	data->socdata = of_device_get_match_data(dev);608	if (!data->socdata) {609		dev_err(dev, "no device match found\n");610		return -ENODEV;611	}612 613	/* make sure the IRQ flag is clear before enabling irq on i.MX6SX */614	if (data->socdata->version == TEMPMON_IMX6SX) {615		regmap_write(map, IMX6_MISC1 + REG_CLR,616			IMX6_MISC1_IRQ_TEMPHIGH | IMX6_MISC1_IRQ_TEMPLOW617			| IMX6_MISC1_IRQ_TEMPPANIC);618		/*619		 * reset value of LOW ALARM is incorrect, set it to lowest620		 * value to avoid false trigger of low alarm.621		 */622		regmap_write(map, data->socdata->low_alarm_ctrl + REG_SET,623			     data->socdata->low_alarm_mask);624	}625 626	data->irq = platform_get_irq(pdev, 0);627	if (data->irq < 0)628		return data->irq;629 630	platform_set_drvdata(pdev, data);631 632	if (of_property_present(dev->of_node, "nvmem-cells")) {633		ret = imx_init_from_nvmem_cells(pdev);634		if (ret)635			return dev_err_probe(dev, ret,636					     "failed to init from nvmem\n");637	} else {638		ret = imx_init_from_tempmon_data(pdev);639		if (ret) {640			dev_err(dev, "failed to init from fsl,tempmon-data\n");641			return ret;642		}643	}644 645	/* Make sure sensor is in known good state for measurements */646	regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,647		     data->socdata->power_down_mask);648	regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,649		     data->socdata->measure_temp_mask);650	regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,651		     data->socdata->measure_freq_mask);652	if (data->socdata->version != TEMPMON_IMX7D)653		regmap_write(map, IMX6_MISC0 + REG_SET,654			IMX6_MISC0_REFTOP_SELBIASOFF);655	regmap_write(map, data->socdata->sensor_ctrl + REG_SET,656		     data->socdata->power_down_mask);657 658	ret = imx_thermal_register_legacy_cooling(data);659	if (ret)660		return dev_err_probe(dev, ret,661				     "failed to register cpufreq cooling device\n");662 663	data->thermal_clk = devm_clk_get(dev, NULL);664	if (IS_ERR(data->thermal_clk)) {665		ret = dev_err_probe(dev, PTR_ERR(data->thermal_clk), "failed to get thermal clk\n");666		goto legacy_cleanup;667	}668 669	/*670	 * Thermal sensor needs clk on to get correct value, normally671	 * we should enable its clk before taking measurement and disable672	 * clk after measurement is done, but if alarm function is enabled,673	 * hardware will auto measure the temperature periodically, so we674	 * need to keep the clk always on for alarm function.675	 */676	ret = clk_prepare_enable(data->thermal_clk);677	if (ret) {678		dev_err(dev, "failed to enable thermal clk: %d\n", ret);679		goto legacy_cleanup;680	}681 682	data->tz = thermal_zone_device_register_with_trips("imx_thermal_zone",683							   trips,684							   ARRAY_SIZE(trips),685							   data,686							   &imx_tz_ops, NULL,687							   IMX_PASSIVE_DELAY,688							   IMX_POLLING_DELAY);689	if (IS_ERR(data->tz)) {690		ret = PTR_ERR(data->tz);691		dev_err(dev, "failed to register thermal zone device %d\n",692			ret);693		goto clk_disable;694	}695 696	dev_info(dev, "%s CPU temperature grade - max:%dC"697		 " critical:%dC passive:%dC\n", data->temp_grade,698		 data->temp_max / 1000, trips[IMX_TRIP_CRITICAL].temperature / 1000,699		 trips[IMX_TRIP_PASSIVE].temperature / 1000);700 701	/* Enable measurements at ~ 10 Hz */702	regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,703		     data->socdata->measure_freq_mask);704	measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */705	regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET,706		     measure_freq << data->socdata->measure_freq_shift);707	imx_set_alarm_temp(data, trips[IMX_TRIP_PASSIVE].temperature);708 709	if (data->socdata->version == TEMPMON_IMX6SX)710		imx_set_panic_temp(data, trips[IMX_TRIP_CRITICAL].temperature);711 712	regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,713		     data->socdata->power_down_mask);714	regmap_write(map, data->socdata->sensor_ctrl + REG_SET,715		     data->socdata->measure_temp_mask);716	/* After power up, we need a delay before first access can be done. */717	usleep_range(20, 50);718 719	/* the core was configured and enabled just before */720	pm_runtime_set_active(dev);721	pm_runtime_enable(data->dev);722 723	ret = pm_runtime_resume_and_get(data->dev);724	if (ret < 0)725		goto disable_runtime_pm;726 727	data->irq_enabled = true;728	ret = thermal_zone_device_enable(data->tz);729	if (ret)730		goto thermal_zone_unregister;731 732	ret = devm_request_threaded_irq(dev, data->irq,733			imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,734			0, "imx_thermal", data);735	if (ret < 0) {736		dev_err(dev, "failed to request alarm irq: %d\n", ret);737		goto thermal_zone_unregister;738	}739 740	pm_runtime_put(data->dev);741 742	return 0;743 744thermal_zone_unregister:745	thermal_zone_device_unregister(data->tz);746disable_runtime_pm:747	pm_runtime_put_noidle(data->dev);748	pm_runtime_disable(data->dev);749clk_disable:750	clk_disable_unprepare(data->thermal_clk);751legacy_cleanup:752	imx_thermal_unregister_legacy_cooling(data);753 754	return ret;755}756 757static void imx_thermal_remove(struct platform_device *pdev)758{759	struct imx_thermal_data *data = platform_get_drvdata(pdev);760 761	pm_runtime_put_noidle(data->dev);762	pm_runtime_disable(data->dev);763 764	thermal_zone_device_unregister(data->tz);765	imx_thermal_unregister_legacy_cooling(data);766}767 768static int imx_thermal_suspend(struct device *dev)769{770	struct imx_thermal_data *data = dev_get_drvdata(dev);771	int ret;772 773	/*774	 * Need to disable thermal sensor, otherwise, when thermal core775	 * try to get temperature before thermal sensor resume, a wrong776	 * temperature will be read as the thermal sensor is powered777	 * down. This is done in change_mode() operation called from778	 * thermal_zone_device_disable()779	 */780	ret = thermal_zone_device_disable(data->tz);781	if (ret)782		return ret;783 784	return pm_runtime_force_suspend(data->dev);785}786 787static int imx_thermal_resume(struct device *dev)788{789	struct imx_thermal_data *data = dev_get_drvdata(dev);790	int ret;791 792	ret = pm_runtime_force_resume(data->dev);793	if (ret)794		return ret;795	/* Enabled thermal sensor after resume */796	return thermal_zone_device_enable(data->tz);797}798 799static int imx_thermal_runtime_suspend(struct device *dev)800{801	struct imx_thermal_data *data = dev_get_drvdata(dev);802	const struct thermal_soc_data *socdata = data->socdata;803	struct regmap *map = data->tempmon;804	int ret;805 806	ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,807			   socdata->measure_temp_mask);808	if (ret)809		return ret;810 811	ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,812			   socdata->power_down_mask);813	if (ret)814		return ret;815 816	clk_disable_unprepare(data->thermal_clk);817 818	return 0;819}820 821static int imx_thermal_runtime_resume(struct device *dev)822{823	struct imx_thermal_data *data = dev_get_drvdata(dev);824	const struct thermal_soc_data *socdata = data->socdata;825	struct regmap *map = data->tempmon;826	int ret;827 828	ret = clk_prepare_enable(data->thermal_clk);829	if (ret)830		return ret;831 832	ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,833			   socdata->power_down_mask);834	if (ret)835		return ret;836 837	ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,838			   socdata->measure_temp_mask);839	if (ret)840		return ret;841 842	/*843	 * According to the temp sensor designers, it may require up to ~17us844	 * to complete a measurement.845	 */846	usleep_range(20, 50);847 848	return 0;849}850 851static const struct dev_pm_ops imx_thermal_pm_ops = {852	SYSTEM_SLEEP_PM_OPS(imx_thermal_suspend, imx_thermal_resume)853	RUNTIME_PM_OPS(imx_thermal_runtime_suspend,854		       imx_thermal_runtime_resume, NULL)855};856 857static struct platform_driver imx_thermal = {858	.driver = {859		.name	= "imx_thermal",860		.pm	= pm_ptr(&imx_thermal_pm_ops),861		.of_match_table = of_imx_thermal_match,862	},863	.probe		= imx_thermal_probe,864	.remove_new	= imx_thermal_remove,865};866module_platform_driver(imx_thermal);867 868MODULE_AUTHOR("Freescale Semiconductor, Inc.");869MODULE_DESCRIPTION("Thermal driver for Freescale i.MX SoCs");870MODULE_LICENSE("GPL v2");871MODULE_ALIAS("platform:imx-thermal");872