Index: sys/arm64/qoriq/qoriq_therm.c =================================================================== --- sys/arm64/qoriq/qoriq_therm.c +++ sys/arm64/qoriq/qoriq_therm.c @@ -65,11 +65,13 @@ #define TMUV2_TEUMR(x) (0xF00 + (4 * (x))) #define TMU_TTRCR(x) (0xF10 + (4 * (x))) +#define TMU_SITE(x) (1 << (15 - (x))) + +#define TMU_MAX_SENSORS 16 struct tsensor { - int site_id; - char *name; - int id; + int id; + char *name; }; struct qoriq_therm_softc { @@ -78,7 +80,7 @@ struct resource *irq_res; void *irq_ih; int ntsensors; - struct tsensor *tsensors; + struct tsensor tsensors[TMU_MAX_SENSORS]; bool little_endian; clk_t clk; int ver; @@ -86,17 +88,6 @@ static struct sysctl_ctx_list qoriq_therm_sysctl_ctx; -struct tsensor default_sensors[] = -{ - { 0, "site0", 0}, - { 1, "site1", 1}, - { 2, "site2", 2}, - { 3, "site3", 3}, - { 4, "site4", 4}, - { 5, "site5", 5}, - { 6, "site6", 6}, -}; - static struct ofw_compat_data compat_data[] = { {"fsl,qoriq-tmu", 1}, {"fsl,imx8mq-tmu", 1}, @@ -129,7 +120,7 @@ /* wait for valid sample */ for (timeout = 1000; timeout > 0; timeout--) { - val = RD4(sc, TMU_TRITSR(sensor->site_id)); + val = RD4(sc, TMU_TRITSR(sensor->id)); if (val & TMU_TRITSR_VALID) break; DELAY(100); @@ -220,6 +211,9 @@ sizeof(*ranges), (void **)&ranges); if (nranges < 2 || nranges > 4) { device_printf(sc->dev, "Invalid 'tmu-range' property\n"); + if (nranges > 0) + OF_prop_free(ranges); + return (ERANGE); } for (i = 0; i < nranges; i++) { @@ -231,6 +225,9 @@ sizeof(*calibs),(void **)&calibs); if (ncalibs <= 0 || (ncalibs % 2) != 0) { device_printf(sc->dev, "Invalid 'tmu-calibration' property\n"); + OF_prop_free(ranges); + if (ncalibs > 0) + OF_prop_free(calibs); return (ERANGE); } for (i = 0; i < ncalibs; i +=2) { @@ -238,6 +235,56 @@ WR4(sc, TMU_TSCFGR, calibs[i + 1]); } + OF_prop_free(ranges); + OF_prop_free(calibs); + return (0); +} + +static int +qoriq_therm_parse_zones(struct qoriq_therm_softc *sc) +{ + phandle_t node, child, dev_node; + uint32_t temp[2]; + ssize_t len; + + sc->ntsensors = 0; + + /* + * We don't have an xref or anything else that would point us to + * the node that describes thermal zones monitored by this device. + * Apparatly the node we're looking for is just supposed to sit at + * the top of DT... + */ + node = OF_finddevice("/thermal-zones"); + if (node <= 0) { + device_printf(sc->dev, "Failed to find thermal-zones DT node\n"); + return (ENXIO); + } + + dev_node = ofw_bus_get_node(sc->dev); + /* Shouldn't happen. */ + if (dev_node <= 0) + return (ENXIO); + + + for (child = OF_child(node); child != 0; child = OF_peer(child)) { + len = OF_getencprop(child, "thermal-sensors", temp, sizeof(temp)); + if (len != sizeof(temp)) + continue; + + /* First cell points to tmu, second is the sensor id. */ + if (OF_node_from_xref(temp[0]) != dev_node) { + continue; + } + sc->tsensors[sc->ntsensors].id = temp[1]; + len = OF_getprop_alloc(child, "name", + (void **)&sc->tsensors[sc->ntsensors].name); + if (len <= 0) + continue; + + sc->ntsensors++; + } + return (0); } @@ -261,7 +308,7 @@ struct qoriq_therm_softc *sc; phandle_t node; uint32_t sites; - int rid, rv; + int rid, rv, i; sc = device_get_softc(dev); sc->dev = dev; @@ -269,6 +316,12 @@ sc->little_endian = OF_hasprop(node, "little-endian"); sysctl_ctx_init(&qoriq_therm_sysctl_ctx); + rv = qoriq_therm_parse_zones(sc); + if (rv != 0) + return (rv); + + if (sc->ntsensors == 0) + return (ENXIO); rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, @@ -307,10 +360,8 @@ } sc->ver = (RD4(sc, TMU_VERSION) >> 8) & 0xFF; - - /* XXX add per SoC customization */ - sc->ntsensors = nitems(default_sensors); - sc->tsensors = default_sensors; + if (bootverbose) + device_printf(dev, "TMU version %d\n", sc->ver); /* stop monitoring */ WR4(sc, TMU_TMR, 0); @@ -337,8 +388,12 @@ "Cannot initialize calibration tables\n"); goto fail; } + + sites = 0; + for (i = 0; i < sc->ntsensors; i++) + sites |= TMU_SITE(sc->tsensors[i].id); + /* start monitoring */ - sites = (1U << sc->ntsensors) - 1; if (sc->ver == 1) { WR4(sc, TMU_TMR, 0x8C000000 | sites); } else { @@ -373,6 +428,8 @@ qoriq_therm_detach(device_t dev) { struct qoriq_therm_softc *sc; + int i; + sc = device_get_softc(dev); if (sc->irq_ih != NULL) @@ -385,6 +442,9 @@ if (sc->mem_res != NULL) bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); + for (i = 0; i < sc->ntsensors; i++) + OF_prop_free(sc->tsensors[i].name); + return (0); }