summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2017-01-21 05:19:09 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2017-01-21 05:19:09 +0000
commit92fa7d6486837f2a03391e450e47bc3ce9d27f8e (patch)
tree8a7ca527357b47f831e0095dbaa21e55f73a39ea /sys
parente089eeed1f688e252d5ecc7956ba4772309235c9 (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.c60
-rw-r--r--sys/arch/armv7/sunxi/sxiccmu_clocks.h75
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