2 * Copyright 2016 Freescale Semiconductor, Inc.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/err.h>
20 #include <linux/of_address.h>
21 #include <linux/thermal.h>
23 #include "thermal_core.h"
30 struct qoriq_tmu_site_regs
{
31 u32 tritsr
; /* Immediate Temperature Site Register */
32 u32 tratsr
; /* Average Temperature Site Register */
36 struct qoriq_tmu_regs
{
37 u32 tmr
; /* Mode Register */
38 #define TMR_DISABLE 0x0
39 #define TMR_ME 0x80000000
40 #define TMR_ALPF 0x0c000000
41 u32 tsr
; /* Status Register */
42 u32 tmtmir
; /* Temperature measurement interval Register */
43 #define TMTMIR_DEFAULT 0x0000000f
45 u32 tier
; /* Interrupt Enable Register */
46 #define TIER_DISABLE 0x0
47 u32 tidr
; /* Interrupt Detect Register */
48 u32 tiscr
; /* Interrupt Site Capture Register */
49 u32 ticscr
; /* Interrupt Critical Site Capture Register */
51 u32 tmhtcrh
; /* High Temperature Capture Register */
52 u32 tmhtcrl
; /* Low Temperature Capture Register */
54 u32 tmhtitr
; /* High Temperature Immediate Threshold */
55 u32 tmhtatr
; /* High Temperature Average Threshold */
56 u32 tmhtactr
; /* High Temperature Average Crit Threshold */
58 u32 ttcfgr
; /* Temperature Configuration Register */
59 u32 tscfgr
; /* Sensor Configuration Register */
61 struct qoriq_tmu_site_regs site
[SITES_MAX
];
63 u32 ipbrr0
; /* IP Block Revision Register 0 */
64 u32 ipbrr1
; /* IP Block Revision Register 1 */
66 u32 ttr0cr
; /* Temperature Range 0 Control Register */
67 u32 ttr1cr
; /* Temperature Range 1 Control Register */
68 u32 ttr2cr
; /* Temperature Range 2 Control Register */
69 u32 ttr3cr
; /* Temperature Range 3 Control Register */
75 struct qoriq_tmu_data
{
76 struct thermal_zone_device
*tz
;
77 struct qoriq_tmu_regs __iomem
*regs
;
82 static void tmu_write(struct qoriq_tmu_data
*p
, u32 val
, void __iomem
*addr
)
87 iowrite32be(val
, addr
);
90 static u32
tmu_read(struct qoriq_tmu_data
*p
, void __iomem
*addr
)
93 return ioread32(addr
);
95 return ioread32be(addr
);
98 static int tmu_get_temp(void *p
, int *temp
)
101 struct qoriq_tmu_data
*data
= p
;
103 val
= tmu_read(data
, &data
->regs
->site
[data
->sensor_id
].tritsr
);
104 *temp
= (val
& 0xff) * 1000;
109 static int qoriq_tmu_get_sensor_id(void)
112 struct of_phandle_args sensor_specs
;
113 struct device_node
*np
, *sensor_np
;
115 np
= of_find_node_by_name(NULL
, "thermal-zones");
119 sensor_np
= of_get_next_child(np
, NULL
);
120 ret
= of_parse_phandle_with_args(sensor_np
, "thermal-sensors",
121 "#thermal-sensor-cells",
125 of_node_put(sensor_np
);
129 if (sensor_specs
.args_count
>= 1) {
130 id
= sensor_specs
.args
[0];
131 WARN(sensor_specs
.args_count
> 1,
132 "%s: too many cells in sensor specifier %d\n",
133 sensor_specs
.np
->name
, sensor_specs
.args_count
);
139 of_node_put(sensor_np
);
144 static int qoriq_tmu_calibration(struct platform_device
*pdev
)
148 const u32
*calibration
;
149 struct device_node
*np
= pdev
->dev
.of_node
;
150 struct qoriq_tmu_data
*data
= platform_get_drvdata(pdev
);
152 if (of_property_read_u32_array(np
, "fsl,tmu-range", range
, 4)) {
153 dev_err(&pdev
->dev
, "missing calibration range.\n");
157 /* Init temperature range registers */
158 tmu_write(data
, range
[0], &data
->regs
->ttr0cr
);
159 tmu_write(data
, range
[1], &data
->regs
->ttr1cr
);
160 tmu_write(data
, range
[2], &data
->regs
->ttr2cr
);
161 tmu_write(data
, range
[3], &data
->regs
->ttr3cr
);
163 calibration
= of_get_property(np
, "fsl,tmu-calibration", &len
);
164 if (calibration
== NULL
|| len
% 8) {
165 dev_err(&pdev
->dev
, "invalid calibration data.\n");
169 for (i
= 0; i
< len
; i
+= 8, calibration
+= 2) {
170 val
= of_read_number(calibration
, 1);
171 tmu_write(data
, val
, &data
->regs
->ttcfgr
);
172 val
= of_read_number(calibration
+ 1, 1);
173 tmu_write(data
, val
, &data
->regs
->tscfgr
);
179 static void qoriq_tmu_init_device(struct qoriq_tmu_data
*data
)
181 /* Disable interrupt, using polling instead */
182 tmu_write(data
, TIER_DISABLE
, &data
->regs
->tier
);
184 /* Set update_interval */
185 tmu_write(data
, TMTMIR_DEFAULT
, &data
->regs
->tmtmir
);
187 /* Disable monitoring */
188 tmu_write(data
, TMR_DISABLE
, &data
->regs
->tmr
);
191 static const struct thermal_zone_of_device_ops tmu_tz_ops
= {
192 .get_temp
= tmu_get_temp
,
195 static int qoriq_tmu_probe(struct platform_device
*pdev
)
198 struct qoriq_tmu_data
*data
;
199 struct device_node
*np
= pdev
->dev
.of_node
;
203 dev_err(&pdev
->dev
, "Device OF-Node is NULL");
207 data
= devm_kzalloc(&pdev
->dev
, sizeof(struct qoriq_tmu_data
),
212 platform_set_drvdata(pdev
, data
);
214 data
->little_endian
= of_property_read_bool(np
, "little-endian");
216 data
->sensor_id
= qoriq_tmu_get_sensor_id();
217 if (data
->sensor_id
< 0) {
218 dev_err(&pdev
->dev
, "Failed to get sensor id\n");
223 data
->regs
= of_iomap(np
, 0);
225 dev_err(&pdev
->dev
, "Failed to get memory region\n");
230 qoriq_tmu_init_device(data
); /* TMU initialization */
232 ret
= qoriq_tmu_calibration(pdev
); /* TMU calibration */
236 data
->tz
= thermal_zone_of_sensor_register(&pdev
->dev
, data
->sensor_id
,
238 if (IS_ERR(data
->tz
)) {
239 ret
= PTR_ERR(data
->tz
);
241 "Failed to register thermal zone device %d\n", ret
);
245 /* Enable monitoring */
246 site
|= 0x1 << (15 - data
->sensor_id
);
247 tmu_write(data
, site
| TMR_ME
| TMR_ALPF
, &data
->regs
->tmr
);
255 platform_set_drvdata(pdev
, NULL
);
260 static int qoriq_tmu_remove(struct platform_device
*pdev
)
262 struct qoriq_tmu_data
*data
= platform_get_drvdata(pdev
);
264 thermal_zone_of_sensor_unregister(&pdev
->dev
, data
->tz
);
266 /* Disable monitoring */
267 tmu_write(data
, TMR_DISABLE
, &data
->regs
->tmr
);
270 platform_set_drvdata(pdev
, NULL
);
275 #ifdef CONFIG_PM_SLEEP
276 static int qoriq_tmu_suspend(struct device
*dev
)
279 struct qoriq_tmu_data
*data
= dev_get_drvdata(dev
);
281 /* Disable monitoring */
282 tmr
= tmu_read(data
, &data
->regs
->tmr
);
284 tmu_write(data
, tmr
, &data
->regs
->tmr
);
289 static int qoriq_tmu_resume(struct device
*dev
)
292 struct qoriq_tmu_data
*data
= dev_get_drvdata(dev
);
294 /* Enable monitoring */
295 tmr
= tmu_read(data
, &data
->regs
->tmr
);
297 tmu_write(data
, tmr
, &data
->regs
->tmr
);
303 static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops
,
304 qoriq_tmu_suspend
, qoriq_tmu_resume
);
306 static const struct of_device_id qoriq_tmu_match
[] = {
307 { .compatible
= "fsl,qoriq-tmu", },
310 MODULE_DEVICE_TABLE(of
, qoriq_tmu_match
);
312 static struct platform_driver qoriq_tmu
= {
314 .name
= "qoriq_thermal",
315 .pm
= &qoriq_tmu_pm_ops
,
316 .of_match_table
= qoriq_tmu_match
,
318 .probe
= qoriq_tmu_probe
,
319 .remove
= qoriq_tmu_remove
,
321 module_platform_driver(qoriq_tmu
);
323 MODULE_AUTHOR("Jia Hongtao <hongtao.jia@nxp.com>");
324 MODULE_DESCRIPTION("QorIQ Thermal Monitoring Unit driver");
325 MODULE_LICENSE("GPL v2");