Index: sys/arm64/qoriq/qoriq_therm.c =================================================================== --- sys/arm64/qoriq/qoriq_therm.c +++ sys/arm64/qoriq/qoriq_therm.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright 2020 Michal Meloun + * Copyright (c) 2022 Bjoern A. Zeeb * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -88,13 +89,22 @@ 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}, + { 0, "site0", 0 }, + { 1, "site1", 1 }, + { 2, "site2", 2 }, + { 3, "site3", 3 }, + { 4, "site4", 4 }, + { 5, "site5", 5 }, + { 6, "site6", 6 }, + { 7, "site7", 7 }, + { 8, "site8", 8 }, + { 9, "site9", 9 }, + { 10, "site10", 10 }, + { 11, "site11", 11 }, + { 12, "site12", 12 }, + { 13, "site13", 13 }, + { 14, "site14", 14 }, + { 15, "site15", 15 }, }; static struct ofw_compat_data compat_data[] = { @@ -259,14 +269,13 @@ qoriq_therm_attach(device_t dev) { struct qoriq_therm_softc *sc; - phandle_t node; + phandle_t child, node; uint32_t sites; - int rid, rv; + int max, rid, rv; sc = device_get_softc(dev); sc->dev = dev; - node = ofw_bus_get_node(sc->dev); - sc->little_endian = OF_hasprop(node, "little-endian"); + sc->little_endian = device_has_property(dev, "little-endian"); sysctl_ctx_init(&qoriq_therm_sysctl_ctx); @@ -308,8 +317,88 @@ sc->ver = (RD4(sc, TMU_VERSION) >> 8) & 0xFF; - /* XXX add per SoC customization */ - sc->ntsensors = nitems(default_sensors); + /* Try to get a meaningful set of sites for the SoC. */ + child = OF_finddevice("/thermal-zones"); + if (child == -1) { + device_printf(sc->dev, "Cannot find '/thermal-zones'\n"); + goto skip_sites; + } + + max = -1; + for (child = OF_child(child); child > 0; child = OF_peer(child)) { + char *name; + pcell_t *cells; + phandle_t xnode; + int id, ncells; + bool has_name; + + if (sc->ntsensors >= nitems(default_sensors)) { + device_printf(sc->dev, "Broken configuration: more " + "thermal zone entries than maximum nodes!\n"); + goto skip_sites; + } + + if (OF_getprop_alloc(child, "name", (void **)&name) == -1) { + name = "node name n/a"; + has_name = false; + } else { + has_name = true; + } + + rv = ofw_bus_parse_xref_list_alloc(child, "thermal-sensors", + "#thermal-sensor-cells", 0, &xnode, &ncells, &cells); + if (rv != 0) { + device_printf(sc->dev, "%s: cannot parse " + "'thermal-sensors' property: %d\n", name, rv); + continue; + } + if (ncells == 0) { + /* Special case for imx8mm and imx8mn. */ + id = 0; + } else if (ncells == 1) { + id = cells[0]; + } else { + device_printf(sc->dev, "%s: Invalid format of " + "'thermal-sensors' property: %d\n", name, ncells); + OF_prop_free(cells); + continue; + } + OF_prop_free(cells); + + if (id >= nitems(default_sensors)) { + device_printf(sc->dev, "Broken configuration: " + "thermal zone entry %d >= maximum %lu!\n", + id, nitems(default_sensors)); + continue; + } + + if (bootverbose) + device_printf(sc->dev, "Found thermal sensor #%d " + "site%d: '%s'\n", sc->ntsensors, id, name); + + /* + * XXX we assume 0.. without gaps here! See "max"-check. + * Otherwise we need to keep the bitmask right away to flag + * each one "valid". powerpc,t1040si-post would be such a case. + */ + if (has_name) + default_sensors[id].name = name; + + max = MAX(max, id); + sc->ntsensors++; + } + if ((sc->ntsensors - 1) != max) { + device_printf(sc->dev, "Non-monotonous allocation of site ids. " + "Found %d-1 with max %d!\n", sc->ntsensors, max); + sc->ntsensors = 0; + } + +skip_sites: + /* If we found nothing, fallback to default-all. */ + if (sc->ntsensors == 0) { + device_printf(sc->dev, "Using default-all site configuration\n"); + sc->ntsensors = nitems(default_sensors); + } sc->tsensors = default_sensors; /* stop monitoring */ @@ -326,11 +415,12 @@ WR4(sc, TMUV2_TMTMIR, 0x0F); /* disable */ /* these registers are not of settings is not in TRM */ WR4(sc, TMUV2_TEUMR(0), 0x51009c00); - for (int i = 0; i < 7; i++) + for (int i = 0; i < sc->ntsensors; i++) WR4(sc, TMUV2_TMSAR(0), 0xE); } /* prepare calibration tables */ + node = ofw_bus_get_node(sc->dev); rv = qoriq_therm_fdt_calib(sc, node); if (rv != 0) { device_printf(sc->dev,