-/* $OpenBSD: sxiccmu.c,v 1.15 2017/12/30 12:45:36 kettenis Exp $ */
+/* $OpenBSD: sxiccmu.c,v 1.16 2017/12/30 16:30:37 kettenis Exp $ */
/*
* Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
* Copyright (c) 2013 Artturi Alm
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_r40_get_frequency(struct sxiccmu_softc *, uint32_t);
+int sxiccmu_r40_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);
OF_is_compatible(node, "allwinner,sun8i-a33-ccu") ||
OF_is_compatible(node, "allwinner,sun8i-h3-ccu") ||
OF_is_compatible(node, "allwinner,sun8i-h3-r-ccu") ||
+ OF_is_compatible(node, "allwinner,sun8i-r40-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") ||
sc->sc_nresets = nitems(sun8i_h3_r_resets);
sc->sc_get_frequency = sxiccmu_h3_r_get_frequency;
sc->sc_set_frequency = sxiccmu_nop_set_frequency;
+ } else if (OF_is_compatible(node, "allwinner,sun8i-r40-ccu")) {
+ KASSERT(faa->fa_nreg > 0);
+ sc->sc_gates = sun8i_r40_gates;
+ sc->sc_ngates = nitems(sun8i_r40_gates);
+ sc->sc_resets = sun8i_r40_resets;
+ sc->sc_nresets = nitems(sun8i_r40_resets);
+ sc->sc_get_frequency = sxiccmu_r40_get_frequency;
+ sc->sc_set_frequency = sxiccmu_r40_set_frequency;
} else if (OF_is_compatible(node, "allwinner,sun9i-a80-ccu")) {
KASSERT(faa->fa_nreg > 0);
sc->sc_gates = sun9i_a80_gates;
return 0;
}
+uint32_t
+sxiccmu_r40_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
+{
+ switch (idx) {
+ case R40_CLK_PLL_PERIPH0:
+ /* Not hardcoded, but recommended. */
+ return 600000000;
+ case R40_CLK_PLL_PERIPH0_2X:
+ return sxiccmu_r40_get_frequency(sc, A64_CLK_PLL_PERIPH0) * 2;
+ case R40_CLK_APB2:
+ /* XXX Controlled by a MUX. */
+ return 24000000;
+ }
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return 0;
+}
+
uint32_t
sxiccmu_nop_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
{
return -1;
}
+int
+sxiccmu_r40_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
+{
+ struct sxiccmu_clock clock;
+ uint32_t parent, parent_freq;
+
+ switch (idx) {
+ case R40_CLK_MMC0:
+ case R40_CLK_MMC1:
+ case R40_CLK_MMC2:
+ case R40_CLK_MMC3:
+ 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 = R40_CLK_PLL_PERIPH0_2X;
+ 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_nop_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
{
#define H3_R_CLK_APB0_PIO 3
#define H3_R_CLK_APB0_I2C 9
-
struct sxiccmu_ccu_bit sun8i_h3_r_gates[] = {
[H3_R_CLK_APB0_PIO] = { 0x0028, 0 },
[H3_R_CLK_APB0_I2C] = { 0x0028, 6, H3_R_CLK_APB0 },
};
+/* R40 */
+
+#define R40_CLK_PLL_PERIPH0 11
+#define R40_CLK_PLL_PERIPH0_2X 13
+
+#define R40_CLK_APB2 28
+
+#define R40_CLK_BUS_MMC0 32
+#define R40_CLK_BUS_MMC1 33
+#define R40_CLK_BUS_MMC2 34
+#define R40_CLK_BUS_MMC3 35
+#define R40_CLK_BUS_EHCI0 47
+#define R40_CLK_BUS_EHCI1 48
+#define R40_CLK_BUS_EHCI2 49
+#define R40_CLK_BUS_OHCI0 50
+#define R40_CLK_BUS_OHCI1 51
+#define R40_CLK_BUS_OHCI2 52
+#define R40_CLK_BUS_PIO 79
+#define R40_CLK_BUS_I2C0 87
+#define R40_CLK_BUS_I2C1 88
+#define R40_CLK_BUS_I2C2 89
+#define R40_CLK_BUS_I2C3 90
+#define R40_CLK_BUS_I2C4 95
+#define R40_CLK_BUS_UART0 96
+#define R40_CLK_BUS_UART1 97
+#define R40_CLK_BUS_UART2 98
+#define R40_CLK_BUS_UART3 99
+#define R40_CLK_BUS_UART4 100
+#define R40_CLK_BUS_UART5 101
+#define R40_CLK_BUS_UART6 102
+#define R40_CLK_BUS_UART7 103
+
+#define R40_CLK_MMC0 107
+#define R40_CLK_MMC1 108
+#define R40_CLK_MMC2 109
+#define R40_CLK_MMC3 110
+#define R40_CLK_USB_PHY0 124
+#define R40_CLK_USB_PHY1 125
+#define R40_CLK_USB_PHY2 126
+
+struct sxiccmu_ccu_bit sun8i_r40_gates[] = {
+ [R40_CLK_BUS_MMC0] = { 0x0060, 8 },
+ [R40_CLK_BUS_MMC1] = { 0x0060, 9 },
+ [R40_CLK_BUS_MMC2] = { 0x0060, 10 },
+ [R40_CLK_BUS_MMC3] = { 0x0060, 11 },
+ [R40_CLK_BUS_EHCI0] = { 0x0060, 26 },
+ [R40_CLK_BUS_EHCI1] = { 0x0060, 27 },
+ [R40_CLK_BUS_EHCI2] = { 0x0060, 28 },
+ [R40_CLK_BUS_OHCI0] = { 0x0060, 29 },
+ [R40_CLK_BUS_OHCI1] = { 0x0060, 30 },
+ [R40_CLK_BUS_OHCI2] = { 0x0060, 31 },
+ [R40_CLK_BUS_PIO] = { 0x0068, 5 },
+ [R40_CLK_BUS_I2C0] = { 0x006c, 0, R40_CLK_APB2 },
+ [R40_CLK_BUS_I2C1] = { 0x006c, 1, R40_CLK_APB2 },
+ [R40_CLK_BUS_I2C2] = { 0x006c, 2, R40_CLK_APB2 },
+ [R40_CLK_BUS_I2C3] = { 0x006c, 3, R40_CLK_APB2 },
+ [R40_CLK_BUS_I2C4] = { 0x006c, 15, R40_CLK_APB2 },
+ [R40_CLK_BUS_UART0] = { 0x006c, 16, R40_CLK_APB2 },
+ [R40_CLK_BUS_UART1] = { 0x006c, 17, R40_CLK_APB2 },
+ [R40_CLK_BUS_UART2] = { 0x006c, 18, R40_CLK_APB2 },
+ [R40_CLK_BUS_UART3] = { 0x006c, 19, R40_CLK_APB2 },
+ [R40_CLK_BUS_UART4] = { 0x006c, 20, R40_CLK_APB2 },
+ [R40_CLK_BUS_UART5] = { 0x006c, 21, R40_CLK_APB2 },
+ [R40_CLK_BUS_UART6] = { 0x006c, 22, R40_CLK_APB2 },
+ [R40_CLK_BUS_UART7] = { 0x006c, 23, R40_CLK_APB2 },
+ [R40_CLK_MMC0] = { 0x0088, 31 },
+ [R40_CLK_MMC1] = { 0x008c, 31 },
+ [R40_CLK_MMC2] = { 0x0090, 31 },
+ [R40_CLK_MMC3] = { 0x0094, 31 },
+ [R40_CLK_USB_PHY0] = { 0x00cc, 8 },
+ [R40_CLK_USB_PHY1] = { 0x00cc, 9 },
+ [R40_CLK_USB_PHY2] = { 0x00cc, 10 },
+};
+
/*
* Reset Signals
*/
struct sxiccmu_ccu_bit sun8i_h3_r_resets[] = {
[H3_R_RST_APB0_I2C] = { 0x00b0, 6 },
};
+
+/* R40 */
+
+#define R40_RST_USB_PHY0 0
+#define R40_RST_USB_PHY1 1
+#define R40_RST_USB_PHY2 2
+
+#define R40_RST_BUS_MMC0 8
+#define R40_RST_BUS_MMC1 9
+#define R40_RST_BUS_MMC2 10
+#define R40_RST_BUS_MMC3 11
+#define R40_RST_BUS_EHCI0 23
+#define R40_RST_BUS_EHCI1 24
+#define R40_RST_BUS_EHCI2 25
+#define R40_RST_BUS_OHCI0 26
+#define R40_RST_BUS_OHCI1 27
+#define R40_RST_BUS_OHCI2 28
+#define R40_RST_BUS_I2C0 64
+#define R40_RST_BUS_I2C1 65
+#define R40_RST_BUS_I2C2 66
+#define R40_RST_BUS_I2C3 67
+#define R40_RST_BUS_I2C4 72
+#define R40_RST_BUS_UART0 73
+#define R40_RST_BUS_UART1 74
+#define R40_RST_BUS_UART2 75
+#define R40_RST_BUS_UART3 76
+#define R40_RST_BUS_UART4 77
+#define R40_RST_BUS_UART5 78
+#define R40_RST_BUS_UART6 79
+#define R40_RST_BUS_UART7 80
+
+struct sxiccmu_ccu_bit sun8i_r40_resets[] = {
+ [R40_RST_USB_PHY0] = { 0x00cc, 0 },
+ [R40_RST_USB_PHY1] = { 0x00cc, 1 },
+ [R40_RST_USB_PHY2] = { 0x00cc, 2 },
+ [R40_RST_BUS_MMC0] = { 0x02c0, 8 },
+ [R40_RST_BUS_MMC1] = { 0x02c0, 9 },
+ [R40_RST_BUS_MMC2] = { 0x02c0, 10 },
+ [R40_RST_BUS_MMC3] = { 0x02c0, 11 },
+ [R40_RST_BUS_EHCI0] = { 0x02c0, 26 },
+ [R40_RST_BUS_EHCI1] = { 0x02c0, 27 },
+ [R40_RST_BUS_EHCI2] = { 0x02c0, 28 },
+ [R40_RST_BUS_OHCI0] = { 0x02c0, 29 },
+ [R40_RST_BUS_OHCI1] = { 0x02c0, 30 },
+ [R40_RST_BUS_OHCI2] = { 0x02c0, 31 },
+ [R40_RST_BUS_I2C0] = { 0x02d8, 0 },
+ [R40_RST_BUS_I2C1] = { 0x02d8, 1 },
+ [R40_RST_BUS_I2C2] = { 0x02d8, 2 },
+ [R40_RST_BUS_I2C3] = { 0x02d8, 3 },
+ [R40_RST_BUS_I2C4] = { 0x02d8, 15 },
+ [R40_RST_BUS_UART0] = { 0x02d8, 16 },
+ [R40_RST_BUS_UART1] = { 0x02d8, 17 },
+ [R40_RST_BUS_UART2] = { 0x02d8, 18 },
+ [R40_RST_BUS_UART3] = { 0x02d8, 19 },
+ [R40_RST_BUS_UART4] = { 0x02d8, 20 },
+ [R40_RST_BUS_UART5] = { 0x02d8, 21 },
+ [R40_RST_BUS_UART6] = { 0x02d8, 22 },
+ [R40_RST_BUS_UART7] = { 0x02d8, 23 },
+};