Sat Sep 1 19:35:53 2018 UTC ()
Add support for RK3399 CPU clocks.


(jmcneill)
diff -r1.2 -r1.3 src/sys/arch/arm/rockchip/rk3399_cru.c
diff -r1.3 -r1.4 src/sys/arch/arm/rockchip/rk_cru.h
diff -r1.1 -r1.2 src/sys/arch/arm/rockchip/rk_cru_arm.c

cvs diff -r1.2 -r1.3 src/sys/arch/arm/rockchip/rk3399_cru.c (expand / switch to unified diff)

--- src/sys/arch/arm/rockchip/rk3399_cru.c 2018/08/12 19:28:41 1.2
+++ src/sys/arch/arm/rockchip/rk3399_cru.c 2018/09/01 19:35:53 1.3
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: rk3399_cru.c,v 1.2 2018/08/12 19:28:41 jmcneill Exp $ */ 1/* $NetBSD: rk3399_cru.c,v 1.3 2018/09/01 19:35:53 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2018 Jared 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.
@@ -18,27 +18,27 @@ @@ -18,27 +18,27 @@
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
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 <sys/cdefs.h> 29#include <sys/cdefs.h>
30 30
31__KERNEL_RCSID(1, "$NetBSD: rk3399_cru.c,v 1.2 2018/08/12 19:28:41 jmcneill Exp $"); 31__KERNEL_RCSID(1, "$NetBSD: rk3399_cru.c,v 1.3 2018/09/01 19:35:53 jmcneill Exp $");
32 32
33#include <sys/param.h> 33#include <sys/param.h>
34#include <sys/bus.h> 34#include <sys/bus.h>
35#include <sys/device.h> 35#include <sys/device.h>
36#include <sys/systm.h> 36#include <sys/systm.h>
37 37
38#include <dev/fdt/fdtvar.h> 38#include <dev/fdt/fdtvar.h>
39 39
40#include <arm/rockchip/rk_cru.h> 40#include <arm/rockchip/rk_cru.h>
41#include <arm/rockchip/rk3399_cru.h> 41#include <arm/rockchip/rk3399_cru.h>
42 42
43#define PLL_CON(n) (0x0000 + (n) * 4) 43#define PLL_CON(n) (0x0000 + (n) * 4)
44#define CLKSEL_CON(n) (0x0100 + (n) * 4) 44#define CLKSEL_CON(n) (0x0100 + (n) * 4)
@@ -129,26 +129,87 @@ static const struct rk_cru_pll_rate pll_ @@ -129,26 +129,87 @@ static const struct rk_cru_pll_rate pll_
129 RK_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0), 129 RK_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
130 RK_PLL_RATE( 148500000, 1, 99, 4, 4, 1, 0), 130 RK_PLL_RATE( 148500000, 1, 99, 4, 4, 1, 0),
131 RK_PLL_RATE( 106500000, 1, 71, 4, 4, 1, 0), 131 RK_PLL_RATE( 106500000, 1, 71, 4, 4, 1, 0),
132 RK_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0), 132 RK_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0),
133 RK_PLL_RATE( 74250000, 2, 99, 4, 4, 1, 0), 133 RK_PLL_RATE( 74250000, 2, 99, 4, 4, 1, 0),
134 RK_PLL_RATE( 65000000, 1, 65, 6, 4, 1, 0), 134 RK_PLL_RATE( 65000000, 1, 65, 6, 4, 1, 0),
135 RK_PLL_RATE( 54000000, 1, 54, 6, 4, 1, 0), 135 RK_PLL_RATE( 54000000, 1, 54, 6, 4, 1, 0),
136 RK_PLL_RATE( 27000000, 1, 27, 6, 4, 1, 0), 136 RK_PLL_RATE( 27000000, 1, 27, 6, 4, 1, 0),
137}; 137};
138 138
139static const struct rk_cru_pll_rate pll_norates[] = { 139static const struct rk_cru_pll_rate pll_norates[] = {
140}; 140};
141 141
 142#define RK3399_ACLKM_MASK __BITS(12,8)
 143#define RK3399_ATCLK_MASK __BITS(4,0)
 144#define RK3399_PDBG_MASK __BITS(12,8)
 145
 146#define RK3399_CPUL_RATE(_rate, _aclkm, _atclk, _pdbg) \
 147 RK_CPU_RATE(_rate, \
 148 CLKSEL_CON(0), RK3399_ACLKM_MASK, \
 149 __SHIFTIN((_aclkm), RK3399_ACLKM_MASK), \
 150 CLKSEL_CON(1), RK3399_ATCLK_MASK|RK3399_PDBG_MASK, \
 151 __SHIFTIN((_atclk), RK3399_ATCLK_MASK)|__SHIFTIN((_pdbg), RK3399_PDBG_MASK))
 152
 153#define RK3399_CPUB_RATE(_rate, _aclkm, _atclk, _pdbg) \
 154 RK_CPU_RATE(_rate, \
 155 CLKSEL_CON(2), RK3399_ACLKM_MASK, \
 156 __SHIFTIN((_aclkm), RK3399_ACLKM_MASK), \
 157 CLKSEL_CON(3), RK3399_ATCLK_MASK|RK3399_PDBG_MASK, \
 158 __SHIFTIN((_atclk), RK3399_ATCLK_MASK)|__SHIFTIN((_pdbg), RK3399_PDBG_MASK))
 159
 160static const struct rk_cru_cpu_rate armclkl_rates[] = {
 161 RK3399_CPUL_RATE(1800000000, 1, 8, 8),
 162 RK3399_CPUL_RATE(1704000000, 1, 8, 8),
 163 RK3399_CPUL_RATE(1608000000, 1, 7, 7),
 164 RK3399_CPUL_RATE(1512000000, 1, 7, 7),
 165 RK3399_CPUL_RATE(1488000000, 1, 6, 6),
 166 RK3399_CPUL_RATE(1416000000, 1, 6, 6),
 167 RK3399_CPUL_RATE(1200000000, 1, 5, 5),
 168 RK3399_CPUL_RATE(1008000000, 1, 4, 4),
 169 RK3399_CPUL_RATE( 816000000, 1, 3, 3),
 170 RK3399_CPUL_RATE( 696000000, 1, 3, 3),
 171 RK3399_CPUL_RATE( 600000000, 1, 2, 2),
 172 RK3399_CPUL_RATE( 408000000, 1, 1, 1),
 173 RK3399_CPUL_RATE( 312000000, 1, 1, 1),
 174 RK3399_CPUL_RATE( 216000000, 1, 1, 1),
 175 RK3399_CPUL_RATE( 96000000, 1, 1, 1),
 176};
 177
 178static const struct rk_cru_cpu_rate armclkb_rates[] = {
 179 RK3399_CPUB_RATE(2208000000, 1, 11, 11),
 180 RK3399_CPUB_RATE(2184000000, 1, 11, 11),
 181 RK3399_CPUB_RATE(2088000000, 1, 10, 10),
 182 RK3399_CPUB_RATE(2040000000, 1, 10, 10),
 183 RK3399_CPUB_RATE(2016000000, 1, 9, 9),
 184 RK3399_CPUB_RATE(1992000000, 1, 9, 9),
 185 RK3399_CPUB_RATE(1896000000, 1, 9, 9),
 186 RK3399_CPUB_RATE(1800000000, 1, 8, 8),
 187 RK3399_CPUB_RATE(1704000000, 1, 8, 8),
 188 RK3399_CPUB_RATE(1608000000, 1, 7, 7),
 189 RK3399_CPUB_RATE(1512000000, 1, 7, 7),
 190 RK3399_CPUB_RATE(1488000000, 1, 6, 6),
 191 RK3399_CPUB_RATE(1416000000, 1, 6, 6),
 192 RK3399_CPUB_RATE(1200000000, 1, 5, 5),
 193 RK3399_CPUB_RATE(1008000000, 1, 5, 5),
 194 RK3399_CPUB_RATE( 816000000, 1, 4, 4),
 195 RK3399_CPUB_RATE( 696000000, 1, 3, 3),
 196 RK3399_CPUB_RATE( 600000000, 1, 3, 3),
 197 RK3399_CPUB_RATE( 408000000, 1, 2, 2),
 198 RK3399_CPUB_RATE( 312000000, 1, 1, 1),
 199 RK3399_CPUB_RATE( 216000000, 1, 1, 1),
 200 RK3399_CPUB_RATE( 96000000, 1, 1, 1),
 201};
 202
142#define PLL_CON0 0x00 203#define PLL_CON0 0x00
143#define PLL_FBDIV __BITS(11,0) 204#define PLL_FBDIV __BITS(11,0)
144 205
145#define PLL_CON1 0x04 206#define PLL_CON1 0x04
146#define PLL_POSTDIV2 __BITS(14,12) 207#define PLL_POSTDIV2 __BITS(14,12)
147#define PLL_POSTDIV1 __BITS(10,8) 208#define PLL_POSTDIV1 __BITS(10,8)
148#define PLL_REFDIV __BITS(5,0) 209#define PLL_REFDIV __BITS(5,0)
149 210
150#define PLL_CON2 0x08 211#define PLL_CON2 0x08
151#define PLL_LOCK __BIT(31) 212#define PLL_LOCK __BIT(31)
152#define PLL_FRACDIV __BITS(23,0) 213#define PLL_FRACDIV __BITS(23,0)
153 214
154#define PLL_CON3 0x0c 215#define PLL_CON3 0x0c
@@ -219,84 +280,81 @@ rk3399_cru_pll_set_rate(struct rk_cru_so @@ -219,84 +280,81 @@ rk3399_cru_pll_set_rate(struct rk_cru_so
219 280
220 for (int i = 0; i < pll->nrates; i++) 281 for (int i = 0; i < pll->nrates; i++)
221 if (pll->rates[i].rate == rate) { 282 if (pll->rates[i].rate == rate) {
222 pll_rate = &pll->rates[i]; 283 pll_rate = &pll->rates[i];
223 break; 284 break;
224 } 285 }
225 if (pll_rate == NULL) 286 if (pll_rate == NULL)
226 return EINVAL; 287 return EINVAL;
227 288
228 val = __SHIFTIN(PLL_WORK_MODE_SLOW, PLL_WORK_MODE) | (PLL_WORK_MODE << 16); 289 val = __SHIFTIN(PLL_WORK_MODE_SLOW, PLL_WORK_MODE) | (PLL_WORK_MODE << 16);
229 CRU_WRITE(sc, pll->con_base + PLL_CON3, val); 290 CRU_WRITE(sc, pll->con_base + PLL_CON3, val);
230 291
231 CRU_WRITE(sc, pll->con_base + PLL_CON0, 292 CRU_WRITE(sc, pll->con_base + PLL_CON0,
232 __SHIFTIN(pll_rate->fbdiv, PLL_FBDIV) | 293 __SHIFTIN(pll_rate->fbdiv, PLL_FBDIV) | (PLL_FBDIV << 16));
233 PLL_WRITE_MASK); 
234 294
235 CRU_WRITE(sc, pll->con_base + PLL_CON1, 295 CRU_WRITE(sc, pll->con_base + PLL_CON1,
236 __SHIFTIN(pll_rate->postdiv2, PLL_POSTDIV2) | 296 __SHIFTIN(pll_rate->postdiv2, PLL_POSTDIV2) |
237 __SHIFTIN(pll_rate->postdiv1, PLL_POSTDIV1) | 297 __SHIFTIN(pll_rate->postdiv1, PLL_POSTDIV1) |
238 __SHIFTIN(pll_rate->refdiv, PLL_REFDIV) | 298 __SHIFTIN(pll_rate->refdiv, PLL_REFDIV) |
239 PLL_WRITE_MASK); 299 ((PLL_POSTDIV2 | PLL_POSTDIV1 | PLL_REFDIV) << 16));
240 300
241 val = CRU_READ(sc, pll->con_base + PLL_CON2); 301 val = CRU_READ(sc, pll->con_base + PLL_CON2);
242 val &= ~PLL_FRACDIV; 302 val &= ~PLL_FRACDIV;
243 val |= __SHIFTIN(pll_rate->fracdiv, PLL_FRACDIV); 303 val |= __SHIFTIN(pll_rate->fracdiv, PLL_FRACDIV);
244 CRU_WRITE(sc, pll->con_base + PLL_CON2, val); 304 CRU_WRITE(sc, pll->con_base + PLL_CON2, val);
245 305
246 val = __SHIFTIN(pll_rate->dsmpd, PLL_DSMPD) | (PLL_DSMPD << 16); 306 val = __SHIFTIN(pll_rate->dsmpd, PLL_DSMPD) | (PLL_DSMPD << 16);
247 CRU_WRITE(sc, pll->con_base + PLL_CON3, val); 307 CRU_WRITE(sc, pll->con_base + PLL_CON3, val);
248 308
249 /* Set PLL work mode to normal */ 
250 const uint32_t write_mask = pll->mode_mask << 16; 
251 const uint32_t write_val = pll->mode_mask; 
252 CRU_WRITE(sc, pll->mode_reg, write_mask | write_val); 
253 
254 for (retry = 1000; retry > 0; retry--) { 309 for (retry = 1000; retry > 0; retry--) {
255 if (CRU_READ(sc, pll->con_base + PLL_CON2) & pll->lock_mask) 310 if (CRU_READ(sc, pll->con_base + PLL_CON2) & pll->lock_mask)
256 break; 311 break;
257 delay(1); 312 delay(1);
258 } 313 }
259 314
260 if (retry == 0) 315 if (retry == 0)
261 device_printf(sc->sc_dev, "WARNING: %s failed to lock\n", 316 device_printf(sc->sc_dev, "WARNING: %s failed to lock\n",
262 clk->base.name); 317 clk->base.name);
263 318
 319 /* Set PLL work mode to normal */
264 val = __SHIFTIN(PLL_WORK_MODE_NORMAL, PLL_WORK_MODE) | (PLL_WORK_MODE << 16); 320 val = __SHIFTIN(PLL_WORK_MODE_NORMAL, PLL_WORK_MODE) | (PLL_WORK_MODE << 16);
265 CRU_WRITE(sc, pll->con_base + PLL_CON3, val); 321 CRU_WRITE(sc, pll->con_base + PLL_CON3, val);
266 322
267 return 0; 323 return 0;
268} 324}
269 325
270#define RK3399_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \ 326#define RK3399_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \
271 { \ 327 { \
272 .id = (_id), \ 328 .id = (_id), \
273 .type = RK_CRU_PLL, \ 329 .type = RK_CRU_PLL, \
274 .base.name = (_name), \ 330 .base.name = (_name), \
275 .base.flags = 0, \ 331 .base.flags = 0, \
276 .u.pll.parents = (_parents), \ 332 .u.pll.parents = (_parents), \
277 .u.pll.nparents = __arraycount(_parents), \ 333 .u.pll.nparents = __arraycount(_parents), \
278 .u.pll.con_base = (_con_base), \ 334 .u.pll.con_base = (_con_base), \
279 .u.pll.mode_reg = (_mode_reg), \ 335 .u.pll.mode_reg = (_mode_reg), \
280 .u.pll.mode_mask = (_mode_mask), \ 336 .u.pll.mode_mask = (_mode_mask), \
281 .u.pll.lock_mask = (_lock_mask), \ 337 .u.pll.lock_mask = (_lock_mask), \
282 .u.pll.rates = (_rates), \ 338 .u.pll.rates = (_rates), \
283 .u.pll.nrates = __arraycount(_rates), \ 339 .u.pll.nrates = __arraycount(_rates), \
284 .get_rate = rk3399_cru_pll_get_rate, \ 340 .get_rate = rk3399_cru_pll_get_rate, \
285 .set_rate = rk3399_cru_pll_set_rate, \ 341 .set_rate = rk3399_cru_pll_set_rate, \
286 .get_parent = rk_cru_pll_get_parent, \ 342 .get_parent = rk_cru_pll_get_parent, \
287 } 343 }
288 344
289static const char * pll_parents[] = { "xin24m", "xin32k" }; 345static const char * pll_parents[] = { "xin24m", "xin32k" };
 346static const char * armclkl_parents[] = { "clk_core_l_lpll_src", "clk_core_l_bpll_src", "clk_core_l_dpll_src", "clk_core_l_gpll_src" };
 347static const char * armclkb_parents[] = { "clk_core_b_lpll_src", "clk_core_b_bpll_src", "clk_core_b_dpll_src", "clk_core_b_gpll_src" };
290static const char * mux_pll_src_cpll_gpll_parents[] = { "cpll", "gpll" }; 348static const char * mux_pll_src_cpll_gpll_parents[] = { "cpll", "gpll" };
291static const char * mux_pll_src_cpll_gpll_npll_parents[] = { "cpll", "gpll", "npll" }; 349static const char * mux_pll_src_cpll_gpll_npll_parents[] = { "cpll", "gpll", "npll" };
292static const char * mux_pll_src_cpll_gpll_upll_parents[] = { "cpll", "gpll", "upll" }; 350static const char * mux_pll_src_cpll_gpll_upll_parents[] = { "cpll", "gpll", "upll" };
293static const char * mux_pll_src_cpll_gpll_npll_ppll_upll_24m_parents[] = { "cpll", "gpll", "npll", "ppll", "upll", "xin24m" }; 351static const char * mux_pll_src_cpll_gpll_npll_ppll_upll_24m_parents[] = { "cpll", "gpll", "npll", "ppll", "upll", "xin24m" };
294static const char * mux_aclk_perilp0_parents[] = { "cpll_aclk_perilp0_src", "gpll_aclk_perilp0_src" }; 352static const char * mux_aclk_perilp0_parents[] = { "cpll_aclk_perilp0_src", "gpll_aclk_perilp0_src" };
295static const char * mux_hclk_perilp1_parents[] = { "cpll_hclk_perilp1_src", "gpll_hclk_perilp1_src" }; 353static const char * mux_hclk_perilp1_parents[] = { "cpll_hclk_perilp1_src", "gpll_hclk_perilp1_src" };
296static const char * mux_aclk_perihp_parents[] = { "cpll_aclk_perihp_src", "gpll_aclk_perihp_src" }; 354static const char * mux_aclk_perihp_parents[] = { "cpll_aclk_perihp_src", "gpll_aclk_perihp_src" };
297static const char * mux_aclk_cci_parents[] = { "cpll_aclk_cci_src", "gpll_aclk_cci_src", "npll_aclk_cci_src", "vpll_aclk_cci_src" }; 355static const char * mux_aclk_cci_parents[] = { "cpll_aclk_cci_src", "gpll_aclk_cci_src", "npll_aclk_cci_src", "vpll_aclk_cci_src" };
298static const char * mux_uart0_parents[] = { "clk_uart0_div", "clk_uart0_frac", "xin24m" }; 356static const char * mux_uart0_parents[] = { "clk_uart0_div", "clk_uart0_frac", "xin24m" };
299static const char * mux_uart1_parents[] = { "clk_uart1_div", "clk_uart1_frac", "xin24m" }; 357static const char * mux_uart1_parents[] = { "clk_uart1_div", "clk_uart1_frac", "xin24m" };
300static const char * mux_uart2_parents[] = { "clk_uart2_div", "clk_uart2_frac", "xin24m" }; 358static const char * mux_uart2_parents[] = { "clk_uart2_div", "clk_uart2_frac", "xin24m" };
301static const char * mux_uart3_parents[] = { "clk_uart3_div", "clk_uart3_frac", "xin24m" }; 359static const char * mux_uart3_parents[] = { "clk_uart3_div", "clk_uart3_frac", "xin24m" };
302static const char * mux_rmii_parents[] = { "clk_gmac", "clkin_gmac" }; 360static const char * mux_rmii_parents[] = { "clk_gmac", "clkin_gmac" };
@@ -336,26 +394,48 @@ static struct rk_cru_clk rk3399_cru_clks @@ -336,26 +394,48 @@ static struct rk_cru_clk rk3399_cru_clks
336 RK3399_PLL(RK3399_PLL_NPLL, "npll", pll_parents, 394 RK3399_PLL(RK3399_PLL_NPLL, "npll", pll_parents,
337 PLL_CON(40), /* con_base */ 395 PLL_CON(40), /* con_base */
338 PLL_CON(43), /* mode_reg */ 396 PLL_CON(43), /* mode_reg */
339 __BIT(8), /* mode_mask */ 397 __BIT(8), /* mode_mask */
340 __BIT(31), /* lock_mask */ 398 __BIT(31), /* lock_mask */
341 pll_rates), 399 pll_rates),
342 RK3399_PLL(RK3399_PLL_VPLL, "vpll", pll_parents, 400 RK3399_PLL(RK3399_PLL_VPLL, "vpll", pll_parents,
343 PLL_CON(43), /* con_base */ 401 PLL_CON(43), /* con_base */
344 PLL_CON(51), /* mode_reg */ 402 PLL_CON(51), /* mode_reg */
345 __BIT(8), /* mode_mask */ 403 __BIT(8), /* mode_mask */
346 __BIT(31), /* lock_mask */ 404 __BIT(31), /* lock_mask */
347 pll_rates), 405 pll_rates),
348 406
 407 RK_GATE(0, "clk_core_l_lpll_src", "lpll", CLKGATE_CON(0), 0),
 408 RK_GATE(0, "clk_core_l_bpll_src", "bpll", CLKGATE_CON(0), 1),
 409 RK_GATE(0, "clk_core_l_dpll_src", "dpll", CLKGATE_CON(0), 2),
 410 RK_GATE(0, "clk_core_l_gpll_src", "gpll", CLKGATE_CON(0), 3),
 411
 412 RK_CPU(RK3399_ARMCLKL, "armclkl", armclkl_parents,
 413 CLKSEL_CON(0), /* reg */
 414 __BITS(7,6), 0, 3, /* mux_mask, mux_main, mux_alt */
 415 __BITS(4,0), /* div_mask */
 416 armclkl_rates),
 417
 418 RK_GATE(0, "clk_core_b_lpll_src", "lpll", CLKGATE_CON(1), 0),
 419 RK_GATE(0, "clk_core_b_bpll_src", "bpll", CLKGATE_CON(1), 1),
 420 RK_GATE(0, "clk_core_b_dpll_src", "dpll", CLKGATE_CON(1), 2),
 421 RK_GATE(0, "clk_core_b_gpll_src", "gpll", CLKGATE_CON(1), 3),
 422
 423 RK_CPU(RK3399_ARMCLKB, "armclkb", armclkb_parents,
 424 CLKSEL_CON(2), /* reg */
 425 __BITS(7,6), 1, 3, /* mux_mask, mux_main, mux_alt */
 426 __BITS(4,0), /* div_mask */
 427 armclkb_rates),
 428
349 /* 429 /*
350 * perilp0 430 * perilp0
351 */ 431 */
352 RK_GATE(0, "gpll_aclk_perilp0_src", "gpll", CLKGATE_CON(7), 0), 432 RK_GATE(0, "gpll_aclk_perilp0_src", "gpll", CLKGATE_CON(7), 0),
353 RK_GATE(0, "cpll_aclk_perilp0_src", "cpll", CLKGATE_CON(7), 1), 433 RK_GATE(0, "cpll_aclk_perilp0_src", "cpll", CLKGATE_CON(7), 1),
354 RK_COMPOSITE(RK3399_ACLK_PERILP0, "aclk_perilp0", mux_aclk_perilp0_parents, 434 RK_COMPOSITE(RK3399_ACLK_PERILP0, "aclk_perilp0", mux_aclk_perilp0_parents,
355 CLKSEL_CON(23), /* muxdiv_reg */ 435 CLKSEL_CON(23), /* muxdiv_reg */
356 __BIT(7), /* mux_mask */ 436 __BIT(7), /* mux_mask */
357 __BITS(4,0), /* div_mask */ 437 __BITS(4,0), /* div_mask */
358 CLKGATE_CON(7), /* gate_reg */ 438 CLKGATE_CON(7), /* gate_reg */
359 __BIT(2), /* gate_mask */ 439 __BIT(2), /* gate_mask */
360 0), 440 0),
361 RK_COMPOSITE_NOMUX(RK3399_HCLK_PERILP0, "hclk_perilp0", "aclk_perilp0", 441 RK_COMPOSITE_NOMUX(RK3399_HCLK_PERILP0, "hclk_perilp0", "aclk_perilp0",

cvs diff -r1.3 -r1.4 src/sys/arch/arm/rockchip/rk_cru.h (expand / switch to unified diff)

--- src/sys/arch/arm/rockchip/rk_cru.h 2018/08/12 16:48:05 1.3
+++ src/sys/arch/arm/rockchip/rk_cru.h 2018/09/01 19:35:53 1.4
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: rk_cru.h,v 1.3 2018/08/12 16:48:05 jmcneill Exp $ */ 1/* $NetBSD: rk_cru.h,v 1.4 2018/09/01 19:35:53 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2018 Jared 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.
@@ -108,64 +108,100 @@ const char *rk_cru_pll_get_parent(struct @@ -108,64 +108,100 @@ const char *rk_cru_pll_get_parent(struct
108/* ARM clocks */ 108/* ARM clocks */
109 109
110struct rk_cru_arm_rate { 110struct rk_cru_arm_rate {
111 u_int rate; 111 u_int rate;
112 u_int div; 112 u_int div;
113}; 113};
114 114
115#define RK_ARM_RATE(_rate, _div) \ 115#define RK_ARM_RATE(_rate, _div) \
116 { \ 116 { \
117 .rate = (_rate), \ 117 .rate = (_rate), \
118 .div = (_div), \ 118 .div = (_div), \
119 } 119 }
120 120
 121struct rk_cru_cpu_rate {
 122 u_int rate;
 123 u_int reg1, reg1_mask, reg1_val;
 124 u_int reg2, reg2_mask, reg2_val;
 125};
 126
 127#define RK_CPU_RATE(_rate, _reg1, _reg1_mask, _reg1_val, _reg2, _reg2_mask, _reg2_val) \
 128 { \
 129 .rate = (_rate), \
 130 .reg1 = (_reg1), .reg1_mask = (_reg1_mask), .reg1_val = (_reg1_val), \
 131 .reg2 = (_reg2), .reg2_mask = (_reg2_mask), .reg2_val = (_reg2_val), \
 132 }
 133
121struct rk_cru_arm { 134struct rk_cru_arm {
122 bus_size_t reg; 135 bus_size_t reg;
123 uint32_t mux_mask; 136 uint32_t mux_mask;
124 u_int mux_main; 137 u_int mux_main;
125 u_int mux_alt; 138 u_int mux_alt;
126 uint32_t div_mask; 139 uint32_t div_mask;
127 const char **parents; 140 const char **parents;
128 u_int nparents; 141 u_int nparents;
129 const struct rk_cru_arm_rate *rates; 142 const struct rk_cru_arm_rate *rates;
 143 const struct rk_cru_cpu_rate *cpurates;
130 u_int nrates; 144 u_int nrates;
131}; 145};
132 146
133u_int rk_cru_arm_get_rate(struct rk_cru_softc *, struct rk_cru_clk *); 147u_int rk_cru_arm_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
134int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int); 148int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
 149int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
135const char *rk_cru_arm_get_parent(struct rk_cru_softc *, struct rk_cru_clk *); 150const char *rk_cru_arm_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
136int rk_cru_arm_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *); 151int rk_cru_arm_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
137 152
138#define RK_ARM(_id, _name, _parents, _reg, _mux_mask, _mux_main, _mux_alt, _div_mask, _rates) \ 153#define RK_ARM(_id, _name, _parents, _reg, _mux_mask, _mux_main, _mux_alt, _div_mask, _rates) \
139 { \ 154 { \
140 .id = (_id), \ 155 .id = (_id), \
141 .type = RK_CRU_ARM, \ 156 .type = RK_CRU_ARM, \
142 .base.name = (_name), \ 157 .base.name = (_name), \
143 .base.flags = 0, \ 158 .base.flags = 0, \
144 .u.arm.parents = (_parents), \ 159 .u.arm.parents = (_parents), \
145 .u.arm.nparents = __arraycount(_parents), \ 160 .u.arm.nparents = __arraycount(_parents), \
146 .u.arm.reg = (_reg), \ 161 .u.arm.reg = (_reg), \
147 .u.arm.mux_mask = (_mux_mask), \ 162 .u.arm.mux_mask = (_mux_mask), \
148 .u.arm.mux_main = (_mux_main), \ 163 .u.arm.mux_main = (_mux_main), \
149 .u.arm.mux_alt = (_mux_alt), \ 164 .u.arm.mux_alt = (_mux_alt), \
150 .u.arm.div_mask = (_div_mask), \ 165 .u.arm.div_mask = (_div_mask), \
151 .u.arm.rates = (_rates), \ 166 .u.arm.rates = (_rates), \
152 .u.arm.nrates = __arraycount(_rates), \ 167 .u.arm.nrates = __arraycount(_rates), \
153 .get_rate = rk_cru_arm_get_rate, \ 168 .get_rate = rk_cru_arm_get_rate, \
154 .set_rate = rk_cru_arm_set_rate, \ 169 .set_rate = rk_cru_arm_set_rate, \
155 .get_parent = rk_cru_arm_get_parent, \ 170 .get_parent = rk_cru_arm_get_parent, \
156 .set_parent = rk_cru_arm_set_parent, \ 171 .set_parent = rk_cru_arm_set_parent, \
157 } 172 }
158 173
 174#define RK_CPU(_id, _name, _parents, _reg, _mux_mask, _mux_main, _mux_alt, _div_mask, _cpurates) \
 175 { \
 176 .id = (_id), \
 177 .type = RK_CRU_ARM, \
 178 .base.name = (_name), \
 179 .base.flags = 0, \
 180 .u.arm.parents = (_parents), \
 181 .u.arm.nparents = __arraycount(_parents), \
 182 .u.arm.reg = (_reg), \
 183 .u.arm.mux_mask = (_mux_mask), \
 184 .u.arm.mux_main = (_mux_main), \
 185 .u.arm.mux_alt = (_mux_alt), \
 186 .u.arm.div_mask = (_div_mask), \
 187 .u.arm.cpurates = (_cpurates), \
 188 .u.arm.nrates = __arraycount(_cpurates), \
 189 .get_rate = rk_cru_arm_get_rate, \
 190 .set_rate = rk_cru_arm_set_rate, \
 191 .get_parent = rk_cru_arm_get_parent, \
 192 .set_parent = rk_cru_arm_set_parent, \
 193 }
 194
159/* Composite clocks */ 195/* Composite clocks */
160 196
161struct rk_cru_composite { 197struct rk_cru_composite {
162 bus_size_t muxdiv_reg; 198 bus_size_t muxdiv_reg;
163 uint32_t mux_mask; 199 uint32_t mux_mask;
164 uint32_t div_mask; 200 uint32_t div_mask;
165 bus_size_t gate_reg; 201 bus_size_t gate_reg;
166 uint32_t gate_mask; 202 uint32_t gate_mask;
167 const char **parents; 203 const char **parents;
168 u_int nparents; 204 u_int nparents;
169 u_int flags; 205 u_int flags;
170#define RK_COMPOSITE_ROUND_DOWN 0x01 206#define RK_COMPOSITE_ROUND_DOWN 0x01
171}; 207};

cvs diff -r1.1 -r1.2 src/sys/arch/arm/rockchip/rk_cru_arm.c (expand / switch to unified diff)

--- src/sys/arch/arm/rockchip/rk_cru_arm.c 2018/06/16 00:19:04 1.1
+++ src/sys/arch/arm/rockchip/rk_cru_arm.c 2018/09/01 19:35:53 1.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: rk_cru_arm.c,v 1.1 2018/06/16 00:19:04 jmcneill Exp $ */ 1/* $NetBSD: rk_cru_arm.c,v 1.2 2018/09/01 19:35:53 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2018 Jared 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.
@@ -17,27 +17,27 @@ @@ -17,27 +17,27 @@
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
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 <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: rk_cru_arm.c,v 1.1 2018/06/16 00:19:04 jmcneill Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: rk_cru_arm.c,v 1.2 2018/09/01 19:35:53 jmcneill Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/bus.h> 33#include <sys/bus.h>
34 34
35#include <dev/clk/clk_backend.h> 35#include <dev/clk/clk_backend.h>
36 36
37#include <arm/rockchip/rk_cru.h> 37#include <arm/rockchip/rk_cru.h>
38 38
39u_int 39u_int
40rk_cru_arm_get_rate(struct rk_cru_softc *sc, 40rk_cru_arm_get_rate(struct rk_cru_softc *sc,
41 struct rk_cru_clk *clk) 41 struct rk_cru_clk *clk)
42{ 42{
43 struct rk_cru_arm *arm = &clk->u.arm; 43 struct rk_cru_arm *arm = &clk->u.arm;
@@ -50,68 +50,143 @@ rk_cru_arm_get_rate(struct rk_cru_softc  @@ -50,68 +50,143 @@ rk_cru_arm_get_rate(struct rk_cru_softc
50 if (clkp_parent == NULL) 50 if (clkp_parent == NULL)
51 return 0; 51 return 0;
52 52
53 const u_int fref = clk_get_rate(clkp_parent); 53 const u_int fref = clk_get_rate(clkp_parent);
54 if (fref == 0) 54 if (fref == 0)
55 return 0; 55 return 0;
56 56
57 const uint32_t val = CRU_READ(sc, arm->reg); 57 const uint32_t val = CRU_READ(sc, arm->reg);
58 const u_int div = __SHIFTOUT(val, arm->div_mask) + 1; 58 const u_int div = __SHIFTOUT(val, arm->div_mask) + 1;
59 59
60 return fref / div; 60 return fref / div;
61} 61}
62 62
63int 63static int
64rk_cru_arm_set_rate(struct rk_cru_softc *sc, 64rk_cru_arm_set_rate_rates(struct rk_cru_softc *sc,
65 struct rk_cru_clk *clk, u_int rate) 65 struct rk_cru_clk *clk, u_int rate)
66{ 66{
67 struct rk_cru_arm *arm = &clk->u.arm; 67 struct rk_cru_arm *arm = &clk->u.arm;
 68 struct rk_cru_clk *main_parent, *alt_parent;
68 const struct rk_cru_arm_rate *arm_rate = NULL; 69 const struct rk_cru_arm_rate *arm_rate = NULL;
69 struct clk *clkp_parent; 
70 int error; 70 int error;
71 71
72 KASSERT(clk->type == RK_CRU_ARM); 72 KASSERT(clk->type == RK_CRU_ARM);
73 73
74 if (arm->rates == NULL || rate == 0) 74 if (arm->rates == NULL || rate == 0)
75 return EIO; 75 return EIO;
76 76
77 for (int i = 0; i < arm->nrates; i++) 77 for (int i = 0; i < arm->nrates; i++)
78 if (arm->rates[i].rate == rate) { 78 if (arm->rates[i].rate == rate) {
79 arm_rate = &arm->rates[i]; 79 arm_rate = &arm->rates[i];
80 break; 80 break;
81 } 81 }
82 if (arm_rate == NULL) 82 if (arm_rate == NULL)
83 return EINVAL; 83 return EINVAL;
84 84
85 error = rk_cru_arm_set_parent(sc, clk, arm->parents[arm->mux_main]); 85 main_parent = rk_cru_clock_find(sc, arm->parents[arm->mux_main]);
 86 alt_parent = rk_cru_clock_find(sc, arm->parents[arm->mux_alt]);
 87 if (main_parent == NULL || alt_parent == NULL) {
 88 device_printf(sc->sc_dev, "couldn't get clock parents\n");
 89 return ENXIO;
 90 }
 91
 92 error = rk_cru_arm_set_parent(sc, clk, arm->parents[arm->mux_alt]);
86 if (error != 0) 93 if (error != 0)
87 return error; 94 return error;
88 95
89 clkp_parent = clk_get_parent(&clk->base); 
90 if (clkp_parent == NULL) 
91 return ENXIO; 
92 
93 const u_int parent_rate = arm_rate->rate / arm_rate->div; 96 const u_int parent_rate = arm_rate->rate / arm_rate->div;
94 97
95 error = clk_set_rate(clkp_parent, parent_rate); 98 error = clk_set_rate(&main_parent->base, parent_rate);
96 if (error != 0) 99 if (error != 0)
97 return error; 100 goto done;
98 101
99 const uint32_t write_mask = arm->div_mask << 16; 102 const uint32_t write_mask = arm->div_mask << 16;
100 const uint32_t write_val = __SHIFTIN(arm_rate->div - 1, arm->div_mask); 103 const uint32_t write_val = __SHIFTIN(arm_rate->div - 1, arm->div_mask);
101 104
102 CRU_WRITE(sc, arm->reg, write_mask | write_val); 105 CRU_WRITE(sc, arm->reg, write_mask | write_val);
103 106
104 return 0; 107done:
 108 rk_cru_arm_set_parent(sc, clk, arm->parents[arm->mux_main]);
 109 return error;
 110}
 111
 112static int
 113rk_cru_arm_set_rate_cpurates(struct rk_cru_softc *sc,
 114 struct rk_cru_clk *clk, u_int rate)
 115{
 116 struct rk_cru_arm *arm = &clk->u.arm;
 117 struct rk_cru_clk *main_parent, *alt_parent;
 118 const struct rk_cru_cpu_rate *cpu_rate = NULL;
 119 uint32_t write_mask, write_val;
 120 int error;
 121
 122 KASSERT(clk->type == RK_CRU_ARM);
 123
 124 if (arm->cpurates == NULL || rate == 0)
 125 return EIO;
 126
 127 for (int i = 0; i < arm->nrates; i++)
 128 if (arm->cpurates[i].rate == rate) {
 129 cpu_rate = &arm->cpurates[i];
 130 break;
 131 }
 132 if (cpu_rate == NULL)
 133 return EINVAL;
 134
 135 main_parent = rk_cru_clock_find(sc, arm->parents[arm->mux_main]);
 136 alt_parent = rk_cru_clock_find(sc, arm->parents[arm->mux_alt]);
 137 if (main_parent == NULL || alt_parent == NULL) {
 138 device_printf(sc->sc_dev, "couldn't get clock parents\n");
 139 return ENXIO;
 140 }
 141
 142 error = rk_cru_arm_set_parent(sc, clk, arm->parents[arm->mux_alt]);
 143 if (error != 0)
 144 return error;
 145
 146 error = clk_set_rate(&main_parent->base, rate);
 147 if (error != 0)
 148 goto done;
 149
 150 write_mask = cpu_rate->reg1_mask << 16;
 151 write_val = cpu_rate->reg1_val;
 152 CRU_WRITE(sc, cpu_rate->reg1, write_mask | write_val);
 153
 154 write_mask = cpu_rate->reg2_mask << 16;
 155 write_val = cpu_rate->reg2_val;
 156 CRU_WRITE(sc, cpu_rate->reg2, write_mask | write_val);
 157
 158 write_mask = arm->div_mask << 16;
 159 write_val = __SHIFTIN(0, arm->div_mask);
 160 CRU_WRITE(sc, arm->reg, write_mask | write_val);
 161
 162done:
 163 rk_cru_arm_set_parent(sc, clk, arm->parents[arm->mux_main]);
 164 return error;
 165}
 166
 167
 168int
 169rk_cru_arm_set_rate(struct rk_cru_softc *sc,
 170 struct rk_cru_clk *clk, u_int rate)
 171{
 172 struct rk_cru_arm *arm = &clk->u.arm;
 173
 174 if (arm->rates)
 175 return rk_cru_arm_set_rate_rates(sc, clk, rate);
 176 else if (arm->cpurates)
 177 return rk_cru_arm_set_rate_cpurates(sc, clk, rate);
 178 else
 179 return EIO;
105} 180}
106 181
107const char * 182const char *
108rk_cru_arm_get_parent(struct rk_cru_softc *sc, 183rk_cru_arm_get_parent(struct rk_cru_softc *sc,
109 struct rk_cru_clk *clk) 184 struct rk_cru_clk *clk)
110{ 185{
111 struct rk_cru_arm *arm = &clk->u.arm; 186 struct rk_cru_arm *arm = &clk->u.arm;
112 187
113 KASSERT(clk->type == RK_CRU_ARM); 188 KASSERT(clk->type == RK_CRU_ARM);
114 189
115 const uint32_t val = CRU_READ(sc, arm->reg); 190 const uint32_t val = CRU_READ(sc, arm->reg);
116 const u_int mux = __SHIFTOUT(val, arm->mux_mask); 191 const u_int mux = __SHIFTOUT(val, arm->mux_mask);
117 192