Add more Allwinner A80 clocks.
authorkettenis <kettenis@openbsd.org>
Tue, 12 Dec 2017 22:31:44 +0000 (22:31 +0000)
committerkettenis <kettenis@openbsd.org>
Tue, 12 Dec 2017 22:31:44 +0000 (22:31 +0000)
sys/dev/fdt/sxiccmu.c
sys/dev/fdt/sxiccmu_clocks.h

index 212f447..bcbe637 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sxiccmu.c,v 1.9 2017/12/11 23:24:58 kettenis Exp $    */
+/*     $OpenBSD: sxiccmu.c,v 1.10 2017/12/12 22:31:44 kettenis Exp $   */
 /*
  * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
  * Copyright (c) 2013 Artturi Alm
@@ -94,14 +94,17 @@ uint32_t sxiccmu_a80_get_frequency(struct sxiccmu_softc *, uint32_t);
 int    sxiccmu_a80_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);
+uint32_t sxiccmu_nop_get_frequency(struct sxiccmu_softc *, uint32_t);
+int    sxiccmu_nop_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
 
 int
 sxiccmu_match(struct device *parent, void *match, void *aux)
 {
        struct fdt_attach_args *faa = aux;
+       int node = faa->fa_node;
 
-       if (faa->fa_node == OF_finddevice("/clocks")) {
-               int node = OF_parent(faa->fa_node);
+       if (node == OF_finddevice("/clocks")) {
+               node = OF_parent(node);
 
                return (OF_is_compatible(node, "allwinner,sun4i-a10") ||
                    OF_is_compatible(node, "allwinner,sun5i-a10s") ||
@@ -113,12 +116,14 @@ sxiccmu_match(struct device *parent, void *match, void *aux)
                    OF_is_compatible(node, "allwinner,sun50i-h5"));
        }
 
-       return (OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-ccu") ||
-           OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-ccu") ||
-           OF_is_compatible(faa->fa_node, "allwinner,sun8i-h3-ccu") ||
-           OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-ccu") ||
-           OF_is_compatible(faa->fa_node, "allwinner,sun50i-a64-ccu") ||
-           OF_is_compatible(faa->fa_node, "allwinner,sun50i-h5-ccu"));
+       return (OF_is_compatible(node, "allwinner,sun4i-a10-ccu") ||
+           OF_is_compatible(node, "allwinner,sun7i-a20-ccu") ||
+           OF_is_compatible(node, "allwinner,sun8i-h3-ccu") ||
+           OF_is_compatible(node, "allwinner,sun9i-a80-ccu") ||
+           OF_is_compatible(node, "allwinner,sun9i-a80-usb-clks") ||
+           OF_is_compatible(node, "allwinner,sun9i-a80-mmc-config-clk") ||
+           OF_is_compatible(node, "allwinner,sun50i-a64-ccu") ||
+           OF_is_compatible(node, "allwinner,sun50i-h5-ccu"));
 }
 
 void
@@ -126,7 +131,7 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux)
 {
        struct sxiccmu_softc *sc = (struct sxiccmu_softc *)self;
        struct fdt_attach_args *faa = aux;
-       int node;
+       int node = faa->fa_node;
 
        sc->sc_node = faa->fa_node;
        sc->sc_iot = faa->fa_iot;
@@ -136,8 +141,8 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux)
 
        printf("\n");
 
-       if (OF_is_compatible(sc->sc_node, "allwinner,sun4i-a10-ccu") ||
-           OF_is_compatible(sc->sc_node, "allwinner,sun7i-a20-ccu")) {
+       if (OF_is_compatible(node, "allwinner,sun4i-a10-ccu") ||
+           OF_is_compatible(node, "allwinner,sun7i-a20-ccu")) {
                KASSERT(faa->fa_nreg > 0);
                sc->sc_gates = sun4i_a10_gates;
                sc->sc_ngates = nitems(sun4i_a10_gates);
@@ -145,8 +150,8 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux)
                sc->sc_nresets = nitems(sun4i_a10_resets);
                sc->sc_get_frequency = sxiccmu_a10_get_frequency;
                sc->sc_set_frequency = sxiccmu_a10_set_frequency;
-       } else if (OF_is_compatible(sc->sc_node, "allwinner,sun8i-h3-ccu") ||
-           OF_is_compatible(sc->sc_node, "allwinner,sun50i-h5-ccu")) {
+       } else if (OF_is_compatible(node, "allwinner,sun8i-h3-ccu") ||
+           OF_is_compatible(node, "allwinner,sun50i-h5-ccu")) {
                KASSERT(faa->fa_nreg > 0);
                sc->sc_gates = sun8i_h3_gates;
                sc->sc_ngates = nitems(sun8i_h3_gates);
@@ -154,7 +159,7 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux)
                sc->sc_nresets = nitems(sun8i_h3_resets);
                sc->sc_get_frequency = sxiccmu_h3_get_frequency;
                sc->sc_set_frequency = sxiccmu_h3_set_frequency;
-       } else if (OF_is_compatible(sc->sc_node, "allwinner,sun9i-a80-ccu")) {
+       } else if (OF_is_compatible(node, "allwinner,sun9i-a80-ccu")) {
                KASSERT(faa->fa_nreg > 0);
                sc->sc_gates = sun9i_a80_gates;
                sc->sc_ngates = nitems(sun9i_a80_gates);
@@ -162,7 +167,23 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux)
                sc->sc_nresets = nitems(sun9i_a80_resets);
                sc->sc_get_frequency = sxiccmu_a80_get_frequency;
                sc->sc_set_frequency = sxiccmu_a80_set_frequency;
-       } else if (OF_is_compatible(sc->sc_node, "allwinner,sun50i-a64-ccu")) {
+       } else if (OF_is_compatible(node, "allwinner,sun9i-a80-usb-clks")) {
+               KASSERT(faa->fa_nreg > 0);
+               sc->sc_gates = sun9i_a80_usb_gates;
+               sc->sc_ngates = nitems(sun9i_a80_usb_gates);
+               sc->sc_resets = sun9i_a80_usb_resets;
+               sc->sc_nresets = nitems(sun9i_a80_usb_resets);
+               sc->sc_get_frequency = sxiccmu_nop_get_frequency;
+               sc->sc_set_frequency = sxiccmu_nop_set_frequency;
+       } else if (OF_is_compatible(node, "allwinner,sun9i-a80-mmc-config-clk")) {
+               KASSERT(faa->fa_nreg > 0);
+               sc->sc_gates = sun9i_a80_mmc_gates;
+               sc->sc_ngates = nitems(sun9i_a80_mmc_gates);
+               sc->sc_resets = sun9i_a80_mmc_resets;
+               sc->sc_nresets = nitems(sun9i_a80_mmc_resets);
+               sc->sc_get_frequency = sxiccmu_nop_get_frequency;
+               sc->sc_set_frequency = sxiccmu_nop_set_frequency;
+       } else 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);
@@ -171,7 +192,7 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux)
                sc->sc_get_frequency = sxiccmu_a64_get_frequency;
                sc->sc_set_frequency = sxiccmu_a64_set_frequency;
        } else {
-               for (node = OF_child(sc->sc_node); node; node = OF_peer(node))
+               for (node = OF_child(node); node; node = OF_peer(node))
                        sxiccmu_attach_clock(sc, node);
        }
 
@@ -857,6 +878,13 @@ sxiccmu_h3_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
        return 0;
 }
 
+uint32_t
+sxiccmu_nop_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
+{
+       printf("%s: 0x%08x\n", __func__, idx);
+       return 0;
+}
+
 int
 sxiccmu_ccu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
 {
@@ -955,6 +983,13 @@ sxiccmu_h3_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
        return -1;
 }
 
+int
+sxiccmu_nop_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
+{
+       printf("%s: 0x%08x\n", __func__, idx);
+       return -1;
+}
+
 void
 sxiccmu_ccu_enable(void *cookie, uint32_t *cells, int on)
 {
@@ -962,7 +997,10 @@ sxiccmu_ccu_enable(void *cookie, uint32_t *cells, int on)
        uint32_t idx = cells[0];
        int reg, bit;
 
-       if (idx >= sc->sc_ngates || sc->sc_gates[idx].reg == 0) {
+       clock_enable_all(sc->sc_node);
+
+       if (idx >= sc->sc_ngates ||
+           (sc->sc_gates[idx].reg == 0 && sc->sc_gates[idx].bit == 0)) {
                printf("%s: 0x%08x\n", __func__, cells[0]);
                return;
        }
@@ -983,7 +1021,10 @@ sxiccmu_ccu_reset(void *cookie, uint32_t *cells, int assert)
        uint32_t idx = cells[0];
        int reg, bit;
 
-       if (idx >= sc->sc_nresets || sc->sc_resets[idx].reg == 0) {
+       reset_deassert_all(sc->sc_node);
+
+       if (idx >= sc->sc_nresets || 
+           (sc->sc_resets[idx].reg == 0 && sc->sc_gates[idx].bit == 0)) {
                printf("%s: 0x%08x\n", __func__, cells[0]);
                return;
        }
index 3d58089..74bed95 100644 (file)
@@ -154,6 +154,8 @@ struct sxiccmu_ccu_bit sun50i_a64_gates[] = {
 #define A80_CLK_MMC2           39
 #define A80_CLK_MMC3           42
 
+#define A80_CLK_BUS_MMC                84
+#define A80_CLK_BUS_USB                96
 #define A80_CLK_BUS_PIO                111
 #define A80_CLK_BUS_UART0      124
 #define A80_CLK_BUS_UART1      125
@@ -166,7 +168,9 @@ struct sxiccmu_ccu_bit sun9i_a80_gates[] = {
        [A80_CLK_MMC0] =      { 0x0410, 31 },
        [A80_CLK_MMC1] =      { 0x0414, 31 },
        [A80_CLK_MMC2] =      { 0x0418, 31 },
-       [A80_CLK_MMC3] =      { 0x041c, 31 },
+       [A80_CLK_MMC3] =      { 0x041c, 31 }, /* Undocumented */
+       [A80_CLK_BUS_MMC] =   { 0x0580, 8 },
+       [A80_CLK_BUS_USB] =   { 0x0584, 1 },
        [A80_CLK_BUS_PIO] =   { 0x0590, 5 },
        [A80_CLK_BUS_UART0] = { 0x0594, 16, A80_CLK_APB1 },
        [A80_CLK_BUS_UART1] = { 0x0594, 17, A80_CLK_APB1 },
@@ -176,6 +180,40 @@ struct sxiccmu_ccu_bit sun9i_a80_gates[] = {
        [A80_CLK_BUS_UART5] = { 0x0594, 21, A80_CLK_APB1 },
 };
 
+#define A80_USB_CLK_HCI0       0
+#define A80_USB_CLK_OHCI0      1
+#define A80_USB_CLK_HCI1       2
+#define A80_USB_CLK_HCI2       3
+#define A80_USB_CLK_OHCI2      4
+
+#define A80_USB_CLK_HCI0_PHY           5
+#define A80_USB_CLK_HCI1_HSIC          6
+#define A80_USB_CLK_HCI1_PHY           7
+#define A80_USB_CLK_HCI2_HSIC          8
+#define A80_USB_CLK_HCI2_UTMIPHY       9
+#define A80_USB_CLK_HCI1_HSIC_12M      10
+
+struct sxiccmu_ccu_bit sun9i_a80_usb_gates[] = {
+       [A80_USB_CLK_HCI0] =          { 0x0000, 1 },
+       [A80_USB_CLK_OHCI0] =         { 0x0000, 2 },
+       [A80_USB_CLK_HCI1] =          { 0x0000, 3 },
+       [A80_USB_CLK_HCI2] =          { 0x0000, 5 },
+       [A80_USB_CLK_OHCI2] =         { 0x0000, 6 },
+       [A80_USB_CLK_HCI0_PHY] =      { 0x0004, 1 },
+       [A80_USB_CLK_HCI1_HSIC] =     { 0x0004, 2 },
+       [A80_USB_CLK_HCI1_PHY] =      { 0x0004, 3 }, /* Undocumented */
+       [A80_USB_CLK_HCI2_HSIC] =     { 0x0004, 4 },
+       [A80_USB_CLK_HCI2_UTMIPHY] =  { 0x0004, 5 },
+       [A80_USB_CLK_HCI1_HSIC_12M] = { 0x0004, 10 },
+};
+
+struct sxiccmu_ccu_bit sun9i_a80_mmc_gates[] = {
+       { 0x0000, 16 },
+       { 0x0004, 16 },
+       { 0x0008, 16 },
+       { 0x000c, 16 },
+};
+
 /* H3/H5 */
 
 #define H3_CLK_PLL_PERIPH0     9
@@ -304,6 +342,7 @@ struct sxiccmu_ccu_bit sun50i_a64_resets[] = {
 
 /* A80 */
 
+#define A80_RST_BUS_MMC                4
 #define A80_RST_BUS_UART0      45
 #define A80_RST_BUS_UART1      46
 #define A80_RST_BUS_UART2      47
@@ -312,12 +351,41 @@ struct sxiccmu_ccu_bit sun50i_a64_resets[] = {
 #define A80_RST_BUS_UART5      50
 
 struct sxiccmu_ccu_bit sun9i_a80_resets[] = {
-       [A80_CLK_BUS_UART0] = { 0x05b4, 16 },
-       [A80_CLK_BUS_UART1] = { 0x05b4, 17 },
-       [A80_CLK_BUS_UART2] = { 0x05b4, 18 },
-       [A80_CLK_BUS_UART3] = { 0x05b4, 19 },
-       [A80_CLK_BUS_UART4] = { 0x05b4, 20 },
-       [A80_CLK_BUS_UART5] = { 0x05b4, 21 },
+       [A80_RST_BUS_MMC] =   { 0x05a0, 8 },
+       [A80_RST_BUS_UART0] = { 0x05b4, 16 },
+       [A80_RST_BUS_UART1] = { 0x05b4, 17 },
+       [A80_RST_BUS_UART2] = { 0x05b4, 18 },
+       [A80_RST_BUS_UART3] = { 0x05b4, 19 },
+       [A80_RST_BUS_UART4] = { 0x05b4, 20 },
+       [A80_RST_BUS_UART5] = { 0x05b4, 21 },
+};
+
+#define A80_USB_RST_HCI0               0
+#define A80_USB_RST_HCI1               1
+#define A80_USB_RST_HCI2               2
+
+#define A80_USB_RST_HCI0_PHY           3
+#define A80_USB_RST_HCI1_HSIC          4
+#define A80_USB_RST_HCI1_PHY           5
+#define A80_USB_RST_HCI2_HSIC          6
+#define A80_USB_RST_HCI2_UTMIPHY       7
+
+struct sxiccmu_ccu_bit sun9i_a80_usb_resets[] = {
+       [A80_USB_RST_HCI0] =         { 0x0000, 17 },
+       [A80_USB_RST_HCI1] =         { 0x0000, 18 },
+       [A80_USB_RST_HCI2] =         { 0x0000, 19 },
+       [A80_USB_RST_HCI0_PHY] =     { 0x0004, 17 },
+       [A80_USB_RST_HCI1_HSIC]=     { 0x0004, 18 },
+       [A80_USB_RST_HCI1_PHY]=      { 0x0004, 19 }, /* Undocumented */
+       [A80_USB_RST_HCI2_HSIC]=     { 0x0004, 20 }, /* Undocumented */
+       [A80_USB_RST_HCI2_UTMIPHY] = { 0x0004, 21 },
+};
+
+struct sxiccmu_ccu_bit sun9i_a80_mmc_resets[] = {
+       { 0x0000, 18 },
+       { 0x0004, 18 },
+       { 0x0008, 18 },
+       { 0x000c, 18 },
 };
 
 /* H3/H5 */