-/* $OpenBSD: sxiccmu.c,v 1.8 2017/11/19 15:42:07 kettenis Exp $ */
+/* $OpenBSD: sxiccmu.c,v 1.9 2017/12/11 23:24:58 kettenis Exp $ */
/*
* Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
* Copyright (c) 2013 Artturi Alm
- * Copyright (c) 2016 Mark Kettenis <kettenis@openbsd.org>
+ * Copyright (c) 2016,2017 Mark Kettenis <kettenis@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
int sxiccmu_a10_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
uint32_t sxiccmu_a64_get_frequency(struct sxiccmu_softc *, uint32_t);
int sxiccmu_a64_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
+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);
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"));
}
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,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(sc->sc_node, "allwinner,sun8i-h3-ccu") ||
OF_is_compatible(sc->sc_node, "allwinner,sun50i-h5-ccu")) {
KASSERT(faa->fa_nreg > 0);
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")) {
+ KASSERT(faa->fa_nreg > 0);
+ sc->sc_gates = sun9i_a80_gates;
+ sc->sc_ngates = nitems(sun9i_a80_gates);
+ sc->sc_resets = sun9i_a80_resets;
+ 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")) {
+ 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 {
for (node = OF_child(sc->sc_node); node; node = OF_peer(node))
sxiccmu_attach_clock(sc, node);
return 0;
}
+uint32_t
+sxiccmu_a80_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
+{
+ switch (idx) {
+ case A80_CLK_PLL_PERIPH0:
+ /* Not hardcoded, but recommended. */
+ return 960000000;
+ case A80_CLK_APB1:
+ /* XXX Controlled by a MUX. */
+ return 24000000;
+ }
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return 0;
+}
+
uint32_t
sxiccmu_h3_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
{
return -1;
}
+int
+sxiccmu_a80_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
+{
+ struct sxiccmu_clock clock;
+ uint32_t parent, parent_freq;
+
+ switch (idx) {
+ case A80_CLK_MMC0:
+ case A80_CLK_MMC1:
+ case A80_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 = A80_CLK_PLL_PERIPH0;
+ 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)
{
[A64_CLK_USB_PHY1] = { 0x00cc, 9 },
};
+/* A80 */
+
+#define A80_CLK_PLL_PERIPH0 3
+
+#define A80_CLK_APB1 23
+
+#define A80_CLK_MMC0 33
+#define A80_CLK_MMC1 36
+#define A80_CLK_MMC2 39
+#define A80_CLK_MMC3 42
+
+#define A80_CLK_BUS_PIO 111
+#define A80_CLK_BUS_UART0 124
+#define A80_CLK_BUS_UART1 125
+#define A80_CLK_BUS_UART2 126
+#define A80_CLK_BUS_UART3 127
+#define A80_CLK_BUS_UART4 128
+#define A80_CLK_BUS_UART5 129
+
+struct sxiccmu_ccu_bit sun9i_a80_gates[] = {
+ [A80_CLK_MMC0] = { 0x0410, 31 },
+ [A80_CLK_MMC1] = { 0x0414, 31 },
+ [A80_CLK_MMC2] = { 0x0418, 31 },
+ [A80_CLK_MMC2] = { 0x041c, 31 },
+ [A80_CLK_BUS_PIO] = { 0x0590, 5 },
+ [A80_CLK_BUS_UART0] = { 0x0594, 16, A80_CLK_APB1 },
+ [A80_CLK_BUS_UART1] = { 0x0594, 17, A80_CLK_APB1 },
+ [A80_CLK_BUS_UART2] = { 0x0594, 18, A80_CLK_APB1 },
+ [A80_CLK_BUS_UART3] = { 0x0594, 19, A80_CLK_APB1 },
+ [A80_CLK_BUS_UART4] = { 0x0594, 20, A80_CLK_APB1 },
+ [A80_CLK_BUS_UART5] = { 0x0594, 21, A80_CLK_APB1 },
+};
+
/* H3/H5 */
#define H3_CLK_PLL_PERIPH0 9
[A64_RST_BUS_I2C2] = { 0x02d8, 2 },
};
+/* A80 */
+
+#define A80_RST_BUS_UART0 45
+#define A80_RST_BUS_UART1 46
+#define A80_RST_BUS_UART2 47
+#define A80_RST_BUS_UART3 48
+#define A80_RST_BUS_UART4 49
+#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 },
+};
+
/* H3/H5 */
#define H3_RST_USB_PHY0 0