Wed Dec 31 16:16:35 2014 UTC ()
add RK3188plus freq scaling, and a 1.4GHz mode. anything above 1GHz with all 4 cores enabled seems to have trouble locking apll, needs more work


(jmcneill)
diff -r1.7 -r1.8 src/sys/arch/arm/rockchip/rockchip_board.c

cvs diff -r1.7 -r1.8 src/sys/arch/arm/rockchip/Attic/rockchip_board.c (expand / switch to unified diff)

--- src/sys/arch/arm/rockchip/Attic/rockchip_board.c 2014/12/30 17:15:31 1.7
+++ src/sys/arch/arm/rockchip/Attic/rockchip_board.c 2014/12/31 16:16:35 1.8
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: rockchip_board.c,v 1.7 2014/12/30 17:15:31 jmcneill Exp $ */ 1/* $NetBSD: rockchip_board.c,v 1.8 2014/12/31 16:16:35 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -19,34 +19,35 @@ @@ -19,34 +19,35 @@
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include "opt_rockchip.h" 29#include "opt_rockchip.h"
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: rockchip_board.c,v 1.7 2014/12/30 17:15:31 jmcneill Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: rockchip_board.c,v 1.8 2014/12/31 16:16:35 jmcneill Exp $");
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/bus.h> 35#include <sys/bus.h>
36#include <sys/cpu.h> 36#include <sys/cpu.h>
37#include <sys/device.h> 37#include <sys/device.h>
38 38
39#include <arm/bootconfig.h> 39#include <arm/bootconfig.h>
 40#include <arm/cpufunc.h>
40 41
41#include <arm/rockchip/rockchip_reg.h> 42#include <arm/rockchip/rockchip_reg.h>
42#include <arm/rockchip/rockchip_crureg.h> 43#include <arm/rockchip/rockchip_crureg.h>
43#include <arm/rockchip/rockchip_var.h> 44#include <arm/rockchip/rockchip_var.h>
44 45
45bus_space_handle_t rockchip_core0_bsh; 46bus_space_handle_t rockchip_core0_bsh;
46bus_space_handle_t rockchip_core1_bsh; 47bus_space_handle_t rockchip_core1_bsh;
47 48
48void 49void
49rockchip_bootstrap(void) 50rockchip_bootstrap(void)
50{ 51{
51 int error; 52 int error;
52 53
@@ -121,50 +122,64 @@ rockchip_cpll_get_rate(void) @@ -121,50 +122,64 @@ rockchip_cpll_get_rate(void)
121} 122}
122 123
123u_int 124u_int
124rockchip_apll_get_rate(void) 125rockchip_apll_get_rate(void)
125{ 126{
126 return rockchip_pll_get_rate(CRU_APLL_CON0_REG, CRU_APLL_CON1_REG); 127 return rockchip_pll_get_rate(CRU_APLL_CON0_REG, CRU_APLL_CON1_REG);
127} 128}
128 129
129static u_int 130static u_int
130rk3188_apll_set_rate(u_int rate) 131rk3188_apll_set_rate(u_int rate)
131{ 132{
132 bus_space_tag_t bst = &rockchip_bs_tag; 133 bus_space_tag_t bst = &rockchip_bs_tag;
133 bus_space_handle_t bsh; 134 bus_space_handle_t bsh;
134 uint32_t apll_con0, apll_con1, clksel0_con, clksel1_con; 135 uint32_t apll_con0, apll_con1, apll_con2, clksel0_con, clksel1_con;
 136 uint32_t reset_mask, reset;
135 u_int no, nr, nf, core_div, core_periph_div, core_axi_div, 137 u_int no, nr, nf, core_div, core_periph_div, core_axi_div,
136 aclk_div, hclk_div, pclk_div, ahb2apb_div; 138 aclk_div, hclk_div, pclk_div, ahb2apb_div;
137 u_int cpu_aclk_div_con; 139 u_int cpu_aclk_div_con;
 140 const bool rk3188plus_p = rockchip_is_chip(ROCKCHIP_CHIPVER_RK3188PLUS);
138 141
139 rockchip_get_cru_bsh(&bsh); 142 rockchip_get_cru_bsh(&bsh);
140 143
141#ifdef ROCKCHIP_CLOCK_DEBUG 144#ifdef ROCKCHIP_CLOCK_DEBUG
142 printf("%s: rate=%u\n", __func__, rate); 145 printf("%s: rate=%u rk3188plus_p=%d\n", __func__, rate, rk3188plus_p);
143#endif 146#endif
144 147
145 switch (rate) { 148 switch (rate) {
146 case 1608000000: 149 case 1608000000:
147 nr = 1; 150 nr = 1;
148 nf = 67; 151 nf = 67;
149 no = 1; 152 no = 1;
150 core_div = 1; 153 core_div = 1;
151 core_periph_div = 8; 154 core_periph_div = 8;
152 core_axi_div = 4; 155 core_axi_div = 4;
153 aclk_div = 4; 156 aclk_div = 4;
154 hclk_div = 2; 157 hclk_div = 2;
155 pclk_div = 4; 158 pclk_div = 4;
156 ahb2apb_div = 2; 159 ahb2apb_div = 2;
157 break; 160 break;
 161 case 1416000000:
 162 nr = 1;
 163 nf = 59;
 164 no = 1;
 165 core_div = 1;
 166 core_periph_div = 8;
 167 core_axi_div = 4;
 168 aclk_div = 4;
 169 hclk_div = 2;
 170 pclk_div = 4;
 171 ahb2apb_div = 2;
 172 break;
158 case 1008000000: 173 case 1008000000:
159 nr = 1; 174 nr = 1;
160 nf = 42; 175 nf = 42;
161 no = 1; 176 no = 1;
162 core_div = 1; 177 core_div = 1;
163 core_periph_div = 8; 178 core_periph_div = 8;
164 core_axi_div = 3; 179 core_axi_div = 3;
165 aclk_div = 3; 180 aclk_div = 3;
166 hclk_div = 2; 181 hclk_div = 2;
167 pclk_div = 4; 182 pclk_div = 4;
168 ahb2apb_div = 2; 183 ahb2apb_div = 2;
169 break; 184 break;
170 case 600000000: 185 case 600000000:
@@ -176,111 +191,130 @@ rk3188_apll_set_rate(u_int rate) @@ -176,111 +191,130 @@ rk3188_apll_set_rate(u_int rate)
176 core_axi_div = 4; 191 core_axi_div = 4;
177 aclk_div = 3; 192 aclk_div = 3;
178 hclk_div = 2; 193 hclk_div = 2;
179 pclk_div = 4; 194 pclk_div = 4;
180 ahb2apb_div = 2; 195 ahb2apb_div = 2;
181 break; 196 break;
182 default: 197 default:
183#ifdef ROCKCHIP_CLOCK_DEBUG 198#ifdef ROCKCHIP_CLOCK_DEBUG
184 printf("%s: unsupported rate %u\n", __func__, rate); 199 printf("%s: unsupported rate %u\n", __func__, rate);
185#endif 200#endif
186 return EINVAL; 201 return EINVAL;
187 } 202 }
188 203
 204 if (rk3188plus_p) {
 205 reset_mask = CRU_PLL_CON3_RESET_MASK;
 206 reset = CRU_PLL_CON3_RESET;
 207 } else {
 208 reset_mask = CRU_PLL_CON3_POWER_DOWN_MASK;
 209 reset = CRU_PLL_CON3_POWER_DOWN;
 210 }
 211
189 apll_con0 = CRU_PLL_CON0_CLKR_MASK | CRU_PLL_CON0_CLKOD_MASK; 212 apll_con0 = CRU_PLL_CON0_CLKR_MASK | CRU_PLL_CON0_CLKOD_MASK;
190 apll_con0 |= __SHIFTIN(no - 1, CRU_PLL_CON0_CLKOD); 213 apll_con0 |= __SHIFTIN(no - 1, CRU_PLL_CON0_CLKOD);
191 apll_con0 |= __SHIFTIN(nr - 1, CRU_PLL_CON0_CLKR); 214 apll_con0 |= __SHIFTIN(nr - 1, CRU_PLL_CON0_CLKR);
192 215
193 apll_con1 = CRU_PLL_CON1_CLKF_MASK; 216 apll_con1 = CRU_PLL_CON1_CLKF_MASK;
194 apll_con1 |= __SHIFTIN(nf - 1, CRU_PLL_CON1_CLKF); 217 apll_con1 |= __SHIFTIN(nf - 1, CRU_PLL_CON1_CLKF);
195 218
 219 if (rk3188plus_p) {
 220 apll_con2 = CRU_PLL_CON2_BWADJ_MASK;
 221 apll_con2 |= __SHIFTIN(nf >> 1, CRU_PLL_CON2_BWADJ);
 222 } else {
 223 apll_con2 = 0;
 224 }
 225
196 clksel0_con = RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON_MASK | 226 clksel0_con = RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON_MASK |
197 CRU_CLKSEL_CON0_CORE_PERI_DIV_CON_MASK | 227 CRU_CLKSEL_CON0_CORE_PERI_DIV_CON_MASK |
198 CRU_CLKSEL_CON0_A9_CORE_DIV_CON_MASK | 228 CRU_CLKSEL_CON0_A9_CORE_DIV_CON_MASK;
199 CRU_CLKSEL_CON0_CPU_CLK_PLL_SEL; 
200 clksel0_con |= __SHIFTIN(core_div - 1, 229 clksel0_con |= __SHIFTIN(core_div - 1,
201 RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON); 230 RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON);
202 clksel0_con |= __SHIFTIN(ffs(core_periph_div) - 2, 231 clksel0_con |= __SHIFTIN(ffs(core_periph_div) - 2,
203 CRU_CLKSEL_CON0_CORE_PERI_DIV_CON); 232 CRU_CLKSEL_CON0_CORE_PERI_DIV_CON);
204 clksel0_con |= __SHIFTIN(aclk_div - 1, 233 clksel0_con |= __SHIFTIN(aclk_div - 1,
205 CRU_CLKSEL_CON0_A9_CORE_DIV_CON); 234 CRU_CLKSEL_CON0_A9_CORE_DIV_CON);
206 235
207 clksel1_con = RK3188_CRU_CLKSEL_CON1_CPU_ACLK_DIV_CON_MASK | 236 clksel1_con = CRU_CLKSEL_CON1_AHB2APB_PCLKEN_DIV_CON_MASK |
208 CRU_CLKSEL_CON1_AHB2APB_PCLKEN_DIV_CON_MASK | 
209 CRU_CLKSEL_CON1_CPU_PCLK_DIV_CON_MASK | 237 CRU_CLKSEL_CON1_CPU_PCLK_DIV_CON_MASK |
210 CRU_CLKSEL_CON1_CPU_HCLK_DIV_CON_MASK; 238 CRU_CLKSEL_CON1_CPU_HCLK_DIV_CON_MASK;
211  239
212 switch (core_axi_div) { 240 switch (core_axi_div) {
213 case 1: cpu_aclk_div_con = 0; break; 241 case 1: cpu_aclk_div_con = 0; break;
214 case 2: cpu_aclk_div_con = 1; break; 242 case 2: cpu_aclk_div_con = 1; break;
215 case 3: cpu_aclk_div_con = 2; break; 243 case 3: cpu_aclk_div_con = 2; break;
216 case 4: cpu_aclk_div_con = 3; break; 244 case 4: cpu_aclk_div_con = 3; break;
217 case 8: cpu_aclk_div_con = 4; break; 245 case 8: cpu_aclk_div_con = 4; break;
218 default: panic("bad core_axi_div"); 246 default: panic("bad core_axi_div");
219 } 247 }
220 clksel1_con |= __SHIFTIN(cpu_aclk_div_con, 
221 RK3188_CRU_CLKSEL_CON1_CPU_ACLK_DIV_CON); 
222 clksel1_con |= __SHIFTIN(ffs(ahb2apb_div) - 1, 248 clksel1_con |= __SHIFTIN(ffs(ahb2apb_div) - 1,
223 CRU_CLKSEL_CON1_AHB2APB_PCLKEN_DIV_CON); 249 CRU_CLKSEL_CON1_AHB2APB_PCLKEN_DIV_CON);
224 clksel1_con |= __SHIFTIN(ffs(hclk_div) - 1, 250 clksel1_con |= __SHIFTIN(ffs(hclk_div) - 1,
225 CRU_CLKSEL_CON1_CPU_HCLK_DIV_CON); 251 CRU_CLKSEL_CON1_CPU_HCLK_DIV_CON);
226 clksel1_con |= __SHIFTIN(ffs(pclk_div) - 1, 252 clksel1_con |= __SHIFTIN(ffs(pclk_div) - 1,
227 CRU_CLKSEL_CON1_CPU_PCLK_DIV_CON); 253 CRU_CLKSEL_CON1_CPU_PCLK_DIV_CON);
228 254
229#ifdef ROCKCHIP_CLOCK_DEBUG 255#ifdef ROCKCHIP_CLOCK_DEBUG
230 printf("before: APLL_CON0: %#x\n", 256 printf("before: APLL_CON0: %#x\n",
231 bus_space_read_4(bst, bsh, CRU_APLL_CON0_REG)); 257 bus_space_read_4(bst, bsh, CRU_APLL_CON0_REG));
232 printf("before: APLL_CON1: %#x\n", 258 printf("before: APLL_CON1: %#x\n",
233 bus_space_read_4(bst, bsh, CRU_APLL_CON1_REG)); 259 bus_space_read_4(bst, bsh, CRU_APLL_CON1_REG));
234 printf("before: CLKSEL0_CON: %#x\n", 260 printf("before: CLKSEL0_CON: %#x\n",
235 bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(0))); 261 bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(0)));
236 printf("before: CLKSEL1_CON: %#x\n", 262 printf("before: CLKSEL1_CON: %#x\n",
237 bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(1))); 263 bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(1)));
238#endif 264#endif
239 265
240 /* Change from normal to slow mode */ 266 /* Set CPU clk src to GPLL */
241 bus_space_write_4(bst, bsh, CRU_MODE_CON_REG, 267 const u_int curcpufreq = rockchip_cpu_get_rate();
242 CRU_MODE_CON_APLL_WORK_MODE_MASK | 268 const u_int gpllfreq = rockchip_gpll_get_rate();
243 __SHIFTIN(CRU_MODE_CON_APLL_WORK_MODE_SLOW, 269
244 CRU_MODE_CON_APLL_WORK_MODE)); 270 bus_space_write_4(bst, bsh, CRU_CLKSEL_CON_REG(0),
 271 RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON_MASK|
 272 CRU_CLKSEL_CON0_CPU_CLK_PLL_SEL_MASK|
 273 __SHIFTIN(howmany(curcpufreq, gpllfreq) - 1,
 274 RK3188_CRU_CLKSEL_CON0_A9_CORE_DIV_CON)|
 275 CRU_CLKSEL_CON0_CPU_CLK_PLL_SEL);
245 276
246 /* Power down */ 277 /* Power down */
247 bus_space_write_4(bst, bsh, CRU_APLL_CON3_REG, 278 bus_space_write_4(bst, bsh, CRU_APLL_CON3_REG, reset_mask | reset);
248 CRU_PLL_CON3_POWER_DOWN_MASK | CRU_PLL_CON3_POWER_DOWN); 
249 279
250 /* Update APLL regs */ 280 /* Update APLL regs */
251 bus_space_write_4(bst, bsh, CRU_APLL_CON0_REG, apll_con0); 281 bus_space_write_4(bst, bsh, CRU_APLL_CON0_REG, apll_con0);
252 bus_space_write_4(bst, bsh, CRU_APLL_CON1_REG, apll_con1); 282 bus_space_write_4(bst, bsh, CRU_APLL_CON1_REG, apll_con1);
 283 if (apll_con2)
 284 bus_space_write_4(bst, bsh, CRU_APLL_CON2_REG, apll_con2);
253 285
254 /* Wait for PLL lock */ 286 /* Wait for PLL lock */
255 for (volatile int i = 5000; i >= 0; i--) 287 for (volatile int i = 5000; i >= 0; i--)
256 ; 288 ;
257 289
258 /* Power up */ 290 /* Power up */
259 bus_space_write_4(bst, bsh, CRU_APLL_CON3_REG, 291 bus_space_write_4(bst, bsh, CRU_APLL_CON3_REG, reset_mask);
260 CRU_PLL_CON3_POWER_DOWN_MASK); 292
 293 for (volatile int i = 50000; i >= 0; i--)
 294 ;
261 295
262 /* Update CLKSEL regs */ 296 /* Update CLKSEL regs */
263 bus_space_write_4(bst, bsh, CRU_CLKSEL_CON_REG(0), clksel0_con); 297 bus_space_write_4(bst, bsh, CRU_CLKSEL_CON_REG(0), clksel0_con);
264 bus_space_write_4(bst, bsh, CRU_CLKSEL_CON_REG(1), clksel1_con); 298 bus_space_write_4(bst, bsh, CRU_CLKSEL_CON_REG(1), clksel1_con);
265 299
266 for (volatile int i = 50000; i >= 0; i--) 300 /* Set CPU clk src to APLL */
267 ; 301 bus_space_write_4(bst, bsh, CRU_CLKSEL_CON_REG(0),
268 302 CRU_CLKSEL_CON0_CPU_CLK_PLL_SEL_MASK);
269 /* Change from slow mode to normal mode */ 303
270 bus_space_write_4(bst, bsh, CRU_MODE_CON_REG, 304 bus_space_write_4(bst, bsh, CRU_CLKSEL_CON_REG(0),
271 CRU_MODE_CON_APLL_WORK_MODE_MASK | 305 RK3188_CRU_CLKSEL_CON1_CPU_ACLK_DIV_CON_MASK |
272 __SHIFTIN(CRU_MODE_CON_APLL_WORK_MODE_NORMAL, 306 __SHIFTIN(cpu_aclk_div_con,
273 CRU_MODE_CON_APLL_WORK_MODE)); 307 RK3188_CRU_CLKSEL_CON1_CPU_ACLK_DIV_CON));
274 308
275#ifdef ROCKCHIP_CLOCK_DEBUG 309#ifdef ROCKCHIP_CLOCK_DEBUG
276 printf("after: APLL_CON0: %#x\n", 310 printf("after: APLL_CON0: %#x\n",
277 bus_space_read_4(bst, bsh, CRU_APLL_CON0_REG)); 311 bus_space_read_4(bst, bsh, CRU_APLL_CON0_REG));
278 printf("after: APLL_CON1: %#x\n", 312 printf("after: APLL_CON1: %#x\n",
279 bus_space_read_4(bst, bsh, CRU_APLL_CON1_REG)); 313 bus_space_read_4(bst, bsh, CRU_APLL_CON1_REG));
280 printf("after: CLKSEL0_CON: %#x\n", 314 printf("after: CLKSEL0_CON: %#x\n",
281 bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(0))); 315 bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(0)));
282 printf("after: CLKSEL1_CON: %#x\n", 316 printf("after: CLKSEL1_CON: %#x\n",
283 bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(1))); 317 bus_space_read_4(bst, bsh, CRU_CLKSEL_CON_REG(1)));
284#endif 318#endif
285 319
286 return 0; 320 return 0;