-/* $OpenBSD: sxiccmu.c,v 1.9 2017/12/11 23:24:58 kettenis Exp $ */
+/* $OpenBSD: sxiccmu.c,v 1.10 2017/12/12 22:31:44 kettenis Exp $ */
/*
* Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
* Copyright (c) 2013 Artturi Alm
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_nop_get_frequency(struct sxiccmu_softc *, uint32_t);
+int sxiccmu_nop_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
int
sxiccmu_match(struct device *parent, void *match, void *aux)
{
struct fdt_attach_args *faa = aux;
+ int node = faa->fa_node;
- if (faa->fa_node == OF_finddevice("/clocks")) {
- int node = OF_parent(faa->fa_node);
+ if (node == OF_finddevice("/clocks")) {
+ node = OF_parent(node);
return (OF_is_compatible(node, "allwinner,sun4i-a10") ||
OF_is_compatible(node, "allwinner,sun5i-a10s") ||
OF_is_compatible(node, "allwinner,sun50i-h5"));
}
- 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"));
+ return (OF_is_compatible(node, "allwinner,sun4i-a10-ccu") ||
+ OF_is_compatible(node, "allwinner,sun7i-a20-ccu") ||
+ OF_is_compatible(node, "allwinner,sun8i-h3-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") ||
+ OF_is_compatible(node, "allwinner,sun50i-a64-ccu") ||
+ OF_is_compatible(node, "allwinner,sun50i-h5-ccu"));
}
void
{
struct sxiccmu_softc *sc = (struct sxiccmu_softc *)self;
struct fdt_attach_args *faa = aux;
- int node;
+ int node = faa->fa_node;
sc->sc_node = faa->fa_node;
sc->sc_iot = faa->fa_iot;
printf("\n");
- if (OF_is_compatible(sc->sc_node, "allwinner,sun4i-a10-ccu") ||
- OF_is_compatible(sc->sc_node, "allwinner,sun7i-a20-ccu")) {
+ if (OF_is_compatible(node, "allwinner,sun4i-a10-ccu") ||
+ OF_is_compatible(node, "allwinner,sun7i-a20-ccu")) {
KASSERT(faa->fa_nreg > 0);
sc->sc_gates = sun4i_a10_gates;
sc->sc_ngates = nitems(sun4i_a10_gates);
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,sun8i-h3-ccu") ||
- OF_is_compatible(sc->sc_node, "allwinner,sun50i-h5-ccu")) {
+ } else if (OF_is_compatible(node, "allwinner,sun8i-h3-ccu") ||
+ OF_is_compatible(node, "allwinner,sun50i-h5-ccu")) {
KASSERT(faa->fa_nreg > 0);
sc->sc_gates = sun8i_h3_gates;
sc->sc_ngates = nitems(sun8i_h3_gates);
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")) {
+ } else if (OF_is_compatible(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_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")) {
+ } else if (OF_is_compatible(node, "allwinner,sun9i-a80-usb-clks")) {
+ KASSERT(faa->fa_nreg > 0);
+ sc->sc_gates = sun9i_a80_usb_gates;
+ sc->sc_ngates = nitems(sun9i_a80_usb_gates);
+ sc->sc_resets = sun9i_a80_usb_resets;
+ sc->sc_nresets = nitems(sun9i_a80_usb_resets);
+ sc->sc_get_frequency = sxiccmu_nop_get_frequency;
+ sc->sc_set_frequency = sxiccmu_nop_set_frequency;
+ } else if (OF_is_compatible(node, "allwinner,sun9i-a80-mmc-config-clk")) {
+ KASSERT(faa->fa_nreg > 0);
+ sc->sc_gates = sun9i_a80_mmc_gates;
+ sc->sc_ngates = nitems(sun9i_a80_mmc_gates);
+ sc->sc_resets = sun9i_a80_mmc_resets;
+ sc->sc_nresets = nitems(sun9i_a80_mmc_resets);
+ sc->sc_get_frequency = sxiccmu_nop_get_frequency;
+ sc->sc_set_frequency = sxiccmu_nop_set_frequency;
+ } else if (OF_is_compatible(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_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))
+ for (node = OF_child(node); node; node = OF_peer(node))
sxiccmu_attach_clock(sc, node);
}
return 0;
}
+uint32_t
+sxiccmu_nop_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
+{
+ printf("%s: 0x%08x\n", __func__, idx);
+ return 0;
+}
+
int
sxiccmu_ccu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
{
return -1;
}
+int
+sxiccmu_nop_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
+{
+ printf("%s: 0x%08x\n", __func__, idx);
+ return -1;
+}
+
void
sxiccmu_ccu_enable(void *cookie, uint32_t *cells, int on)
{
uint32_t idx = cells[0];
int reg, bit;
- if (idx >= sc->sc_ngates || sc->sc_gates[idx].reg == 0) {
+ clock_enable_all(sc->sc_node);
+
+ if (idx >= sc->sc_ngates ||
+ (sc->sc_gates[idx].reg == 0 && sc->sc_gates[idx].bit == 0)) {
printf("%s: 0x%08x\n", __func__, cells[0]);
return;
}
uint32_t idx = cells[0];
int reg, bit;
- if (idx >= sc->sc_nresets || sc->sc_resets[idx].reg == 0) {
+ reset_deassert_all(sc->sc_node);
+
+ if (idx >= sc->sc_nresets ||
+ (sc->sc_resets[idx].reg == 0 && sc->sc_gates[idx].bit == 0)) {
printf("%s: 0x%08x\n", __func__, cells[0]);
return;
}
#define A80_CLK_MMC2 39
#define A80_CLK_MMC3 42
+#define A80_CLK_BUS_MMC 84
+#define A80_CLK_BUS_USB 96
#define A80_CLK_BUS_PIO 111
#define A80_CLK_BUS_UART0 124
#define A80_CLK_BUS_UART1 125
[A80_CLK_MMC0] = { 0x0410, 31 },
[A80_CLK_MMC1] = { 0x0414, 31 },
[A80_CLK_MMC2] = { 0x0418, 31 },
- [A80_CLK_MMC3] = { 0x041c, 31 },
+ [A80_CLK_MMC3] = { 0x041c, 31 }, /* Undocumented */
+ [A80_CLK_BUS_MMC] = { 0x0580, 8 },
+ [A80_CLK_BUS_USB] = { 0x0584, 1 },
[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_UART5] = { 0x0594, 21, A80_CLK_APB1 },
};
+#define A80_USB_CLK_HCI0 0
+#define A80_USB_CLK_OHCI0 1
+#define A80_USB_CLK_HCI1 2
+#define A80_USB_CLK_HCI2 3
+#define A80_USB_CLK_OHCI2 4
+
+#define A80_USB_CLK_HCI0_PHY 5
+#define A80_USB_CLK_HCI1_HSIC 6
+#define A80_USB_CLK_HCI1_PHY 7
+#define A80_USB_CLK_HCI2_HSIC 8
+#define A80_USB_CLK_HCI2_UTMIPHY 9
+#define A80_USB_CLK_HCI1_HSIC_12M 10
+
+struct sxiccmu_ccu_bit sun9i_a80_usb_gates[] = {
+ [A80_USB_CLK_HCI0] = { 0x0000, 1 },
+ [A80_USB_CLK_OHCI0] = { 0x0000, 2 },
+ [A80_USB_CLK_HCI1] = { 0x0000, 3 },
+ [A80_USB_CLK_HCI2] = { 0x0000, 5 },
+ [A80_USB_CLK_OHCI2] = { 0x0000, 6 },
+ [A80_USB_CLK_HCI0_PHY] = { 0x0004, 1 },
+ [A80_USB_CLK_HCI1_HSIC] = { 0x0004, 2 },
+ [A80_USB_CLK_HCI1_PHY] = { 0x0004, 3 }, /* Undocumented */
+ [A80_USB_CLK_HCI2_HSIC] = { 0x0004, 4 },
+ [A80_USB_CLK_HCI2_UTMIPHY] = { 0x0004, 5 },
+ [A80_USB_CLK_HCI1_HSIC_12M] = { 0x0004, 10 },
+};
+
+struct sxiccmu_ccu_bit sun9i_a80_mmc_gates[] = {
+ { 0x0000, 16 },
+ { 0x0004, 16 },
+ { 0x0008, 16 },
+ { 0x000c, 16 },
+};
+
/* H3/H5 */
#define H3_CLK_PLL_PERIPH0 9
/* A80 */
+#define A80_RST_BUS_MMC 4
#define A80_RST_BUS_UART0 45
#define A80_RST_BUS_UART1 46
#define A80_RST_BUS_UART2 47
#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 },
+ [A80_RST_BUS_MMC] = { 0x05a0, 8 },
+ [A80_RST_BUS_UART0] = { 0x05b4, 16 },
+ [A80_RST_BUS_UART1] = { 0x05b4, 17 },
+ [A80_RST_BUS_UART2] = { 0x05b4, 18 },
+ [A80_RST_BUS_UART3] = { 0x05b4, 19 },
+ [A80_RST_BUS_UART4] = { 0x05b4, 20 },
+ [A80_RST_BUS_UART5] = { 0x05b4, 21 },
+};
+
+#define A80_USB_RST_HCI0 0
+#define A80_USB_RST_HCI1 1
+#define A80_USB_RST_HCI2 2
+
+#define A80_USB_RST_HCI0_PHY 3
+#define A80_USB_RST_HCI1_HSIC 4
+#define A80_USB_RST_HCI1_PHY 5
+#define A80_USB_RST_HCI2_HSIC 6
+#define A80_USB_RST_HCI2_UTMIPHY 7
+
+struct sxiccmu_ccu_bit sun9i_a80_usb_resets[] = {
+ [A80_USB_RST_HCI0] = { 0x0000, 17 },
+ [A80_USB_RST_HCI1] = { 0x0000, 18 },
+ [A80_USB_RST_HCI2] = { 0x0000, 19 },
+ [A80_USB_RST_HCI0_PHY] = { 0x0004, 17 },
+ [A80_USB_RST_HCI1_HSIC]= { 0x0004, 18 },
+ [A80_USB_RST_HCI1_PHY]= { 0x0004, 19 }, /* Undocumented */
+ [A80_USB_RST_HCI2_HSIC]= { 0x0004, 20 }, /* Undocumented */
+ [A80_USB_RST_HCI2_UTMIPHY] = { 0x0004, 21 },
+};
+
+struct sxiccmu_ccu_bit sun9i_a80_mmc_resets[] = {
+ { 0x0000, 18 },
+ { 0x0004, 18 },
+ { 0x0008, 18 },
+ { 0x000c, 18 },
};
/* H3/H5 */