From 22652d99765773f177bc9238b6276c63ee3b5c92 Mon Sep 17 00:00:00 2001 From: uaa Date: Wed, 7 Feb 2024 22:00:38 +0000 Subject: [PATCH] add allwinner H616 support ok kettenis@ --- sys/dev/fdt/sxiccmu.c | 118 ++++++++++++++++++++++--- sys/dev/fdt/sxiccmu_clocks.h | 164 +++++++++++++++++++++++++++++++++++ sys/dev/fdt/sxisyscon.c | 5 +- 3 files changed, 274 insertions(+), 13 deletions(-) diff --git a/sys/dev/fdt/sxiccmu.c b/sys/dev/fdt/sxiccmu.c index d64ba10c326..31d4c7eebd3 100644 --- a/sys/dev/fdt/sxiccmu.c +++ b/sys/dev/fdt/sxiccmu.c @@ -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 * 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); diff --git a/sys/dev/fdt/sxiccmu_clocks.h b/sys/dev/fdt/sxiccmu_clocks.h index f8b4a85fd0a..bda6855fef7 100644 --- a/sys/dev/fdt/sxiccmu_clocks.h +++ b/sys/dev/fdt/sxiccmu_clocks.h @@ -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 diff --git a/sys/dev/fdt/sxisyscon.c b/sys/dev/fdt/sxisyscon.c index 9d547024444..abb8fed32bb 100644 --- a/sys/dev/fdt/sxisyscon.c +++ b/sys/dev/fdt/sxisyscon.c @@ -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 * @@ -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; -- 2.20.1