From a6d148da84b47c4102c8c5731874b69dfcd38dbc Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 30 Dec 2017 16:30:37 +0000 Subject: [PATCH] Implement Allwinner A40/V40 support. --- sys/dev/fdt/sxiccmu.c | 54 +++++++++++++- sys/dev/fdt/sxiccmu_clocks.h | 134 ++++++++++++++++++++++++++++++++++- 2 files changed, 186 insertions(+), 2 deletions(-) diff --git a/sys/dev/fdt/sxiccmu.c b/sys/dev/fdt/sxiccmu.c index 8e9f3aa9086..43c9ff91c83 100644 --- a/sys/dev/fdt/sxiccmu.c +++ b/sys/dev/fdt/sxiccmu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sxiccmu.c,v 1.15 2017/12/30 12:45:36 kettenis Exp $ */ +/* $OpenBSD: sxiccmu.c,v 1.16 2017/12/30 16:30:37 kettenis Exp $ */ /* * Copyright (c) 2007,2009 Dale Rahn * Copyright (c) 2013 Artturi Alm @@ -97,6 +97,8 @@ int sxiccmu_a80_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); uint32_t sxiccmu_h3_get_frequency(struct sxiccmu_softc *, uint32_t); int sxiccmu_h3_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); uint32_t sxiccmu_h3_r_get_frequency(struct sxiccmu_softc *, uint32_t); +uint32_t sxiccmu_r40_get_frequency(struct sxiccmu_softc *, uint32_t); +int sxiccmu_r40_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); uint32_t sxiccmu_nop_get_frequency(struct sxiccmu_softc *, uint32_t); int sxiccmu_nop_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); @@ -128,6 +130,7 @@ sxiccmu_match(struct device *parent, void *match, void *aux) OF_is_compatible(node, "allwinner,sun8i-a33-ccu") || OF_is_compatible(node, "allwinner,sun8i-h3-ccu") || OF_is_compatible(node, "allwinner,sun8i-h3-r-ccu") || + OF_is_compatible(node, "allwinner,sun8i-r40-ccu") || OF_is_compatible(node, "allwinner,sun9i-a80-ccu") || OF_is_compatible(node, "allwinner,sun9i-a80-usb-clks") || OF_is_compatible(node, "allwinner,sun9i-a80-mmc-config-clk") || @@ -185,6 +188,14 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux) sc->sc_nresets = nitems(sun8i_h3_r_resets); sc->sc_get_frequency = sxiccmu_h3_r_get_frequency; sc->sc_set_frequency = sxiccmu_nop_set_frequency; + } else if (OF_is_compatible(node, "allwinner,sun8i-r40-ccu")) { + KASSERT(faa->fa_nreg > 0); + sc->sc_gates = sun8i_r40_gates; + sc->sc_ngates = nitems(sun8i_r40_gates); + sc->sc_resets = sun8i_r40_resets; + sc->sc_nresets = nitems(sun8i_r40_resets); + sc->sc_get_frequency = sxiccmu_r40_get_frequency; + sc->sc_set_frequency = sxiccmu_r40_set_frequency; } else if (OF_is_compatible(node, "allwinner,sun9i-a80-ccu")) { KASSERT(faa->fa_nreg > 0); sc->sc_gates = sun9i_a80_gates; @@ -1116,6 +1127,24 @@ sxiccmu_h3_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) return 0; } +uint32_t +sxiccmu_r40_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) +{ + switch (idx) { + case R40_CLK_PLL_PERIPH0: + /* Not hardcoded, but recommended. */ + return 600000000; + case R40_CLK_PLL_PERIPH0_2X: + return sxiccmu_r40_get_frequency(sc, A64_CLK_PLL_PERIPH0) * 2; + case R40_CLK_APB2: + /* XXX Controlled by a MUX. */ + return 24000000; + } + + printf("%s: 0x%08x\n", __func__, idx); + return 0; +} + uint32_t sxiccmu_nop_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) { @@ -1243,6 +1272,29 @@ sxiccmu_h3_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) return -1; } +int +sxiccmu_r40_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) +{ + struct sxiccmu_clock clock; + uint32_t parent, parent_freq; + + switch (idx) { + case R40_CLK_MMC0: + case R40_CLK_MMC1: + case R40_CLK_MMC2: + case R40_CLK_MMC3: + 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 = R40_CLK_PLL_PERIPH0_2X; + 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_nop_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 11bae0047bc..f71a54e7bc1 100644 --- a/sys/dev/fdt/sxiccmu_clocks.h +++ b/sys/dev/fdt/sxiccmu_clocks.h @@ -348,12 +348,85 @@ struct sxiccmu_ccu_bit sun8i_h3_gates[] = { #define H3_R_CLK_APB0_PIO 3 #define H3_R_CLK_APB0_I2C 9 - struct sxiccmu_ccu_bit sun8i_h3_r_gates[] = { [H3_R_CLK_APB0_PIO] = { 0x0028, 0 }, [H3_R_CLK_APB0_I2C] = { 0x0028, 6, H3_R_CLK_APB0 }, }; +/* R40 */ + +#define R40_CLK_PLL_PERIPH0 11 +#define R40_CLK_PLL_PERIPH0_2X 13 + +#define R40_CLK_APB2 28 + +#define R40_CLK_BUS_MMC0 32 +#define R40_CLK_BUS_MMC1 33 +#define R40_CLK_BUS_MMC2 34 +#define R40_CLK_BUS_MMC3 35 +#define R40_CLK_BUS_EHCI0 47 +#define R40_CLK_BUS_EHCI1 48 +#define R40_CLK_BUS_EHCI2 49 +#define R40_CLK_BUS_OHCI0 50 +#define R40_CLK_BUS_OHCI1 51 +#define R40_CLK_BUS_OHCI2 52 +#define R40_CLK_BUS_PIO 79 +#define R40_CLK_BUS_I2C0 87 +#define R40_CLK_BUS_I2C1 88 +#define R40_CLK_BUS_I2C2 89 +#define R40_CLK_BUS_I2C3 90 +#define R40_CLK_BUS_I2C4 95 +#define R40_CLK_BUS_UART0 96 +#define R40_CLK_BUS_UART1 97 +#define R40_CLK_BUS_UART2 98 +#define R40_CLK_BUS_UART3 99 +#define R40_CLK_BUS_UART4 100 +#define R40_CLK_BUS_UART5 101 +#define R40_CLK_BUS_UART6 102 +#define R40_CLK_BUS_UART7 103 + +#define R40_CLK_MMC0 107 +#define R40_CLK_MMC1 108 +#define R40_CLK_MMC2 109 +#define R40_CLK_MMC3 110 +#define R40_CLK_USB_PHY0 124 +#define R40_CLK_USB_PHY1 125 +#define R40_CLK_USB_PHY2 126 + +struct sxiccmu_ccu_bit sun8i_r40_gates[] = { + [R40_CLK_BUS_MMC0] = { 0x0060, 8 }, + [R40_CLK_BUS_MMC1] = { 0x0060, 9 }, + [R40_CLK_BUS_MMC2] = { 0x0060, 10 }, + [R40_CLK_BUS_MMC3] = { 0x0060, 11 }, + [R40_CLK_BUS_EHCI0] = { 0x0060, 26 }, + [R40_CLK_BUS_EHCI1] = { 0x0060, 27 }, + [R40_CLK_BUS_EHCI2] = { 0x0060, 28 }, + [R40_CLK_BUS_OHCI0] = { 0x0060, 29 }, + [R40_CLK_BUS_OHCI1] = { 0x0060, 30 }, + [R40_CLK_BUS_OHCI2] = { 0x0060, 31 }, + [R40_CLK_BUS_PIO] = { 0x0068, 5 }, + [R40_CLK_BUS_I2C0] = { 0x006c, 0, R40_CLK_APB2 }, + [R40_CLK_BUS_I2C1] = { 0x006c, 1, R40_CLK_APB2 }, + [R40_CLK_BUS_I2C2] = { 0x006c, 2, R40_CLK_APB2 }, + [R40_CLK_BUS_I2C3] = { 0x006c, 3, R40_CLK_APB2 }, + [R40_CLK_BUS_I2C4] = { 0x006c, 15, R40_CLK_APB2 }, + [R40_CLK_BUS_UART0] = { 0x006c, 16, R40_CLK_APB2 }, + [R40_CLK_BUS_UART1] = { 0x006c, 17, R40_CLK_APB2 }, + [R40_CLK_BUS_UART2] = { 0x006c, 18, R40_CLK_APB2 }, + [R40_CLK_BUS_UART3] = { 0x006c, 19, R40_CLK_APB2 }, + [R40_CLK_BUS_UART4] = { 0x006c, 20, R40_CLK_APB2 }, + [R40_CLK_BUS_UART5] = { 0x006c, 21, R40_CLK_APB2 }, + [R40_CLK_BUS_UART6] = { 0x006c, 22, R40_CLK_APB2 }, + [R40_CLK_BUS_UART7] = { 0x006c, 23, R40_CLK_APB2 }, + [R40_CLK_MMC0] = { 0x0088, 31 }, + [R40_CLK_MMC1] = { 0x008c, 31 }, + [R40_CLK_MMC2] = { 0x0090, 31 }, + [R40_CLK_MMC3] = { 0x0094, 31 }, + [R40_CLK_USB_PHY0] = { 0x00cc, 8 }, + [R40_CLK_USB_PHY1] = { 0x00cc, 9 }, + [R40_CLK_USB_PHY2] = { 0x00cc, 10 }, +}; + /* * Reset Signals */ @@ -542,3 +615,62 @@ struct sxiccmu_ccu_bit sun8i_h3_resets[] = { struct sxiccmu_ccu_bit sun8i_h3_r_resets[] = { [H3_R_RST_APB0_I2C] = { 0x00b0, 6 }, }; + +/* R40 */ + +#define R40_RST_USB_PHY0 0 +#define R40_RST_USB_PHY1 1 +#define R40_RST_USB_PHY2 2 + +#define R40_RST_BUS_MMC0 8 +#define R40_RST_BUS_MMC1 9 +#define R40_RST_BUS_MMC2 10 +#define R40_RST_BUS_MMC3 11 +#define R40_RST_BUS_EHCI0 23 +#define R40_RST_BUS_EHCI1 24 +#define R40_RST_BUS_EHCI2 25 +#define R40_RST_BUS_OHCI0 26 +#define R40_RST_BUS_OHCI1 27 +#define R40_RST_BUS_OHCI2 28 +#define R40_RST_BUS_I2C0 64 +#define R40_RST_BUS_I2C1 65 +#define R40_RST_BUS_I2C2 66 +#define R40_RST_BUS_I2C3 67 +#define R40_RST_BUS_I2C4 72 +#define R40_RST_BUS_UART0 73 +#define R40_RST_BUS_UART1 74 +#define R40_RST_BUS_UART2 75 +#define R40_RST_BUS_UART3 76 +#define R40_RST_BUS_UART4 77 +#define R40_RST_BUS_UART5 78 +#define R40_RST_BUS_UART6 79 +#define R40_RST_BUS_UART7 80 + +struct sxiccmu_ccu_bit sun8i_r40_resets[] = { + [R40_RST_USB_PHY0] = { 0x00cc, 0 }, + [R40_RST_USB_PHY1] = { 0x00cc, 1 }, + [R40_RST_USB_PHY2] = { 0x00cc, 2 }, + [R40_RST_BUS_MMC0] = { 0x02c0, 8 }, + [R40_RST_BUS_MMC1] = { 0x02c0, 9 }, + [R40_RST_BUS_MMC2] = { 0x02c0, 10 }, + [R40_RST_BUS_MMC3] = { 0x02c0, 11 }, + [R40_RST_BUS_EHCI0] = { 0x02c0, 26 }, + [R40_RST_BUS_EHCI1] = { 0x02c0, 27 }, + [R40_RST_BUS_EHCI2] = { 0x02c0, 28 }, + [R40_RST_BUS_OHCI0] = { 0x02c0, 29 }, + [R40_RST_BUS_OHCI1] = { 0x02c0, 30 }, + [R40_RST_BUS_OHCI2] = { 0x02c0, 31 }, + [R40_RST_BUS_I2C0] = { 0x02d8, 0 }, + [R40_RST_BUS_I2C1] = { 0x02d8, 1 }, + [R40_RST_BUS_I2C2] = { 0x02d8, 2 }, + [R40_RST_BUS_I2C3] = { 0x02d8, 3 }, + [R40_RST_BUS_I2C4] = { 0x02d8, 15 }, + [R40_RST_BUS_UART0] = { 0x02d8, 16 }, + [R40_RST_BUS_UART1] = { 0x02d8, 17 }, + [R40_RST_BUS_UART2] = { 0x02d8, 18 }, + [R40_RST_BUS_UART3] = { 0x02d8, 19 }, + [R40_RST_BUS_UART4] = { 0x02d8, 20 }, + [R40_RST_BUS_UART5] = { 0x02d8, 21 }, + [R40_RST_BUS_UART6] = { 0x02d8, 22 }, + [R40_RST_BUS_UART7] = { 0x02d8, 23 }, +}; -- 2.20.1