1 /*- 2 * 3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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