1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Copyright 2016 Freescale Semiconductor, Inc.
4 
5 #include <linux/clk.h>
6 #include <linux/module.h>
7 #include <linux/platform_device.h>
8 #include <linux/err.h>
9 #include <linux/io.h>
10 #include <linux/of.h>
11 #include <linux/of_address.h>
12 #include <linux/thermal.h>
13 
14 #include "thermal_core.h"
15 
16 #define SITES_MAX	16
17 
18 /*
19  * QorIQ TMU Registers
20  */
21 struct qoriq_tmu_site_regs {
22 	u32 tritsr;		/* Immediate Temperature Site Register */
23 	u32 tratsr;		/* Average Temperature Site Register */
24 	u8 res0[0x8];
25 };
26 
27 struct qoriq_tmu_regs {
28 	u32 tmr;		/* Mode Register */
29 #define TMR_DISABLE	0x0
30 #define TMR_ME		0x80000000
31 #define TMR_ALPF	0x0c000000
32 	u32 tsr;		/* Status Register */
33 	u32 tmtmir;		/* Temperature measurement interval Register */
34 #define TMTMIR_DEFAULT	0x0000000f
35 	u8 res0[0x14];
36 	u32 tier;		/* Interrupt Enable Register */
37 #define TIER_DISABLE	0x0
38 	u32 tidr;		/* Interrupt Detect Register */
39 	u32 tiscr;		/* Interrupt Site Capture Register */
40 	u32 ticscr;		/* Interrupt Critical Site Capture Register */
41 	u8 res1[0x10];
42 	u32 tmhtcrh;		/* High Temperature Capture Register */
43 	u32 tmhtcrl;		/* Low Temperature Capture Register */
44 	u8 res2[0x8];
45 	u32 tmhtitr;		/* High Temperature Immediate Threshold */
46 	u32 tmhtatr;		/* High Temperature Average Threshold */
47 	u32 tmhtactr;	/* High Temperature Average Crit Threshold */
48 	u8 res3[0x24];
49 	u32 ttcfgr;		/* Temperature Configuration Register */
50 	u32 tscfgr;		/* Sensor Configuration Register */
51 	u8 res4[0x78];
52 	struct qoriq_tmu_site_regs site[SITES_MAX];
53 	u8 res5[0x9f8];
54 	u32 ipbrr0;		/* IP Block Revision Register 0 */
55 	u32 ipbrr1;		/* IP Block Revision Register 1 */
56 	u8 res6[0x310];
57 	u32 ttr0cr;		/* Temperature Range 0 Control Register */
58 	u32 ttr1cr;		/* Temperature Range 1 Control Register */
59 	u32 ttr2cr;		/* Temperature Range 2 Control Register */
60 	u32 ttr3cr;		/* Temperature Range 3 Control Register */
61 };
62 
63 struct qoriq_tmu_data;
64 
65 /*
66  * Thermal zone data
67  */
68 struct qoriq_sensor {
69 	struct thermal_zone_device	*tzd;
70 	struct qoriq_tmu_data		*qdata;
71 	int				id;
72 };
73 
74 struct qoriq_tmu_data {
75 	struct qoriq_tmu_regs __iomem *regs;
76 	struct clk *clk;
77 	bool little_endian;
78 	struct qoriq_sensor	*sensor[SITES_MAX];
79 };
80 
81 static void tmu_write(struct qoriq_tmu_data *p, u32 val, void __iomem *addr)
82 {
83 	if (p->little_endian)
84 		iowrite32(val, addr);
85 	else
86 		iowrite32be(val, addr);
87 }
88 
89 static u32 tmu_read(struct qoriq_tmu_data *p, void __iomem *addr)
90 {
91 	if (p->little_endian)
92 		return ioread32(addr);
93 	else
94 		return ioread32be(addr);
95 }
96 
97 static int tmu_get_temp(void *p, int *temp)
98 {
99 	struct qoriq_sensor *qsensor = p;
100 	struct qoriq_tmu_data *qdata = qsensor->qdata;
101 	u32 val;
102 
103 	val = tmu_read(qdata, &qdata->regs->site[qsensor->id].tritsr);
104 	*temp = (val & 0xff) * 1000;
105 
106 	return 0;
107 }
108 
109 static const struct thermal_zone_of_device_ops tmu_tz_ops = {
110 	.get_temp = tmu_get_temp,
111 };
112 
113 static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev)
114 {
115 	struct qoriq_tmu_data *qdata = platform_get_drvdata(pdev);
116 	int id, sites = 0;
117 
118 	for (id = 0; id < SITES_MAX; id++) {
119 		qdata->sensor[id] = devm_kzalloc(&pdev->dev,
120 				sizeof(struct qoriq_sensor), GFP_KERNEL);
121 		if (!qdata->sensor[id])
122 			return -ENOMEM;
123 
124 		qdata->sensor[id]->id = id;
125 		qdata->sensor[id]->qdata = qdata;
126 		qdata->sensor[id]->tzd = devm_thermal_zone_of_sensor_register(
127 				&pdev->dev, id, qdata->sensor[id], &tmu_tz_ops);
128 		if (IS_ERR(qdata->sensor[id]->tzd)) {
129 			if (PTR_ERR(qdata->sensor[id]->tzd) == -ENODEV)
130 				continue;
131 			else
132 				return PTR_ERR(qdata->sensor[id]->tzd);
133 		}
134 
135 		sites |= 0x1 << (15 - id);
136 	}
137 
138 	/* Enable monitoring */
139 	if (sites != 0)
140 		tmu_write(qdata, sites | TMR_ME | TMR_ALPF, &qdata->regs->tmr);
141 
142 	return 0;
143 }
144 
145 static int qoriq_tmu_calibration(struct platform_device *pdev)
146 {
147 	int i, val, len;
148 	u32 range[4];
149 	const u32 *calibration;
150 	struct device_node *np = pdev->dev.of_node;
151 	struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
152 
153 	if (of_property_read_u32_array(np, "fsl,tmu-range", range, 4)) {
154 		dev_err(&pdev->dev, "missing calibration range.\n");
155 		return -ENODEV;
156 	}
157 
158 	/* Init temperature range registers */
159 	tmu_write(data, range[0], &data->regs->ttr0cr);
160 	tmu_write(data, range[1], &data->regs->ttr1cr);
161 	tmu_write(data, range[2], &data->regs->ttr2cr);
162 	tmu_write(data, range[3], &data->regs->ttr3cr);
163 
164 	calibration = of_get_property(np, "fsl,tmu-calibration", &len);
165 	if (calibration == NULL || len % 8) {
166 		dev_err(&pdev->dev, "invalid calibration data.\n");
167 		return -ENODEV;
168 	}
169 
170 	for (i = 0; i < len; i += 8, calibration += 2) {
171 		val = of_read_number(calibration, 1);
172 		tmu_write(data, val, &data->regs->ttcfgr);
173 		val = of_read_number(calibration + 1, 1);
174 		tmu_write(data, val, &data->regs->tscfgr);
175 	}
176 
177 	return 0;
178 }
179 
180 static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
181 {
182 	/* Disable interrupt, using polling instead */
183 	tmu_write(data, TIER_DISABLE, &data->regs->tier);
184 
185 	/* Set update_interval */
186 	tmu_write(data, TMTMIR_DEFAULT, &data->regs->tmtmir);
187 
188 	/* Disable monitoring */
189 	tmu_write(data, TMR_DISABLE, &data->regs->tmr);
190 }
191 
192 static int qoriq_tmu_probe(struct platform_device *pdev)
193 {
194 	int ret;
195 	struct qoriq_tmu_data *data;
196 	struct device_node *np = pdev->dev.of_node;
197 
198 	data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data),
199 			    GFP_KERNEL);
200 	if (!data)
201 		return -ENOMEM;
202 
203 	platform_set_drvdata(pdev, data);
204 
205 	data->little_endian = of_property_read_bool(np, "little-endian");
206 
207 	data->regs = devm_platform_ioremap_resource(pdev, 0);
208 	if (IS_ERR(data->regs)) {
209 		dev_err(&pdev->dev, "Failed to get memory region\n");
210 		return PTR_ERR(data->regs);
211 	}
212 
213 	data->clk = devm_clk_get_optional(&pdev->dev, NULL);
214 	if (IS_ERR(data->clk))
215 		return PTR_ERR(data->clk);
216 
217 	ret = clk_prepare_enable(data->clk);
218 	if (ret) {
219 		dev_err(&pdev->dev, "Failed to enable clock\n");
220 		return ret;
221 	}
222 
223 	qoriq_tmu_init_device(data);	/* TMU initialization */
224 
225 	ret = qoriq_tmu_calibration(pdev);	/* TMU calibration */
226 	if (ret < 0)
227 		goto err;
228 
229 	ret = qoriq_tmu_register_tmu_zone(pdev);
230 	if (ret < 0) {
231 		dev_err(&pdev->dev, "Failed to register sensors\n");
232 		ret = -ENODEV;
233 		goto err;
234 	}
235 
236 	return 0;
237 
238 err:
239 	clk_disable_unprepare(data->clk);
240 	platform_set_drvdata(pdev, NULL);
241 
242 	return ret;
243 }
244 
245 static int qoriq_tmu_remove(struct platform_device *pdev)
246 {
247 	struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
248 
249 	/* Disable monitoring */
250 	tmu_write(data, TMR_DISABLE, &data->regs->tmr);
251 
252 	clk_disable_unprepare(data->clk);
253 
254 	platform_set_drvdata(pdev, NULL);
255 
256 	return 0;
257 }
258 
259 static int __maybe_unused qoriq_tmu_suspend(struct device *dev)
260 {
261 	u32 tmr;
262 	struct qoriq_tmu_data *data = dev_get_drvdata(dev);
263 
264 	/* Disable monitoring */
265 	tmr = tmu_read(data, &data->regs->tmr);
266 	tmr &= ~TMR_ME;
267 	tmu_write(data, tmr, &data->regs->tmr);
268 
269 	clk_disable_unprepare(data->clk);
270 
271 	return 0;
272 }
273 
274 static int __maybe_unused qoriq_tmu_resume(struct device *dev)
275 {
276 	u32 tmr;
277 	int ret;
278 	struct qoriq_tmu_data *data = dev_get_drvdata(dev);
279 
280 	ret = clk_prepare_enable(data->clk);
281 	if (ret)
282 		return ret;
283 
284 	/* Enable monitoring */
285 	tmr = tmu_read(data, &data->regs->tmr);
286 	tmr |= TMR_ME;
287 	tmu_write(data, tmr, &data->regs->tmr);
288 
289 	return 0;
290 }
291 
292 static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
293 			 qoriq_tmu_suspend, qoriq_tmu_resume);
294 
295 static const struct of_device_id qoriq_tmu_match[] = {
296 	{ .compatible = "fsl,qoriq-tmu", },
297 	{ .compatible = "fsl,imx8mq-tmu", },
298 	{},
299 };
300 MODULE_DEVICE_TABLE(of, qoriq_tmu_match);
301 
302 static struct platform_driver qoriq_tmu = {
303 	.driver	= {
304 		.name		= "qoriq_thermal",
305 		.pm		= &qoriq_tmu_pm_ops,
306 		.of_match_table	= qoriq_tmu_match,
307 	},
308 	.probe	= qoriq_tmu_probe,
309 	.remove	= qoriq_tmu_remove,
310 };
311 module_platform_driver(qoriq_tmu);
312 
313 MODULE_AUTHOR("Jia Hongtao <hongtao.jia@nxp.com>");
314 MODULE_DESCRIPTION("QorIQ Thermal Monitoring Unit driver");
315 MODULE_LICENSE("GPL v2");
316