xref: /freebsd/sys/arm64/qoriq/qoriq_therm.c (revision 4e8d558c)
1 /*-
2  *
3  * SPDX-License-Identifier: BSD-2-Clause
4  *
5  * Copyright  2020 Michal Meloun <mmel@FreeBSD.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 /*
33  * Thermometer driver for QorIQ  SoCs.
34  */
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/endian.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/malloc.h>
42 #include <sys/rman.h>
43 #include <sys/sysctl.h>
44 
45 #include <machine/bus.h>
46 
47 #include <dev/extres/clk/clk.h>
48 #include <dev/ofw/ofw_bus.h>
49 #include <dev/ofw/ofw_bus_subr.h>
50 
51 #include "qoriq_therm_if.h"
52 
53 #define	TMU_TMR		0x00
54 #define	TMU_TSR		0x04
55 #define TMUV1_TMTMIR	0x08
56 #define TMUV2_TMSR	0x08
57 #define TMUV2_TMTMIR	0x0C
58 #define	TMU_TIER	0x20
59 #define	TMU_TTCFGR	0x80
60 #define	TMU_TSCFGR	0x84
61 #define	TMU_TRITSR(x)	(0x100 + (16 * (x)))
62 #define	 TMU_TRITSR_VALID	(1U << 31)
63 #define	TMUV2_TMSAR(x)	(0x304 + (16 * (x)))
64 #define	TMU_VERSION	0xBF8			/* not in TRM */
65 #define	TMUV2_TEUMR(x)	(0xF00 + (4 * (x)))
66 #define	TMU_TTRCR(x)	(0xF10 + (4 * (x)))
67 
68 
69 struct tsensor {
70 	int			site_id;
71 	char 			*name;
72 	int			id;
73 };
74 
75 struct qoriq_therm_softc {
76 	device_t		dev;
77 	struct resource		*mem_res;
78 	struct resource		*irq_res;
79 	void			*irq_ih;
80 	int			ntsensors;
81 	struct tsensor		*tsensors;
82 	bool			little_endian;
83 	clk_t			clk;
84 	int			ver;
85 };
86 
87 static struct sysctl_ctx_list qoriq_therm_sysctl_ctx;
88 
89 struct tsensor default_sensors[] =
90 {
91 	{ 0,	"site0",		0 },
92 	{ 1,	"site1",		1 },
93 	{ 2,	"site2",		2 },
94 	{ 3,	"site3",		3 },
95 	{ 4,	"site4",		4 },
96 	{ 5,	"site5",		5 },
97 	{ 6,	"site6",		6 },
98 	{ 7,	"site7",		7 },
99 	{ 8,	"site8",		8 },
100 	{ 9,	"site9",		9 },
101 	{ 10,	"site10",		10 },
102 	{ 11,	"site11",		11 },
103 	{ 12,	"site12",		12 },
104 	{ 13,	"site13",		13 },
105 	{ 14,	"site14",		14 },
106 	{ 15,	"site15",		15 },
107 };
108 
109 static struct tsensor imx8mq_sensors[] =
110 {
111 	{ 0,	"cpu",			0 },
112 	{ 1,	"gpu",			1 },
113 	{ 2,	"vpu",			2 },
114 };
115 
116 static struct tsensor ls1012_sensors[] =
117 {
118 	{ 0,	"cpu-thermal",		0 },
119 };
120 
121 static struct tsensor ls1028_sensors[] =
122 {
123 	{ 0,	"ddr-controller",	0 },
124 	{ 1,	"core-cluster",		1 },
125 };
126 
127 static struct tsensor ls1043_sensors[] =
128 {
129 	{ 0,	"ddr-controller",	0 },
130 	{ 1,	"serdes",		1 },
131 	{ 2,	"fman",			2 },
132 	{ 3,	"core-cluster",		3 },
133 };
134 
135 static struct tsensor ls1046_sensors[] =
136 {
137 	{ 0,	"ddr-controller",	0 },
138 	{ 1,	"serdes",		1 },
139 	{ 2,	"fman",			2 },
140 	{ 3,	"core-cluster",		3 },
141 	{ 4,	"sec",			4 },
142 };
143 
144 static struct tsensor ls1088_sensors[] =
145 {
146 	{ 0,	"core-cluster",		0 },
147 	{ 1,	"soc",			1 },
148 };
149 
150 /* Note: tmu[1..7] not [0..6]. */
151 static struct tsensor lx2080_sensors[] =
152 {
153 	{ 1,	"ddr-controller1",	0 },
154 	{ 2,	"ddr-controller2",	1 },
155 	{ 3,	"ddr-controller3",	2 },
156 	{ 4,	"core-cluster1",	3 },
157 	{ 5,	"core-cluster2",	4 },
158 	{ 6,	"core-cluster3",	5 },
159 	{ 7,	"core-cluster4",	6 },
160 };
161 
162 static struct tsensor lx2160_sensors[] =
163 {
164 	{ 0,	"cluster6-7",		0 },
165 	{ 1,	"ddr-cluster5",		1 },
166 	{ 2,	"wriop",		2 },
167 	{ 3,	"dce-qbman-hsio2",	3 },
168 	{ 4,	"ccn-dpaa-tbu",		4 },
169 	{ 5,	"cluster4-hsio3",	5 },
170 	{ 6,	"cluster2-3",		6 },
171 };
172 
173 struct qoriq_therm_socs {
174 	const char		*name;
175 	struct tsensor		*tsensors;
176 	int			ntsensors;
177 } qoriq_therm_socs[] = {
178 #define	_SOC(_n, _a)	{ _n, _a, nitems(_a) }
179 	_SOC("fsl,imx8mq",	imx8mq_sensors),
180 	_SOC("fsl,ls1012a",	ls1012_sensors),
181 	_SOC("fsl,ls1028a",	ls1028_sensors),
182 	_SOC("fsl,ls1043a",	ls1043_sensors),
183 	_SOC("fsl,ls1046a",	ls1046_sensors),
184 	_SOC("fsl,ls1088a",	ls1088_sensors),
185 	_SOC("fsl,ls2080a",	lx2080_sensors),
186 	_SOC("fsl,lx2160a",	lx2160_sensors),
187 	{ NULL,	NULL, 0 }
188 #undef _SOC
189 };
190 
191 static struct ofw_compat_data compat_data[] = {
192 	{"fsl,qoriq-tmu",	1},
193 	{"fsl,imx8mq-tmu",	1},
194 	{NULL,			0},
195 };
196 
197 static inline void
198 WR4(struct qoriq_therm_softc *sc, bus_size_t addr, uint32_t val)
199 {
200 
201 	val = sc->little_endian ? htole32(val): htobe32(val);
202 	bus_write_4(sc->mem_res, addr, val);
203 }
204 
205 static inline uint32_t
206 RD4(struct qoriq_therm_softc *sc, bus_size_t addr)
207 {
208 	uint32_t val;
209 
210 	val = bus_read_4(sc->mem_res, addr);
211 	return (sc->little_endian ? le32toh(val): be32toh(val));
212 }
213 
214 static int
215 qoriq_therm_read_temp(struct qoriq_therm_softc *sc, struct tsensor *sensor,
216     int *temp)
217 {
218 	int timeout;
219 	uint32_t val;
220 
221 	/* wait for valid sample */
222 	for (timeout = 1000; timeout > 0; timeout--) {
223 		val = RD4(sc, TMU_TRITSR(sensor->site_id));
224 		if (val & TMU_TRITSR_VALID)
225 			break;
226 		DELAY(100);
227 	}
228 	if (timeout <= 0)
229 		device_printf(sc->dev, "Sensor %s timeouted\n", sensor->name);
230 
231 	*temp = (int)(val & 0x1FF) * 1000;
232 	if (sc->ver == 1)
233 		*temp = (int)(val & 0xFF) * 1000;
234 	else
235 		*temp = (int)(val & 0x1FF) * 1000 - 273100;
236 
237 	return (0);
238 }
239 
240 static int
241 qoriq_therm_get_temp(device_t dev, device_t cdev, uintptr_t id, int *val)
242 {
243 	struct qoriq_therm_softc *sc;
244 
245 	sc = device_get_softc(dev);
246 	if (id >= sc->ntsensors)
247 		return (ERANGE);
248 	return(qoriq_therm_read_temp(sc, sc->tsensors + id, val));
249 }
250 
251 static int
252 qoriq_therm_sysctl_temperature(SYSCTL_HANDLER_ARGS)
253 {
254 	struct qoriq_therm_softc *sc;
255 	int val;
256 	int rv;
257 	int id;
258 
259 	/* Write request */
260 	if (req->newptr != NULL)
261 		return (EINVAL);
262 
263 	sc = arg1;
264 	id = arg2;
265 
266 	if (id >= sc->ntsensors)
267 		return (ERANGE);
268 	rv =  qoriq_therm_read_temp(sc, sc->tsensors + id, &val);
269 	if (rv != 0)
270 		return (rv);
271 
272 	val = val / 100;
273 	val +=  2731;
274 	rv = sysctl_handle_int(oidp, &val, 0, req);
275 	return (rv);
276 }
277 
278 static int
279 qoriq_therm_init_sysctl(struct qoriq_therm_softc *sc)
280 {
281 	int i;
282 	struct sysctl_oid *oid, *tmp;
283 
284 	/* create node for hw.temp */
285 	oid = SYSCTL_ADD_NODE(&qoriq_therm_sysctl_ctx,
286 	    SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "temperature",
287 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
288 	if (oid == NULL)
289 		return (ENXIO);
290 
291 	/* add sensors */
292 	for (i = sc->ntsensors  - 1; i >= 0; i--) {
293 		tmp = SYSCTL_ADD_PROC(&qoriq_therm_sysctl_ctx,
294 		    SYSCTL_CHILDREN(oid), OID_AUTO, sc->tsensors[i].name,
295 		    CTLTYPE_INT | CTLFLAG_RD , sc, i,
296 		    qoriq_therm_sysctl_temperature, "IK", "SoC Temperature");
297 		if (tmp == NULL)
298 			return (ENXIO);
299 	}
300 	return (0);
301 }
302 
303 static int
304 qoriq_therm_fdt_calib(struct qoriq_therm_softc *sc, phandle_t node)
305 {
306 	int 	nranges, ncalibs, i;
307 	int	*ranges, *calibs;
308 
309 	/* initialize temperature range control registes */
310 	nranges = OF_getencprop_alloc_multi(node, "fsl,tmu-range",
311 	    sizeof(*ranges), (void **)&ranges);
312 	if (nranges < 2 || nranges > 4) {
313 		device_printf(sc->dev, "Invalid 'tmu-range' property\n");
314 		return (ERANGE);
315 	}
316 	for (i = 0; i < nranges; i++) {
317 		WR4(sc, TMU_TTRCR(i), ranges[i]);
318 	}
319 
320 	/* initialize calibration data for above ranges */
321 	ncalibs = OF_getencprop_alloc_multi(node, "fsl,tmu-calibration",
322 	    sizeof(*calibs),(void **)&calibs);
323 	if (ncalibs <= 0 || (ncalibs % 2) != 0) {
324 		device_printf(sc->dev, "Invalid 'tmu-calibration' property\n");
325 		return (ERANGE);
326 	}
327 	for (i = 0; i < ncalibs; i +=2) {
328 		WR4(sc, TMU_TTCFGR, calibs[i]);
329 		WR4(sc, TMU_TSCFGR, calibs[i + 1]);
330 	}
331 
332 	return (0);
333 }
334 
335 static int
336 qoriq_therm_probe(device_t dev)
337 {
338 
339 	if (!ofw_bus_status_okay(dev))
340 		return (ENXIO);
341 
342 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
343 		return (ENXIO);
344 
345 	device_set_desc(dev, "QorIQ temperature sensors");
346 	return (BUS_PROBE_DEFAULT);
347 }
348 
349 static int
350 qoriq_therm_attach(device_t dev)
351 {
352 	struct qoriq_therm_softc *sc;
353 	struct qoriq_therm_socs *soc;
354 	phandle_t node, root;
355 	uint32_t sites;
356 	int rid, rv;
357 
358 	sc = device_get_softc(dev);
359 	sc->dev = dev;
360 	node = ofw_bus_get_node(sc->dev);
361 	sc->little_endian = OF_hasprop(node, "little-endian");
362 
363 	sysctl_ctx_init(&qoriq_therm_sysctl_ctx);
364 
365 	rid = 0;
366 	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
367 	    RF_ACTIVE);
368 	if (sc->mem_res == NULL) {
369 		device_printf(dev, "Cannot allocate memory resources\n");
370 		goto fail;
371 	}
372 
373 	rid = 0;
374 	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
375 	if (sc->irq_res == NULL) {
376 		device_printf(dev, "Cannot allocate IRQ resources\n");
377 		goto fail;
378 	}
379 
380 /*
381 	if ((bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
382 	    qoriq_therm_intr, NULL, sc, &sc->irq_ih))) {
383 		device_printf(dev,
384 		    "WARNING: unable to register interrupt handler\n");
385 		goto fail;
386 	}
387 */
388 	rv = clk_get_by_ofw_index(dev, 0, 0, &sc->clk);
389 	if (rv != 0 && rv != ENOENT) {
390 		device_printf(dev, "Cannot get clock: %d %d\n", rv, ENOENT);
391 		goto fail;
392 	}
393 	if (sc->clk != NULL) {
394 		rv = clk_enable(sc->clk);
395 		if (rv != 0) {
396 			device_printf(dev, "Cannot enable clock: %d\n", rv);
397 			goto fail;
398 		}
399 	}
400 
401 	sc->ver = (RD4(sc, TMU_VERSION) >> 8) & 0xFF;
402 
403 	/* Select per SoC configuration. */
404 	root = OF_finddevice("/");
405 	if (root < 0) {
406 		device_printf(dev, "Cannot get root node: %d\n", root);
407 		goto fail;
408 	}
409 	soc = qoriq_therm_socs;
410 	while (soc != NULL && soc->name != NULL) {
411 		if (ofw_bus_node_is_compatible(root, soc->name))
412 			break;
413 		soc++;
414 	}
415 	if (soc == NULL) {
416 		device_printf(dev, "Unsupported SoC, using default sites.\n");
417 		sc->tsensors = default_sensors;
418 		sc->ntsensors = nitems(default_sensors);
419 	} else {
420 		sc->tsensors = soc->tsensors;
421 		sc->ntsensors = soc->ntsensors;
422 	}
423 
424 	/* stop monitoring */
425 	WR4(sc, TMU_TMR, 0);
426 	RD4(sc, TMU_TMR);
427 
428 	/* disable all interrupts */
429 	WR4(sc, TMU_TIER, 0);
430 
431 	/* setup measurement interval */
432 	if (sc->ver == 1) {
433 		WR4(sc, TMUV1_TMTMIR, 0x0F);
434 	} else {
435 		WR4(sc, TMUV2_TMTMIR, 0x0F);	/* disable */
436 		/* these registers are not of settings is not in TRM */
437 		WR4(sc, TMUV2_TEUMR(0), 0x51009c00);
438 		for (int i = 0; i < sc->ntsensors; i++)
439 			WR4(sc, TMUV2_TMSAR(sc->tsensors[i].site_id), 0xE);
440 	}
441 
442 	/* prepare calibration tables */
443 	rv = qoriq_therm_fdt_calib(sc, node);
444 	if (rv != 0) {
445 		device_printf(sc->dev,
446 		    "Cannot initialize calibration tables\n");
447 		goto fail;
448 	}
449 	/* start monitoring */
450 	sites = 0;
451 	if (sc->ver == 1) {
452 		for (int i = 0; i < sc->ntsensors; i++)
453 			sites |= 1 << (15 - sc->tsensors[i].site_id);
454 		WR4(sc, TMU_TMR, 0x8C000000 | sites);
455 	} else {
456 		for (int i = 0; i < sc->ntsensors; i++)
457 			sites |= 1 << sc->tsensors[i].site_id;
458 		WR4(sc, TMUV2_TMSR, sites);
459 		WR4(sc, TMU_TMR, 0x83000000);
460 	}
461 
462 	rv = qoriq_therm_init_sysctl(sc);
463 	if (rv != 0) {
464 		device_printf(sc->dev, "Cannot initialize sysctls\n");
465 		goto fail;
466 	}
467 
468 	OF_device_register_xref(OF_xref_from_node(node), dev);
469 	return (bus_generic_attach(dev));
470 
471 fail:
472 	if (sc->irq_ih != NULL)
473 		bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
474 	sysctl_ctx_free(&qoriq_therm_sysctl_ctx);
475 	if (sc->clk != NULL)
476 		clk_release(sc->clk);
477 	if (sc->irq_res != NULL)
478 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
479 	if (sc->mem_res != NULL)
480 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
481 
482 	return (ENXIO);
483 }
484 
485 static int
486 qoriq_therm_detach(device_t dev)
487 {
488 	struct qoriq_therm_softc *sc;
489 	sc = device_get_softc(dev);
490 
491 	if (sc->irq_ih != NULL)
492 		bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
493 	sysctl_ctx_free(&qoriq_therm_sysctl_ctx);
494 	if (sc->clk != NULL)
495 		clk_release(sc->clk);
496 	if (sc->irq_res != NULL)
497 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
498 	if (sc->mem_res != NULL)
499 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
500 
501 	return (0);
502 }
503 
504 static device_method_t qoriq_qoriq_therm_methods[] = {
505 	/* Device interface */
506 	DEVMETHOD(device_probe,			qoriq_therm_probe),
507 	DEVMETHOD(device_attach,		qoriq_therm_attach),
508 	DEVMETHOD(device_detach,		qoriq_therm_detach),
509 
510 	/* SOCTHERM interface */
511 	DEVMETHOD(qoriq_therm_get_temperature,	qoriq_therm_get_temp),
512 
513 	DEVMETHOD_END
514 };
515 
516 static DEFINE_CLASS_0(soctherm, qoriq_qoriq_therm_driver, qoriq_qoriq_therm_methods,
517     sizeof(struct qoriq_therm_softc));
518 DRIVER_MODULE(qoriq_soctherm, simplebus, qoriq_qoriq_therm_driver, NULL, NULL);
519