From b8bc161064220811cd2f7f048ea4b34b9907be84 Mon Sep 17 00:00:00 2001 From: jmcneill Date: Sun, 29 Nov 2015 19:16:58 +0000 Subject: [PATCH] Fix A9 periph clock when selecting frequencies below 1200MHz. Remove frequencies below 312MHz as they require special handling. We can now choose between 1536 1488 1320 1200 1008 816 720 600 504 408 312. --- sys/arch/arm/amlogic/amlogic_cpufreq.c | 40 +++++++++++++++++++++----- sys/arch/arm/amlogic/amlogic_crureg.h | 3 +- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/sys/arch/arm/amlogic/amlogic_cpufreq.c b/sys/arch/arm/amlogic/amlogic_cpufreq.c index 4f527e503d07..733a82ff84e8 100644 --- a/sys/arch/arm/amlogic/amlogic_cpufreq.c +++ b/sys/arch/arm/amlogic/amlogic_cpufreq.c @@ -1,4 +1,4 @@ -/* $NetBSD: amlogic_cpufreq.c,v 1.4 2015/11/29 16:52:00 jmcneill Exp $ */ +/* $NetBSD: amlogic_cpufreq.c,v 1.5 2015/11/29 19:16:58 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill @@ -31,7 +31,7 @@ #include "opt_amlogic.h" #include -__KERNEL_RCSID(0, "$NetBSD: amlogic_cpufreq.c,v 1.4 2015/11/29 16:52:00 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: amlogic_cpufreq.c,v 1.5 2015/11/29 19:16:58 jmcneill Exp $"); #include #include @@ -73,6 +73,9 @@ static size_t meson8b_cpu_get_available(u_int *, size_t); #define CBUS_WRITE(x, v) \ bus_space_write_4(&armv7_generic_bs_tag, amlogic_core_bsh, \ AMLOGIC_CBUS_OFFSET + (x), (v)) +#define CBUS_SET_CLEAR(x, s, c) \ + amlogic_reg_set_clear(&armv7_generic_bs_tag, amlogic_core_bsh, \ + AMLOGIC_CBUS_OFFSET + (x), (s), (c)) void amlogic_cpufreq_bootstrap(void) @@ -206,7 +209,7 @@ amlogic_cpufreq_freq_helper(SYSCTLFN_ARGS) * meson8b */ static const u_int meson8b_rates[] = { - 1536, 1488, 1320, 1200, 1008, 816, 720, 600, 504, 408, 312, 192, 96 + 1536, 1488, 1320, 1200, 1008, 816, 720, 600, 504, 408, 312 }; static size_t @@ -248,9 +251,17 @@ meson8b_cpu_set_rate(u_int rate) uint32_t cntl0 = CBUS_READ(HHI_SYS_CPU_CLK_CNTL0_REG); uint32_t cntl = CBUS_READ(HHI_SYS_PLL_CNTL_REG); - const u_int new_mul = new_rate / xtal_rate; - const u_int new_div = 1; - const u_int new_od = 0; + u_int new_mul = new_rate / xtal_rate; + u_int new_div = 1; + u_int new_od = 0; + + if (new_rate < 600 * 1000000) { + new_od = 2; + new_mul *= 4; + } else if (new_rate < 1200 * 1000000) { + new_od = 1; + new_mul *= 2; + } /* * XXX make some assumptions about the state of cpu clk cntl regs @@ -269,7 +280,22 @@ meson8b_cpu_set_rate(u_int rate) cntl &= ~HHI_SYS_PLL_CNTL_OD; cntl |= __SHIFTIN(new_od, HHI_SYS_PLL_CNTL_OD); - CBUS_WRITE(HHI_SYS_PLL_CNTL_REG, cntl); + /* Switch CPU to XTAL clock */ + CBUS_SET_CLEAR(HHI_SYS_CPU_CLK_CNTL0_REG, 0, + HHI_SYS_CPU_CLK_CNTL0_CLKSEL); + + delay((100 * old_rate) / xtal_rate); + + /* Update multiplier */ + do { + CBUS_WRITE(HHI_SYS_PLL_CNTL_REG, cntl); + + /* Switch CPU to sys pll */ + CBUS_SET_CLEAR(HHI_SYS_CPU_CLK_CNTL0_REG, + HHI_SYS_CPU_CLK_CNTL0_CLKSEL, 0); + + delay((500 * old_rate) / new_rate); + } while (!(CBUS_READ(HHI_SYS_PLL_CNTL_REG) & HHI_SYS_PLL_CNTL_LOCK)); if (!cold) { a9tmr_update_freq(amlogic_get_rate_a9periph()); diff --git a/sys/arch/arm/amlogic/amlogic_crureg.h b/sys/arch/arm/amlogic/amlogic_crureg.h index c04e37c063a0..d520cf128250 100644 --- a/sys/arch/arm/amlogic/amlogic_crureg.h +++ b/sys/arch/arm/amlogic/amlogic_crureg.h @@ -1,4 +1,4 @@ -/* $NetBSD: amlogic_crureg.h,v 1.12 2015/11/29 16:52:00 jmcneill Exp $ */ +/* $NetBSD: amlogic_crureg.h,v 1.13 2015/11/29 19:16:58 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill @@ -67,6 +67,7 @@ #define HHI_SYS_PLL_CNTL_MUL __BITS(8,0) #define HHI_SYS_PLL_CNTL_DIV __BITS(14,9) #define HHI_SYS_PLL_CNTL_OD __BITS(17,16) +#define HHI_SYS_PLL_CNTL_LOCK __BIT(31) #define HHI_MPLL_CNTL_REG CBUS_REG(0x10a0) #define HHI_MPLL_CNTL_MUL __BITS(8,0)