Index: sys/arm/allwinner/aw_sid.h =================================================================== --- /dev/null +++ sys/arm/allwinner/aw_sid.h @@ -0,0 +1,34 @@ +/*- + * Copyright (c) 2016 Jared McNeill + * 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$ + */ + +#ifndef __AW_SID_H__ +#define __AW_SID_H__ + +int aw_sid_read_tscalib(uint32_t *, uint32_t *); + +#endif /* !__AW_SID_H__ */ Index: sys/arm/allwinner/aw_sid.c =================================================================== --- /dev/null +++ sys/arm/allwinner/aw_sid.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 2016 Jared McNeill + * 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 secure ID controller + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define SID_SRAM 0x200 +#define SID_THERMAL_CALIB0 (SID_SRAM + 0x34) +#define SID_THERMAL_CALIB1 (SID_SRAM + 0x38) + +static struct ofw_compat_data compat_data[] = { + { "allwinner,sun8i-a83t-sid", 1 }, + { NULL, 0 } +}; + +struct aw_sid_softc { + struct resource *res; +}; + +static struct aw_sid_softc *aw_sid_sc; + +static struct resource_spec aw_sid_spec[] = { + { SYS_RES_MEMORY, 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)) + +static int +aw_sid_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 Secure ID Controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +aw_sid_attach(device_t dev) +{ + struct aw_sid_softc *sc; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, aw_sid_spec, &sc->res) != 0) { + device_printf(dev, "cannot allocate resources for device\n"); + return (ENXIO); + } + + aw_sid_sc = sc; + + return (0); +} + +int +aw_sid_read_tscalib(uint32_t *calib0, uint32_t *calib1) +{ + struct aw_sid_softc *sc; + + sc = aw_sid_sc; + if (sc == NULL) + return (ENXIO); + + *calib0 = RD4(sc, SID_THERMAL_CALIB0); + *calib1 = RD4(sc, SID_THERMAL_CALIB1); + + return (0); +} + +static device_method_t aw_sid_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, aw_sid_probe), + DEVMETHOD(device_attach, aw_sid_attach), + + DEVMETHOD_END +}; + +static driver_t aw_sid_driver = { + "aw_sid", + aw_sid_methods, + sizeof(struct aw_sid_softc), +}; + +static devclass_t aw_sid_devclass; + +EARLY_DRIVER_MODULE(aw_sid, simplebus, aw_sid_driver, aw_sid_devclass, 0, 0, + BUS_PASS_RESOURCE + BUS_PASS_ORDER_FIRST); +MODULE_VERSION(aw_sid, 1); Index: sys/arm/allwinner/aw_thermal.c =================================================================== --- /dev/null +++ sys/arm/allwinner/aw_thermal.c @@ -0,0 +1,232 @@ +/*- + * Copyright (c) 2016 Jared McNeill + * 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 thermal sensor controller + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define THS_CTRL0 0x00 +#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 THS_FILTER 0x70 +#define FILTER_EN (1 << 2) +#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 TEMP_BASE 2719 +#define TEMP_MUL 1000 +#define TEMP_DIV 14186 +#define TEMP_TO_K 273 +#define ADC_ACQUIRE_TIME (24 - 1) +#define SENSOR_ENABLE_ALL (SENSOR0_EN|SENSOR1_EN|SENSOR2_EN) + +enum aw_thermal_sensor { + THS_SENSOR_CPU_CLUSTER0, + THS_SENSOR_CPU_CLUSTER1, + THS_SENSOR_GPU, + THS_SENSOR_END = -1 +}; + +struct aw_thermal_sensor_config { + enum aw_thermal_sensor 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 } +}; + +static struct ofw_compat_data compat_data[] = { + { "allwinner,sun8i-a83t-ts", (uintptr_t)&a83t_sensor_config }, + { NULL, (uintptr_t)NULL } +}; + +#define THS_CONF(d) \ + (void *)ofw_bus_search_compatible((d), compat_data)->ocd_data + +struct aw_thermal_softc { + struct resource *res; + struct aw_thermal_sensor_config *conf; +}; + +static struct resource_spec aw_thermal_spec[] = { + { SYS_RES_MEMORY, 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)) + +static int +aw_thermal_init(struct aw_thermal_softc *sc) +{ + uint32_t calib0, calib1; + int error; + + /* Read calibration settings from SRAM */ + error = aw_sid_read_tscalib(&calib0, &calib1); + if (error != 0) + return (error); + + /* Write calibration settings to thermal controller */ + WR4(sc, THS_CALIB0, calib0); + 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); + + /* Disable interrupts */ + WR4(sc, THS_INTC, 0); + WR4(sc, THS_INTS, RD4(sc, THS_INTS)); + + /* Enable average filter */ + WR4(sc, THS_FILTER, RD4(sc, THS_FILTER) | FILTER_EN); + + return (0); +} + +static int +aw_thermal_gettemp(uint32_t val) +{ + int raw; + + raw = val & DATA_MASK; + return (((TEMP_BASE - raw) * TEMP_MUL) / TEMP_DIV) + TEMP_TO_K; +} + +static int +aw_thermal_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct aw_thermal_softc *sc; + enum aw_thermal_sensor sensor; + int val; + + sc = arg1; + sensor = arg2; + + val = aw_thermal_gettemp(RD4(sc, THS_DATA0 + (sensor * 4))); + + return sysctl_handle_opaque(oidp, &val, sizeof(val), req); +} + +static int +aw_thermal_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (THS_CONF(dev) == NULL) + return (ENXIO); + + device_set_desc(dev, "Allwinner Thermal Sensor Controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +aw_thermal_attach(device_t dev) +{ + struct aw_thermal_softc *sc; + int i; + + sc = device_get_softc(dev); + + sc->conf = THS_CONF(dev); + + if (bus_alloc_resources(dev, aw_thermal_spec, &sc->res) != 0) { + device_printf(dev, "cannot allocate resources for device\n"); + return (ENXIO); + } + + if (aw_thermal_init(sc) != 0) + return (ENXIO); + + for (i = 0; sc->conf[i].sensor != THS_SENSOR_END; i++) + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, sc->conf[i].name, + CTLTYPE_INT | CTLFLAG_RD, + sc, sc->conf[i].sensor, aw_thermal_sysctl, "IK0", + sc->conf[i].desc); + + return (0); +} + +static device_method_t aw_thermal_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, aw_thermal_probe), + DEVMETHOD(device_attach, aw_thermal_attach), + + DEVMETHOD_END +}; + +static driver_t aw_thermal_driver = { + "aw_thermal", + aw_thermal_methods, + sizeof(struct aw_thermal_softc), +}; + +static devclass_t aw_thermal_devclass; + +DRIVER_MODULE(aw_thermal, simplebus, aw_thermal_driver, aw_thermal_devclass, + 0, 0); +MODULE_VERSION(aw_thermal, 1); Index: sys/arm/allwinner/files.allwinner =================================================================== --- sys/arm/allwinner/files.allwinner +++ sys/arm/allwinner/files.allwinner @@ -24,6 +24,8 @@ arm/allwinner/if_emac.c optional emac arm/allwinner/sunxi_dma_if.m standard dev/iicbus/twsi/a10_twsi.c optional twsi +arm/allwinner/aw_sid.c standard +arm/allwinner/aw_thermal.c standard #arm/allwinner/console.c standard arm/allwinner/a10_fb.c optional vt Index: sys/boot/fdt/dts/arm/a83t.dtsi =================================================================== --- sys/boot/fdt/dts/arm/a83t.dtsi +++ sys/boot/fdt/dts/arm/a83t.dtsi @@ -185,6 +185,18 @@ #address-cells = <1>; #size-cells = <0>; }; + + sid: eeprom@01c14000 { + compatible = "allwinner,sun8i-a83t-sid"; + reg = <0x01c14000 0x400>; + }; + + rtp: rtp@01f04000 { + compatible = "allwinner,sun8i-a83t-ts"; + reg = <0x01f04000 0x400>; + interrupts = ; + #thermal-sensor-cells = <0>; + }; }; };