Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch Add support for setting RK3188/RK3188+ CPU frequenc...
details: https://anonhg.NetBSD.org/src/rev/a4a26fa04911
branches: trunk
changeset: 335209:a4a26fa04911
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Tue Dec 30 03:53:52 2014 +0000
description:
Add support for setting RK3188/RK3188+ CPU frequency. If the SoC ID is
passed in bootargs matching RK3188 or RK3188+, and the cpu.frequency
option specifies a supported rate (currently 600, 1008, 1608 MHz), the
APLL clock will be adjusted accordingly.
diffstat:
sys/arch/arm/rockchip/rockchip_board.c | 209 +++++++++++++++++++++++++--
sys/arch/arm/rockchip/rockchip_crureg.h | 25 +++-
sys/arch/arm/rockchip/rockchip_var.h | 8 +-
sys/arch/evbarm/rockchip/rockchip_machdep.c | 17 +-
4 files changed, 236 insertions(+), 23 deletions(-)
diffs (truncated from 402 to 300 lines):
diff -r 1df6f0b5265f -r a4a26fa04911 sys/arch/arm/rockchip/rockchip_board.c
--- a/sys/arch/arm/rockchip/rockchip_board.c Tue Dec 30 03:52:03 2014 +0000
+++ b/sys/arch/arm/rockchip/rockchip_board.c Tue Dec 30 03:53:52 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rockchip_board.c,v 1.5 2014/12/27 19:14:05 jmcneill Exp $ */
+/* $NetBSD: rockchip_board.c,v 1.6 2014/12/30 03:53:52 jmcneill Exp $ */
/*-
* Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,13 +29,15 @@
#include "opt_rockchip.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rockchip_board.c,v 1.5 2014/12/27 19:14:05 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rockchip_board.c,v 1.6 2014/12/30 03:53:52 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/cpu.h>
#include <sys/device.h>
+#include <arm/bootconfig.h>
+
#include <arm/rockchip/rockchip_reg.h>
#include <arm/rockchip/rockchip_crureg.h>
#include <arm/rockchip/rockchip_var.h>
@@ -59,6 +61,20 @@
panic("%s: failed to map CORE1 registers: %d", __func__, error);
}
+bool
+rockchip_is_chip(const char *chipver)
+{
+ const size_t chipver_len = 16;
+ char *env_chipver;
+
+ if (get_bootconf_option(boot_args, "chipver",
+ BOOTOPT_TYPE_STRING, &env_chipver) == 0) {
+ return false;
+ }
+
+ return strncmp(env_chipver, chipver, chipver_len) == 0;
+}
+
static void
rockchip_get_cru_bsh(bus_space_handle_t *pbsh)
{
@@ -104,6 +120,177 @@
return rockchip_pll_get_rate(CRU_APLL_CON0_REG, CRU_APLL_CON1_REG);
}
+static u_int
+rk3188_apll_set_rate(u_int rate)
+{
+ bus_space_tag_t bst = &rockchip_bs_tag;
+ bus_space_handle_t bsh;
+ uint32_t apll_con0, apll_con1, clksel0_con, clksel1_con;
+ u_int no, nr, nf, core_div, core_periph_div, core_axi_div,
+ aclk_div, hclk_div, pclk_div, ahb2apb_div;
+ u_int cpu_aclk_div_con;
+
+ rockchip_get_cru_bsh(&bsh);
+
+#ifdef ROCKCHIP_CLOCK_DEBUG
+ printf("%s: rate=%u\n", __func__, rate);
+#endif
+
+ switch (rate) {
+ case 1608000000:
+ nr = 1;
+ nf = 67;
+ no = 1;
+ core_div = 1;
+ core_periph_div = 8;
+ core_axi_div = 4;
+ aclk_div = 4;
+ hclk_div = 2;
+ pclk_div = 4;
+ ahb2apb_div = 2;
+ break;
+ case 1008000000:
+ nr = 1;
+ nf = 42;
+ no = 1;
+ core_div = 1;
+ core_periph_div = 8;
+ core_axi_div = 3;
+ aclk_div = 3;
+ hclk_div = 2;
+ pclk_div = 4;
+ ahb2apb_div = 2;
+ break;
+ case 600000000:
+ nr = 1;
+ nf = 50;
+ no = 2;
+ core_div = 1;
+ core_periph_div = 4;
+ core_axi_div = 4;
+ aclk_div = 3;
+ hclk_div = 2;
+ pclk_div = 4;
+ ahb2apb_div = 2;
+ break;
+ default:
+#ifdef ROCKCHIP_CLOCK_DEBUG
+ printf("%s: unsupported rate %u\n", __func__, rate);
+#endif
+ return EINVAL;
+ }
+
+ apll_con0 = CRU_PLL_CON0_CLKR_MASK | CRU_PLL_CON0_CLKOD_MASK;
+ apll_con0 |= __SHIFTIN(no - 1, CRU_PLL_CON0_CLKOD);
+ apll_con0 |= __SHIFTIN(nr - 1, CRU_PLL_CON0_CLKR);
+
+ apll_con1 = CRU_PLL_CON1_CLKF_MASK;
+ apll_con1 |= __SHIFTIN(nf - 1, CRU_PLL_CON1_CLKF);
+
+ clksel0_con = RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON_MASK |
+ CRU_CLKSEL_CON0_CORE_PERI_DIV_CON_MASK |
+ CRU_CLKSEL_CON0_A9_CORE_DIV_CON_MASK |
+ CRU_CLKSEL_CON0_CPU_CLK_PLL_SEL;
+ clksel0_con |= __SHIFTIN(core_div - 1,
+ RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON);
+ clksel0_con |= __SHIFTIN(ffs(core_periph_div) - 2,
+ CRU_CLKSEL_CON0_CORE_PERI_DIV_CON);
+ clksel0_con |= __SHIFTIN(aclk_div - 1,
+ CRU_CLKSEL_CON0_A9_CORE_DIV_CON);
+
+ clksel1_con = RK3188_CRU_CLKSEL_CON1_CPU_ACLK_DIV_CON_MASK |
+ CRU_CLKSEL_CON1_AHB2APB_PCLKEN_DIV_CON_MASK |
+ CRU_CLKSEL_CON1_CPU_PCLK_DIV_CON_MASK |
+ CRU_CLKSEL_CON1_CPU_HCLK_DIV_CON_MASK;
+
+ switch (core_axi_div) {
+ case 1: cpu_aclk_div_con = 0; break;
+ case 2: cpu_aclk_div_con = 1; break;
+ case 3: cpu_aclk_div_con = 2; break;
+ case 4: cpu_aclk_div_con = 3; break;
+ case 8: cpu_aclk_div_con = 4; break;
+ default: panic("bad core_axi_div");
+ }
+ clksel1_con |= __SHIFTIN(cpu_aclk_div_con,
+ RK3188_CRU_CLKSEL_CON1_CPU_ACLK_DIV_CON);
+ clksel1_con |= __SHIFTIN(ffs(ahb2apb_div) - 1,
+ CRU_CLKSEL_CON1_AHB2APB_PCLKEN_DIV_CON);
+ clksel1_con |= __SHIFTIN(ffs(hclk_div) - 1,
+ CRU_CLKSEL_CON1_CPU_HCLK_DIV_CON);
+ clksel1_con |= __SHIFTIN(ffs(pclk_div) - 1,
+ CRU_CLKSEL_CON1_CPU_PCLK_DIV_CON);
+
+#ifdef ROCKCHIP_CLOCK_DEBUG
+ printf("before: APLL_CON0: %#x\n",
+ bus_space_read_4(bst, bsh, CRU_APLL_CON0_REG));
+ printf("before: APLL_CON1: %#x\n",
+ bus_space_read_4(bst, bsh, CRU_APLL_CON1_REG));
+ printf("before: CLKSEL0_CON: %#x\n",
+ bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(0)));
+ printf("before: CLKSEL1_CON: %#x\n",
+ bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(1)));
+#endif
+
+ /* Change from normal to slow mode */
+ bus_space_write_4(bst, bsh, CRU_MODE_CON_REG,
+ CRU_MODE_CON_APLL_WORK_MODE_MASK |
+ __SHIFTIN(CRU_MODE_CON_APLL_WORK_MODE_SLOW,
+ CRU_MODE_CON_APLL_WORK_MODE));
+
+ /* Power down */
+ bus_space_write_4(bst, bsh, CRU_APLL_CON3_REG,
+ CRU_PLL_CON3_POWER_DOWN_MASK | CRU_PLL_CON3_POWER_DOWN);
+
+ /* Update APLL regs */
+ bus_space_write_4(bst, bsh, CRU_APLL_CON0_REG, apll_con0);
+ bus_space_write_4(bst, bsh, CRU_APLL_CON1_REG, apll_con1);
+
+ /* Wait for PLL lock */
+ for (volatile int i = 5000; i >= 0; i--)
+ ;
+
+ /* Power up */
+ bus_space_write_4(bst, bsh, CRU_APLL_CON3_REG,
+ CRU_PLL_CON3_POWER_DOWN_MASK);
+
+ /* Update CLKSEL regs */
+ bus_space_write_4(bst, bsh, CRU_CLKSEL_CON_REG(0), clksel0_con);
+ bus_space_write_4(bst, bsh, CRU_CLKSEL_CON_REG(1), clksel1_con);
+
+ for (volatile int i = 50000; i >= 0; i--)
+ ;
+
+ /* Change from slow mode to normal mode */
+ bus_space_write_4(bst, bsh, CRU_MODE_CON_REG,
+ CRU_MODE_CON_APLL_WORK_MODE_MASK |
+ __SHIFTIN(CRU_MODE_CON_APLL_WORK_MODE_NORMAL,
+ CRU_MODE_CON_APLL_WORK_MODE));
+
+#ifdef ROCKCHIP_CLOCK_DEBUG
+ printf("after: APLL_CON0: %#x\n",
+ bus_space_read_4(bst, bsh, CRU_APLL_CON0_REG));
+ printf("after: APLL_CON1: %#x\n",
+ bus_space_read_4(bst, bsh, CRU_APLL_CON1_REG));
+ printf("after: CLKSEL0_CON: %#x\n",
+ bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(0)));
+ printf("after: CLKSEL1_CON: %#x\n",
+ bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(1)));
+#endif
+
+ return 0;
+}
+
+u_int
+rockchip_apll_set_rate(u_int rate)
+{
+ if (rockchip_is_chip(ROCKCHIP_CHIPVER_RK3188) ||
+ rockchip_is_chip(ROCKCHIP_CHIPVER_RK3188PLUS)) {
+ return rk3188_apll_set_rate(rate);
+ }
+
+ return ENODEV;
+}
+
u_int
rockchip_cpu_get_rate(void)
{
@@ -122,17 +309,13 @@
rate = rockchip_apll_get_rate();
}
-#if notyet
- if (rockchip_chip_id() == ROCKCHIP_CHIP_ID_RK3188) {
+ if (rockchip_is_chip(ROCKCHIP_CHIPVER_RK3066)) {
a9_core_div_con = __SHIFTOUT(clksel_con0,
- RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON);
+ CRU_CLKSEL_CON0_A9_CORE_DIV_CON);
} else {
a9_core_div_con = __SHIFTOUT(clksel_con0,
- CRU_CLKSEL_CON0_A9_CORE_DIV_CON);
+ RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON);
}
-#else
- a9_core_div_con = 0;
-#endif
#ifdef ROCKCHIP_CLOCK_DEBUG
printf("%s: clksel_con0=%#x\n", __func__, clksel_con0);
@@ -153,11 +336,7 @@
rockchip_get_cru_bsh(&bsh);
clksel_con0 = bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(0));
- if (clksel_con0 & CRU_CLKSEL_CON0_CPU_CLK_PLL_SEL) {
- rate = rockchip_gpll_get_rate();
- } else {
- rate = rockchip_apll_get_rate();
- }
+ rate = rockchip_cpu_get_rate();
core_peri_div_con = __SHIFTOUT(clksel_con0,
CRU_CLKSEL_CON0_CORE_PERI_DIV_CON);
@@ -216,7 +395,7 @@
clksel_con11 = CRU_CLKSEL_CON11_MMC0_PLL_SEL_MASK |
CRU_CLKSEL_CON11_MMC0_DIV_CON_MASK;
- //clksel_con11 |= CRU_CLKSEL_CON11_MMC0_PLL_SEL; /* GPLL */
+ clksel_con11 |= CRU_CLKSEL_CON11_MMC0_PLL_SEL; /* GPLL */
clksel_con11 |= __SHIFTIN(div - 1, CRU_CLKSEL_CON11_MMC0_DIV_CON);
#ifdef ROCKCHIP_CLOCK_DEBUG
diff -r 1df6f0b5265f -r a4a26fa04911 sys/arch/arm/rockchip/rockchip_crureg.h
--- a/sys/arch/arm/rockchip/rockchip_crureg.h Tue Dec 30 03:52:03 2014 +0000
+++ b/sys/arch/arm/rockchip/rockchip_crureg.h Tue Dec 30 03:53:52 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rockchip_crureg.h,v 1.4 2014/12/27 19:14:34 jmcneill Exp $ */
+/* $NetBSD: rockchip_crureg.h,v 1.5 2014/12/30 03:53:52 jmcneill Exp $ */
/*-
* Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -62,13 +62,34 @@
#define CRU_PLL_CON1_CLKF_MASK __BITS(31,16)
#define CRU_PLL_CON1_CLKF __BITS(15,0)
+#define CRU_PLL_CON3_POWER_DOWN_MASK __BIT(17)
+#define CRU_PLL_CON3_POWER_DOWN __BIT(1)
+
+#define CRU_MODE_CON_APLL_WORK_MODE_MASK __BITS(17,16)
+#define CRU_MODE_CON_APLL_WORK_MODE __BITS(1,0)
+#define CRU_MODE_CON_APLL_WORK_MODE_SLOW 0
+#define CRU_MODE_CON_APLL_WORK_MODE_NORMAL 1
+#define CRU_MODE_CON_APLL_WORK_MODE_DEEP_SLOW 2
+
+#define RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON_MASK __BITS(29,25)
#define CRU_CLKSEL_CON0_CPU_CLK_PLL_SEL_MASK __BIT(24)
#define CRU_CLKSEL_CON0_CORE_PERI_DIV_CON_MASK __BITS(23,22)
#define CRU_CLKSEL_CON0_A9_CORE_DIV_CON_MASK __BITS(20,16)
+#define RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON __BITS(13,9)
#define CRU_CLKSEL_CON0_CPU_CLK_PLL_SEL __BIT(8)
#define CRU_CLKSEL_CON0_CORE_PERI_DIV_CON __BITS(7,6)
#define CRU_CLKSEL_CON0_A9_CORE_DIV_CON __BITS(4,0)
-#define RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON __BITS(13,9)
+
Home |
Main Index |
Thread Index |
Old Index