summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2019-09-08 16:45:21 +0000
committerkettenis <kettenis@openbsd.org>2019-09-08 16:45:21 +0000
commit8b22851bda0c871cbea009d5d4c3b64d7f3d198d (patch)
tree38cbf2170448093f9d64205c6a87762444d686e4
parentHave sm_install() use install -F (fsync). (diff)
downloadwireguard-openbsd-8b22851bda0c871cbea009d5d4c3b64d7f3d198d.tar.xz
wireguard-openbsd-8b22851bda0c871cbea009d5d4c3b64d7f3d198d.zip
Add Allwinner H6 support.
-rw-r--r--sys/dev/fdt/sxiccmu.c138
-rw-r--r--sys/dev/fdt/sxiccmu_clocks.h87
2 files changed, 220 insertions, 5 deletions
diff --git a/sys/dev/fdt/sxiccmu.c b/sys/dev/fdt/sxiccmu.c
index a53e8562b8e..a19f505042c 100644
--- a/sys/dev/fdt/sxiccmu.c
+++ b/sys/dev/fdt/sxiccmu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sxiccmu.c,v 1.23 2019/09/02 13:08:49 kettenis Exp $ */
+/* $OpenBSD: sxiccmu.c,v 1.24 2019/09/08 16:45:21 kettenis Exp $ */
/*
* Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
* Copyright (c) 2013 Artturi Alm
@@ -101,6 +101,9 @@ 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_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_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);
@@ -144,7 +147,9 @@ sxiccmu_match(struct device *parent, void *match, void *aux)
OF_is_compatible(node, "allwinner,sun9i-a80-mmc-config-clk") ||
OF_is_compatible(node, "allwinner,sun50i-a64-ccu") ||
OF_is_compatible(node, "allwinner,sun50i-a64-r-ccu") ||
- OF_is_compatible(node, "allwinner,sun50i-h5-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"));
}
void
@@ -255,6 +260,22 @@ sxiccmu_attach(struct device *parent, struct device *self, void *aux)
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,sun50i-h6-ccu")) {
+ KASSERT(faa->fa_nreg > 0);
+ sc->sc_gates = sun50i_h6_gates;
+ sc->sc_ngates = nitems(sun50i_h6_gates);
+ sc->sc_resets = sun50i_h6_resets;
+ sc->sc_nresets = nitems(sun50i_h6_resets);
+ sc->sc_get_frequency = sxiccmu_h6_get_frequency;
+ sc->sc_set_frequency = sxiccmu_h6_set_frequency;
+ } else if (OF_is_compatible(node, "allwinner,sun50i-h6-r-ccu")) {
+ KASSERT(faa->fa_nreg > 0);
+ sc->sc_gates = sun50i_h6_r_gates;
+ sc->sc_ngates = nitems(sun50i_h6_r_gates);
+ sc->sc_resets = sun50i_h6_r_resets;
+ 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 {
for (node = OF_child(node); node; node = OF_peer(node))
sxiccmu_attach_clock(sc, node, faa->fa_nreg);
@@ -975,13 +996,13 @@ sxiccmu_a23_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
#define A64_PLL_CPUX_LOCK (1 << 28)
#define A64_PLL_CPUX_OUT_EXT_DIVP(x) (((x) >> 16) & 0x3)
#define A64_PLL_CPUX_OUT_EXT_DIVP_MASK (0x3 << 16)
-#define A64_PLL_CPUX_FACTOR_N(x) (((x) >> 8) & 0x1f)
+#define A64_PLL_CPUX_FACTOR_N(x) (((x) >> 8) & 0x1f)
#define A64_PLL_CPUX_FACTOR_N_MASK (0x1f << 8)
#define A64_PLL_CPUX_FACTOR_N_SHIFT 8
-#define A64_PLL_CPUX_FACTOR_K(x) (((x) >> 4) & 0x3)
+#define A64_PLL_CPUX_FACTOR_K(x) (((x) >> 4) & 0x3)
#define A64_PLL_CPUX_FACTOR_K_MASK (0x3 << 4)
#define A64_PLL_CPUX_FACTOR_K_SHIFT 4
-#define A64_PLL_CPUX_FACTOR_M(x) (((x) >> 0) & 0x3)
+#define A64_PLL_CPUX_FACTOR_M(x) (((x) >> 0) & 0x3)
#define A64_PLL_CPUX_FACTOR_M_MASK (0x3 << 0)
#define A64_CPUX_AXI_CFG_REG 0x0050
#define A64_CPUX_CLK_SRC_SEL (0x3 << 16)
@@ -1243,6 +1264,39 @@ sxiccmu_h3_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
}
uint32_t
+sxiccmu_h6_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
+{
+ switch (idx) {
+ case H6_CLK_PLL_PERIPH0:
+ /* Not hardcoded, but recommended. */
+ return 600000000;
+ case H6_CLK_PLL_PERIPH0_2X:
+ return sxiccmu_h6_get_frequency(sc, H6_CLK_PLL_PERIPH0) * 2;
+ case H6_CLK_APB2:
+ /* XXX Controlled by a MUX. */
+ return 24000000;
+ break;
+ }
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return 0;
+}
+
+uint32_t
+sxiccmu_h6_r_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
+{
+ switch (idx) {
+ case H6_R_CLK_APB2:
+ /* XXX Controlled by a MUX. */
+ return 24000000;
+ break;
+ }
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return 0;
+}
+
+uint32_t
sxiccmu_r40_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
{
uint32_t parent;
@@ -1553,6 +1607,76 @@ sxiccmu_h3_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
return -1;
}
+#define H6_SMHC0_CLK_REG 0x0830
+#define H6_SMHC1_CLK_REG 0x0834
+#define H6_SMHC2_CLK_REG 0x0838
+#define H6_SMHC_CLK_SRC_SEL (0x3 << 24)
+#define H6_SMHC_CLK_SRC_SEL_OSC24M (0x0 << 24)
+#define H6_SMHC_CLK_SRC_SEL_PLL_PERIPH0_2X (0x1 << 24)
+#define H6_SMHC_FACTOR_N_MASK (0x3 << 8)
+#define H6_SMHC_FACTOR_N_SHIFT 8
+#define H6_SMHC_FACTOR_M_MASK (0xf << 0)
+#define H6_SMHC_FACTOR_M_SHIFT 0
+
+int
+sxiccmu_h6_mmc_set_frequency(struct sxiccmu_softc *sc, bus_size_t offset,
+ uint32_t freq)
+{
+ uint32_t parent_freq;
+ uint32_t reg, m, n;
+ uint32_t clk_src;
+
+ switch (freq) {
+ case 400000:
+ n = 2, m = 15;
+ clk_src = H6_SMHC_CLK_SRC_SEL_OSC24M;
+ break;
+ case 20000000:
+ case 25000000:
+ case 26000000:
+ case 50000000:
+ 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)
+ m++;
+ break;
+ default:
+ return -1;
+ }
+
+ reg = SXIREAD4(sc, offset);
+ reg &= ~H6_SMHC_CLK_SRC_SEL;
+ reg |= clk_src;
+ reg &= ~H6_SMHC_FACTOR_N_MASK;
+ reg |= n << H6_SMHC_FACTOR_N_SHIFT;
+ reg &= ~H6_SMHC_FACTOR_M_MASK;
+ reg |= m << H6_SMHC_FACTOR_M_SHIFT;
+ SXIWRITE4(sc, offset, reg);
+
+ return 0;
+}
+
+int
+sxiccmu_h6_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
+{
+ switch (idx) {
+ case H6_CLK_MMC0:
+ return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC0_CLK_REG, freq);
+ case H6_CLK_MMC1:
+ return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC1_CLK_REG, freq);
+ case H6_CLK_MMC2:
+ return sxiccmu_h6_mmc_set_frequency(sc, H6_SMHC2_CLK_REG, freq);
+ }
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return -1;
+}
+
int
sxiccmu_r40_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
{
@@ -1620,6 +1744,10 @@ sxiccmu_ccu_enable(void *cookie, uint32_t *cells, int on)
return;
}
+ /* If the clock can't be gated, simply return. */
+ if (sc->sc_gates[idx].reg == 0xffff && sc->sc_gates[idx].bit == 0xff)
+ return;
+
reg = sc->sc_gates[idx].reg;
bit = sc->sc_gates[idx].bit;
diff --git a/sys/dev/fdt/sxiccmu_clocks.h b/sys/dev/fdt/sxiccmu_clocks.h
index ebc83c1edba..558c9a66f32 100644
--- a/sys/dev/fdt/sxiccmu_clocks.h
+++ b/sys/dev/fdt/sxiccmu_clocks.h
@@ -387,6 +387,59 @@ struct sxiccmu_ccu_bit sun8i_h3_r_gates[] = {
[H3_R_CLK_APB0_I2C] = { 0x0028, 6, H3_R_CLK_APB0 },
};
+/* H6 */
+
+#define H6_CLK_PLL_PERIPH0 3
+#define H6_CLK_PLL_PERIPH0_2X 4
+#define H6_CLK_APB1 26
+#define H6_CLK_APB2 27
+#define H6_CLK_MMC0 64
+#define H6_CLK_MMC1 65
+#define H6_CLK_MMC2 66
+#define H6_CLK_BUS_MMC0 67
+#define H6_CLK_BUS_MMC1 68
+#define H6_CLK_BUS_MMC2 69
+#define H6_CLK_BUS_UART0 70
+#define H6_CLK_BUS_UART1 71
+#define H6_CLK_BUS_UART2 72
+#define H6_CLK_BUS_UART3 73
+#define H6_CLK_USB_OHCI0 104
+#define H6_CLK_USB_OHCI3 107
+#define H6_CLK_BUS_OHCI0 111
+#define H6_CLK_BUS_OHCI3 112
+#define H6_CLK_BUS_EHCI0 113
+#define H6_CLK_BUS_EHCI3 115
+
+struct sxiccmu_ccu_bit sun50i_h6_gates[] = {
+ [H6_CLK_PLL_PERIPH0] = { 0x0020, 31 },
+ [H6_CLK_APB1] = { 0xffff, 0xff },
+ [H6_CLK_MMC0] = { 0x0830, 31 },
+ [H6_CLK_MMC1] = { 0x0834, 31 },
+ [H6_CLK_MMC2] = { 0x0838, 31 },
+ [H6_CLK_BUS_MMC0] = { 0x084c, 0 },
+ [H6_CLK_BUS_MMC1] = { 0x084c, 1 },
+ [H6_CLK_BUS_MMC2] = { 0x084c, 2 },
+ [H6_CLK_BUS_UART0] = { 0x090c, 0, H6_CLK_APB2 },
+ [H6_CLK_BUS_UART1] = { 0x090c, 1, H6_CLK_APB2 },
+ [H6_CLK_BUS_UART2] = { 0x090c, 2, H6_CLK_APB2 },
+ [H6_CLK_BUS_UART3] = { 0x090c, 3, H6_CLK_APB2 },
+ [H6_CLK_USB_OHCI0] = { 0x0a70, 31 },
+ [H6_CLK_USB_OHCI3] = { 0x0a7c, 31 },
+ [H6_CLK_BUS_OHCI0] = { 0x0a8c, 0 },
+ [H6_CLK_BUS_OHCI3] = { 0x0a8c, 3 },
+ [H6_CLK_BUS_EHCI0] = { 0x0a8c, 4 },
+ [H6_CLK_BUS_EHCI3] = { 0x0a8c, 7 },
+};
+
+#define H6_R_CLK_APB1 2
+#define H6_R_CLK_APB2 3
+#define H6_R_CLK_APB2_I2C 8
+
+struct sxiccmu_ccu_bit sun50i_h6_r_gates[] = {
+ [H6_R_CLK_APB1] = { 0xffff, 0xff },
+ [H6_R_CLK_APB2_I2C] = { 0x019c, 1, H6_R_CLK_APB2 },
+};
+
/* R40 */
#define R40_CLK_PLL_PERIPH0 11
@@ -724,6 +777,40 @@ struct sxiccmu_ccu_bit sun8i_h3_r_resets[] = {
[H3_R_RST_APB0_I2C] = { 0x00b0, 6 },
};
+/* H6 */
+
+#define H6_RST_BUS_MMC0 18
+#define H6_RST_BUS_MMC1 19
+#define H6_RST_BUS_MMC2 20
+#define H6_RST_BUS_UART0 21
+#define H6_RST_BUS_UART1 22
+#define H6_RST_BUS_UART2 23
+#define H6_RST_BUS_UART3 24
+#define H6_RST_BUS_OHCI0 48
+#define H6_RST_BUS_OHCI3 49
+#define H6_RST_BUS_EHCI0 50
+#define H6_RST_BUS_EHCI3 52
+
+struct sxiccmu_ccu_bit sun50i_h6_resets[] = {
+ [H6_RST_BUS_MMC0] = { 0x084c, 16 },
+ [H6_RST_BUS_MMC1] = { 0x084c, 17 },
+ [H6_RST_BUS_MMC2] = { 0x084c, 18 },
+ [H6_RST_BUS_UART0] = { 0x090c, 16 },
+ [H6_RST_BUS_UART1] = { 0x090c, 17 },
+ [H6_RST_BUS_UART2] = { 0x090c, 18 },
+ [H6_RST_BUS_UART3] = { 0x090c, 19 },
+ [H6_RST_BUS_OHCI0] = { 0x0a8c, 16 },
+ [H6_RST_BUS_OHCI3] = { 0x0a8c, 19 },
+ [H6_RST_BUS_EHCI0] = { 0x0a8c, 20 },
+ [H6_RST_BUS_EHCI3] = { 0x0a8c, 23 },
+};
+
+#define H6_R_RST_APB2_I2C 4
+
+struct sxiccmu_ccu_bit sun50i_h6_r_resets[] = {
+ [H6_R_RST_APB2_I2C] = { 0x019c, 16 },
+};
+
/* R40 */
#define R40_RST_USB_PHY0 0