From 34802c4d5eacf59501183db45b2a895aaa38e9fc Mon Sep 17 00:00:00 2001 From: Kevin Lo Date: Tue, 26 Dec 2017 09:31:52 +0000 Subject: Implement support for the "next-generation" clock bindings for the Allwinner A23/A33. ok kettenis@ --- sys/dev/fdt/sxiccmu.c | 109 ++++++++++++++++++++++++++++++++++++++++++- sys/dev/fdt/sxiccmu_clocks.h | 80 +++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 1 deletion(-) (limited to 'sys/dev') diff --git a/sys/dev/fdt/sxiccmu.c b/sys/dev/fdt/sxiccmu.c index 238641813a8..f84fb44e7f2 100644 --- a/sys/dev/fdt/sxiccmu.c +++ b/sys/dev/fdt/sxiccmu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sxiccmu.c,v 1.12 2017/12/24 18:24:06 kettenis Exp $ */ +/* $OpenBSD: sxiccmu.c,v 1.13 2017/12/26 09:31:51 kevlo Exp $ */ /* * Copyright (c) 2007,2009 Dale Rahn * Copyright (c) 2013 Artturi Alm @@ -88,6 +88,8 @@ void sxiccmu_ccu_reset(void *, uint32_t *, int); uint32_t sxiccmu_a10_get_frequency(struct sxiccmu_softc *, uint32_t); int sxiccmu_a10_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); +uint32_t sxiccmu_a23_get_frequency(struct sxiccmu_softc *, uint32_t); +int sxiccmu_a23_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); uint32_t sxiccmu_a64_get_frequency(struct sxiccmu_softc *, uint32_t); int sxiccmu_a64_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); uint32_t sxiccmu_a80_get_frequency(struct sxiccmu_softc *, uint32_t); @@ -110,6 +112,8 @@ sxiccmu_match(struct device *parent, void *match, void *aux) OF_is_compatible(node, "allwinner,sun5i-a10s") || OF_is_compatible(node, "allwinner,sun5i-r8") || OF_is_compatible(node, "allwinner,sun7i-a20") || + OF_is_compatible(node, "allwinner,sun8i-a23") || + OF_is_compatible(node, "allwinner,sun8i-a33") || OF_is_compatible(node, "allwinner,sun8i-h3") || OF_is_compatible(node, "allwinner,sun9i-a80") || OF_is_compatible(node, "allwinner,sun50i-a64") || @@ -118,6 +122,8 @@ sxiccmu_match(struct device *parent, void *match, void *aux) return (OF_is_compatible(node, "allwinner,sun4i-a10-ccu") || OF_is_compatible(node, "allwinner,sun7i-a20-ccu") || + OF_is_compatible(node, "allwinner,sun8i-a23-ccu") || + OF_is_compatible(node, "allwinner,sun8i-a33-ccu") || OF_is_compatible(node, "allwinner,sun8i-h3-ccu") || OF_is_compatible(node, "allwinner,sun9i-a80-ccu") || OF_is_compatible(node, "allwinner,sun9i-a80-usb-clks") || @@ -150,6 +156,15 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux) sc->sc_nresets = nitems(sun4i_a10_resets); sc->sc_get_frequency = sxiccmu_a10_get_frequency; sc->sc_set_frequency = sxiccmu_a10_set_frequency; + } else if (OF_is_compatible(node, "allwinner,sun8i-a23-ccu") || + OF_is_compatible(node, "allwinner,sun8i-a33-ccu")) { + KASSERT(faa->fa_nreg > 0); + sc->sc_gates = sun8i_a23_gates; + sc->sc_ngates = nitems(sun8i_a23_gates); + sc->sc_resets = sun8i_a23_resets; + sc->sc_nresets = nitems(sun8i_a23_resets); + sc->sc_get_frequency = sxiccmu_a23_get_frequency; + sc->sc_set_frequency = sxiccmu_a23_set_frequency; } else if (OF_is_compatible(node, "allwinner,sun8i-h3-ccu") || OF_is_compatible(node, "allwinner,sun50i-h5-ccu")) { KASSERT(faa->fa_nreg > 0); @@ -356,6 +371,32 @@ struct sxiccmu_device sxiccmu_devices[] = { .compat = "allwinner,sun8i-a23-apb0-clk", .get_frequency = sxiccmu_apbs_get_frequency }, + { + .compat = "allwinner,sun8i-a23-ahb1-gates-clk", + .get_frequency = sxiccmu_gen_get_frequency, + .enable = sxiccmu_gate_enable + }, + { + .compat = "allwinner,sun8i-a23-apb0-gates-clk", + .get_frequency = sxiccmu_gen_get_frequency, + .enable = sxiccmu_gate_enable + }, + { + .compat = "allwinner,sun8i-a23-apb1-gates-clk", + .get_frequency = sxiccmu_gen_get_frequency, + .enable = sxiccmu_gate_enable + }, + { + .compat = "allwinner,sun8i-a23-apb2-gates-clk", + .get_frequency = sxiccmu_gen_get_frequency, + .enable = sxiccmu_gate_enable + }, + { + .compat = "allwinner,sun8i-a23-usb-clk", + .get_frequency = sxiccmu_gen_get_frequency, + .enable = sxiccmu_gate_enable, + .reset = sxiccmu_reset + }, { .compat = "allwinner,sun8i-h3-apb0-gates-clk", .get_frequency = sxiccmu_gen_get_frequency, @@ -828,6 +869,50 @@ sxiccmu_a10_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) #define CCU_AHB2_CFG_REG 0x005c #define CCU_AHB2_CLK_CFG (3 << 0) +uint32_t +sxiccmu_a23_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) +{ + uint32_t parent; + uint32_t reg, div; + + switch (idx) { + case A23_CLK_LOSC: + return clock_get_frequency(sc->sc_node, "losc"); + case A23_CLK_HOSC: + return clock_get_frequency(sc->sc_node, "hosc"); + case A23_CLK_PLL_PERIPH: + /* Not hardcoded, but recommended. */ + return 600000000; + case A23_CLK_APB2: + /* XXX Controlled by a MUX. */ + return 24000000; + case A23_CLK_AHB1: + reg = SXIREAD4(sc, CCU_AHB1_APB1_CFG_REG); + div = CCU_AHB1_CLK_DIV_RATIO(reg); + switch (reg & CCU_AHB1_CLK_SRC_SEL) { + case CCU_AHB1_CLK_SRC_SEL_LOSC: + parent = A23_CLK_LOSC; + break; + case CCU_AHB1_CLK_SRC_SEL_OSC24M: + parent = A23_CLK_HOSC; + break; + case CCU_AHB1_CLK_SRC_SEL_AXI: + parent = A23_CLK_AXI; + break; + case CCU_AHB1_CLK_SRC_SEL_PERIPH0: + parent = A23_CLK_PLL_PERIPH; + div *= CCU_AHB1_PRE_DIV(reg); + break; + default: + return 0; + } + return sxiccmu_ccu_get_frequency(sc, &parent) / div; + } + + printf("%s: 0x%08x\n", __func__, idx); + return 0; +} + uint32_t sxiccmu_a64_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) { @@ -1003,6 +1088,28 @@ sxiccmu_a10_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) return -1; } +int +sxiccmu_a23_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) +{ + struct sxiccmu_clock clock; + uint32_t parent, parent_freq; + + switch (idx) { + case A23_CLK_MMC0: + case A23_CLK_MMC1: + case A23_CLK_MMC2: + clock.sc_iot = sc->sc_iot; + bus_space_subregion(sc->sc_iot, sc->sc_ioh, + sc->sc_gates[idx].reg, 4, &clock.sc_ioh); + parent = A23_CLK_PLL_PERIPH; + parent_freq = sxiccmu_ccu_get_frequency(sc, &parent); + return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq); + } + + printf("%s: 0x%08x\n", __func__, idx); + return -1; +} + int sxiccmu_a64_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) { diff --git a/sys/dev/fdt/sxiccmu_clocks.h b/sys/dev/fdt/sxiccmu_clocks.h index 58800aab6a6..7b25fb625e9 100644 --- a/sys/dev/fdt/sxiccmu_clocks.h +++ b/sys/dev/fdt/sxiccmu_clocks.h @@ -80,6 +80,54 @@ struct sxiccmu_ccu_bit sun4i_a10_gates[] = { [A10_CLK_USB_PHY] = { 0x00cc, 8 }, }; +/* A23/A33 */ + +#define A23_CLK_PLL_PERIPH 10 + +#define A23_CLK_AXI 19 +#define A23_CLK_AHB1 20 +#define A23_CLK_APB1 21 +#define A23_CLK_APB2 22 + +#define A23_CLK_BUS_MMC0 26 +#define A23_CLK_BUS_MMC1 27 +#define A23_CLK_BUS_MMC2 28 +#define A23_CLK_BUS_EHCI 35 +#define A23_CLK_BUS_OHCI 36 +#define A23_CLK_BUS_PIO 48 +#define A23_CLK_BUS_I2C0 51 +#define A23_CLK_BUS_I2C1 52 +#define A23_CLK_BUS_I2C2 53 +#define A23_CLK_BUS_UART0 54 +#define A23_CLK_BUS_UART1 55 +#define A23_CLK_BUS_UART2 56 +#define A23_CLK_BUS_UART3 57 +#define A23_CLK_BUS_UART4 58 + +#define A23_CLK_MMC0 60 +#define A23_CLK_MMC1 63 +#define A23_CLK_MMC2 66 + +struct sxiccmu_ccu_bit sun8i_a23_gates[] = { + [A23_CLK_BUS_MMC0] = { 0x0060, 8 }, + [A23_CLK_BUS_MMC1] = { 0x0060, 9 }, + [A23_CLK_BUS_MMC2] = { 0x0060, 10 }, + [A23_CLK_BUS_EHCI] = { 0x0060, 26 }, + [A23_CLK_BUS_OHCI] = { 0x0060, 29 }, + [A23_CLK_BUS_PIO] = { 0x0068, 5 }, + [A23_CLK_BUS_I2C0] = { 0x006c, 0, A23_CLK_APB2 }, + [A23_CLK_BUS_I2C1] = { 0x006c, 1, A23_CLK_APB2 }, + [A23_CLK_BUS_I2C2] = { 0x006c, 2, A23_CLK_APB2 }, + [A23_CLK_BUS_UART0] = { 0x006c, 16, A23_CLK_APB2 }, + [A23_CLK_BUS_UART1] = { 0x006c, 17, A23_CLK_APB2 }, + [A23_CLK_BUS_UART2] = { 0x006c, 18, A23_CLK_APB2 }, + [A23_CLK_BUS_UART3] = { 0x006c, 19, A23_CLK_APB2 }, + [A23_CLK_BUS_UART4] = { 0x006c, 20, A23_CLK_APB2 }, + [A23_CLK_MMC0] = { 0x0088, 31 }, + [A23_CLK_MMC1] = { 0x008c, 31 }, + [A23_CLK_MMC2] = { 0x0090, 31 }, +}; + /* A64 */ #define A64_CLK_PLL_PERIPH0 11 @@ -309,6 +357,38 @@ struct sxiccmu_ccu_bit sun4i_a10_resets[] = { [A10_RST_USB_PHY2] = { 0x00cc, 2 }, }; +/* A23/A33 */ + +#define A23_RST_USB_PHY0 0 +#define A23_RST_USB_PHY1 1 + +#define A23_RST_BUS_MMC0 7 +#define A23_RST_BUS_MMC1 8 +#define A23_RST_BUS_MMC2 9 + +#define A23_RST_BUS_EHCI 16 +#define A23_RST_BUS_OHCI 17 + +#define A23_RST_BUS_I2C0 32 +#define A23_RST_BUS_I2C1 33 +#define A23_RST_BUS_I2C2 34 + +#define A23_CLK_HOSC 253 +#define A23_CLK_LOSC 254 + +struct sxiccmu_ccu_bit sun8i_a23_resets[] = { + [A23_RST_USB_PHY0] = { 0x00cc, 0 }, + [A23_RST_USB_PHY1] = { 0x00cc, 1 }, + [A23_RST_BUS_MMC0] = { 0x02c0, 8 }, + [A23_RST_BUS_MMC1] = { 0x02c0, 9 }, + [A23_RST_BUS_MMC2] = { 0x02c0, 10 }, + [A23_RST_BUS_EHCI] = { 0x02c0, 26 }, + [A23_RST_BUS_OHCI] = { 0x02c0, 29 }, + [A23_RST_BUS_I2C0] = { 0x02d8, 0 }, + [A23_RST_BUS_I2C1] = { 0x02d8, 1 }, + [A23_RST_BUS_I2C2] = { 0x02d8, 2 }, +}; + /* A64 */ #define A64_RST_USB_PHY0 0 -- cgit v1.2.3