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