Re: sunxi: add Allwinner A64 support for USB and USB clocks
On Sat, Jan 21, 2017 at 10:50:20AM +1000, Patrick Wildt wrote: > Hi, > > so this diff makes the Pine64 work with EHCI. The only not nice thing > is the switch. It would be better if this depends on the compatible > since the A64 and H3 have different numbers (and clock parents) for the > APB2 clock. > > I would still like to go ahead with this version since I don't think > that the switch without the compatible check is going to hurt for now. > > ok? > > Patrick After discussion with kettenis@ and his commit I have updated the diff. I also added the clocks for MMC, which means that we now have a usable USB port and MMC. ok? Patrick diff --git a/sys/arch/armv7/sunxi/sxiccmu.c b/sys/arch/armv7/sunxi/sxiccmu.c index 921b1dd4fe4..e0146cb0164 100644 --- a/sys/arch/armv7/sunxi/sxiccmu.c +++ b/sys/arch/armv7/sunxi/sxiccmu.c @@ -25,8 +25,6 @@ #include #include -#include - #include #include #include @@ -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); +intsxiccmu_a64_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t); uint32_t sxiccmu_h3_get_frequency(struct sxiccmu_softc *, uint32_t); intsxiccmu_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 6; + 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 2400; + } + + 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 */ +#defi
sunxi: add Allwinner A64 support for USB and USB clocks
Hi, so this diff makes the Pine64 work with EHCI. The only not nice thing is the switch. It would be better if this depends on the compatible since the A64 and H3 have different numbers (and clock parents) for the APB2 clock. I would still like to go ahead with this version since I don't think that the switch without the compatible check is going to hurt for now. ok? Patrick diff --git a/sys/arch/armv7/sunxi/sxiccmu.c b/sys/arch/armv7/sunxi/sxiccmu.c index 7b67f749ff4..397349cd27a 100644 --- a/sys/arch/armv7/sunxi/sxiccmu.c +++ b/sys/arch/armv7/sunxi/sxiccmu.c @@ -25,8 +25,6 @@ #include #include -#include - #include #include #include @@ -94,12 +92,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 @@ -116,7 +116,13 @@ 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); + } 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); @@ -643,6 +649,7 @@ sxiccmu_ccu_get_frequency(void *cookie, uint32_t *cells) case H3_CLK_PLL_PERIPH0: /* XXX default value. */ return 6; + case A64_CLK_APB2: case H3_CLK_APB2: /* XXX Controlled by a MUX. */ return 2400; diff --git a/sys/arch/armv7/sunxi/sxiccmu_clocks.h b/sys/arch/armv7/sunxi/sxiccmu_clocks.h index 84791762035..256da5f1f03 100644 --- a/sys/arch/armv7/sunxi/sxiccmu_clocks.h +++ b/sys/arch/armv7/sunxi/sxiccmu_clocks.h @@ -5,6 +5,40 @@ * Clocks Signals */ +#define A64_CLK_APB2 26 + +#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_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_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_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_APB218 @@ -68,6 +102,23 @@ 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_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_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_PHY00 #define H3_RST_USB_PHY11 #define H3_RST_USB_PHY22 diff --git a/sys/arch/armv7/sunxi/sxiehci.c b/sys/arch/armv7/sunxi/sxiehci.c index 1b266853bf7..4041318f6b9 100644 --- a/sys/arch/armv7/sunxi/sxiehci.c +++ b/sys/arch/armv7/su