add allwinner H616 support
authoruaa <uaa@openbsd.org>
Wed, 7 Feb 2024 22:00:38 +0000 (22:00 +0000)
committeruaa <uaa@openbsd.org>
Wed, 7 Feb 2024 22:00:38 +0000 (22:00 +0000)
ok kettenis@

sys/dev/fdt/sxiccmu.c
sys/dev/fdt/sxiccmu_clocks.h
sys/dev/fdt/sxisyscon.c

index d64ba10..31d4c7e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sxiccmu.c,v 1.34 2024/02/02 12:01:49 kettenis Exp $   */
+/*     $OpenBSD: sxiccmu.c,v 1.35 2024/02/07 22:00:38 uaa Exp $        */
 /*
  * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
  * Copyright (c) 2013 Artturi Alm
@@ -106,6 +106,9 @@ uint32_t sxiccmu_h3_r_get_frequency(struct sxiccmu_softc *, uint32_t);
 uint32_t sxiccmu_h6_get_frequency(struct sxiccmu_softc *, uint32_t);
 int    sxiccmu_h6_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
 uint32_t sxiccmu_h6_r_get_frequency(struct sxiccmu_softc *, uint32_t);
+uint32_t sxiccmu_h616_get_frequency(struct sxiccmu_softc *, uint32_t);
+int    sxiccmu_h616_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
+uint32_t sxiccmu_h616_r_get_frequency(struct sxiccmu_softc *, uint32_t);
 uint32_t sxiccmu_r40_get_frequency(struct sxiccmu_softc *, uint32_t);
 int    sxiccmu_r40_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
 uint32_t sxiccmu_v3s_get_frequency(struct sxiccmu_softc *, uint32_t);
@@ -152,7 +155,9 @@ sxiccmu_match(struct device *parent, void *match, void *aux)
            OF_is_compatible(node, "allwinner,sun50i-a64-r-ccu") ||
            OF_is_compatible(node, "allwinner,sun50i-h5-ccu") ||
            OF_is_compatible(node, "allwinner,sun50i-h6-ccu") ||
-           OF_is_compatible(node, "allwinner,sun50i-h6-r-ccu"));
+           OF_is_compatible(node, "allwinner,sun50i-h6-r-ccu") ||
+           OF_is_compatible(node, "allwinner,sun50i-h616-ccu") ||
+           OF_is_compatible(node, "allwinner,sun50i-h616-r-ccu"));
 }
 
 void
@@ -287,6 +292,22 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux)
                sc->sc_nresets = nitems(sun50i_h6_r_resets);
                sc->sc_get_frequency = sxiccmu_h6_r_get_frequency;
                sc->sc_set_frequency = sxiccmu_nop_set_frequency;
+       } else if (OF_is_compatible(node, "allwinner,sun50i-h616-ccu")) {
+               KASSERT(faa->fa_nreg > 0);
+               sc->sc_gates = sun50i_h616_gates;
+               sc->sc_ngates = nitems(sun50i_h616_gates);
+               sc->sc_resets = sun50i_h616_resets;
+               sc->sc_nresets = nitems(sun50i_h616_resets);
+               sc->sc_get_frequency = sxiccmu_h616_get_frequency;
+               sc->sc_set_frequency = sxiccmu_h616_set_frequency;
+       } else if (OF_is_compatible(node, "allwinner,sun50i-h616-r-ccu")) {
+               KASSERT(faa->fa_nreg > 0);
+               sc->sc_gates = sun50i_h616_r_gates;
+               sc->sc_ngates = nitems(sun50i_h616_r_gates);
+               sc->sc_resets = sun50i_h616_r_resets;
+               sc->sc_nresets = nitems(sun50i_h616_r_resets);
+               sc->sc_get_frequency = sxiccmu_h616_r_get_frequency;
+               sc->sc_set_frequency = sxiccmu_nop_set_frequency;
        } else {
                for (node = OF_child(node); node; node = OF_peer(node))
                        sxiccmu_attach_clock(sc, node, faa->fa_nreg);
@@ -1400,7 +1421,6 @@ sxiccmu_h6_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
        case H6_CLK_APB2:
                /* XXX Controlled by a MUX. */
                return 24000000;
-               break;
        }
 
        printf("%s: 0x%08x\n", __func__, idx);
@@ -1414,7 +1434,52 @@ sxiccmu_h6_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
        case H6_R_CLK_APB2:
                /* XXX Controlled by a MUX. */
                return 24000000;
-               break;
+       }
+
+       printf("%s: 0x%08x\n", __func__, idx);
+       return 0;
+}
+
+/* Allwinner H616 */
+#define H616_AHB3_CFG_REG              0x051c
+#define H616_AHB3_CLK_FACTOR_N(x)      (((x) >> 8) & 0x3)
+#define H616_AHB3_CLK_FACTOR_M(x)      (((x) >> 0) & 0x3)
+
+uint32_t
+sxiccmu_h616_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
+{
+       uint32_t reg, m, n;
+       uint32_t freq;
+
+       switch (idx) {
+       case H616_CLK_PLL_PERIPH0:
+               /* Not hardcoded, but recommended. */
+               return 600000000;
+       case H616_CLK_PLL_PERIPH0_2X:
+               return sxiccmu_h616_get_frequency(sc, H616_CLK_PLL_PERIPH0) * 2;
+       case H616_CLK_AHB3:
+               reg = SXIREAD4(sc, H616_AHB3_CFG_REG);
+               /* assume PLL_PERIPH0 source */
+               freq = sxiccmu_h616_get_frequency(sc, H616_CLK_PLL_PERIPH0);
+               m = H616_AHB3_CLK_FACTOR_M(reg) + 1;
+               n = 1 << H616_AHB3_CLK_FACTOR_N(reg);
+               return freq / (m * n);
+       case H616_CLK_APB2:
+               /* XXX Controlled by a MUX. */
+               return 24000000;
+       }
+
+       printf("%s: 0x%08x\n", __func__, idx);
+       return 0;
+}
+
+uint32_t
+sxiccmu_h616_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
+{
+       switch (idx) {
+       case H616_R_CLK_APB2:
+               /* XXX Controlled by a MUX. */
+               return 24000000;
        }
 
        printf("%s: 0x%08x\n", __func__, idx);
@@ -1864,9 +1929,8 @@ sxiccmu_h3_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
 
 int
 sxiccmu_h6_mmc_set_frequency(struct sxiccmu_softc *sc, bus_size_t offset,
-    uint32_t freq)
+    uint32_t freq, uint32_t parent_freq)
 {
-       uint32_t parent_freq;
        uint32_t reg, m, n;
        uint32_t clk_src;
 
@@ -1882,8 +1946,6 @@ sxiccmu_h6_mmc_set_frequency(struct sxiccmu_softc *sc, bus_size_t offset,
        case 52000000:
                n = 0, m = 0;
                clk_src = H6_SMHC_CLK_SRC_SEL_PLL_PERIPH0_2X;
-               parent_freq =
-                   sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0_2X);
                while ((parent_freq / (1 << n) / 16) > freq)
                        n++;
                while ((parent_freq / (1 << n) / (m + 1)) > freq)
@@ -1908,13 +1970,47 @@ sxiccmu_h6_mmc_set_frequency(struct sxiccmu_softc *sc, bus_size_t offset,
 int
 sxiccmu_h6_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
 {
+       uint32_t parent_freq;
+
+       parent_freq = sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0_2X);
+
        switch (idx) {
        case H6_CLK_MMC0:
-               return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC0_CLK_REG, freq);
+               return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC0_CLK_REG,
+                                                   freq, parent_freq);
        case H6_CLK_MMC1:
-               return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC1_CLK_REG, freq);
+               return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC1_CLK_REG,
+                                                   freq, parent_freq);
        case H6_CLK_MMC2:
-               return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC2_CLK_REG, freq);
+               return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC2_CLK_REG,
+                                                   freq, parent_freq);
+       }
+
+       printf("%s: 0x%08x\n", __func__, idx);
+       return -1;
+}
+
+#define H616_SMHC0_CLK_REG             0x0830
+#define H616_SMHC1_CLK_REG             0x0834
+#define H616_SMHC2_CLK_REG             0x0838
+
+int
+sxiccmu_h616_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
+{
+       uint32_t parent_freq;
+
+       parent_freq = sxiccmu_h616_get_frequency(sc, H616_CLK_PLL_PERIPH0_2X);
+
+       switch (idx) {
+       case H616_CLK_MMC0:
+               return sxiccmu_h6_mmc_set_frequency(sc, H616_SMHC0_CLK_REG,
+                                                   freq, parent_freq);
+       case H616_CLK_MMC1:
+               return sxiccmu_h6_mmc_set_frequency(sc, H616_SMHC1_CLK_REG,
+                                                   freq, parent_freq);
+       case H616_CLK_MMC2:
+               return sxiccmu_h6_mmc_set_frequency(sc, H616_SMHC2_CLK_REG,
+                                                   freq, parent_freq);
        }
 
        printf("%s: 0x%08x\n", __func__, idx);
index f8b4a85..bda6855 100644 (file)
@@ -516,6 +516,100 @@ const struct sxiccmu_ccu_bit sun50i_h6_r_gates[] = {
        [H6_R_CLK_APB2_RSB] = { 0x01bc, 0, H6_R_CLK_APB2 },
 };
 
+/* H616 */
+
+#define H616_CLK_PLL_PERIPH0   4
+#define H616_CLK_PLL_PERIPH0_2X        5
+#define H616_CLK_AHB3          25
+#define H616_CLK_APB1          26
+#define H616_CLK_APB2          27
+#define H616_CLK_MMC0          60
+#define H616_CLK_MMC1          61
+#define H616_CLK_MMC2          62
+#define H616_CLK_BUS_MMC0      63
+#define H616_CLK_BUS_MMC1      64
+#define H616_CLK_BUS_MMC2      65
+#define H616_CLK_BUS_UART0     66
+#define H616_CLK_BUS_UART1     67
+#define H616_CLK_BUS_UART2     68
+#define H616_CLK_BUS_UART3     69
+#define H616_CLK_BUS_UART4     70
+#define H616_CLK_BUS_UART5     71
+#define H616_CLK_BUS_I2C0      72
+#define H616_CLK_BUS_I2C1      73
+#define H616_CLK_BUS_I2C2      74
+#define H616_CLK_BUS_I2C3      75
+#define H616_CLK_BUS_I2C4      76
+#define H616_CLK_BUS_EMAC0     82
+#define H616_CLK_BUS_EMAC1     83
+#define H616_CLK_USB_OHCI0     96
+#define H616_CLK_USB_PHY0      97
+#define H616_CLK_USB_OHCI1     98
+#define H616_CLK_USB_PHY1      99
+#define H616_CLK_USB_OHCI2     100
+#define H616_CLK_USB_PHY2      101
+#define H616_CLK_USB_OHCI3     102
+#define H616_CLK_USB_PHY3      103
+#define H616_CLK_BUS_OHCI0     104
+#define H616_CLK_BUS_OHCI1     105
+#define H616_CLK_BUS_OHCI2     106
+#define H616_CLK_BUS_OHCI3     107
+#define H616_CLK_BUS_EHCI0     108
+#define H616_CLK_BUS_EHCI1     109
+#define H616_CLK_BUS_EHCI2     110
+#define H616_CLK_BUS_EHCI3     111
+
+struct sxiccmu_ccu_bit sun50i_h616_gates[] = {
+       [H616_CLK_PLL_PERIPH0] = { 0x0020, 31 },
+       [H616_CLK_APB1] = { 0xffff, 0xff },
+       [H616_CLK_MMC0] = { 0x0830, 31 },
+       [H616_CLK_MMC1] = { 0x0834, 31 },
+       [H616_CLK_MMC2] = { 0x0838, 31 },
+       [H616_CLK_BUS_MMC0] = { 0x084c, 0 },
+       [H616_CLK_BUS_MMC1] = { 0x084c, 1 },
+       [H616_CLK_BUS_MMC2] = { 0x084c, 2 },
+       [H616_CLK_BUS_UART0] = { 0x090c, 0, H616_CLK_APB2 },
+       [H616_CLK_BUS_UART1] = { 0x090c, 1, H616_CLK_APB2 },
+       [H616_CLK_BUS_UART2] = { 0x090c, 2, H616_CLK_APB2 },
+       [H616_CLK_BUS_UART3] = { 0x090c, 3, H616_CLK_APB2 },
+       [H616_CLK_BUS_UART4] = { 0x090c, 4, H616_CLK_APB2 },
+       [H616_CLK_BUS_UART5] = { 0x090c, 5, H616_CLK_APB2 },
+       [H616_CLK_BUS_I2C0] = { 0x091c, 0, H616_CLK_APB2 },
+       [H616_CLK_BUS_I2C1] = { 0x091c, 1, H616_CLK_APB2 },
+       [H616_CLK_BUS_I2C2] = { 0x091c, 2, H616_CLK_APB2 },
+       [H616_CLK_BUS_I2C3] = { 0x091c, 3, H616_CLK_APB2 },
+       [H616_CLK_BUS_I2C4] = { 0x091c, 4, H616_CLK_APB2 },
+       [H616_CLK_BUS_EMAC0] = { 0x097c, 0, H616_CLK_AHB3 },
+       [H616_CLK_BUS_EMAC1] = { 0x097c, 1, H616_CLK_AHB3 },
+       [H616_CLK_USB_OHCI0] = { 0x0a70, 31 },
+       [H616_CLK_USB_PHY0] = { 0x0a70, 29 },
+       [H616_CLK_USB_OHCI1] = { 0x0a74, 31 },
+       [H616_CLK_USB_PHY1] = { 0x0a74, 29 },
+       [H616_CLK_USB_OHCI2] = { 0x0a78, 31 },
+       [H616_CLK_USB_PHY2] = { 0x0a78, 29 },
+       [H616_CLK_USB_OHCI3] = { 0x0a7c, 31 },
+       [H616_CLK_USB_PHY3] = { 0x0a7c, 29 },
+       [H616_CLK_BUS_OHCI0] = { 0x0a8c, 0 },
+       [H616_CLK_BUS_OHCI1] = { 0x0a8c, 1 },
+       [H616_CLK_BUS_OHCI2] = { 0x0a8c, 2 },
+       [H616_CLK_BUS_OHCI3] = { 0x0a8c, 3 },
+       [H616_CLK_BUS_EHCI0] = { 0x0a8c, 4 },
+       [H616_CLK_BUS_EHCI1] = { 0x0a8c, 5 },
+       [H616_CLK_BUS_EHCI2] = { 0x0a8c, 6 },
+       [H616_CLK_BUS_EHCI3] = { 0x0a8c, 7 },
+};
+
+#define H616_R_CLK_APB1                2
+#define H616_R_CLK_APB2                3
+#define H616_R_CLK_APB2_I2C    8
+#define H616_R_CLK_APB2_RSB    13
+
+struct sxiccmu_ccu_bit sun50i_h616_r_gates[] = {
+       [H616_R_CLK_APB1] = { 0xffff, 0xff },
+       [H616_R_CLK_APB2_I2C] = { 0x019c, 0, H616_R_CLK_APB2 },
+       [H616_R_CLK_APB2_RSB] = { 0x01bc, 0, H616_R_CLK_APB2 },
+};
+
 /* R40 */
 
 #define R40_CLK_PLL_PERIPH0    11
@@ -963,6 +1057,76 @@ const struct sxiccmu_ccu_bit sun50i_h6_r_resets[] = {
        [H6_R_RST_APB2_RSB] = { 0x01bc, 16 },
 };
 
+/* H616 */
+
+#define H616_RST_BUS_MMC0      14
+#define H616_RST_BUS_MMC1      15
+#define H616_RST_BUS_MMC2      16
+#define H616_RST_BUS_UART0     17
+#define H616_RST_BUS_UART1     18
+#define H616_RST_BUS_UART2     19
+#define H616_RST_BUS_UART3     20
+#define H616_RST_BUS_UART4     21
+#define H616_RST_BUS_UART5     22
+#define H616_RST_BUS_I2C0      23
+#define H616_RST_BUS_I2C1      24
+#define H616_RST_BUS_I2C2      25
+#define H616_RST_BUS_I2C3      26
+#define H616_RST_BUS_I2C4      27
+#define H616_RST_BUS_EMAC0     30
+#define H616_RST_BUS_EMAC1     31
+#define H616_RST_USB_PHY0      38
+#define H616_RST_USB_PHY1      39
+#define H616_RST_USB_PHY2      40
+#define H616_RST_USB_PHY3      41
+#define H616_RST_BUS_OHCI0     42
+#define H616_RST_BUS_OHCI1     43
+#define H616_RST_BUS_OHCI2     44
+#define H616_RST_BUS_OHCI3     45
+#define H616_RST_BUS_EHCI0     46
+#define H616_RST_BUS_EHCI1     47
+#define H616_RST_BUS_EHCI2     48
+#define H616_RST_BUS_EHCI3     49
+
+struct sxiccmu_ccu_bit sun50i_h616_resets[] = {
+       [H616_RST_BUS_MMC0] = { 0x084c, 16 },
+       [H616_RST_BUS_MMC1] = { 0x084c, 17 },
+       [H616_RST_BUS_MMC2] = { 0x084c, 18 },
+       [H616_RST_BUS_UART0] = { 0x090c, 16 },
+       [H616_RST_BUS_UART1] = { 0x090c, 17 },
+       [H616_RST_BUS_UART2] = { 0x090c, 18 },
+       [H616_RST_BUS_UART3] = { 0x090c, 19 },
+       [H616_RST_BUS_UART4] = { 0x090c, 20 },
+       [H616_RST_BUS_UART5] = { 0x090c, 21 },
+       [H616_RST_BUS_I2C0] = { 0x091c, 16 },
+       [H616_RST_BUS_I2C1] = { 0x091c, 17 },
+       [H616_RST_BUS_I2C2] = { 0x091c, 18 },
+       [H616_RST_BUS_I2C3] = { 0x091c, 19 },
+       [H616_RST_BUS_I2C4] = { 0x091c, 20 },
+       [H616_RST_BUS_EMAC0] = { 0x097c, 16 },
+       [H616_RST_BUS_EMAC1] = { 0x097c, 17 },
+       [H616_RST_USB_PHY0] = { 0x0a70, 30 },
+       [H616_RST_USB_PHY1] = { 0x0a74, 30 },
+       [H616_RST_USB_PHY2] = { 0x0a78, 30 },
+       [H616_RST_USB_PHY3] = { 0x0a7c, 30 },
+       [H616_RST_BUS_OHCI0] = { 0x0a8c, 16 },
+       [H616_RST_BUS_OHCI1] = { 0x0a8c, 17 },
+       [H616_RST_BUS_OHCI2] = { 0x0a8c, 18 },
+       [H616_RST_BUS_OHCI3] = { 0x0a8c, 19 },
+       [H616_RST_BUS_EHCI0] = { 0x0a8c, 20 },
+       [H616_RST_BUS_EHCI1] = { 0x0a8c, 21 },
+       [H616_RST_BUS_EHCI2] = { 0x0a8c, 22 },
+       [H616_RST_BUS_EHCI3] = { 0x0a8c, 23 },
+};
+
+#define H616_R_RST_APB2_I2C    4
+#define H616_R_RST_APB2_RSB    7
+
+struct sxiccmu_ccu_bit sun50i_h616_r_resets[] = {
+       [H616_R_RST_APB2_I2C] = { 0x019c, 16 },
+       [H616_R_RST_APB2_RSB] = { 0x01bc, 16 },
+};
+
 /* R40 */
 
 #define R40_RST_USB_PHY0       0
index 9d54702..abb8fed 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sxisyscon.c,v 1.2 2021/10/24 17:52:27 mpi Exp $       */
+/*     $OpenBSD: sxisyscon.c,v 1.3 2024/02/07 22:00:38 uaa Exp $       */
 /*
  * Copyright (c) 2019 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -52,7 +52,8 @@ sxisyscon_match(struct device *parent, void *match, void *aux)
        if (OF_is_compatible(node, "allwinner,sun8i-h3-system-control") ||
            OF_is_compatible(node, "allwinner,sun50i-a64-system-control") ||
            OF_is_compatible(node, "allwinner,sun50i-h5-system-control") ||
-           OF_is_compatible(node, "allwinner,sun50i-h6-system-control"))
+           OF_is_compatible(node, "allwinner,sun50i-h6-system-control") ||
+           OF_is_compatible(node, "allwinner,sun50i-h616-system-control"))
                return 10;      /* Must beat syscon(4). */
 
        return 0;