1 // SPDX-License-Identifier: GPL-2.0
3 // Copyright 2016 Freescale Semiconductor, Inc.
5 #include <linux/module.h>
6 #include <linux/platform_device.h>
10 #include <linux/of_address.h>
11 #include <linux/thermal.h>
13 #include "thermal_core.h"
20 struct qoriq_tmu_site_regs
{
21 u32 tritsr
; /* Immediate Temperature Site Register */
22 u32 tratsr
; /* Average Temperature Site Register */
26 struct qoriq_tmu_regs
{
27 u32 tmr
; /* Mode Register */
28 #define TMR_DISABLE 0x0
29 #define TMR_ME 0x80000000
30 #define TMR_ALPF 0x0c000000
31 u32 tsr
; /* Status Register */
32 u32 tmtmir
; /* Temperature measurement interval Register */
33 #define TMTMIR_DEFAULT 0x0000000f
35 u32 tier
; /* Interrupt Enable Register */
36 #define TIER_DISABLE 0x0
37 u32 tidr
; /* Interrupt Detect Register */
38 u32 tiscr
; /* Interrupt Site Capture Register */
39 u32 ticscr
; /* Interrupt Critical Site Capture Register */
41 u32 tmhtcrh
; /* High Temperature Capture Register */
42 u32 tmhtcrl
; /* Low Temperature Capture Register */
44 u32 tmhtitr
; /* High Temperature Immediate Threshold */
45 u32 tmhtatr
; /* High Temperature Average Threshold */
46 u32 tmhtactr
; /* High Temperature Average Crit Threshold */
48 u32 ttcfgr
; /* Temperature Configuration Register */
49 u32 tscfgr
; /* Sensor Configuration Register */
51 struct qoriq_tmu_site_regs site
[SITES_MAX
];
53 u32 ipbrr0
; /* IP Block Revision Register 0 */
54 u32 ipbrr1
; /* IP Block Revision Register 1 */
56 u32 ttr0cr
; /* Temperature Range 0 Control Register */
57 u32 ttr1cr
; /* Temperature Range 1 Control Register */
58 u32 ttr2cr
; /* Temperature Range 2 Control Register */
59 u32 ttr3cr
; /* Temperature Range 3 Control Register */
65 struct qoriq_tmu_data
{
66 struct thermal_zone_device
*tz
;
67 struct qoriq_tmu_regs __iomem
*regs
;
72 static void tmu_write(struct qoriq_tmu_data
*p
, u32 val
, void __iomem
*addr
)
77 iowrite32be(val
, addr
);
80 static u32
tmu_read(struct qoriq_tmu_data
*p
, void __iomem
*addr
)
83 return ioread32(addr
);
85 return ioread32be(addr
);
88 static int tmu_get_temp(void *p
, int *temp
)
91 struct qoriq_tmu_data
*data
= p
;
93 val
= tmu_read(data
, &data
->regs
->site
[data
->sensor_id
].tritsr
);
94 *temp
= (val
& 0xff) * 1000;
99 static int qoriq_tmu_get_sensor_id(void)
102 struct of_phandle_args sensor_specs
;
103 struct device_node
*np
, *sensor_np
;
105 np
= of_find_node_by_name(NULL
, "thermal-zones");
109 sensor_np
= of_get_next_child(np
, NULL
);
110 ret
= of_parse_phandle_with_args(sensor_np
, "thermal-sensors",
111 "#thermal-sensor-cells",
115 of_node_put(sensor_np
);
119 if (sensor_specs
.args_count
>= 1) {
120 id
= sensor_specs
.args
[0];
121 WARN(sensor_specs
.args_count
> 1,
122 "%s: too many cells in sensor specifier %d\n",
123 sensor_specs
.np
->name
, sensor_specs
.args_count
);
129 of_node_put(sensor_np
);
134 static int qoriq_tmu_calibration(struct platform_device
*pdev
)
138 const u32
*calibration
;
139 struct device_node
*np
= pdev
->dev
.of_node
;
140 struct qoriq_tmu_data
*data
= platform_get_drvdata(pdev
);
142 if (of_property_read_u32_array(np
, "fsl,tmu-range", range
, 4)) {
143 dev_err(&pdev
->dev
, "missing calibration range.\n");
147 /* Init temperature range registers */
148 tmu_write(data
, range
[0], &data
->regs
->ttr0cr
);
149 tmu_write(data
, range
[1], &data
->regs
->ttr1cr
);
150 tmu_write(data
, range
[2], &data
->regs
->ttr2cr
);
151 tmu_write(data
, range
[3], &data
->regs
->ttr3cr
);
153 calibration
= of_get_property(np
, "fsl,tmu-calibration", &len
);
154 if (calibration
== NULL
|| len
% 8) {
155 dev_err(&pdev
->dev
, "invalid calibration data.\n");
159 for (i
= 0; i
< len
; i
+= 8, calibration
+= 2) {
160 val
= of_read_number(calibration
, 1);
161 tmu_write(data
, val
, &data
->regs
->ttcfgr
);
162 val
= of_read_number(calibration
+ 1, 1);
163 tmu_write(data
, val
, &data
->regs
->tscfgr
);
169 static void qoriq_tmu_init_device(struct qoriq_tmu_data
*data
)
171 /* Disable interrupt, using polling instead */
172 tmu_write(data
, TIER_DISABLE
, &data
->regs
->tier
);
174 /* Set update_interval */
175 tmu_write(data
, TMTMIR_DEFAULT
, &data
->regs
->tmtmir
);
177 /* Disable monitoring */
178 tmu_write(data
, TMR_DISABLE
, &data
->regs
->tmr
);
181 static const struct thermal_zone_of_device_ops tmu_tz_ops
= {
182 .get_temp
= tmu_get_temp
,
185 static int qoriq_tmu_probe(struct platform_device
*pdev
)
188 struct qoriq_tmu_data
*data
;
189 struct device_node
*np
= pdev
->dev
.of_node
;
193 dev_err(&pdev
->dev
, "Device OF-Node is NULL");
197 data
= devm_kzalloc(&pdev
->dev
, sizeof(struct qoriq_tmu_data
),
202 platform_set_drvdata(pdev
, data
);
204 data
->little_endian
= of_property_read_bool(np
, "little-endian");
206 data
->sensor_id
= qoriq_tmu_get_sensor_id();
207 if (data
->sensor_id
< 0) {
208 dev_err(&pdev
->dev
, "Failed to get sensor id\n");
213 data
->regs
= of_iomap(np
, 0);
215 dev_err(&pdev
->dev
, "Failed to get memory region\n");
220 qoriq_tmu_init_device(data
); /* TMU initialization */
222 ret
= qoriq_tmu_calibration(pdev
); /* TMU calibration */
226 data
->tz
= devm_thermal_zone_of_sensor_register(&pdev
->dev
,
229 if (IS_ERR(data
->tz
)) {
230 ret
= PTR_ERR(data
->tz
);
232 "Failed to register thermal zone device %d\n", ret
);
236 /* Enable monitoring */
237 site
= 0x1 << (15 - data
->sensor_id
);
238 tmu_write(data
, site
| TMR_ME
| TMR_ALPF
, &data
->regs
->tmr
);
246 platform_set_drvdata(pdev
, NULL
);
251 static int qoriq_tmu_remove(struct platform_device
*pdev
)
253 struct qoriq_tmu_data
*data
= platform_get_drvdata(pdev
);
255 /* Disable monitoring */
256 tmu_write(data
, TMR_DISABLE
, &data
->regs
->tmr
);
259 platform_set_drvdata(pdev
, NULL
);
264 #ifdef CONFIG_PM_SLEEP
265 static int qoriq_tmu_suspend(struct device
*dev
)
268 struct qoriq_tmu_data
*data
= dev_get_drvdata(dev
);
270 /* Disable monitoring */
271 tmr
= tmu_read(data
, &data
->regs
->tmr
);
273 tmu_write(data
, tmr
, &data
->regs
->tmr
);
278 static int qoriq_tmu_resume(struct device
*dev
)
281 struct qoriq_tmu_data
*data
= dev_get_drvdata(dev
);
283 /* Enable monitoring */
284 tmr
= tmu_read(data
, &data
->regs
->tmr
);
286 tmu_write(data
, tmr
, &data
->regs
->tmr
);
292 static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops
,
293 qoriq_tmu_suspend
, qoriq_tmu_resume
);
295 static const struct of_device_id qoriq_tmu_match
[] = {
296 { .compatible
= "fsl,qoriq-tmu", },
299 MODULE_DEVICE_TABLE(of
, qoriq_tmu_match
);
301 static struct platform_driver qoriq_tmu
= {
303 .name
= "qoriq_thermal",
304 .pm
= &qoriq_tmu_pm_ops
,
305 .of_match_table
= qoriq_tmu_match
,
307 .probe
= qoriq_tmu_probe
,
308 .remove
= qoriq_tmu_remove
,
310 module_platform_driver(qoriq_tmu
);
312 MODULE_AUTHOR("Jia Hongtao <hongtao.jia@nxp.com>");
313 MODULE_DESCRIPTION("QorIQ Thermal Monitoring Unit driver");
314 MODULE_LICENSE("GPL v2");