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 <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
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/sunxi/sxiehci.c
@@ -104,6 +104,8 @@ sxiehci_match(struct device *parent, void *match, void *aux)
            return 1;
        if (OF_is_compatible(faa->fa_node, "allwinner,sun5i-a13-ehci"))
            return 1;
+       if (OF_is_compatible(faa->fa_node, "allwinner,sun50i-a64-ehci"))
+           return 1;
        if (OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-ehci"))
            return 1;
        if (OF_is_compatible(faa->fa_node, "allwinner,sun8i-h3-ehci"))

Reply via email to