Re: sunxi: add Allwinner A64 support for USB and USB clocks

2017-01-20 Thread Patrick Wildt
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

2017-01-20 Thread Patrick Wildt
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