diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-01-21 05:19:09 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-01-21 05:19:09 +0000 |
commit | 92fa7d6486837f2a03391e450e47bc3ce9d27f8e (patch) | |
tree | 8a7ca527357b47f831e0095dbaa21e55f73a39ea /sys | |
parent | e089eeed1f688e252d5ecc7956ba4772309235c9 (diff) |
Implement EHCI and MMC clock support for the Allwinner A64 SoC.
Unfortunately this does not yet enable us to use the MMC on the
Pine64.
ok kettenis@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/armv7/sunxi/sxiccmu.c | 60 | ||||
-rw-r--r-- | sys/arch/armv7/sunxi/sxiccmu_clocks.h | 75 |
2 files changed, 130 insertions, 5 deletions
diff --git a/sys/arch/armv7/sunxi/sxiccmu.c b/sys/arch/armv7/sunxi/sxiccmu.c index 921b1dd4fe4..cf0f6d9c197 100644 --- a/sys/arch/armv7/sunxi/sxiccmu.c +++ b/sys/arch/armv7/sunxi/sxiccmu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sxiccmu.c,v 1.28 2017/01/21 03:51:18 kettenis Exp $ */ +/* $OpenBSD: sxiccmu.c,v 1.29 2017/01/21 05:19:08 patrick Exp $ */ /* * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org> * Copyright (c) 2013 Artturi Alm @@ -25,8 +25,6 @@ #include <sys/time.h> #include <sys/device.h> -#include <arm/cpufunc.h> - #include <machine/bus.h> #include <machine/fdt.h> #include <machine/intr.h> @@ -88,6 +86,8 @@ int sxiccmu_ccu_set_frequency(void *, uint32_t *, uint32_t); void sxiccmu_ccu_enable(void *, uint32_t *, int); void sxiccmu_ccu_reset(void *, uint32_t *, int); +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_h3_get_frequency(struct sxiccmu_softc *, uint32_t); int sxiccmu_h3_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); @@ -102,12 +102,14 @@ sxiccmu_match(struct device *parent, void *match, void *aux) return (OF_is_compatible(node, "allwinner,sun4i-a10") || OF_is_compatible(node, "allwinner,sun5i-a10s") || OF_is_compatible(node, "allwinner,sun5i-r8") || + OF_is_compatible(node, "allwinner,sun50i-a64") || OF_is_compatible(node, "allwinner,sun7i-a20") || OF_is_compatible(node, "allwinner,sun8i-h3") || OF_is_compatible(node, "allwinner,sun9i-a80")); } - return OF_is_compatible(faa->fa_node, "allwinner,sun8i-h3-ccu"); + return (OF_is_compatible(faa->fa_node, "allwinner,sun50i-a64-ccu") || + OF_is_compatible(faa->fa_node, "allwinner,sun8i-h3-ccu")); } void @@ -124,7 +126,15 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux) printf("\n"); - if (OF_is_compatible(node, "allwinner,sun8i-h3-ccu")) { + if (OF_is_compatible(node, "allwinner,sun50i-a64-ccu")) { + KASSERT(faa->fa_nreg > 0); + sc->sc_gates = sun50i_a64_gates; + sc->sc_ngates = nitems(sun50i_a64_gates); + sc->sc_resets = sun50i_a64_resets; + sc->sc_nresets = nitems(sun50i_a64_resets); + sc->sc_get_frequency = sxiccmu_a64_get_frequency; + sc->sc_set_frequency = sxiccmu_a64_set_frequency; + } else if (OF_is_compatible(node, "allwinner,sun8i-h3-ccu")) { KASSERT(faa->fa_nreg > 0); sc->sc_gates = sun8i_h3_gates; sc->sc_ngates = nitems(sun8i_h3_gates); @@ -653,6 +663,24 @@ sxiccmu_ccu_get_frequency(void *cookie, uint32_t *cells) } uint32_t +sxiccmu_a64_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) +{ + switch (idx) { + case A64_CLK_PLL_PERIPH0: + /* XXX default value. */ + return 600000000; + case A64_CLK_PLL_PERIPH0_2X: + return sxiccmu_a64_get_frequency(sc, A64_CLK_PLL_PERIPH0) * 2; + case A64_CLK_APB2: + /* XXX Controlled by a MUX. */ + return 24000000; + } + + printf("%s: 0x%08x\n", __func__, idx); + return 0; +} + +uint32_t sxiccmu_h3_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) { switch (idx) { @@ -678,6 +706,28 @@ sxiccmu_ccu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) } int +sxiccmu_a64_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) +{ + struct sxiccmu_clock clock; + uint32_t parent, parent_freq; + + switch (idx) { + case A64_CLK_MMC0: + case A64_CLK_MMC1: + case A64_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 = A64_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_h3_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) { struct sxiccmu_clock clock; diff --git a/sys/arch/armv7/sunxi/sxiccmu_clocks.h b/sys/arch/armv7/sunxi/sxiccmu_clocks.h index 84791762035..fdd0282623b 100644 --- a/sys/arch/armv7/sunxi/sxiccmu_clocks.h +++ b/sys/arch/armv7/sunxi/sxiccmu_clocks.h @@ -5,6 +5,57 @@ * Clocks Signals */ +#define A64_CLK_PLL_PERIPH0 11 +#define A64_CLK_PLL_PERIPH0_2X 12 + +#define A64_CLK_APB2 26 + +#define A64_CLK_BUS_MMC0 31 +#define A64_CLK_BUS_MMC1 32 +#define A64_CLK_BUS_MMC2 33 + +#define A64_CLK_BUS_EHCI0 42 +#define A64_CLK_BUS_EHCI1 43 +#define A64_CLK_BUS_OHCI0 44 +#define A64_CLK_BUS_OHCI1 45 + +#define A64_CLK_BUS_UART0 67 +#define A64_CLK_BUS_UART1 68 +#define A64_CLK_BUS_UART2 69 +#define A64_CLK_BUS_UART3 70 +#define A64_CLK_BUS_UART4 71 + +#define A64_CLK_MMC0 75 +#define A64_CLK_MMC1 76 +#define A64_CLK_MMC2 77 + +#define A64_CLK_USB_OHCI0 91 +#define A64_CLK_USB_OHCI1 93 +#define A64_CLK_USB_PHY0 86 +#define A64_CLK_USB_PHY1 87 + +struct sxiccmu_ccu_bit sun50i_a64_gates[] = { + [A64_CLK_BUS_MMC0] = { 0x0060, 8 }, + [A64_CLK_BUS_MMC1] = { 0x0060, 9 }, + [A64_CLK_BUS_MMC2] = { 0x0060, 10 }, + [A64_CLK_BUS_EHCI0] = { 0x0060, 24 }, + [A64_CLK_BUS_EHCI1] = { 0x0060, 25 }, + [A64_CLK_BUS_OHCI0] = { 0x0060, 28 }, + [A64_CLK_BUS_OHCI1] = { 0x0060, 29 }, + [A64_CLK_BUS_UART0] = { 0x006c, 16, A64_CLK_APB2 }, + [A64_CLK_BUS_UART1] = { 0x006c, 17, A64_CLK_APB2 }, + [A64_CLK_BUS_UART2] = { 0x006c, 18, A64_CLK_APB2 }, + [A64_CLK_BUS_UART3] = { 0x006c, 19, A64_CLK_APB2 }, + [A64_CLK_BUS_UART4] = { 0x006c, 20, A64_CLK_APB2 }, + [A64_CLK_MMC0] = { 0x0088, 31 }, + [A64_CLK_MMC1] = { 0x008c, 31 }, + [A64_CLK_MMC2] = { 0x0090, 31 }, + [A64_CLK_USB_OHCI0] = { 0x00cc, 16 }, + [A64_CLK_USB_OHCI1] = { 0x00cc, 17 }, + [A64_CLK_USB_PHY0] = { 0x00cc, 8 }, + [A64_CLK_USB_PHY1] = { 0x00cc, 9 }, +}; + #define H3_CLK_PLL_PERIPH0 9 #define H3_CLK_APB2 18 @@ -68,6 +119,30 @@ struct sxiccmu_ccu_bit sun8i_h3_gates[] = { * Reset Signals */ +#define A64_RST_USB_PHY0 0 +#define A64_RST_USB_PHY1 1 + +#define A64_RST_BUS_MMC0 8 +#define A64_RST_BUS_MMC1 9 +#define A64_RST_BUS_MMC2 10 + +#define A64_RST_BUS_EHCI0 19 +#define A64_RST_BUS_EHCI1 20 +#define A64_RST_BUS_OHCI0 21 +#define A64_RST_BUS_OHCI1 22 + +struct sxiccmu_ccu_bit sun50i_a64_resets[] = { + [A64_RST_USB_PHY0] = { 0x00cc, 0 }, + [A64_RST_USB_PHY1] = { 0x00cc, 1 }, + [A64_RST_BUS_MMC0] = { 0x02c0, 8 }, + [A64_RST_BUS_MMC1] = { 0x02c0, 9 }, + [A64_RST_BUS_MMC2] = { 0x02c0, 10 }, + [A64_RST_BUS_EHCI0] = { 0x02c0, 24 }, + [A64_RST_BUS_EHCI1] = { 0x02c0, 25 }, + [A64_RST_BUS_OHCI0] = { 0x02c0, 28 }, + [A64_RST_BUS_OHCI1] = { 0x02c0, 29 }, +}; + #define H3_RST_USB_PHY0 0 #define H3_RST_USB_PHY1 1 #define H3_RST_USB_PHY2 2 |