summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2017-07-23 10:12:58 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2017-07-23 10:12:58 +0000
commitc0383d349e33c632972d97bd13a94ad0d2d11bcd (patch)
tree56dcc5a20c4d723f7729cc82c32dd6e6adb6fdd7
parent429d76352955b5ab348af5dbba58142f1ab0b963 (diff)
Add RK3288 support.
-rw-r--r--sys/dev/fdt/rkclock.c154
-rw-r--r--sys/dev/fdt/rkclock_clocks.h16
2 files changed, 167 insertions, 3 deletions
diff --git a/sys/dev/fdt/rkclock.c b/sys/dev/fdt/rkclock.c
index 4c0a921ddee..f6d25a914c4 100644
--- a/sys/dev/fdt/rkclock.c
+++ b/sys/dev/fdt/rkclock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rkclock.c,v 1.6 2017/05/20 23:12:40 kettenis Exp $ */
+/* $OpenBSD: rkclock.c,v 1.7 2017/07/23 10:12:57 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
*
@@ -28,7 +28,12 @@
#include <dev/ofw/ofw_clock.h>
#include <dev/ofw/fdt.h>
-/* Registers */
+/* RK3288 registers */
+#define RK3288_CRU_CPLL_CON(i) (0x0020 + (i) * 4)
+#define RK3288_CRU_GPLL_CON(i) (0x0030 + (i) * 4)
+#define RK3288_CRU_CLKSEL_CON(i) (0x0060 + (i) * 4)
+
+/* RK3399 registers */
#define RK3399_CRU_CPLL_CON(i) (0x0060 + (i) * 4)
#define RK3399_CRU_GPLL_CON(i) (0x0080 + (i) * 4)
#define RK3399_CRU_NPLL_CON(i) (0x00a0 + (i) * 4)
@@ -68,6 +73,11 @@ struct cfdriver rkclock_cd = {
NULL, "rkclock", DV_DULL
};
+uint32_t rk3288_get_frequency(void *, uint32_t *);
+int rk3288_set_frequency(void *, uint32_t *, uint32_t);
+void rk3288_enable(void *, uint32_t *, int);
+void rk3288_reset(void *, uint32_t *, int);
+
uint32_t rk3399_get_frequency(void *, uint32_t *);
int rk3399_set_frequency(void *, uint32_t *, uint32_t);
void rk3399_enable(void *, uint32_t *, int);
@@ -88,8 +98,13 @@ struct rkclock_compat {
struct rkclock_compat rkclock_compat[] = {
{
+ "rockchip,rk3288-cru",
+ rk3288_enable, rk3288_get_frequency,
+ rk3288_set_frequency, rk3288_reset
+ },
+ {
"rockchip,rk3399-cru",
- rk3399_enable,rk3399_get_frequency,
+ rk3399_enable, rk3399_get_frequency,
rk3399_set_frequency, rk3399_reset
},
{
@@ -156,9 +171,142 @@ rkclock_attach(struct device *parent, struct device *self, void *aux)
reset_register(&sc->sc_rd);
}
+/*
+ * Rockchip RK3288
+ */
+
+uint32_t
+rk3288_get_pll(struct rkclock_softc *sc, bus_size_t base)
+{
+ uint32_t clkod, clkr, clkf;
+ uint32_t reg;
+
+ reg = HREAD4(sc, base);
+ clkod = (reg >> 0) & 0xf;
+ clkr = (reg >> 8) & 0x3f;
+ reg = HREAD4(sc, base + 4);
+ clkf = (reg >> 0) & 0x1fff;
+ return 24000000ULL * (clkf + 1) / (clkr + 1) / (clkod + 1);
+}
+
+uint32_t
+rk3288_get_frequency(void *cookie, uint32_t *cells)
+{
+ struct rkclock_softc *sc = cookie;
+ uint32_t idx = cells[0];
+ uint32_t reg, mux, div_con;
+
+ switch (idx) {
+ case RK3288_PLL_CPLL:
+ return rk3288_get_pll(sc, RK3288_CRU_CPLL_CON(0));
+ case RK3288_PLL_GPLL:
+ return rk3288_get_pll(sc, RK3288_CRU_GPLL_CON(0));
+ case RK3288_CLK_SDMMC:
+ reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(11));
+ mux = (reg >> 6) & 0x3;
+ div_con = reg & 0x3f;
+ switch (mux) {
+ case 0:
+ idx = RK3288_PLL_CPLL;
+ break;
+ case 1:
+ idx = RK3288_PLL_GPLL;
+ break;
+ case 2:
+ return 24000000 / (div_con + 1);
+ default:
+ return 0;
+ }
+ return rk3288_get_frequency(sc, &idx) / (div_con + 1);
+ break;
+ case RK3288_CLK_UART0:
+ reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(13));
+ mux = (reg >> 8) & 0x3;
+ div_con = reg & 0x7f;
+ if (mux == 2)
+ return 24000000 / (div_con + 1);
+ break;
+ case RK3288_CLK_UART1:
+ reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(14));
+ mux = (reg >> 8) & 0x3;
+ div_con = reg & 0x7f;
+ if (mux == 2)
+ return 24000000 / (div_con + 1);
+ break;
+ case RK3288_CLK_UART2:
+ reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(15));
+ mux = (reg >> 8) & 0x3;
+ div_con = reg & 0x7f;
+ if (mux == 2)
+ return 24000000 / (div_con + 1);
+ break;
+ case RK3288_CLK_UART3:
+ reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(16));
+ mux = (reg >> 8) & 0x3;
+ div_con = reg & 0x7f;
+ if (mux == 2)
+ return 24000000 / (div_con + 1);
+ break;
+ case RK3288_CLK_UART4:
+ reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(3));
+ mux = (reg >> 8) & 0x3;
+ div_con = reg & 0x7f;
+ if (mux == 2)
+ return 24000000 / (div_con + 1);
+ break;
+ default:
+ break;
+ }
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return 0;
+}
+
+int
+rk3288_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
+{
+ uint32_t idx = cells[0];
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return -1;
+}
+
+void
+rk3288_enable(void *cookie, uint32_t *cells, int on)
+{
+ uint32_t idx = cells[0];
+
+ switch (idx) {
+ case RK3288_CLK_SDMMC:
+ case RK3288_CLK_UART0:
+ case RK3288_CLK_UART1:
+ case RK3288_CLK_UART2:
+ case RK3288_CLK_UART3:
+ case RK3288_CLK_UART4:
+ case RK3288_CLK_SDMMC_DRV:
+ case RK3288_CLK_SDMMC_SAMPLE:
+ case RK3288_HCLK_HOST0:
+ case RK3288_HCLK_SDMMC:
+ /* Enabled by default. */
+ break;
+ default:
+ printf("%s: 0x%08x\n", __func__, idx);
+ break;
+ }
+}
+
+void
+rk3288_reset(void *cookie, uint32_t *cells, int on)
+{
+ uint32_t idx = cells[0];
+
+ printf("%s: 0x%08x\n", __func__, idx);
+}
+
/*
* Rockchip RK3399
*/
+
uint32_t
rk3399_get_pll(struct rkclock_softc *sc, bus_size_t base)
{
diff --git a/sys/dev/fdt/rkclock_clocks.h b/sys/dev/fdt/rkclock_clocks.h
index 44500398645..cd497ce4472 100644
--- a/sys/dev/fdt/rkclock_clocks.h
+++ b/sys/dev/fdt/rkclock_clocks.h
@@ -1,5 +1,21 @@
/* Public Domain */
+#define RK3288_PLL_CPLL 3
+#define RK3288_PLL_GPLL 4
+
+#define RK3288_CLK_SDMMC 68
+#define RK3288_CLK_UART0 77
+#define RK3288_CLK_UART1 78
+#define RK3288_CLK_UART2 79
+#define RK3288_CLK_UART3 80
+#define RK3288_CLK_UART4 81
+
+#define RK3288_CLK_SDMMC_DRV 114
+#define RK3288_CLK_SDMMC_SAMPLE 118
+
+#define RK3288_HCLK_HOST0 450
+#define RK3288_HCLK_SDMMC 456
+
#define RK3399_PLL_CPLL 4
#define RK3399_PLL_GPLL 5
#define RK3399_PLL_NPLL 6