> Date: Fri, 6 Sep 2019 21:55:43 +0200
> From: Krystian Lewandowski <[email protected]>
>
> Good evening Mark (and tech@),
> thank you for thermal zones support.
>
> I thought it would be nice to use it in A64 as well.
> I tested it by running 'ubench -c' in a loop and checking clocks
> and CPU temp. Clock went down when temperature rised limiting available
> operating-points as expected (as far as I could tell).
>
> I used following device tree entries:
> (excerpt that should present the idea)
>
> thermal-zones {
> cpu-thermal {
> polling-delay-passive = <250>;
> polling-delay = <1000>;
> thermal-sensors = <&ths 0>;
>
> trips {
> cpu_warm: cpu_warm {
> temperature = <65000000>;
> hysteresis = <2000000>;
> type = "passive";
> };
>
> cpu_hot_pre: cpu_hot_pre {
> temperature = <70000000>;
> hysteresis = <2000000>;
> type = "passive";
> };
>
> cpu_hot: cpu_hot {
> temperature = <75000000>;
> hysteresis = <2000000>;
> type = "passive";
> };
>
> cpu_very_hot: cpu_very_hot {
> temperature = <90000000>;
> hysteresis = <2000000>;
> type = "passive";
> };
> };
>
> cooling-maps {
> cpu_warm_limit_cpu {
> trip = <&cpu_warm>;
> cooling-device = <&cpu0
> THERMAL_NO_LIMIT 2>;
> };
>
> cpu_hot_pre_limit_cpu {
> trip = <&cpu_hot_pre>;
> cooling-device = <&cpu0 2 3>;
> };
>
> cpu_hot_limit_cpu {
> trip = <&cpu_hot>;
> cooling-device = <&cpu0 3 4>;
> };
>
> cpu_very_hot_pre_limit_cpu {
> trip = <&cpu_very_hot>;
> cooling-device = <&cpu0 5 6>;
> };
>
> cpu_very_hot_limit_cpu {
> trip = <&cpu_very_hot>;
> cooling-device = <&cpu0 7
> THERMAL_NO_LIMIT>;
> };
> };
> };
> };
>
> cpu0_opp_table: opp_table0 {
> compatible = "operating-points-v2";
> opp-shared;
>
> opp-648000000 {
> opp-hz = /bits/ 64 <648000000>;
> opp-microvolt = <1040000>;
> clock-latency-ns = <244144>; /* 8 32k periods */
> };
> opp-792000000 {
> opp-hz = /bits/ 64 <792000000>;
> opp-microvolt = <1100000>;
> clock-latency-ns = <244144>; /* 8 32k periods */
> };
> opp-816000000 {
> opp-hz = /bits/ 64 <816000000>;
> opp-microvolt = <1100000>;
> clock-latency-ns = <244144>; /* 8 32k periods */
> };
> opp-912000000 {
> opp-hz = /bits/ 64 <912000000>;
> opp-microvolt = <1120000>;
> clock-latency-ns = <244144>; /* 8 32k periods */
> };
> opp-960000000 {
> opp-hz = /bits/ 64 <960000000>;
> opp-microvolt = <1160000>;
> clock-latency-ns = <244144>; /* 8 32k periods */
> };
> opp-1008000000 {
> opp-hz = /bits/ 64 <1008000000>;
> opp-microvolt = <1200000>;
> clock-latency-ns = <244144>; /* 8 32k periods */
> };
> opp-1056000000 {
> opp-hz = /bits/ 64 <1056000000>;
> opp-microvolt = <1240000>;
> clock-latency-ns = <244144>; /* 8 32k periods */
> };
> opp-1104000000 {
> opp-hz = /bits/ 64 <1104000000>;
> opp-microvolt = <1260000>;
> clock-latency-ns = <244144>; /* 8 32k periods */
> };
> opp-1152000000 {
> opp-hz = /bits/ 64 <1152000000>;
> opp-microvolt = <1300000>;
> clock-latency-ns = <244144>; /* 8 32k periods */
> };
> };
>
> --
> Krystian
It's a shame that mainline Linux still doesn't have this. But it is
hard to imagine a way to do the binding for the thermal sensors
differently.
I have committed this now. Sorry for the delay.
> Index: sys/dev/fdt/sxitemp.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/fdt/sxitemp.c,v
> retrieving revision 1.4
> diff -u -p -r1.4 sxitemp.c
> --- sys/dev/fdt/sxitemp.c 27 May 2018 21:59:26 -0000 1.4
> +++ sys/dev/fdt/sxitemp.c 6 Sep 2019 19:25:27 -0000
> @@ -28,6 +28,7 @@
> #include <dev/ofw/ofw_clock.h>
> #include <dev/ofw/ofw_misc.h>
> #include <dev/ofw/ofw_pinctrl.h>
> +#include <dev/ofw/ofw_thermal.h>
> #include <dev/ofw/fdt.h>
>
> /* Registers */
> @@ -63,6 +64,8 @@ struct sxitemp_softc {
>
> struct ksensor sc_sensors[3];
> struct ksensordev sc_sensordev;
> +
> + struct thermal_sensor sc_ts;
> };
>
> int sxitemp_match(struct device *, void *, void *);
> @@ -82,6 +85,7 @@ uint64_t sxitemp_a64_calc_temp(int64_t);
> uint64_t sxitemp_h5_calc_temp0(int64_t);
> uint64_t sxitemp_h5_calc_temp1(int64_t);
> void sxitemp_refresh_sensors(void *);
> +int32_t sxitemp_get_temperature(void *, uint32_t *);
>
> int
> sxitemp_match(struct device *parent, void *match, void *aux)
> @@ -172,6 +176,11 @@ sxitemp_attach(struct device *parent, st
> }
> sensordev_install(&sc->sc_sensordev);
> sensor_task_register(sc, sxitemp_refresh_sensors, 5);
> +
> + sc->sc_ts.ts_node = node;
> + sc->sc_ts.ts_cookie = sc;
> + sc->sc_ts.ts_get_temperature = sxitemp_get_temperature;
> + thermal_sensor_register(&sc->sc_ts);
> }
>
> uint64_t
> @@ -236,4 +245,25 @@ sxitemp_refresh_sensors(void *arg)
> sc->sc_sensors[2].value = sc->sc_calc_temp2(data) + 273150000;
> sc->sc_sensors[2].flags &= ~SENSOR_FINVALID;
> }
> +}
> +
> +int32_t
> +sxitemp_get_temperature(void *cookie, uint32_t *cells)
> +{
> + struct sxitemp_softc *sc = cookie;
> + uint32_t idx = cells[0];
> + uint32_t data;
> +
> + if (idx == 0 && sc->sc_calc_temp0) {
> + data = HREAD4(sc, THS0_DATA);
> + return sc->sc_calc_temp0(data);
> + } else if (idx == 1 && sc->sc_calc_temp1) {
> + data = HREAD4(sc, THS1_DATA);
> + return sc->sc_calc_temp1(data);
> + } else if (idx == 2 && sc->sc_calc_temp2) {
> + data = HREAD4(sc, THS2_DATA);
> + return sc->sc_calc_temp2(data);
> + }
> +
> + return THERMAL_SENSOR_MAX;
> }
>