Index: head/sys/arm/allwinner/aw_thermal.c =================================================================== --- head/sys/arm/allwinner/aw_thermal.c (revision 305415) +++ head/sys/arm/allwinner/aw_thermal.c (revision 305416) @@ -1,384 +1,420 @@ /*- * 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 #include #include #include #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_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_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 217000000 +#define H3_TEMP_MUL 121168 +#define H3_TEMP_DIV 1000000 +#define H3_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) #define MAX_SENSORS 3 struct aw_thermal_sensor { const char *name; const char *desc; }; 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; + int temp_base; + int temp_mul; + int temp_div; + int calib; }; 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_mul = A83T_TEMP_MUL, .temp_div = A83T_TEMP_DIV, + .calib = 1, }; 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_mul = A64_TEMP_MUL, .temp_div = A64_TEMP_DIV, }; +static const struct aw_thermal_config h3_config = { + .nsensors = 1, + .sensors = { + [0] = { + .name = "cpu", + .desc = "CPU temperature", + }, + }, + .clk_rate = H3_CLK_RATE, + .adc_acquire_time = H3_ADC_ACQUIRE_TIME, + .filter = H3_FILTER, + .intc = H3_INTC, + .temp_base = H3_TEMP_BASE, + .temp_mul = H3_TEMP_MUL, + .temp_div = H3_TEMP_DIV, +}; + 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 }, { 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[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[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) { uint32_t calib0, calib1; int error; - /* Read calibration settings from SRAM */ - error = aw_sid_read_tscalib(&calib0, &calib1); - if (error != 0) - return (error); + if (sc->conf->calib) { + /* 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); + /* 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_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); /* Enable interrupts */ WR4(sc, THS_INTS, RD4(sc, THS_INTS)); WR4(sc, THS_INTC, sc->conf->intc | SHUT_INT_ALL); /* Enable sensors */ WR4(sc, THS_CTRL2, RD4(sc, THS_CTRL2) | SENSOR_ENABLE_ALL); return (0); } static int aw_thermal_reg_to_temp(struct aw_thermal_softc *sc, uint32_t val) { - return ((sc->conf->temp_base - val * 1000) / sc->conf->temp_div); + return ((sc->conf->temp_base - (val * sc->conf->temp_mul)) / + sc->conf->temp_div); } static int aw_thermal_gettemp(struct aw_thermal_softc *sc, int sensor) { uint32_t val; val = RD4(sc, THS_DATA0 + (sensor * 4)); 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; int sensor, val; sc = arg1; sensor = arg2; 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) { 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; 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) { 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) goto fail; 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->sensors[i].name, CTLTYPE_INT | CTLFLAG_RD, 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[] = { /* 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: head/sys/arm/allwinner/clk/aw_thsclk.c =================================================================== --- head/sys/arm/allwinner/clk/aw_thsclk.c (revision 305415) +++ head/sys/arm/allwinner/clk/aw_thsclk.c (revision 305416) @@ -1,320 +1,321 @@ /*- * 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 THS clocks */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #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,sun8i-h3-ths-clk", 1 }, { "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); Index: head/sys/arm/allwinner/files.allwinner =================================================================== --- head/sys/arm/allwinner/files.allwinner (revision 305415) +++ head/sys/arm/allwinner/files.allwinner (revision 305416) @@ -1,55 +1,56 @@ # $FreeBSD$ kern/kern_clocksource.c standard arm/allwinner/a10_ahci.c optional ahci arm/allwinner/a10_codec.c optional sound arm/allwinner/a10_common.c standard arm/allwinner/a10_dmac.c standard arm/allwinner/a10_ehci.c optional ehci arm/allwinner/aw_usbphy.c optional ehci arm/allwinner/a10_gpio.c optional gpio arm/allwinner/a10_mmc.c optional mmc arm/allwinner/a10_sramc.c standard arm/allwinner/aw_nmi.c optional intrng arm/allwinner/aw_if_dwc.c optional dwc arm/allwinner/aw_rsb.c optional rsb arm/allwinner/aw_rtc.c standard arm/allwinner/aw_ts.c standard arm/allwinner/aw_wdog.c standard arm/allwinner/aw_machdep.c standard arm/allwinner/aw_mp.c optional smp arm/allwinner/axp209.c optional axp209 arm/allwinner/axp81x.c optional axp81x arm/allwinner/if_awg.c optional awg arm/allwinner/if_emac.c optional emac arm/allwinner/sunxi_dma_if.m standard dev/iicbus/twsi/a10_twsi.c optional twsi dev/usb/controller/generic_ohci.c optional ohci dev/usb/controller/generic_usb_if.m optional ohci arm/allwinner/aw_sid.c standard arm/allwinner/aw_thermal.c standard #arm/allwinner/console.c standard arm/allwinner/a10_fb.c optional vt arm/allwinner/a10_hdmi.c optional hdmi arm/allwinner/a10_hdmiaudio.c optional hdmi sound arm/arm/hdmi_if.m optional hdmi arm/allwinner/aw_reset.c standard arm/allwinner/aw_ccu.c standard arm/allwinner/clk/aw_ahbclk.c standard arm/allwinner/clk/aw_apbclk.c standard arm/allwinner/clk/aw_axiclk.c standard arm/allwinner/clk/aw_codecclk.c standard arm/allwinner/clk/aw_cpuclk.c standard arm/allwinner/clk/aw_cpusclk.c standard arm/allwinner/clk/aw_debeclk.c standard arm/allwinner/clk/aw_gate.c standard arm/allwinner/clk/aw_gmacclk.c standard arm/allwinner/clk/aw_hdmiclk.c standard arm/allwinner/clk/aw_lcdclk.c standard arm/allwinner/clk/aw_modclk.c standard arm/allwinner/clk/aw_mmcclk.c standard arm/allwinner/clk/aw_oscclk.c standard arm/allwinner/clk/aw_pll.c standard +arm/allwinner/clk/aw_thsclk.c standard arm/allwinner/clk/aw_usbclk.c standard