Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/sunxi Add driver for thermal sensor controller ...



details:   https://anonhg.NetBSD.org/src/rev/70d12ea07a3a
branches:  trunk
changeset: 826907:70d12ea07a3a
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Thu Oct 05 01:30:26 2017 +0000

description:
Add driver for thermal sensor controller found in Allwinner H3, A64, and
A83T SoCs.

diffstat:

 sys/arch/arm/sunxi/files.sunxi     |    7 +-
 sys/arch/arm/sunxi/sunxi_thermal.c |  572 +++++++++++++++++++++++++++++++++++++
 2 files changed, 578 insertions(+), 1 deletions(-)

diffs (truncated from 597 to 300 lines):

diff -r c0f90f3875e7 -r 70d12ea07a3a sys/arch/arm/sunxi/files.sunxi
--- a/sys/arch/arm/sunxi/files.sunxi    Thu Oct 05 01:29:49 2017 +0000
+++ b/sys/arch/arm/sunxi/files.sunxi    Thu Oct 05 01:30:26 2017 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.sunxi,v 1.25 2017/10/03 23:42:17 jmcneill Exp $
+#      $NetBSD: files.sunxi,v 1.26 2017/10/05 01:30:26 jmcneill Exp $
 #
 # Configuration info for Allwinner sunxi family SoCs
 #
@@ -174,6 +174,11 @@
 attach sunxisid at fdt with sunxi_sid
 file   arch/arm/sunxi/sunxi_sid.c              sunxi_sid
 
+# Thermal sensor controller
+device sunxithermal: sysmon_envsys, sysmon_taskq
+attach sunxithermal at fdt with sunxi_thermal
+file   arch/arm/sunxi/sunxi_thermal.c          sunxi_thermal
+
 # SOC parameters
 defflag        opt_soc.h                       SOC_SUNXI
 defflag        opt_soc.h                       SOC_SUN5I: SOC_SUNXI
diff -r c0f90f3875e7 -r 70d12ea07a3a sys/arch/arm/sunxi/sunxi_thermal.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/sunxi/sunxi_thermal.c        Thu Oct 05 01:30:26 2017 +0000
@@ -0,0 +1,572 @@
+/* $NetBSD: sunxi_thermal.c,v 1.1 2017/10/05 01:30:26 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2016-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Allwinner thermal sensor controller
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sunxi_thermal.c,v 1.1 2017/10/05 01:30:26 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/reboot.h>
+
+#include <dev/sysmon/sysmonvar.h>
+#include <dev/sysmon/sysmon_taskq.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/sunxi/sunxi_sid.h>
+
+#define        THS_CTRL0               0x00
+#define        THS_CTRL1               0x04
+#define         ADC_CALI_EN            (1 << 17)
+#define        THS_CTRL2               0x40
+#define         SENSOR_ACQ1_SHIFT      16
+#define         SENSOR2_EN             (1 << 2)
+#define         SENSOR1_EN             (1 << 1)
+#define         SENSOR0_EN             (1 << 0)
+#define        THS_INTC                0x44
+#define        THS_INTS                0x48
+#define         THS2_DATA_IRQ_STS      (1 << 10)
+#define         THS1_DATA_IRQ_STS      (1 << 9)
+#define         THS0_DATA_IRQ_STS      (1 << 8)
+#define         SHUT_INT2_STS          (1 << 6)
+#define         SHUT_INT1_STS          (1 << 5)
+#define         SHUT_INT0_STS          (1 << 4)
+#define         ALARM_INT2_STS         (1 << 2)
+#define         ALARM_INT1_STS         (1 << 1)
+#define         ALARM_INT0_STS         (1 << 0)
+#define        THS_ALARM0_CTRL         0x50
+#define         ALARM_T_HOT_MASK       0xfff
+#define         ALARM_T_HOT_SHIFT      16
+#define         ALARM_T_HYST_MASK      0xfff
+#define         ALARM_T_HYST_SHIFT     0
+#define        THS_SHUTDOWN0_CTRL      0x60
+#define         SHUT_T_HOT_MASK        0xfff
+#define         SHUT_T_HOT_SHIFT       16
+#define        THS_FILTER              0x70
+#define        THS_CALIB0              0x74
+#define        THS_CALIB1              0x78
+#define        THS_DATA0               0x80
+#define        THS_DATA1               0x84
+#define        THS_DATA2               0x88
+#define         DATA_MASK              0xfff
+
+#define        A83T_ADC_ACQUIRE_TIME   0x17
+#define        A83T_FILTER             0x4
+#define        A83T_INTC               0x1000
+#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_TEMP_BASE           2170000
+#define        A64_TEMP_MUL            1000
+#define        A64_TEMP_DIV            8560
+#define        A64_CLK_RATE            4000000
+
+#define        H3_ADC_ACQUIRE_TIME     0x3f
+#define        H3_FILTER               0x6
+#define        H3_INTC                 0x191000
+#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        TEMP_C_TO_K             273150000
+#define        SENSOR_ENABLE_ALL       (SENSOR0_EN|SENSOR1_EN|SENSOR2_EN)
+#define        SHUT_INT_ALL            (SHUT_INT0_STS|SHUT_INT1_STS|SHUT_INT2_STS)
+#define        ALARM_INT_ALL           (ALARM_INT0_STS)
+
+#define        MAX_SENSORS     3
+
+#if notyet
+#define        THROTTLE_ENABLE_DEFAULT 1
+
+/* Enable thermal throttling */
+static int sunxi_thermal_throttle_enable = THROTTLE_ENABLE_DEFAULT;
+#endif
+
+struct sunxi_thermal_sensor {
+       const char              *name;
+       const char              *desc;
+       int                     init_alarm;
+       int                     init_shut;
+};
+
+struct sunxi_thermal_config {
+       struct sunxi_thermal_sensor     sensors[MAX_SENSORS];
+       int                             nsensors;
+       uint64_t                        clk_rate;
+       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);
+       int                             temp_base;
+       int                             temp_mul;
+       int                             temp_div;
+       int                             calib0, calib1;
+       uint32_t                        calib0_mask, calib1_mask;
+};
+
+static int
+a83t_to_temp(uint32_t val)
+{
+       return ((A83T_TEMP_BASE - (val * A83T_TEMP_MUL)) / A83T_TEMP_DIV);
+}
+
+static const struct sunxi_thermal_config a83t_config = {
+       .nsensors = 3,
+       .sensors = {
+               [0] = {
+                       .name = "cluster0",
+                       .desc = "CPU cluster 0 temperature",
+               },
+               [1] = {
+                       .name = "cluster1",
+                       .desc = "CPU cluster 1 temperature",
+               },
+               [2] = {
+                       .name = "gpu",
+                       .desc = "GPU temperature",
+               },
+       },
+       .clk_rate = A83T_CLK_RATE,
+       .adc_acquire_time = A83T_ADC_ACQUIRE_TIME,
+       .adc_cali_en = 1,
+       .filter = A83T_FILTER,
+       .intc = A83T_INTC,
+       .to_temp = a83t_to_temp,
+       .calib0_mask = 0xffffffff,
+       .calib1_mask = 0xffffffff,
+};
+
+static int
+a64_to_temp(uint32_t val)
+{
+       return ((A64_TEMP_BASE - (val * A64_TEMP_MUL)) / A64_TEMP_DIV);
+}
+
+static const struct sunxi_thermal_config a64_config = {
+       .nsensors = 3,
+       .sensors = {
+               [0] = {
+                       .name = "cpu",
+                       .desc = "CPU temperature",
+               },
+               [1] = {
+                       .name = "gpu1",
+                       .desc = "GPU temperature 1",
+               },
+               [2] = {
+                       .name = "gpu2",
+                       .desc = "GPU temperature 2",
+               },
+       },
+       .clk_rate = A64_CLK_RATE,
+       .adc_acquire_time = A64_ADC_ACQUIRE_TIME,
+       .filter = A64_FILTER,
+       .intc = A64_INTC,
+       .to_temp = a64_to_temp,
+};
+
+static int
+h3_to_temp(uint32_t val)
+{
+       return (H3_TEMP_BASE - ((val * H3_TEMP_MUL) / H3_TEMP_DIV));
+}
+
+static uint32_t
+h3_to_reg(int val)
+{
+       return ((H3_TEMP_MINUS - (val * H3_TEMP_DIV)) / H3_TEMP_MUL);
+}
+
+static const struct sunxi_thermal_config h3_config = {
+       .nsensors = 1,
+       .sensors = {
+               [0] = {
+                       .name = "cpu",
+                       .desc = "CPU temperature",
+                       .init_alarm = H3_INIT_ALARM,
+                       .init_shut = H3_INIT_SHUT,
+               },
+       },
+       .clk_rate = H3_CLK_RATE,
+       .adc_acquire_time = H3_ADC_ACQUIRE_TIME,
+       .filter = H3_FILTER,
+       .intc = H3_INTC,
+       .to_temp = h3_to_temp,
+       .to_reg = h3_to_reg,
+       .calib0_mask = 0xfff,
+};
+
+static struct of_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 },
+       { NULL,                         (uintptr_t)NULL }
+};
+
+struct sunxi_thermal_softc {
+       device_t                        dev;
+       int                             phandle;
+       bus_space_tag_t                 bst;
+       bus_space_handle_t              bsh;
+       struct sunxi_thermal_config     *conf;
+
+       kmutex_t                        lock;
+       callout_t                       tick;
+
+       struct sysmon_envsys            *sme;
+       envsys_data_t                   data[MAX_SENSORS];
+};
+
+#define        RD4(sc, reg)            \
+       bus_space_read_4((sc)->bst, (sc)->bsh, (reg))
+#define        WR4(sc, reg, val)       \
+       bus_space_write_4((sc)->bst, (sc)->bsh, (reg), (val))
+
+static int
+sunxi_thermal_init(struct sunxi_thermal_softc *sc)
+{
+       uint32_t calib[2];
+       int error;
+
+       if (sc->conf->calib0_mask != 0 || sc->conf->calib1_mask != 0) {
+               /* Read calibration settings from SRAM */
+               error = sunxi_sid_read_tscalib(calib);



Home | Main Index | Thread Index | Old Index