blob: c22b24273eb19c57b1267156869a8ba635359cf3 [file] [log] [blame]
Alexandru Gagniucbc30b2b2013-12-24 16:48:03 -05001/*
2 * Helpers for clock control and gating on Allwinner CPUs
3 *
4 * Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
5 * Subject to the GNU GPL v2, or (at your option) any later version.
6 */
7
8#include "clock.h"
9
10#include <arch/io.h>
Alexandru Gagniuc601b5b52013-12-28 19:29:36 -050011#include <console/console.h>
12#include <delay.h>
13#include <lib.h>
14#include <stdlib.h>
Alexandru Gagniucbc30b2b2013-12-24 16:48:03 -050015
Alexandru Gagniuccce6c1c2013-12-31 13:20:27 -050016static struct a10_ccm *const ccm = (void *)A1X_CCM_BASE;
17
Alexandru Gagniucbc30b2b2013-12-24 16:48:03 -050018/**
19 * \brief Enable the clock source for the peripheral
20 *
21 * @param[in] periph peripheral and clock type to enable @see a1x_clken
22 */
23void a1x_periph_clock_enable(enum a1x_clken periph)
24{
25 void *addr;
26 u32 reg32;
27
28 addr = (void *)A1X_CCM_BASE + (periph >> 5);
29 reg32 = read32(addr);
30 reg32 |= 1 << (periph & 0x1f);
Julius Werner2f37bd62015-02-19 14:51:15 -080031 write32(addr, reg32);
Alexandru Gagniucbc30b2b2013-12-24 16:48:03 -050032}
33
34/**
35 * \brief Disable the clock source for the peripheral
36 *
37 * @param[in] periph peripheral and clock type to disable @see a1x_clken
38 */
39void a1x_periph_clock_disable(enum a1x_clken periph)
40{
41 void *addr;
42 u32 reg32;
43
44 addr = (void *)A1X_CCM_BASE + (periph >> 5);
45 reg32 = read32(addr);
46 reg32 &= ~(1 << (periph & 0x1f));
Julius Werner2f37bd62015-02-19 14:51:15 -080047 write32(addr, reg32);
Alexandru Gagniucbc30b2b2013-12-24 16:48:03 -050048}
Alexandru Gagniuccce6c1c2013-12-31 13:20:27 -050049
50/**
51 * \brief Configure PLL5 factors
52 *
53 * This is a low-level accessor to configure the divisors and multipliers of
54 * PLL5. PLL5 uses two factors to multiply the 24MHz oscillator clock to
55 * generate a pre-clock. The pre-divided clock is then divided by one of two
56 * independent divisors, one for DRAM, and another for peripherals clocked from
57 * this PLL. If the PLL was previously disabled, this function will enable it.
58 * Other than that, this function only modifies these factors, and leaves the
59 * other settings unchanged.
60 *
61 * The output clocks are given by the following formulas:
62 *
63 * Pre-clock = (24 MHz * N * K) <- Must be between 240MHz and 2GHz
64 * DRAM clock = pre / M
65 * Other module = pre / P
66 *
67 * It is the caller's responsibility to make sure the pre-divided clock falls
68 * within the operational range of the PLL, and that the divisors and
69 * multipliers are within their ranges.
70 *
71 * @param[in] mul_n Multiplier N, between 0 and 32
72 * @param[in] mul_k Multiplier K, between 1 and 4
73 * @param[in] div_m DRAM clock divisor, between 1 and 4
74 * @param[in] exp_div_p Peripheral clock divisor exponent, between 0 and 3
75 * (P = 1/2/4/8, respectively)
76 */
77void a1x_pll5_configure(u8 mul_n, u8 mul_k, u8 div_m, u8 exp_div_p)
78{
79 u32 reg32;
80
81 reg32 = read32(&ccm->pll5_cfg);
82 reg32 &= ~(PLL5_FACTOR_M_MASK | PLL5_FACTOR_N_MASK |
83 PLL5_FACTOR_K_MASK | PLL5_DIV_EXP_P_MASK);
84 /* The M1 factor is not documented in the datasheet, and the reference
85 * raminit code does not use it. Whether this is a fractional divisor,
86 * or an additional divisor is unknown, so don't use it for now */
87 reg32 &= ~PLL5_FACTOR_M1_MASK;
88 reg32 |= (PLL5_FACTOR_M(div_m) | PLL5_FACTOR_N(mul_n) |
89 PLL5_FACTOR_K(mul_k) | PLL5_DIV_EXP_P(exp_div_p));
90 reg32 |= PLL5_PLL_ENABLE;
Julius Werner2f37bd62015-02-19 14:51:15 -080091 write32(&ccm->pll5_cfg, reg32);
Alexandru Gagniuccce6c1c2013-12-31 13:20:27 -050092}
93
94/**
95 * \brief Enable the clock output to DRAM chips
96 *
97 * This enables the DRAM clock to be sent to DRAM chips. This should normally be
98 * done after PLL5 is configured and locked. Note that the clock may be gated,
99 * and also needs to be ungated in order to reach the DDR chips.
100 * Also see @ref clock_ungate_dram_clk_output
101 */
102void a1x_pll5_enable_dram_clock_output(void)
103{
104 setbits_le32(&ccm->pll5_cfg, PLL5_DDR_CLK_OUT_EN);
105}
106
107/**
108 * \brief Ungate the clock to DRAM chips
109 *
110 * Although the DRAM clock output may be enabled, it is by default gated. It
111 * needs to be ungated before reaching DRAM.
112 */
113void a1x_ungate_dram_clock_output(void)
114{
115 setbits_le32(&ccm->dram_clk_cfg, DRAM_CTRL_DCLK_OUT);
116}
117
118/**
119 * \brief Gate the clock to DRAM chips
120 *
121 * Disable the clock to DRAM without altering PLL configuration, by closing the
122 * DRAM clock gate.
123 */
124void a1x_gate_dram_clock_output(void)
125{
126 clrbits_le32(&ccm->dram_clk_cfg, DRAM_CTRL_DCLK_OUT);
127}
Alexandru Gagniuc601b5b52013-12-28 19:29:36 -0500128
129/*
130 * Linker doesn't garbage collect and the function below adds about half
131 * kilobyte to the bootblock, and log2_ceil is not available in the bootblock.
132 */
Patrick Georgi56b83092015-04-02 19:44:19 +0200133#ifndef __BOOTBLOCK__
Alexandru Gagniuc601b5b52013-12-28 19:29:36 -0500134
135#define PLL1_CFG(N, K, M, P_EXP) \
136 ((1 << 31 | 0 << 30 | 8 << 26 | 0 << 25 | 16 << 20 | 2 << 13) | \
137 (P_EXP) << 16 | (N) << 8 | \
138 (K - 1) << 4 | 0 << 3 | 0 << 2 | (M -1) << 0)
139
140static const struct {
141 u32 pll1_cfg;
142 u16 freq_mhz;
143} pll1_table[] = {
144 /* PLL1 output = (24MHz * N * K) / (M * P) */
145 { PLL1_CFG(16, 1, 1, 0), 384 },
146 { PLL1_CFG(16, 2, 1, 0), 768 },
147 { PLL1_CFG(20, 2, 1, 0), 960 },
148 { PLL1_CFG(21, 2, 1, 0), 1008 },
149 { PLL1_CFG(22, 2, 1, 0), 1056 },
150 { PLL1_CFG(23, 2, 1, 0), 1104 },
151 { PLL1_CFG(24, 2, 1, 0), 1152 },
152 { PLL1_CFG(25, 2, 1, 0), 1200 },
153 { PLL1_CFG(26, 2, 1, 0), 1248 },
154 { PLL1_CFG(27, 2, 1, 0), 1296 },
155 { PLL1_CFG(28, 2, 1, 0), 1344 },
156 { PLL1_CFG(29, 2, 1, 0), 1392 },
157 { PLL1_CFG(30, 2, 1, 0), 1440 },
158 { PLL1_CFG(31, 2, 1, 0), 1488 },
159 { PLL1_CFG(20, 4, 1, 0), 1944 },
160};
161
Alexandru Gagniuc601b5b52013-12-28 19:29:36 -0500162static void cpu_clk_src_switch(u32 clksel_bits)
163{
164 u32 reg32;
165
166 reg32 = read32(&ccm->cpu_ahb_apb0_cfg);
167 reg32 &= ~CPU_CLK_SRC_MASK;
168 reg32 |= clksel_bits & CPU_CLK_SRC_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800169 write32(&ccm->cpu_ahb_apb0_cfg, reg32);
Alexandru Gagniuc601b5b52013-12-28 19:29:36 -0500170}
171
172static void change_sys_divisors(u8 axi, u8 ahb_exp, u8 apb0_exp)
173{
174 u32 reg32;
175
176 reg32 = read32(&ccm->cpu_ahb_apb0_cfg);
177 /* Not a typo: We want to keep only the CLK_SRC bits */
178 reg32 &= CPU_CLK_SRC_MASK;
179 reg32 |= ((axi - 1) << 0) & AXI_DIV_MASK;
180 reg32 |= (ahb_exp << 4) & AHB_DIV_MASK;
181 reg32 |= (apb0_exp << 8) & APB0_DIV_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800182 write32(&ccm->cpu_ahb_apb0_cfg, reg32);
Alexandru Gagniuc601b5b52013-12-28 19:29:36 -0500183}
184
185static void spin_delay(u32 loops)
186{
187 volatile u32 x = loops;
188 while (x--);
189}
190
191/**
192 * \brief Configure the CPU clock and PLL1
193 *
194 * To run at full speed, the CPU uses PLL1 as the clock source. AXI, AHB, and
195 * APB0 are derived from the CPU clock, and need to be kept within certain
196 * limits. This function configures PLL1 as close as possible to the desired
197 * frequency, based on a set of known working configurations for PLL1. It then
198 * calculates and applies the appropriate divisors for the AXI/AHB/APB0 clocks,
199 * before finally switching the CPU to run from the new clock.
200 * No further configuration of the CPU clock or divisors is needed. after
201 * calling this function.
202 *
203 * @param[in] cpu_clk_mhz Desired CPU clock, in MHz
204 */
205void a1x_set_cpu_clock(u16 cpu_clk_mhz)
206{
207 int i = 0;
208 u8 axi, ahb, ahb_exp, apb0, apb0_exp;
209 u32 actual_mhz;
210
211 /*
212 * Rated clock for PLL1 is 2000 MHz, but there is no combination of
213 * parameters that yields that exact frequency. 1944 MHz is the highest.
214 */
215 if (cpu_clk_mhz > 1944) {
216 printk(BIOS_CRIT, "BUG! maximum PLL1 clock is 1944 MHz,"
217 "but asked to clock CPU at %d MHz\n",
218 cpu_clk_mhz);
219 cpu_clk_mhz = 1944;
220 }
221 /* Find target frequency */
222 while (pll1_table[i].freq_mhz < cpu_clk_mhz)
223 i++;
224
225 actual_mhz = pll1_table[i].freq_mhz;
226
227 if (cpu_clk_mhz != actual_mhz) {
228 printk(BIOS_WARNING, "Parameters for %d MHz not available, "
229 "setting CPU clock at %d MHz\n",
230 cpu_clk_mhz, actual_mhz);
231 }
232
233 /*
234 * Calculate system clock divisors:
235 * The minimum clock divisor for APB0 is 2, which guarantees that AHB0
236 * will always be in spec, as long as AHB is in spec, although the max
237 * AHB0 clock we can get is 125 MHz
238 */
Edward O'Callaghan7116ac82014-07-08 01:53:24 +1000239 axi = CEIL_DIV(actual_mhz, 450); /* Max 450 MHz */
240 ahb = CEIL_DIV(actual_mhz/axi, 250); /* Max 250 MHz */
Alexandru Gagniuc601b5b52013-12-28 19:29:36 -0500241 apb0 = 2; /* Max 150 MHz */
242
243 ahb_exp = log2_ceil(ahb);
244 ahb = 1 << ahb_exp;
245 apb0_exp = 1;
246
247 printk(BIOS_INFO, "CPU: %d MHz, AXI %d Mhz, AHB: %d MHz APB0: %d MHz\n",
248 actual_mhz,
249 actual_mhz / axi,
250 actual_mhz / (axi * ahb),
251 actual_mhz / (axi * ahb * apb0));
252
253 /* Keep the CPU off PLL1 while we change PLL parameters */
254 cpu_clk_src_switch(CPU_CLK_SRC_OSC24M);
255 /*
256 * We can't use udelay() here. udelay() relies on timer 0, but timers
257 * have the habit of not ticking when the CPU is clocked from the main
258 * oscillator.
259 */
260 spin_delay(8);
261
262 change_sys_divisors(axi, ahb_exp, apb0_exp);
263
264 /* Configure PLL1 at the desired frequency */
Julius Werner2f37bd62015-02-19 14:51:15 -0800265 write32(&ccm->pll1_cfg, pll1_table[i].pll1_cfg);
Alexandru Gagniuc601b5b52013-12-28 19:29:36 -0500266 spin_delay(8);
267
268 cpu_clk_src_switch(CPU_CLK_SRC_PLL1);
269 /* Here, we're running from PLL, so timers will tick */
270 udelay(1);
271}
272
Patrick Georgi56b83092015-04-02 19:44:19 +0200273#endif /* __BOOTBLOCK__ */