summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2018-02-25 20:42:14 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2018-02-25 20:42:14 +0000
commitef272bc4464dc228a5ef784f8b970cf096c1a608 (patch)
tree48e184fc96a8ce3ee025fd8519deaba0827b3080 /sys/dev
parent4b362b849bb1f5b8552a2c310ef80e198fa45b7e (diff)
More RK3328 clocks.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fdt/rkclock.c125
-rw-r--r--sys/dev/fdt/rkclock_clocks.h12
2 files changed, 105 insertions, 32 deletions
diff --git a/sys/dev/fdt/rkclock.c b/sys/dev/fdt/rkclock.c
index c26f80b1d60..505f97d0e18 100644
--- a/sys/dev/fdt/rkclock.c
+++ b/sys/dev/fdt/rkclock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rkclock.c,v 1.21 2018/02/25 13:25:57 kettenis Exp $ */
+/* $OpenBSD: rkclock.c,v 1.22 2018/02/25 20:42:13 kettenis Exp $ */
/*
* Copyright (c) 2017, 2018 Mark Kettenis <kettenis@openbsd.org>
*
@@ -46,8 +46,11 @@
#define RK3288_CRU_CLKSEL_CON(i) (0x0060 + (i) * 4)
/* RK3328 registers */
+#define RK3328_CRU_APLL_CON(i) (0x0000 + (i) * 4)
+#define RK3328_CRU_DPLL_CON(i) (0x0020 + (i) * 4)
#define RK3328_CRU_CPLL_CON(i) (0x0040 + (i) * 4)
#define RK3328_CRU_GPLL_CON(i) (0x0060 + (i) * 4)
+#define RK3328_CRU_NPLL_CON(i) (0x0080 + (i) * 4)
#define RK3328_CRU_CLKSEL_CON(i) (0x0100 + (i) * 4)
#define RK3328_CRU_PLL_POSTDIV1_MASK (0x7 << 12)
#define RK3328_CRU_PLL_POSTDIV1_SHIFT 12
@@ -582,6 +585,48 @@ rk3328_get_pll(struct rkclock_softc *sc, bus_size_t base)
}
uint32_t
+rk3328_get_sdmmc(struct rkclock_softc *sc, bus_size_t base)
+{
+ uint32_t reg, mux, div_con;
+ uint32_t idx;
+
+ reg = HREAD4(sc, base);
+ mux = (reg >> 8) & 0x3;
+ div_con = reg & 0xff;
+ switch (mux) {
+ case 0:
+ idx = RK3328_PLL_CPLL;
+ break;
+ case 1:
+ idx = RK3328_PLL_GPLL;
+ break;
+ case 2:
+ return 24000000 / (div_con + 1);
+#ifdef notyet
+ case 3:
+ idx = RK3328_USB_480M;
+ break;
+#endif
+ default:
+ return 0;
+ }
+ return rk3328_get_frequency(sc, &idx) / (div_con + 1);
+}
+
+uint32_t
+rk3328_get_i2c(struct rkclock_softc *sc, size_t base, int shift)
+{
+ uint32_t reg, mux, div_con;
+ uint32_t idx;
+
+ reg = HREAD4(sc, base);
+ mux = (reg >> (7 + shift)) & 0x1;
+ div_con = (reg >> shift) & 0x7f;
+ idx = (mux == 0) ? RK3328_PLL_CPLL : RK3328_PLL_GPLL;
+ return rk3328_get_frequency(sc, &idx) / (div_con + 1);
+}
+
+uint32_t
rk3328_get_frequency(void *cookie, uint32_t *cells)
{
struct rkclock_softc *sc = cookie;
@@ -589,56 +634,72 @@ rk3328_get_frequency(void *cookie, uint32_t *cells)
uint32_t reg, mux, div_con;
switch (idx) {
+ case RK3328_PLL_APLL:
+ return rk3328_get_pll(sc, RK3328_CRU_APLL_CON(0));
+ break;
+ case RK3328_PLL_DPLL:
+ return rk3328_get_pll(sc, RK3328_CRU_DPLL_CON(0));
+ break;
case RK3328_PLL_CPLL:
return rk3328_get_pll(sc, RK3328_CRU_CPLL_CON(0));
break;
case RK3328_PLL_GPLL:
return rk3328_get_pll(sc, RK3328_CRU_GPLL_CON(0));
break;
- case RK3328_CLK_SDMMC:
- reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(30));
- mux = (reg >> 8) & 0x3;
- div_con = reg & 0xff;
+ case RK3328_PLL_NPLL:
+ return rk3328_get_pll(sc, RK3328_CRU_NPLL_CON(0));
+ break;
+ case RK3328_ARMCLK:
+ reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(0));
+ mux = (reg >> 6) & 0x3;
+ div_con = reg & 0x1f;
switch (mux) {
case 0:
- idx = RK3328_PLL_CPLL;
+ idx = RK3328_PLL_APLL;
break;
case 1:
idx = RK3328_PLL_GPLL;
break;
case 2:
- return 24000000 / (div_con + 1);
-#ifdef notyet
+ idx = RK3328_PLL_DPLL;
+ break;
case 3:
- idx = RK3328_USB_480M;
+ idx = RK3328_PLL_NPLL;
break;
-#endif
- default:
- return 0;
}
return rk3328_get_frequency(sc, &idx) / (div_con + 1);
+ case RK3328_CLK_SDMMC:
+ return rk3328_get_sdmmc(sc, RK3328_CRU_CLKSEL_CON(30));
+ case RK3328_CLK_SDIO:
+ return rk3328_get_sdmmc(sc, RK3328_CRU_CLKSEL_CON(31));
case RK3328_CLK_EMMC:
- reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(32));
+ return rk3328_get_sdmmc(sc, RK3328_CRU_CLKSEL_CON(32));
+ case RK3328_CLK_UART0:
+ reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(14));
mux = (reg >> 8) & 0x3;
- div_con = reg & 0xff;
- switch (mux) {
- case 0:
- idx = RK3328_PLL_CPLL;
- break;
- case 1:
- idx = RK3328_PLL_GPLL;
- break;
- case 2:
- return 24000000 / (div_con + 1);
-#ifdef notyet
- case 3:
- idx = RK3328_USB_480M;
- break;
-#endif
- default:
- return 0;
- }
- return rk3328_get_frequency(sc, &idx) / (div_con + 1);
+ if (mux == 2)
+ return 24000000;
+ break;
+ case RK3328_CLK_UART1:
+ reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(16));
+ mux = (reg >> 8) & 0x3;
+ if (mux == 2)
+ return 24000000;
+ break;
+ case RK3328_CLK_UART2:
+ reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(18));
+ mux = (reg >> 8) & 0x3;
+ if (mux == 2)
+ return 24000000;
+ break;
+ case RK3328_CLK_I2C0:
+ return rk3328_get_i2c(sc, RK3399_CRU_CLKSEL_CON(34), 0);
+ case RK3328_CLK_I2C1:
+ return rk3328_get_i2c(sc, RK3399_CRU_CLKSEL_CON(34), 8);
+ case RK3328_CLK_I2C2:
+ return rk3328_get_i2c(sc, RK3399_CRU_CLKSEL_CON(35), 0);
+ case RK3328_CLK_I2C3:
+ return rk3328_get_i2c(sc, RK3399_CRU_CLKSEL_CON(35), 8);
}
printf("%s: 0x%08x\n", __func__, idx);
diff --git a/sys/dev/fdt/rkclock_clocks.h b/sys/dev/fdt/rkclock_clocks.h
index ea28cfc549c..3bdc4f0c107 100644
--- a/sys/dev/fdt/rkclock_clocks.h
+++ b/sys/dev/fdt/rkclock_clocks.h
@@ -38,11 +38,23 @@
* RK3328 clocks.
*/
+#define RK3328_PLL_APLL 1
+#define RK3328_PLL_DPLL 2
#define RK3328_PLL_CPLL 3
#define RK3328_PLL_GPLL 4
+#define RK3328_PLL_NPLL 5
+#define RK3328_ARMCLK 6
#define RK3328_CLK_SDMMC 33
+#define RK3328_CLK_SDIO 34
#define RK3328_CLK_EMMC 35
+#define RK3328_CLK_UART0 38
+#define RK3328_CLK_UART1 39
+#define RK3328_CLK_UART2 40
+#define RK3328_CLK_I2C0 55
+#define RK3328_CLK_I2C1 56
+#define RK3328_CLK_I2C2 57
+#define RK3328_CLK_I2C3 58
/*
* RK3399 clocks.