Author: manu
Date: Mon Aug  6 05:36:00 2018
New Revision: 337372
URL: https://svnweb.freebsd.org/changeset/base/337372

Log:
  aw_thermal: Add nvmem and H5 support
  
  Now that aw_sid expose nvmem interface, use that to read the calibration
  data.
  Add support for H5 SoC.
  Fix the bindings, we used to have non-upstreamed bindings. Switch to the
  one that have been sent upstream. They are not stable yet, so we switch
  from custom, wrong, bindings to correct, proposed bindings

Modified:
  head/sys/arm/allwinner/aw_thermal.c

Modified: head/sys/arm/allwinner/aw_thermal.c
==============================================================================
--- head/sys/arm/allwinner/aw_thermal.c Mon Aug  6 05:35:24 2018        
(r337371)
+++ head/sys/arm/allwinner/aw_thermal.c Mon Aug  6 05:36:00 2018        
(r337372)
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
 #define         SENSOR1_EN             (1 << 1)
 #define         SENSOR0_EN             (1 << 0)
 #define        THS_INTC                0x44
+#define         THS_THERMAL_PER_SHIFT  12
 #define        THS_INTS                0x48
 #define         THS2_DATA_IRQ_STS      (1 << 10)
 #define         THS1_DATA_IRQ_STS      (1 << 9)
@@ -92,33 +93,49 @@ __FBSDID("$FreeBSD$");
 #define        THS_DATA2               0x88
 #define         DATA_MASK              0xfff
 
-#define        A83T_ADC_ACQUIRE_TIME   0x17
-#define        A83T_FILTER             0x4
-#define        A83T_INTC               0x1000
+#define        A83T_CLK_RATE           24000000
+#define        A83T_ADC_ACQUIRE_TIME   23      /* 24Mhz/(23 + 1) = 1us */
+#define        A83T_THERMAL_PER        1       /* 4096 * (1 + 1) / 24Mhz = 341 
us */
+#define        A83T_FILTER             0x5     /* Filter enabled, avg of 4 */
 #define        A83T_TEMP_BASE          2719000
 #define        A83T_TEMP_MUL           1000
 #define        A83T_TEMP_DIV           14186
-#define        A83T_CLK_RATE           24000000
 
-#define        A64_ADC_ACQUIRE_TIME    0x190
-#define        A64_FILTER              0x6
-#define        A64_INTC                0x18000
+#define        A64_CLK_RATE            4000000
+#define        A64_ADC_ACQUIRE_TIME    400     /* 4Mhz/(400 + 1) = 100 us */
+#define        A64_THERMAL_PER         24      /* 4096 * (24 + 1) / 4Mhz = 
25.6 ms */
+#define        A64_FILTER              0x6     /* Filter enabled, avg of 8 */
 #define        A64_TEMP_BASE           2170000
 #define        A64_TEMP_MUL            1000
 #define        A64_TEMP_DIV            8560
-#define        A64_CLK_RATE            4000000
 
+#define        H3_CLK_RATE             4000000
 #define        H3_ADC_ACQUIRE_TIME     0x3f
-#define        H3_FILTER               0x6
-#define        H3_INTC                 0x191000
+#define        H3_THERMAL_PER          401
+#define        H3_FILTER               0x6     /* Filter enabled, avg of 8 */
 #define        H3_TEMP_BASE            217
 #define        H3_TEMP_MUL             1000
 #define        H3_TEMP_DIV             8253
 #define        H3_TEMP_MINUS           1794000
-#define        H3_CLK_RATE             4000000
 #define        H3_INIT_ALARM           90      /* degC */
 #define        H3_INIT_SHUT            105     /* degC */
 
+#define        H5_CLK_RATE             24000000
+#define        H5_ADC_ACQUIRE_TIME     479     /* 24Mhz/479 = 20us */
+#define        H5_THERMAL_PER          58      /* 4096 * (58 + 1) / 24Mhz = 
10ms */
+#define        H5_FILTER               0x6     /* Filter enabled, avg of 8 */
+#define        H5_TEMP_BASE            233832448
+#define        H5_TEMP_MUL             124885
+#define        H5_TEMP_DIV             20
+#define        H5_TEMP_BASE_CPU        271581184
+#define        H5_TEMP_MUL_CPU         152253
+#define        H5_TEMP_BASE_GPU        289406976
+#define        H5_TEMP_MUL_GPU         166724
+#define        H5_INIT_CPU_ALARM       80      /* degC */
+#define        H5_INIT_CPU_SHUT        96      /* degC */
+#define        H5_INIT_GPU_ALARM       84      /* degC */
+#define        H5_INIT_GPU_SHUT        100     /* degC */
+
 #define        TEMP_C_TO_K             273
 #define        SENSOR_ENABLE_ALL       (SENSOR0_EN|SENSOR1_EN|SENSOR2_EN)
 #define        SHUT_INT_ALL            
(SHUT_INT0_STS|SHUT_INT1_STS|SHUT_INT2_STS)
@@ -147,9 +164,9 @@ struct aw_thermal_config {
        uint32_t                        adc_acquire_time;
        int                             adc_cali_en;
        uint32_t                        filter;
-       uint32_t                        intc;
-       int                             (*to_temp)(uint32_t);
-       uint32_t                        (*to_reg)(int);
+       uint32_t                        thermal_per;
+       int                             (*to_temp)(uint32_t, int);
+       uint32_t                        (*to_reg)(int, int);
        int                             temp_base;
        int                             temp_mul;
        int                             temp_div;
@@ -158,7 +175,7 @@ struct aw_thermal_config {
 };
 
 static int
-a83t_to_temp(uint32_t val)
+a83t_to_temp(uint32_t val, int sensor)
 {
        return ((A83T_TEMP_BASE - (val * A83T_TEMP_MUL)) / A83T_TEMP_DIV);
 }
@@ -183,14 +200,14 @@ static const struct aw_thermal_config a83t_config = {
        .adc_acquire_time = A83T_ADC_ACQUIRE_TIME,
        .adc_cali_en = 1,
        .filter = A83T_FILTER,
-       .intc = A83T_INTC,
+       .thermal_per = A83T_THERMAL_PER,
        .to_temp = a83t_to_temp,
        .calib0_mask = 0xffffffff,
-       .calib1_mask = 0xffffffff,
+       .calib1_mask = 0xffff,
 };
 
 static int
-a64_to_temp(uint32_t val)
+a64_to_temp(uint32_t val, int sensor)
 {
        return ((A64_TEMP_BASE - (val * A64_TEMP_MUL)) / A64_TEMP_DIV);
 }
@@ -213,19 +230,22 @@ static const struct aw_thermal_config a64_config = {
        },
        .clk_rate = A64_CLK_RATE,
        .adc_acquire_time = A64_ADC_ACQUIRE_TIME,
+       .adc_cali_en = 1,
        .filter = A64_FILTER,
-       .intc = A64_INTC,
+       .thermal_per = A64_THERMAL_PER,
        .to_temp = a64_to_temp,
+       .calib0_mask = 0xffffffff,
+       .calib1_mask = 0xffff,
 };
 
 static int
-h3_to_temp(uint32_t val)
+h3_to_temp(uint32_t val, int sensor)
 {
        return (H3_TEMP_BASE - ((val * H3_TEMP_MUL) / H3_TEMP_DIV));
 }
 
 static uint32_t
-h3_to_reg(int val)
+h3_to_reg(int val, int sensor)
 {
        return ((H3_TEMP_MINUS - (val * H3_TEMP_DIV)) / H3_TEMP_MUL);
 }
@@ -242,17 +262,93 @@ static const struct aw_thermal_config h3_config = {
        },
        .clk_rate = H3_CLK_RATE,
        .adc_acquire_time = H3_ADC_ACQUIRE_TIME,
+       .adc_cali_en = 1,
        .filter = H3_FILTER,
-       .intc = H3_INTC,
+       .thermal_per = H3_THERMAL_PER,
        .to_temp = h3_to_temp,
        .to_reg = h3_to_reg,
-       .calib0_mask = 0xfff,
+       .calib0_mask = 0xffff,
 };
 
+static int
+h5_to_temp(uint32_t val, int sensor)
+{
+       int tmp;
+
+       /* Temp is lower than 70 degrees */
+       if (val > 0x500) {
+               tmp = H5_TEMP_BASE - (val * H5_TEMP_MUL);
+               tmp >>= H5_TEMP_DIV;
+               return (tmp);
+       }
+
+       if (sensor == 0)
+               tmp = H5_TEMP_BASE_CPU - (val * H5_TEMP_MUL_CPU);
+       else if (sensor == 1)
+               tmp = H5_TEMP_BASE_GPU - (val * H5_TEMP_MUL_GPU);
+       else {
+               printf("Unknown sensor %d\n", sensor);
+               return (val);
+       }
+
+       tmp >>= H5_TEMP_DIV;
+       return (tmp);
+}
+
+static uint32_t
+h5_to_reg(int val, int sensor)
+{
+       int tmp;
+
+       if (val < 70) {
+               tmp = H5_TEMP_BASE - (val << H5_TEMP_DIV);
+               tmp /= H5_TEMP_MUL;
+       } else {
+               if (sensor == 0) {
+                       tmp = H5_TEMP_BASE_CPU - (val << H5_TEMP_DIV);
+                       tmp /= H5_TEMP_MUL_CPU;
+               } else if (sensor == 1) {
+                       tmp = H5_TEMP_BASE_GPU - (val << H5_TEMP_DIV);
+                       tmp /= H5_TEMP_MUL_GPU;
+               } else {
+                       printf("Unknown sensor %d\n", sensor);
+                       return (val);
+               }
+       }
+
+       return ((uint32_t)tmp);
+}
+
+static const struct aw_thermal_config h5_config = {
+       .nsensors = 2,
+       .sensors = {
+               [0] = {
+                       .name = "cpu",
+                       .desc = "CPU temperature",
+                       .init_alarm = H5_INIT_CPU_ALARM,
+                       .init_shut = H5_INIT_CPU_SHUT,
+               },
+               [1] = {
+                       .name = "gpu",
+                       .desc = "GPU temperature",
+                       .init_alarm = H5_INIT_GPU_ALARM,
+                       .init_shut = H5_INIT_GPU_SHUT,
+               },
+       },
+       .clk_rate = H5_CLK_RATE,
+       .adc_acquire_time = H5_ADC_ACQUIRE_TIME,
+       .filter = H5_FILTER,
+       .thermal_per = H5_THERMAL_PER,
+       .to_temp = h5_to_temp,
+       .to_reg = h5_to_reg,
+       .calib0_mask = 0xffffffff,
+};
+
 static struct ofw_compat_data compat_data[] = {
-       { "allwinner,sun8i-a83t-ts",    (uintptr_t)&a83t_config },
-       { "allwinner,sun8i-h3-ts",      (uintptr_t)&h3_config },
-       { "allwinner,sun50i-a64-ts",    (uintptr_t)&a64_config },
+       { "allwinner,sun8i-a83t-ths",   (uintptr_t)&a83t_config },
+       { "allwinner,sun8i-h3-ths",     (uintptr_t)&h3_config },
+       { "allwinner,sun50i-a64-ths",   (uintptr_t)&a64_config },
+       { "allwinner,sun50i-h5-ths",    (uintptr_t)&h5_config },
        { NULL,                         (uintptr_t)NULL }
 };
 
@@ -269,6 +365,9 @@ struct aw_thermal_softc {
        int                             min_freq;
        struct cf_level                 levels[MAX_CF_LEVELS];
        eventhandler_tag                cf_pre_tag;
+
+       clk_t                           clk_apb;
+       clk_t                           clk_ths;
 };
 
 static struct resource_spec aw_thermal_spec[] = {
@@ -288,39 +387,41 @@ aw_thermal_init(struct aw_thermal_softc *sc)
        int error;
 
        node = ofw_bus_get_node(sc->dev);
-       if (sc->conf->calib0_mask != 0 || sc->conf->calib1_mask != 0) {
-               error = nvmem_read_cell_by_name(node, "ths_calibration",
-                   (void *)calib, sizeof(calib));
-               /* Read calibration settings from EFUSE */
-               if (error != 0) {
-                       device_printf(sc->dev, "Cannot read THS efuse\n");
-                       return (error);
-               }
+       if (nvmem_get_cell_len(node, "ths-calib") > sizeof(calib)) {
+               device_printf(sc->dev, "ths-calib nvmem cell is too large\n");
+               return (ENXIO);
+       }
+       error = nvmem_read_cell_by_name(node, "ths-calib",
+           (void *)&calib, nvmem_get_cell_len(node, "ths-calib"));
+       /* Read calibration settings from EFUSE */
+       if (error != 0) {
+               device_printf(sc->dev, "Cannot read THS efuse\n");
+               return (error);
+       }
 
-               device_printf(sc->dev, "calib0: %x\n", calib[0]);
-               device_printf(sc->dev, "calib1: %x\n", calib[1]);
+       calib[0] &= sc->conf->calib0_mask;
+       calib[1] &= sc->conf->calib1_mask;
 
-               calib[0] &= sc->conf->calib0_mask;
-               calib[1] &= sc->conf->calib1_mask;
+       /* Write calibration settings to thermal controller */
+       if (calib[0] != 0)
+               WR4(sc, THS_CALIB0, calib[0]);
+       if (calib[1] != 0)
+               WR4(sc, THS_CALIB1, calib[1]);
 
-               /* Write calibration settings to thermal controller */
-               if (calib[0] != 0)
-                       WR4(sc, THS_CALIB0, calib[0]);
-               if (calib[1] != 0)
-                       WR4(sc, THS_CALIB1, calib[1]);
-       }
-
        /* Configure ADC acquire time (CLK_IN/(N+1)) and enable sensors */
        WR4(sc, THS_CTRL1, ADC_CALI_EN);
        WR4(sc, THS_CTRL0, sc->conf->adc_acquire_time);
        WR4(sc, THS_CTRL2, sc->conf->adc_acquire_time << SENSOR_ACQ1_SHIFT);
 
+       /* Set thermal period */
+       WR4(sc, THS_INTC, sc->conf->thermal_per << THS_THERMAL_PER_SHIFT);
+
        /* Enable average filter */
        WR4(sc, THS_FILTER, sc->conf->filter);
 
        /* Enable interrupts */
        WR4(sc, THS_INTS, RD4(sc, THS_INTS));
-       WR4(sc, THS_INTC, sc->conf->intc | SHUT_INT_ALL | ALARM_INT_ALL);
+       WR4(sc, THS_INTC, RD4(sc, THS_INTC) | SHUT_INT_ALL | ALARM_INT_ALL);
 
        /* Enable sensors */
        WR4(sc, THS_CTRL2, RD4(sc, THS_CTRL2) | SENSOR_ENABLE_ALL);
@@ -335,7 +436,7 @@ aw_thermal_gettemp(struct aw_thermal_softc *sc, int se
 
        val = RD4(sc, THS_DATA0 + (sensor * 4));
 
-       return (sc->conf->to_temp(val));
+       return (sc->conf->to_temp(val, sensor));
 }
 
 static int
@@ -346,7 +447,7 @@ aw_thermal_getshut(struct aw_thermal_softc *sc, int se
        val = RD4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4));
        val = (val >> SHUT_T_HOT_SHIFT) & SHUT_T_HOT_MASK;
 
-       return (sc->conf->to_temp(val));
+       return (sc->conf->to_temp(val, sensor));
 }
 
 static void
@@ -356,7 +457,7 @@ aw_thermal_setshut(struct aw_thermal_softc *sc, int se
 
        val = RD4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4));
        val &= ~(SHUT_T_HOT_MASK << SHUT_T_HOT_SHIFT);
-       val |= (sc->conf->to_reg(temp) << SHUT_T_HOT_SHIFT);
+       val |= (sc->conf->to_reg(temp, sensor) << SHUT_T_HOT_SHIFT);
        WR4(sc, THS_SHUTDOWN0_CTRL + (sensor * 4), val);
 }
 
@@ -368,7 +469,7 @@ aw_thermal_gethyst(struct aw_thermal_softc *sc, int se
        val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4));
        val = (val >> ALARM_T_HYST_SHIFT) & ALARM_T_HYST_MASK;
 
-       return (sc->conf->to_temp(val));
+       return (sc->conf->to_temp(val, sensor));
 }
 
 static int
@@ -379,7 +480,7 @@ aw_thermal_getalarm(struct aw_thermal_softc *sc, int s
        val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4));
        val = (val >> ALARM_T_HOT_SHIFT) & ALARM_T_HOT_MASK;
 
-       return (sc->conf->to_temp(val));
+       return (sc->conf->to_temp(val, sensor));
 }
 
 static void
@@ -389,7 +490,7 @@ aw_thermal_setalarm(struct aw_thermal_softc *sc, int s
 
        val = RD4(sc, THS_ALARM0_CTRL + (sensor * 4));
        val &= ~(ALARM_T_HOT_MASK << ALARM_T_HOT_SHIFT);
-       val |= (sc->conf->to_reg(temp) << ALARM_T_HOT_SHIFT);
+       val |= (sc->conf->to_reg(temp, sensor) << ALARM_T_HOT_SHIFT);
        WR4(sc, THS_ALARM0_CTRL + (sensor * 4), val);
 }
 
@@ -506,13 +607,12 @@ static int
 aw_thermal_attach(device_t dev)
 {
        struct aw_thermal_softc *sc;
-       clk_t clk_ahb, clk_ths;
        hwreset_t rst;
        int i, error;
        void *ih;
 
        sc = device_get_softc(dev);
-       clk_ahb = clk_ths = NULL;
+       sc->dev = dev;
        rst = NULL;
        ih = NULL;
 
@@ -524,25 +624,27 @@ aw_thermal_attach(device_t dev)
                return (ENXIO);
        }
 
-       if (clk_get_by_ofw_name(dev, 0, "ahb", &clk_ahb) == 0) {
-               error = clk_enable(clk_ahb);
+       if (clk_get_by_ofw_name(dev, 0, "apb", &sc->clk_apb) == 0) {
+               error = clk_enable(sc->clk_apb);
                if (error != 0) {
-                       device_printf(dev, "cannot enable ahb clock\n");
+                       device_printf(dev, "cannot enable apb clock\n");
                        goto fail;
                }
        }
-       if (clk_get_by_ofw_name(dev, 0, "ths", &clk_ths) == 0) {
-               error = clk_set_freq(clk_ths, sc->conf->clk_rate, 0);
+
+       if (clk_get_by_ofw_name(dev, 0, "ths", &sc->clk_ths) == 0) {
+               error = clk_set_freq(sc->clk_ths, sc->conf->clk_rate, 0);
                if (error != 0) {
                        device_printf(dev, "cannot set ths clock rate\n");
                        goto fail;
                }
-               error = clk_enable(clk_ths);
+               error = clk_enable(sc->clk_ths);
                if (error != 0) {
                        device_printf(dev, "cannot enable ths clock\n");
                        goto fail;
                }
        }
+
        if (hwreset_get_by_ofw_idx(dev, 0, 0, &rst) == 0) {
                error = hwreset_deassert(rst);
                if (error != 0) {
@@ -581,7 +683,8 @@ aw_thermal_attach(device_t dev)
        if (bootverbose)
                for (i = 0; i < sc->conf->nsensors; i++) {
                        device_printf(dev,
-                           "#%d: alarm %dC hyst %dC shut %dC\n", i,
+                           "%s: alarm %dC hyst %dC shut %dC\n",
+                           sc->conf->sensors[i].name,
                            aw_thermal_getalarm(sc, i),
                            aw_thermal_gethyst(sc, i),
                            aw_thermal_getshut(sc, i));
@@ -597,10 +700,10 @@ fail:
                bus_teardown_intr(dev, sc->res[1], ih);
        if (rst != NULL)
                hwreset_release(rst);
-       if (clk_ahb != NULL)
-               clk_release(clk_ahb);
-       if (clk_ths != NULL)
-               clk_release(clk_ths);
+       if (sc->clk_apb != NULL)
+               clk_release(sc->clk_apb);
+       if (sc->clk_ths != NULL)
+               clk_release(sc->clk_ths);
        bus_release_resources(dev, aw_thermal_spec, sc->res);
 
        return (ENXIO);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to