Author: jmcneill
Date: Sat Sep  3 15:26:00 2016
New Revision: 305352
URL: https://svnweb.freebsd.org/changeset/base/305352

Log:
  Add support for Allwinner A64 thermal sensors.

Added:
  head/sys/arm/allwinner/clk/aw_thsclk.c   (contents, props changed)
Modified:
  head/sys/arm/allwinner/aw_thermal.c
  head/sys/arm64/conf/GENERIC
  head/sys/conf/files.arm64

Modified: head/sys/arm/allwinner/aw_thermal.c
==============================================================================
--- head/sys/arm/allwinner/aw_thermal.c Sat Sep  3 15:24:30 2016        
(r305351)
+++ head/sys/arm/allwinner/aw_thermal.c Sat Sep  3 15:26:00 2016        
(r305352)
@@ -39,15 +39,21 @@ __FBSDID("$FreeBSD$");
 #include <sys/rman.h>
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
+#include <sys/reboot.h>
 #include <sys/module.h>
 #include <machine/bus.h>
 
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
 
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+
 #include <arm/allwinner/aw_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)
@@ -55,8 +61,16 @@ __FBSDID("$FreeBSD$");
 #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_FILTER              0x70
-#define         FILTER_EN              (1 << 2)
 #define        THS_CALIB0              0x74
 #define        THS_CALIB1              0x78
 #define        THS_DATA0               0x80
@@ -64,38 +78,93 @@ __FBSDID("$FreeBSD$");
 #define        THS_DATA2               0x88
 #define         DATA_MASK              0xfff
 
-#define        TEMP_BASE               2719
-#define        TEMP_MUL                1000
-#define        TEMP_DIV                14186
-#define        TEMP_TO_K               273
-#define        ADC_ACQUIRE_TIME        (24 - 1)
+#define        A83T_ADC_ACQUIRE_TIME   0x17
+#define        A83T_FILTER             0x4
+#define        A83T_INTC               0x1000
+#define        A83T_TEMP_BASE          2719000
+#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_DIV            8560
+#define        A64_CLK_RATE            4000000
+
+#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)
 
-enum aw_thermal_sensor {
-       THS_SENSOR_CPU_CLUSTER0,
-       THS_SENSOR_CPU_CLUSTER1,
-       THS_SENSOR_GPU,
-       THS_SENSOR_END = -1
-};
+#define        MAX_SENSORS     3
 
-struct aw_thermal_sensor_config {
-       enum aw_thermal_sensor  sensor;
+struct aw_thermal_sensor {
        const char              *name;
        const char              *desc;
 };
 
-static const struct aw_thermal_sensor_config a83t_sensor_config[] = {
-       { .sensor = THS_SENSOR_CPU_CLUSTER0,
-         .name = "cluster0",   .desc = "CPU cluster 0 temperature" },
-       { .sensor = THS_SENSOR_CPU_CLUSTER1,
-         .name = "cluster1",   .desc = "CPU cluster 1 temperature" },
-       { .sensor = THS_SENSOR_GPU,
-         .name = "gpu",        .desc = "GPU temperature" },
-       { .sensor = THS_SENSOR_END }
+struct aw_thermal_config {
+       struct aw_thermal_sensor        sensors[MAX_SENSORS];
+       int                             nsensors;
+       uint64_t                        clk_rate;
+       uint32_t                        adc_acquire_time;
+       uint32_t                        filter;
+       uint32_t                        intc;
+       uint32_t                        temp_base;
+       uint32_t                        temp_div;
+};
+
+static const struct aw_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,
+       .filter = A83T_FILTER,
+       .intc = A83T_INTC,
+       .temp_base = A83T_TEMP_BASE,
+       .temp_div = A83T_TEMP_DIV,
+};
+
+static const struct aw_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,
+       .temp_base = A64_TEMP_BASE,
+       .temp_div = A64_TEMP_DIV,
 };
 
 static struct ofw_compat_data compat_data[] = {
-       { "allwinner,sun8i-a83t-ts",    (uintptr_t)&a83t_sensor_config },
+       { "allwinner,sun8i-a83t-ts",    (uintptr_t)&a83t_config },
+       { "allwinner,sun50i-a64-ts",    (uintptr_t)&a64_config },
        { NULL,                         (uintptr_t)NULL }
 };
 
@@ -103,17 +172,18 @@ static struct ofw_compat_data compat_dat
        (void *)ofw_bus_search_compatible((d), compat_data)->ocd_data
 
 struct aw_thermal_softc {
-       struct resource                 *res;
-       struct aw_thermal_sensor_config *conf;
+       struct resource                 *res[2];
+       struct aw_thermal_config        *conf;
 };
 
 static struct resource_spec aw_thermal_spec[] = {
        { SYS_RES_MEMORY,       0,      RF_ACTIVE },
+       { SYS_RES_IRQ,          0,      RF_ACTIVE },
        { -1, 0 }
 };
 
-#define        RD4(sc, reg)            bus_read_4((sc)->res, (reg))
-#define        WR4(sc, reg, val)       bus_write_4((sc)->res, (reg), (val))
+#define        RD4(sc, reg)            bus_read_4((sc)->res[0], (reg))
+#define        WR4(sc, reg, val)       bus_write_4((sc)->res[0], (reg), (val))
 
 static int
 aw_thermal_init(struct aw_thermal_softc *sc)
@@ -131,44 +201,73 @@ aw_thermal_init(struct aw_thermal_softc 
        WR4(sc, THS_CALIB1, calib1);
 
        /* Configure ADC acquire time (CLK_IN/(N+1)) and enable sensors */
-       WR4(sc, THS_CTRL0, ADC_ACQUIRE_TIME);
-       WR4(sc, THS_CTRL2, (ADC_ACQUIRE_TIME << SENSOR_ACQ1_SHIFT) |
-           SENSOR_ENABLE_ALL);
+       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);
+
+       /* Enable average filter */
+       WR4(sc, THS_FILTER, sc->conf->filter);
 
-       /* Disable interrupts */
-       WR4(sc, THS_INTC, 0);
+       /* Enable interrupts */
        WR4(sc, THS_INTS, RD4(sc, THS_INTS));
+       WR4(sc, THS_INTC, sc->conf->intc | SHUT_INT_ALL);
 
-       /* Enable average filter */
-       WR4(sc, THS_FILTER, RD4(sc, THS_FILTER) | FILTER_EN);
+       /* Enable sensors */
+       WR4(sc, THS_CTRL2, RD4(sc, THS_CTRL2) | SENSOR_ENABLE_ALL);
 
        return (0);
 }
 
 static int
-aw_thermal_gettemp(uint32_t val)
+aw_thermal_reg_to_temp(struct aw_thermal_softc *sc, uint32_t val)
+{
+       return ((sc->conf->temp_base - val * 1000) / sc->conf->temp_div);
+}
+
+static int
+aw_thermal_gettemp(struct aw_thermal_softc *sc, int sensor)
 {
-       int raw;
+       uint32_t val;
+
+       val = RD4(sc, THS_DATA0 + (sensor * 4));
 
-       raw = val & DATA_MASK;
-       return (((TEMP_BASE - raw) * TEMP_MUL) / TEMP_DIV) + TEMP_TO_K;
+       return (aw_thermal_reg_to_temp(sc, val) + TEMP_C_TO_K);
 }
 
 static int
 aw_thermal_sysctl(SYSCTL_HANDLER_ARGS)
 {
        struct aw_thermal_softc *sc;
-       enum aw_thermal_sensor sensor;
-       int val;
+       int sensor, val;
 
        sc = arg1;
        sensor = arg2;
 
-       val = aw_thermal_gettemp(RD4(sc, THS_DATA0 + (sensor * 4)));
+       val = aw_thermal_gettemp(sc, sensor);
 
        return sysctl_handle_opaque(oidp, &val, sizeof(val), req);
 }
 
+static void
+aw_thermal_intr(void *arg)
+{
+       struct aw_thermal_softc *sc;
+       device_t dev;
+       uint32_t ints;
+
+       dev = arg;
+       sc = device_get_softc(dev);
+
+       ints = RD4(sc, THS_INTS);
+       WR4(sc, THS_INTS, ints);
+
+       if ((ints & SHUT_INT_ALL) != 0) {
+               device_printf(dev,
+                  "WARNING - current temperature exceeds safe limits\n");
+               shutdown_nice(RB_POWEROFF);
+       }
+}
+
 static int
 aw_thermal_probe(device_t dev)
 {
@@ -186,29 +285,82 @@ static int
 aw_thermal_attach(device_t dev)
 {
        struct aw_thermal_softc *sc;
-       int i;
+       clk_t clk_ahb, clk_ths;
+       hwreset_t rst;
+       int i, error;
+       void *ih;
 
        sc = device_get_softc(dev);
+       clk_ahb = clk_ths = NULL;
+       rst = NULL;
+       ih = NULL;
 
        sc->conf = THS_CONF(dev);
 
-       if (bus_alloc_resources(dev, aw_thermal_spec, &sc->res) != 0) {
+       if (bus_alloc_resources(dev, aw_thermal_spec, sc->res) != 0) {
                device_printf(dev, "cannot allocate resources for device\n");
                return (ENXIO);
        }
 
+       if (clk_get_by_ofw_name(dev, 0, "ahb", &clk_ahb) == 0) {
+               error = clk_enable(clk_ahb);
+               if (error != 0) {
+                       device_printf(dev, "cannot enable ahb 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 (error != 0) {
+                       device_printf(dev, "cannot set ths clock rate\n");
+                       goto fail;
+               }
+               error = clk_enable(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) {
+                       device_printf(dev, "cannot de-assert reset\n");
+                       goto fail;
+               }
+       }
+
+       error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
+           NULL, aw_thermal_intr, dev, &ih);
+       if (error != 0) {
+               device_printf(dev, "cannot setup interrupt handler\n");
+               goto fail;
+       }
+
        if (aw_thermal_init(sc) != 0)
-               return (ENXIO);
+               goto fail;
 
-       for (i = 0; sc->conf[i].sensor != THS_SENSOR_END; i++)
+       for (i = 0; i < sc->conf->nsensors; i++)
                SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
                    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-                   OID_AUTO, sc->conf[i].name,
+                   OID_AUTO, sc->conf->sensors[i].name,
                    CTLTYPE_INT | CTLFLAG_RD,
-                   sc, sc->conf[i].sensor, aw_thermal_sysctl, "IK0",
-                   sc->conf[i].desc);
+                   sc, i, aw_thermal_sysctl, "IK0",
+                   sc->conf->sensors[i].desc);
 
        return (0);
+
+fail:
+       if (ih != NULL)
+               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);
+       bus_release_resources(dev, aw_thermal_spec, sc->res);
+
+       return (ENXIO);
 }
 
 static device_method_t aw_thermal_methods[] = {

Added: head/sys/arm/allwinner/clk/aw_thsclk.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/arm/allwinner/clk/aw_thsclk.c      Sat Sep  3 15:26:00 2016        
(r305352)
@@ -0,0 +1,320 @@
+/*-
+ * Copyright (c) 2016 Jared McNeill <jmcne...@invisible.ca>
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Allwinner THS clocks
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofw_subr.h>
+
+#include <dev/extres/clk/clk_mux.h>
+#include <dev/extres/clk/clk_gate.h>
+
+#include "clkdev_if.h"
+
+#define        SCLK_GATING             (1 << 31)
+#define        CLK_SRC_SEL             (0x3 << 24)
+#define        CLK_SRC_SEL_SHIFT       24
+#define        CLK_SRC_SEL_MAX         1
+#define        CLK_DIV_RATIO           (0x3 << 0)
+#define        CLK_DIV_RATIO_SHIFT     0
+#define        CLK_DIV_RATIO_MAX       3
+
+static struct ofw_compat_data compat_data[] = {
+       { "allwinner,sun50i-a64-ths-clk",       1 },
+       { NULL, 0 }
+};
+
+struct aw_thsclk_sc {
+       device_t        clkdev;
+       bus_addr_t      reg;
+};
+
+#define        THSCLK_READ(sc, val)    CLKDEV_READ_4((sc)->clkdev, (sc)->reg, 
(val))
+#define        THSCLK_WRITE(sc, val)   CLKDEV_WRITE_4((sc)->clkdev, (sc)->reg, 
(val))
+#define        DEVICE_LOCK(sc)         CLKDEV_DEVICE_LOCK((sc)->clkdev)
+#define        DEVICE_UNLOCK(sc)       CLKDEV_DEVICE_UNLOCK((sc)->clkdev)
+
+static int
+aw_thsclk_init(struct clknode *clk, device_t dev)
+{
+       struct aw_thsclk_sc *sc;
+       uint32_t val, index;
+
+       sc = clknode_get_softc(clk);
+
+       DEVICE_LOCK(sc);
+       THSCLK_READ(sc, &val);
+       DEVICE_UNLOCK(sc);
+
+       index = (val & CLK_SRC_SEL) >> CLK_SRC_SEL_SHIFT;
+
+       clknode_init_parent_idx(clk, index);
+       return (0);
+}
+
+static int
+aw_thsclk_set_mux(struct clknode *clk, int index)
+{
+       struct aw_thsclk_sc *sc;
+       uint32_t val;
+
+       sc = clknode_get_softc(clk);
+
+       if (index < 0 || index >= CLK_SRC_SEL_MAX)
+               return (ERANGE);
+
+       DEVICE_LOCK(sc);
+       THSCLK_READ(sc, &val);
+       val &= ~CLK_SRC_SEL;
+       val |= (index << CLK_SRC_SEL_SHIFT);
+       THSCLK_WRITE(sc, val);
+       DEVICE_UNLOCK(sc);
+
+       return (0);
+}
+
+static int
+aw_thsclk_set_gate(struct clknode *clk, bool enable)
+{
+       struct aw_thsclk_sc *sc;
+       uint32_t val;
+
+       sc = clknode_get_softc(clk);
+
+       DEVICE_LOCK(sc);
+       THSCLK_READ(sc, &val);
+       if (enable)
+               val |= SCLK_GATING;
+       else
+               val &= ~SCLK_GATING;
+       THSCLK_WRITE(sc, val);
+       DEVICE_UNLOCK(sc);
+
+       return (0);
+}
+
+static int
+aw_thsclk_recalc_freq(struct clknode *clk, uint64_t *freq)
+{
+       struct aw_thsclk_sc *sc;
+       uint32_t val, div;
+
+       sc = clknode_get_softc(clk);
+
+       DEVICE_LOCK(sc);
+       THSCLK_READ(sc, &val);
+       DEVICE_UNLOCK(sc);
+
+       switch (val & CLK_DIV_RATIO) {
+       case 3:
+               div = 6;
+               break;
+       default:
+               div = 1 << (val & CLK_DIV_RATIO);
+               break;
+       }
+
+       *freq = *freq / div;
+
+       return (0);
+}
+
+static int
+aw_thsclk_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
+    int flags, int *stop)
+{
+       struct aw_thsclk_sc *sc;
+       uint32_t val, div, n, best_div, best_n;
+       uint64_t cur_freq;
+       int64_t best_diff, cur_diff;
+
+       sc = clknode_get_softc(clk);
+       best_diff = (int64_t)*fout; 
+       best_n = 0;
+
+       for (div = 0; div <= CLK_DIV_RATIO_MAX; div++) {
+               n = (div == 3) ? 6 : (1 << div);
+               cur_freq = fin / n;
+               cur_diff = (int64_t)*fout - cur_freq;
+               if (cur_diff >= 0 && cur_diff < best_diff) {
+                       best_diff = cur_diff;
+                       best_div = div;
+                       best_n = n;
+               }
+       }
+
+       if (best_diff == (int64_t)*fout || best_n == 0)
+               return (ERANGE);
+
+       DEVICE_LOCK(sc);
+       THSCLK_READ(sc, &val);
+       val &= ~CLK_DIV_RATIO;
+       val |= (best_div << CLK_DIV_RATIO_SHIFT);
+       THSCLK_WRITE(sc, val);
+       DEVICE_UNLOCK(sc);
+
+       *fout = fin / best_n;
+       *stop = 1;
+
+       return (0);
+}
+
+static clknode_method_t aw_thsclk_clknode_methods[] = {
+       /* Device interface */
+       CLKNODEMETHOD(clknode_init,             aw_thsclk_init),
+       CLKNODEMETHOD(clknode_set_gate,         aw_thsclk_set_gate),
+       CLKNODEMETHOD(clknode_set_mux,          aw_thsclk_set_mux),
+       CLKNODEMETHOD(clknode_recalc_freq,      aw_thsclk_recalc_freq),
+       CLKNODEMETHOD(clknode_set_freq,         aw_thsclk_set_freq),
+       CLKNODEMETHOD_END
+};
+DEFINE_CLASS_1(aw_thsclk_clknode, aw_thsclk_clknode_class,
+    aw_thsclk_clknode_methods, sizeof(struct aw_thsclk_sc), clknode_class);
+
+static int
+aw_thsclk_probe(device_t dev)
+{
+       if (!ofw_bus_status_okay(dev))
+               return (ENXIO);
+
+       if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+               return (ENXIO);
+
+       device_set_desc(dev, "Allwinner THS Clock");
+       return (BUS_PROBE_DEFAULT);
+}
+
+static int
+aw_thsclk_attach(device_t dev)
+{
+       struct clknode_init_def def;
+       struct aw_thsclk_sc *sc;
+       struct clkdom *clkdom;
+       struct clknode *clk;
+       clk_t clk_parent;
+       bus_addr_t paddr;
+       bus_size_t psize;
+       phandle_t node;
+       int error, ncells, i;
+
+       node = ofw_bus_get_node(dev);
+
+       if (ofw_reg_to_paddr(node, 0, &paddr, &psize, NULL) != 0) {
+               device_printf(dev, "cannot parse 'reg' property\n");
+               return (ENXIO);
+       }
+
+       error = ofw_bus_parse_xref_list_get_length(node, "clocks",
+           "#clock-cells", &ncells);
+       if (error != 0) {
+               device_printf(dev, "cannot get clock count\n");
+               return (error);
+       }
+
+       clkdom = clkdom_create(dev);
+
+       memset(&def, 0, sizeof(def));
+       error = clk_parse_ofw_clk_name(dev, node, &def.name);
+       if (error != 0) {
+               device_printf(dev, "cannot parse clock name\n");
+               error = ENXIO;
+               goto fail;
+       }
+       def.id = 1;
+       def.parent_names = malloc(sizeof(char *) * ncells, M_OFWPROP, M_WAITOK);
+       for (i = 0; i < ncells; i++) {
+               error = clk_get_by_ofw_index(dev, 0, i, &clk_parent);
+               if (error != 0) {
+                       device_printf(dev, "cannot get clock %d\n", i);
+                       goto fail;
+               }
+               def.parent_names[i] = clk_get_name(clk_parent);
+               clk_release(clk_parent);
+       }
+       def.parent_cnt = ncells;
+
+       clk = clknode_create(clkdom, &aw_thsclk_clknode_class, &def);
+       if (clk == NULL) {
+               device_printf(dev, "cannot create clknode\n");
+               error = ENXIO;
+               goto fail;
+       }
+
+       sc = clknode_get_softc(clk);
+       sc->reg = paddr;
+       sc->clkdev = device_get_parent(dev);
+
+       clknode_register(clkdom, clk);
+
+       if (clkdom_finit(clkdom) != 0) {
+               device_printf(dev, "cannot finalize clkdom initialization\n");
+               error = ENXIO;
+               goto fail;
+       }
+
+       if (bootverbose)
+               clkdom_dump(clkdom);
+
+       return (0);
+
+fail:
+       return (error);
+}
+
+static device_method_t aw_thsclk_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,         aw_thsclk_probe),
+       DEVMETHOD(device_attach,        aw_thsclk_attach),
+
+       DEVMETHOD_END
+};
+
+static driver_t aw_thsclk_driver = {
+       "aw_thsclk",
+       aw_thsclk_methods,
+       0
+};
+
+static devclass_t aw_thsclk_devclass;
+
+EARLY_DRIVER_MODULE(aw_thsclk, simplebus, aw_thsclk_driver,
+    aw_thsclk_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);

Modified: head/sys/arm64/conf/GENERIC
==============================================================================
--- head/sys/arm64/conf/GENERIC Sat Sep  3 15:24:30 2016        (r305351)
+++ head/sys/arm64/conf/GENERIC Sat Sep  3 15:26:00 2016        (r305352)
@@ -167,6 +167,12 @@ device             aw_wdog         # Allwinner Watchdog
 # Power management controllers
 device         axp81x          # X-Powers AXP81x PMIC
 
+# EFUSE
+device         aw_sid          # Allwinner Secure ID EFUSE
+
+# Thermal sensors
+device         aw_thermal      # Allwinner Thermal Sensor Controller
+
 # Pseudo devices.
 device         loop            # Network loopback
 device         random          # Entropy device

Modified: head/sys/conf/files.arm64
==============================================================================
--- head/sys/conf/files.arm64   Sat Sep  3 15:24:30 2016        (r305351)
+++ head/sys/conf/files.arm64   Sat Sep  3 15:26:00 2016        (r305352)
@@ -22,6 +22,8 @@ arm/allwinner/aw_nmi.c                optional        aw_nmi 
 arm/allwinner/aw_reset.c       optional        aw_ccu
 arm/allwinner/aw_rsb.c         optional        aw_rsb
 arm/allwinner/aw_rtc.c         optional        aw_rtc
+arm/allwinner/aw_sid.c         optional        aw_sid
+arm/allwinner/aw_thermal.c     optional        aw_thermal
 arm/allwinner/aw_usbphy.c      optional        ehci aw_usbphy
 arm/allwinner/aw_wdog.c                optional        aw_wdog
 arm/allwinner/axp81x.c         optional        axp81x
@@ -33,6 +35,7 @@ arm/allwinner/clk/aw_gate.c   optional        aw_
 arm/allwinner/clk/aw_modclk.c  optional        aw_ccu
 arm/allwinner/clk/aw_pll.c     optional        aw_ccu \
        compile-with "${NORMAL_C} -I$S/gnu/dts/include"
+arm/allwinner/clk/aw_thsclk.c  optional        aw_ccu
 arm/allwinner/clk/aw_usbclk.c  optional        aw_ccu
 arm/allwinner/if_awg.c         optional        awg
 arm/arm/generic_timer.c                standard
_______________________________________________
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