jcs's openbsd hax
openbsd
1/* $OpenBSD: rkclock.c,v 1.94 2025/12/27 14:55:18 patrick Exp $ */
2/*
3 * Copyright (c) 2017, 2018 Mark Kettenis <kettenis@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/param.h>
19#include <sys/systm.h>
20#include <sys/sysctl.h>
21#include <sys/device.h>
22
23#include <machine/intr.h>
24#include <machine/bus.h>
25#include <machine/fdt.h>
26
27#include <dev/ofw/openfirm.h>
28#include <dev/ofw/ofw_clock.h>
29#include <dev/ofw/ofw_misc.h>
30#include <dev/ofw/fdt.h>
31
32/* RK3288 registers */
33#define RK3288_CRU_APLL_CON(i) (0x0000 + (i) * 4)
34#define RK3288_CRU_CPLL_CON(i) (0x0020 + (i) * 4)
35#define RK3288_CRU_GPLL_CON(i) (0x0030 + (i) * 4)
36#define RK3288_CRU_NPLL_CON(i) (0x0040 + (i) * 4)
37#define RK3288_CRU_PLL_CLKR_MASK (0x3f << 8)
38#define RK3288_CRU_PLL_CLKR_SHIFT 8
39#define RK3288_CRU_PLL_CLKOD_MASK (0xf << 0)
40#define RK3288_CRU_PLL_CLKOD_SHIFT 0
41#define RK3288_CRU_PLL_CLKF_MASK (0x1fff << 0)
42#define RK3288_CRU_PLL_CLKF_SHIFT 0
43#define RK3288_CRU_PLL_RESET (1 << 5)
44#define RK3288_CRU_MODE_CON 0x0050
45#define RK3288_CRU_MODE_PLL_WORK_MODE_MASK 0x3
46#define RK3288_CRU_MODE_PLL_WORK_MODE_SLOW 0x0
47#define RK3288_CRU_MODE_PLL_WORK_MODE_NORMAL 0x1
48#define RK3288_CRU_CLKSEL_CON(i) (0x0060 + (i) * 4)
49#define RK3288_CRU_SOFTRST_CON(i) (0x01b8 + (i) * 4)
50
51/* RK3308 registers */
52#define RK3308_CRU_APLL_CON(i) (0x0000 + (i) * 4)
53#define RK3308_CRU_DPLL_CON(i) (0x0020 + (i) * 4)
54#define RK3308_CRU_VPLL0_CON(i) (0x0040 + (i) * 4)
55#define RK3308_CRU_VPLL1_CON(i) (0x0060 + (i) * 4)
56#define RK3308_CRU_PLL_POSTDIV1_MASK (0x7 << 12)
57#define RK3308_CRU_PLL_POSTDIV1_SHIFT 12
58#define RK3308_CRU_PLL_FBDIV_MASK (0xfff << 0)
59#define RK3308_CRU_PLL_FBDIV_SHIFT 0
60#define RK3308_CRU_PLL_DSMPD (1 << 12)
61#define RK3308_CRU_PLL_PLL_LOCK (1 << 10)
62#define RK3308_CRU_PLL_POSTDIV2_MASK (0x7 << 6)
63#define RK3308_CRU_PLL_POSTDIV2_SHIFT 6
64#define RK3308_CRU_PLL_REFDIV_MASK (0x3f << 0)
65#define RK3308_CRU_PLL_REFDIV_SHIFT 0
66#define RK3308_CRU_PLL_FRACDIV_MASK (0xffffff << 0)
67#define RK3308_CRU_PLL_FRACDIV_SHIFT 0
68#define RK3308_CRU_CRU_MODE 0x00a0
69#define RK3308_CRU_CRU_MODE_MASK 0x3
70#define RK3308_CRU_CRU_MODE_SLOW 0x0
71#define RK3308_CRU_CRU_MODE_NORMAL 0x1
72#define RK3308_CRU_CRU_MODE_DEEP 0x2
73#define RK3308_CRU_CLKSEL_CON(i) (0x0100 + (i) * 4)
74#define RK3308_CRU_ACLK_CORE_DIV_CON_MASK (0x07 << 12)
75#define RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT 12
76#define RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK (0x0f << 8)
77#define RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT 8
78#define RK3308_CRU_CORE_CLK_PLL_SEL_MASK (0x03 << 6)
79#define RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT 6
80#define RK3308_CRU_CLK_CORE_DIV_CON_MASK (0x0f << 0)
81#define RK3308_CRU_CLK_CORE_DIV_CON_SHIFT 0
82#define RK3308_CRU_CLKGATE_CON(i) (0x0300 + (i) * 4)
83#define RK3308_CRU_SOFTRST_CON(i) (0x0400 + (i) * 4)
84
85/* RK3328 registers */
86#define RK3328_CRU_APLL_CON(i) (0x0000 + (i) * 4)
87#define RK3328_CRU_DPLL_CON(i) (0x0020 + (i) * 4)
88#define RK3328_CRU_CPLL_CON(i) (0x0040 + (i) * 4)
89#define RK3328_CRU_GPLL_CON(i) (0x0060 + (i) * 4)
90#define RK3328_CRU_NPLL_CON(i) (0x00a0 + (i) * 4)
91#define RK3328_CRU_PLL_POSTDIV1_MASK (0x7 << 12)
92#define RK3328_CRU_PLL_POSTDIV1_SHIFT 12
93#define RK3328_CRU_PLL_FBDIV_MASK (0xfff << 0)
94#define RK3328_CRU_PLL_FBDIV_SHIFT 0
95#define RK3328_CRU_PLL_DSMPD (1 << 12)
96#define RK3328_CRU_PLL_PLL_LOCK (1 << 10)
97#define RK3328_CRU_PLL_POSTDIV2_MASK (0x7 << 6)
98#define RK3328_CRU_PLL_POSTDIV2_SHIFT 6
99#define RK3328_CRU_PLL_REFDIV_MASK (0x3f << 0)
100#define RK3328_CRU_PLL_REFDIV_SHIFT 0
101#define RK3328_CRU_PLL_FRACDIV_MASK (0xffffff << 0)
102#define RK3328_CRU_PLL_FRACDIV_SHIFT 0
103#define RK3328_CRU_CRU_MODE 0x0080
104#define RK3328_CRU_CRU_MODE_MASK 0x1
105#define RK3328_CRU_CRU_MODE_SLOW 0x0
106#define RK3328_CRU_CRU_MODE_NORMAL 0x1
107#define RK3328_CRU_CLKSEL_CON(i) (0x0100 + (i) * 4)
108#define RK3328_CRU_CORE_CLK_PLL_SEL_MASK (0x3 << 6)
109#define RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT 6
110#define RK3328_CRU_CLK_CORE_DIV_CON_MASK (0x1f << 0)
111#define RK3328_CRU_CLK_CORE_DIV_CON_SHIFT 0
112#define RK3328_CRU_ACLK_CORE_DIV_CON_MASK (0x7 << 4)
113#define RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT 4
114#define RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK (0xf << 0)
115#define RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT 0
116#define RK3328_CRU_VOP_DCLK_SRC_SEL_MASK (0x1 << 1)
117#define RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT 1
118#define RK3328_CRU_CLKGATE_CON(i) (0x0200 + (i) * 4)
119#define RK3328_CRU_SOFTRST_CON(i) (0x0300 + (i) * 4)
120
121#define RK3328_GRF_SOC_CON4 0x0410
122#define RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN (1 << 14)
123#define RK3328_GRF_MAC_CON1 0x0904
124#define RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL (1 << 10)
125
126/* RK3399 registers */
127#define RK3399_CRU_LPLL_CON(i) (0x0000 + (i) * 4)
128#define RK3399_CRU_BPLL_CON(i) (0x0020 + (i) * 4)
129#define RK3399_CRU_DPLL_CON(i) (0x0020 + (i) * 4)
130#define RK3399_CRU_CPLL_CON(i) (0x0060 + (i) * 4)
131#define RK3399_CRU_GPLL_CON(i) (0x0080 + (i) * 4)
132#define RK3399_CRU_NPLL_CON(i) (0x00a0 + (i) * 4)
133#define RK3399_CRU_VPLL_CON(i) (0x00c0 + (i) * 4)
134#define RK3399_CRU_PLL_FBDIV_MASK (0xfff << 0)
135#define RK3399_CRU_PLL_FBDIV_SHIFT 0
136#define RK3399_CRU_PLL_POSTDIV2_MASK (0x7 << 12)
137#define RK3399_CRU_PLL_POSTDIV2_SHIFT 12
138#define RK3399_CRU_PLL_POSTDIV1_MASK (0x7 << 8)
139#define RK3399_CRU_PLL_POSTDIV1_SHIFT 8
140#define RK3399_CRU_PLL_REFDIV_MASK (0x3f << 0)
141#define RK3399_CRU_PLL_REFDIV_SHIFT 0
142#define RK3399_CRU_PLL_PLL_WORK_MODE_MASK (0x3 << 8)
143#define RK3399_CRU_PLL_PLL_WORK_MODE_SLOW (0x0 << 8)
144#define RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL (0x1 << 8)
145#define RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW (0x2 << 8)
146#define RK3399_CRU_PLL_PLL_LOCK (1U << 31)
147#define RK3399_CRU_CLKSEL_CON(i) (0x0100 + (i) * 4)
148#define RK3399_CRU_ACLKM_CORE_DIV_CON_MASK (0x1f << 8)
149#define RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT 8
150#define RK3399_CRU_CORE_PLL_SEL_MASK (0x3 << 6)
151#define RK3399_CRU_CORE_PLL_SEL_APLL (0x0 << 6)
152#define RK3399_CRU_CORE_PLL_SEL_BPLL (0x1 << 6)
153#define RK3399_CRU_CORE_PLL_SEL_DPLL (0x2 << 6)
154#define RK3399_CRU_CORE_PLL_SEL_GPLL (0x3 << 6)
155#define RK3399_CRU_CORE_PLL_SEL_SHIFT 6
156#define RK3399_CRU_CLK_CORE_DIV_CON_MASK (0x1f << 0)
157#define RK3399_CRU_CLK_CORE_DIV_CON_SHIFT 0
158#define RK3399_CRU_PCLK_DBG_DIV_CON_MASK (0x1f << 8)
159#define RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT 8
160#define RK3399_CRU_ATCLK_CORE_DIV_CON_MASK (0x1f << 0)
161#define RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT 0
162#define RK3399_CRU_CLK_SD_PLL_SEL_MASK (0x7 << 8)
163#define RK3399_CRU_CLK_SD_PLL_SEL_SHIFT 8
164#define RK3399_CRU_CLK_SD_DIV_CON_MASK (0x7f << 0)
165#define RK3399_CRU_CLK_SD_DIV_CON_SHIFT 0
166#define RK3399_CRU_CLKGATE_CON(i) (0x0300 + (i) * 4)
167#define RK3399_CRU_SOFTRST_CON(i) (0x0400 + (i) * 4)
168#define RK3399_CRU_SDMMC_CON(i) (0x0580 + (i) * 4)
169
170#define RK3399_PMUCRU_PPLL_CON(i) (0x0000 + (i) * 4)
171#define RK3399_PMUCRU_CLKSEL_CON(i) (0x0080 + (i) * 4)
172
173/* RK3528 registers */
174#define RK3528_CRU_PLL_CON(i) (0x00000 + (i) * 4)
175#define RK3528_CRU_CLKSEL_CON(i) (0x00300 + (i) * 4)
176#define RK3528_CRU_GATE_CON(i) (0x00800 + (i) * 4)
177#define RK3528_CRU_SOFTRST_CON(i) (0x00a00 + (i) * 4)
178#define RK3528_PCIE_CRU_PLL_CON(i) (0x20000 + (i) * 4)
179
180/* RK3568 registers */
181#define RK3568_CRU_APLL_CON(i) (0x0000 + (i) * 4)
182#define RK3568_CRU_DPLL_CON(i) (0x0020 + (i) * 4)
183#define RK3568_CRU_GPLL_CON(i) (0x0040 + (i) * 4)
184#define RK3568_CRU_CPLL_CON(i) (0x0060 + (i) * 4)
185#define RK3568_CRU_NPLL_CON(i) (0x0080 + (i) * 4)
186#define RK3568_CRU_VPLL_CON(i) (0x00a0 + (i) * 4)
187#define RK3568_CRU_MODE_CON 0x00c0
188#define RK3568_CRU_CLKSEL_CON(i) (0x0100 + (i) * 4)
189#define RK3568_CRU_GATE_CON(i) (0x0300 + (i) * 4)
190#define RK3568_CRU_SOFTRST_CON(i) (0x0400 + (i) * 4)
191
192#define RK3568_PMUCRU_PPLL_CON(i) (0x0000 + (i) * 4)
193#define RK3568_PMUCRU_HPLL_CON(i) (0x0040 + (i) * 4)
194#define RK3568_PMUCRU_MODE_CON 0x0080
195#define RK3568_PMUCRU_CLKSEL_CON(i) (0x0100 + (i) * 4)
196#define RK3568_PMUCRU_GATE_CON(i) (0x0180 + (i) * 4)
197
198/* RK3588 registers */
199#define RK3588_CRU_AUPLL_CON(i) (0x00180 + (i) * 4)
200#define RK3588_CRU_CPLL_CON(i) (0x001a0 + (i) * 4)
201#define RK3588_CRU_GPLL_CON(i) (0x001c0 + (i) * 4)
202#define RK3588_CRU_NPLL_CON(i) (0x001e0 + (i) * 4)
203#define RK3588_CRU_PLL_M_MASK (0x3ff << 0)
204#define RK3588_CRU_PLL_M_SHIFT 0
205#define RK3588_CRU_PLL_RESETB (1 << 13)
206#define RK3588_CRU_PLL_S_MASK (0x7 << 6)
207#define RK3588_CRU_PLL_S_SHIFT 6
208#define RK3588_CRU_PLL_P_MASK (0x3f << 0)
209#define RK3588_CRU_PLL_P_SHIFT 0
210#define RK3588_CRU_PLL_K_MASK (0xffff << 0)
211#define RK3588_CRU_PLL_K_SHIFT 0
212#define RK3588_CRU_PLL_PLL_LOCK (1 << 15)
213#define RK3588_CRU_MODE_CON 0x00280
214#define RK3588_CRU_MODE_MASK 0x3
215#define RK3588_CRU_MODE_SLOW 0x0
216#define RK3588_CRU_MODE_NORMAL 0x1
217
218#define RK3588_CRU_CLKSEL_CON(i) (0x00300 + (i) * 4)
219#define RK3588_CRU_GATE_CON(i) (0x00800 + (i) * 4)
220#define RK3588_CRU_SOFTRST_CON(i) (0x00a00 + (i) * 4)
221
222#define RK3588_PHPTOPCRU_PPLL_CON(i) (0x08200 + (i) * 4)
223#define RK3588_PHPTOPCRU_SOFTRST_CON(i) (0x08a00 + (i) * 4)
224#define RK3588_PMUCRU_CLKSEL_CON(i) (0x30300 + (i) * 4)
225
226#include "rkclock_clocks.h"
227
228struct rkclock {
229 uint16_t idx;
230 uint32_t reg;
231 uint16_t sel_mask;
232 uint16_t div_mask;
233 uint16_t parents[8];
234 uint32_t flags;
235};
236
237#define SEL(l, f) (((1 << (l - f + 1)) - 1) << f)
238#define DIV(l, f) SEL(l, f)
239
240#define FIXED_PARENT (1 << 0)
241#define SET_PARENT (1 << 1)
242
243#define HREAD4(sc, reg) \
244 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
245#define HWRITE4(sc, reg, val) \
246 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
247#define HSET4(sc, reg, bits) \
248 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
249#define HCLR4(sc, reg, bits) \
250 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
251
252struct rkclock_softc {
253 struct device sc_dev;
254 bus_space_tag_t sc_iot;
255 bus_space_handle_t sc_ioh;
256 struct regmap *sc_grf;
257
258 uint32_t sc_phandle;
259 const struct rkclock *sc_clocks;
260
261 struct clock_device sc_cd;
262 struct reset_device sc_rd;
263};
264
265int rkclock_match(struct device *, void *, void *);
266void rkclock_attach(struct device *, struct device *, void *);
267
268const struct cfattach rkclock_ca = {
269 sizeof (struct rkclock_softc), rkclock_match, rkclock_attach
270};
271
272struct cfdriver rkclock_cd = {
273 NULL, "rkclock", DV_DULL
274};
275
276void rk3288_init(struct rkclock_softc *);
277uint32_t rk3288_get_frequency(void *, uint32_t *);
278int rk3288_set_frequency(void *, uint32_t *, uint32_t);
279void rk3288_enable(void *, uint32_t *, int);
280void rk3288_reset(void *, uint32_t *, int);
281
282void rk3308_init(struct rkclock_softc *);
283uint32_t rk3308_get_frequency(void *, uint32_t *);
284int rk3308_set_frequency(void *, uint32_t *, uint32_t);
285int rk3308_set_parent(void *, uint32_t *, uint32_t *);
286void rk3308_enable(void *, uint32_t *, int);
287void rk3308_reset(void *, uint32_t *, int);
288
289void rk3328_init(struct rkclock_softc *);
290uint32_t rk3328_get_frequency(void *, uint32_t *);
291int rk3328_set_frequency(void *, uint32_t *, uint32_t);
292int rk3328_set_parent(void *, uint32_t *, uint32_t *);
293void rk3328_enable(void *, uint32_t *, int);
294void rk3328_reset(void *, uint32_t *, int);
295
296void rk3399_init(struct rkclock_softc *);
297uint32_t rk3399_get_frequency(void *, uint32_t *);
298int rk3399_set_frequency(void *, uint32_t *, uint32_t);
299int rk3399_set_parent(void *, uint32_t *, uint32_t *);
300void rk3399_enable(void *, uint32_t *, int);
301void rk3399_reset(void *, uint32_t *, int);
302
303void rk3399_pmu_init(struct rkclock_softc *);
304uint32_t rk3399_pmu_get_frequency(void *, uint32_t *);
305int rk3399_pmu_set_frequency(void *, uint32_t *, uint32_t);
306void rk3399_pmu_enable(void *, uint32_t *, int);
307void rk3399_pmu_reset(void *, uint32_t *, int);
308
309void rk3528_init(struct rkclock_softc *);
310uint32_t rk3528_get_frequency(void *, uint32_t *);
311int rk3528_set_frequency(void *, uint32_t *, uint32_t);
312int rk3528_set_parent(void *, uint32_t *, uint32_t *);
313void rk3528_enable(void *, uint32_t *, int);
314void rk3528_reset(void *, uint32_t *, int);
315
316void rk3568_init(struct rkclock_softc *);
317uint32_t rk3568_get_frequency(void *, uint32_t *);
318int rk3568_set_frequency(void *, uint32_t *, uint32_t);
319int rk3568_set_parent(void *, uint32_t *, uint32_t *);
320void rk3568_enable(void *, uint32_t *, int);
321void rk3568_reset(void *, uint32_t *, int);
322
323void rk3568_pmu_init(struct rkclock_softc *);
324uint32_t rk3568_pmu_get_frequency(void *, uint32_t *);
325int rk3568_pmu_set_frequency(void *, uint32_t *, uint32_t);
326void rk3568_pmu_enable(void *, uint32_t *, int);
327void rk3568_pmu_reset(void *, uint32_t *, int);
328
329void rk3588_init(struct rkclock_softc *);
330uint32_t rk3588_get_frequency(void *, uint32_t *);
331int rk3588_set_frequency(void *, uint32_t *, uint32_t);
332void rk3588_enable(void *, uint32_t *, int);
333void rk3588_reset(void *, uint32_t *, int);
334
335struct rkclock_compat {
336 const char *compat;
337 const char *name;
338 int assign;
339 void (*init)(struct rkclock_softc *);
340 void (*enable)(void *, uint32_t *, int);
341 uint32_t (*get_frequency)(void *, uint32_t *);
342 int (*set_frequency)(void *, uint32_t *, uint32_t);
343 int (*set_parent)(void *, uint32_t *, uint32_t *);
344 void (*reset)(void *, uint32_t *, int);
345};
346
347const struct rkclock_compat rkclock_compat[] = {
348 {
349 "rockchip,rk3288-cru", NULL, 0, rk3288_init,
350 rk3288_enable, rk3288_get_frequency,
351 rk3288_set_frequency, NULL,
352 rk3288_reset
353 },
354 {
355 "rockchip,rk3308-cru", NULL, 1, rk3308_init,
356 rk3308_enable, rk3308_get_frequency,
357 rk3308_set_frequency, rk3308_set_parent,
358 rk3308_reset
359 },
360 {
361 "rockchip,rk3328-cru", NULL, 1, rk3328_init,
362 rk3328_enable, rk3328_get_frequency,
363 rk3328_set_frequency, rk3328_set_parent,
364 rk3328_reset
365 },
366 {
367 "rockchip,rk3399-cru", NULL, 1, rk3399_init,
368 rk3399_enable, rk3399_get_frequency,
369 rk3399_set_frequency, rk3399_set_parent,
370 rk3399_reset
371 },
372 {
373 "rockchip,rk3399-pmucru", NULL, 1, rk3399_pmu_init,
374 rk3399_pmu_enable, rk3399_pmu_get_frequency,
375 rk3399_pmu_set_frequency, NULL,
376 rk3399_pmu_reset
377 },
378 {
379 "rockchip,rk3528-cru", NULL, 1, rk3528_init,
380 rk3528_enable, rk3528_get_frequency,
381 rk3528_set_frequency, rk3528_set_parent,
382 rk3528_reset
383 },
384 {
385 "rockchip,rk3568-cru", "CRU", 1, rk3568_init,
386 rk3568_enable, rk3568_get_frequency,
387 rk3568_set_frequency, rk3568_set_parent,
388 rk3568_reset
389 },
390 {
391 "rockchip,rk3568-pmucru", "PMUCRU", 1, rk3568_pmu_init,
392 rk3568_pmu_enable, rk3568_pmu_get_frequency,
393 rk3568_pmu_set_frequency, NULL,
394 rk3568_pmu_reset
395 },
396 {
397 "rockchip,rk3588-cru", NULL, 1, rk3588_init,
398 rk3588_enable, rk3588_get_frequency,
399 rk3588_set_frequency, NULL,
400 rk3588_reset
401 },
402};
403
404int
405rkclock_match(struct device *parent, void *match, void *aux)
406{
407 struct fdt_attach_args *faa = aux;
408 int i;
409
410 for (i = 0; i < nitems(rkclock_compat); i++) {
411 if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat))
412 return 10;
413 }
414
415 return 0;
416}
417
418void
419rkclock_attach(struct device *parent, struct device *self, void *aux)
420{
421 struct rkclock_softc *sc = (struct rkclock_softc *)self;
422 struct fdt_attach_args *faa = aux;
423 uint32_t grf;
424 int i;
425
426 if (faa->fa_nreg < 1) {
427 printf(": no registers\n");
428 return;
429 }
430
431 sc->sc_iot = faa->fa_iot;
432 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
433 faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
434 printf(": can't map registers\n");
435 return;
436 }
437
438 grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0);
439 sc->sc_grf = regmap_byphandle(grf);
440
441 sc->sc_phandle = OF_getpropint(faa->fa_node, "phandle", 0);
442
443 for (i = 0; i < nitems(rkclock_compat); i++) {
444 if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat)) {
445 break;
446 }
447 }
448 KASSERT(i < nitems(rkclock_compat));
449
450 if (rkclock_compat[i].name != NULL)
451 printf(": %s", rkclock_compat[i].name);
452
453 printf("\n");
454
455 if (rkclock_compat[i].init)
456 rkclock_compat[i].init(sc);
457
458 sc->sc_cd.cd_node = faa->fa_node;
459 sc->sc_cd.cd_cookie = sc;
460 sc->sc_cd.cd_enable = rkclock_compat[i].enable;
461 sc->sc_cd.cd_get_frequency = rkclock_compat[i].get_frequency;
462 sc->sc_cd.cd_set_frequency = rkclock_compat[i].set_frequency;
463 sc->sc_cd.cd_set_parent = rkclock_compat[i].set_parent;
464 clock_register(&sc->sc_cd);
465
466 sc->sc_rd.rd_node = faa->fa_node;
467 sc->sc_rd.rd_cookie = sc;
468 sc->sc_rd.rd_reset = rkclock_compat[i].reset;
469 reset_register(&sc->sc_rd);
470
471 if (rkclock_compat[i].assign)
472 clock_set_assigned(faa->fa_node);
473}
474
475const struct rkclock *
476rkclock_lookup(struct rkclock_softc *sc, uint32_t idx)
477{
478 const struct rkclock *clk;
479
480 for (clk = sc->sc_clocks; clk->idx; clk++) {
481 if (clk->idx == idx)
482 return clk;
483 }
484
485 return NULL;
486}
487
488uint32_t
489rkclock_external_frequency(const char *name)
490{
491 char buf[64] = {};
492 int len, node;
493
494 /*
495 * Hunt through the device tree to find a fixed-rate clock
496 * that has the requested clock output signal name. This may
497 * be too simple.
498 */
499 node = OF_peer(0);
500 for (node = OF_child(node); node != 0; node = OF_peer(node)) {
501 len = OF_getproplen(node, "clock-output-names");
502 if (len <= 0 || len > sizeof(buf))
503 continue;
504 OF_getprop(node, "clock-output-names", buf, sizeof(buf));
505 if (strcmp(buf, name) != 0)
506 continue;
507 if (OF_is_compatible(node, "fixed-clock"))
508 return OF_getpropint(node, "clock-frequency", 0);
509 }
510
511 return 0;
512}
513
514uint32_t
515rkclock_div_con(struct rkclock_softc *sc, const struct rkclock *clk,
516 uint32_t mux, uint32_t freq)
517{
518 uint32_t parent_freq, div, div_con, max_div_con;
519 uint32_t idx = clk->parents[mux];
520
521 /* Derive maximum value from mask. */
522 max_div_con = clk->div_mask >> (ffs(clk->div_mask) - 1);
523
524 parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx);
525 div = (parent_freq + freq - 1) / freq;
526 div_con = (div > 0 ? div - 1 : 0);
527 return (div_con < max_div_con) ? div_con : max_div_con;
528}
529
530uint32_t
531rkclock_freq(struct rkclock_softc *sc, const struct rkclock *clk,
532 uint32_t mux, uint32_t freq)
533{
534 uint32_t parent_freq, div_con;
535 uint32_t idx = clk->parents[mux];
536
537 parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx);
538 div_con = rkclock_div_con(sc, clk, mux, freq);
539 return parent_freq / (div_con + 1);
540}
541
542uint32_t
543rkclock_get_frequency(struct rkclock_softc *sc, uint32_t idx)
544{
545 const struct rkclock *clk;
546 uint32_t reg, mux, div_con;
547 int shift;
548
549 clk = rkclock_lookup(sc, idx);
550 if (clk == NULL) {
551 printf("%s(%s, %u)\n", __func__, sc->sc_dev.dv_xname, idx);
552 return 0;
553 }
554
555 reg = HREAD4(sc, clk->reg);
556 shift = ffs(clk->sel_mask) - 1;
557 if (shift == -1)
558 mux = 0;
559 else
560 mux = (reg & clk->sel_mask) >> shift;
561 shift = ffs(clk->div_mask) - 1;
562 if (shift == -1)
563 div_con = 0;
564 else
565 div_con = (reg & clk->div_mask) >> shift;
566
567 if (clk->parents[mux] == 0) {
568 printf("%s: parent 0x%08x\n", __func__, idx);
569 return 0;
570 }
571 idx = clk->parents[mux];
572 return sc->sc_cd.cd_get_frequency(sc, &idx) / (div_con + 1);
573}
574
575int
576rkclock_set_frequency(struct rkclock_softc *sc, uint32_t idx, uint32_t freq)
577{
578 const struct rkclock *clk;
579 uint32_t reg, mux, div_con;
580 uint32_t best_freq, best_mux, f;
581 uint32_t parent;
582 int sel_shift, div_shift, i;
583
584 clk = rkclock_lookup(sc, idx);
585 if (clk == NULL) {
586 printf("%s(%s, %u, %u)\n", __func__, sc->sc_dev.dv_xname,
587 idx, freq);
588 return -1;
589 }
590
591 reg = HREAD4(sc, clk->reg);
592 sel_shift = ffs(clk->sel_mask) - 1;
593 if (sel_shift == -1)
594 mux = sel_shift = 0;
595 else
596 mux = (reg & clk->sel_mask) >> sel_shift;
597
598 if (clk->parents[mux] == 0) {
599 printf("%s(%s, %u, %u) parent\n", __func__,
600 sc->sc_dev.dv_xname, idx, freq);
601 return 0;
602 }
603
604 if (clk->flags & SET_PARENT) {
605 parent = clk->parents[mux];
606 sc->sc_cd.cd_set_frequency(sc, &parent, freq);
607 if (clk->div_mask == 0)
608 return 0;
609 }
610
611 /*
612 * If there is no divider, pick the parent with the frequency
613 * closest to the target frequency.
614 */
615 if (clk->div_mask == 0) {
616 /*
617 * Start out with the current parent. This prevents
618 * unnecessary switching to a different parent.
619 */
620 parent = clk->parents[mux];
621 best_freq = sc->sc_cd.cd_get_frequency(sc, &parent);
622 best_mux = mux;
623
624 for (i = 0; i < nitems(clk->parents); i++) {
625 if (clk->parents[i] == 0)
626 continue;
627 parent = clk->parents[i];
628 f = sc->sc_cd.cd_get_frequency(sc, &parent);
629 if ((best_freq > freq && f < best_freq) ||
630 (f > best_freq && f <= freq)) {
631 best_freq = f;
632 best_mux = i;
633 }
634 }
635
636 HWRITE4(sc, clk->reg,
637 clk->sel_mask << 16 | best_mux << sel_shift);
638 return 0;
639 }
640
641 /*
642 * Start out with the current parent. This prevents
643 * unnecessary switching to a different parent.
644 */
645 best_freq = rkclock_freq(sc, clk, mux, freq);
646 best_mux = mux;
647
648 /*
649 * Find the parent that allows configuration of a frequency
650 * closest to the target frequency.
651 */
652 if ((clk->flags & FIXED_PARENT) == 0) {
653 for (i = 0; i < nitems(clk->parents); i++) {
654 if (clk->parents[i] == 0)
655 continue;
656 f = rkclock_freq(sc, clk, i, freq);
657 if ((best_freq > freq && f < best_freq) ||
658 (f > best_freq && f <= freq)) {
659 best_freq = f;
660 best_mux = i;
661 }
662 }
663 }
664
665 div_con = rkclock_div_con(sc, clk, best_mux, freq);
666 div_shift = ffs(clk->div_mask) - 1;
667 HWRITE4(sc, clk->reg,
668 clk->sel_mask << 16 | best_mux << sel_shift |
669 clk->div_mask << 16 | div_con << div_shift);
670 return 0;
671}
672
673int
674rkclock_set_parent(struct rkclock_softc *sc, uint32_t idx, uint32_t parent)
675{
676 const struct rkclock *clk;
677 uint32_t mux;
678 int shift;
679
680 clk = rkclock_lookup(sc, idx);
681 if (clk == NULL || clk->sel_mask == 0) {
682 printf("%s: 0x%08x\n", __func__, idx);
683 return -1;
684 }
685
686 for (mux = 0; mux < nitems(clk->parents); mux++) {
687 if (clk->parents[mux] == parent)
688 break;
689 }
690 if (mux == nitems(clk->parents) || parent == 0) {
691 printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, parent);
692 return -1;
693 }
694
695 shift = ffs(clk->sel_mask) - 1;
696 HWRITE4(sc, clk->reg, clk->sel_mask << 16 | mux << shift);
697 return 0;
698}
699
700/*
701 * Rockchip RK3288
702 */
703
704const struct rkclock rk3288_clocks[] = {
705 {
706 RK3288_CLK_SDMMC, RK3288_CRU_CLKSEL_CON(11),
707 SEL(7, 6), DIV(5, 0),
708 { RK3288_PLL_CPLL, RK3288_PLL_GPLL, RK3288_XIN24M }
709 }
710};
711
712void
713rk3288_init(struct rkclock_softc *sc)
714{
715 int node;
716
717 /*
718 * Since the hardware comes up with a really conservative CPU
719 * clock frequency, and U-Boot doesn't set it to a more
720 * reasonable default, try to do so here. These defaults were
721 * chosen assuming that the CPU voltage is at least 1.1 V.
722 * Only do this on the Tinker-RK3288 for now where this is
723 * likely to be true given the default voltages for the
724 * regulators on that board.
725 */
726 node = OF_finddevice("/");
727 if (OF_is_compatible(node, "rockchip,rk3288-tinker")) {
728 uint32_t idx;
729
730 /* Run at 1.2 GHz. */
731 idx = RK3288_ARMCLK;
732 rk3288_set_frequency(sc, &idx, 1200000000);
733 }
734
735 sc->sc_clocks = rk3288_clocks;
736}
737
738uint32_t
739rk3288_get_pll(struct rkclock_softc *sc, bus_size_t base)
740{
741 uint32_t clkod, clkr, clkf;
742 uint32_t reg;
743
744 reg = HREAD4(sc, base);
745 clkod = (reg & RK3288_CRU_PLL_CLKOD_MASK) >>
746 RK3288_CRU_PLL_CLKOD_SHIFT;
747 clkr = (reg & RK3288_CRU_PLL_CLKR_MASK) >>
748 RK3288_CRU_PLL_CLKR_SHIFT;
749 reg = HREAD4(sc, base + 4);
750 clkf = (reg & RK3288_CRU_PLL_CLKF_MASK) >>
751 RK3288_CRU_PLL_CLKF_SHIFT;
752 return 24000000ULL * (clkf + 1) / (clkr + 1) / (clkod + 1);
753}
754
755int
756rk3288_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
757{
758 int shift = 4 * (base / RK3288_CRU_CPLL_CON(0));
759 uint32_t no, nr, nf;
760
761 /*
762 * It is not clear whether all combinations of the clock
763 * dividers result in a stable clock. Therefore this function
764 * only supports a limited set of PLL clock rates. For now
765 * this set covers all the CPU frequencies supported by the
766 * Linux kernel.
767 */
768 switch (freq) {
769 case 1800000000:
770 case 1704000000:
771 case 1608000000:
772 case 1512000000:
773 case 1488000000:
774 case 1416000000:
775 case 1200000000:
776 nr = no = 1;
777 break;
778 case 1008000000:
779 case 816000000:
780 case 696000000:
781 case 600000000:
782 nr = 1; no = 2;
783 break;
784 case 408000000:
785 case 312000000:
786 nr = 1; no = 4;
787 break;
788 case 216000000:
789 case 126000000:
790 nr = 1; no = 8;
791 break;
792 default:
793 printf("%s: %u Hz\n", __func__, freq);
794 return -1;
795 }
796
797 /* Calculate feedback divider. */
798 nf = freq * nr * no / 24000000;
799
800 /*
801 * Select slow mode to guarantee a stable clock while we're
802 * adjusting the PLL.
803 */
804 HWRITE4(sc, RK3288_CRU_MODE_CON,
805 (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 |
806 RK3288_CRU_MODE_PLL_WORK_MODE_SLOW) << shift);
807
808 /* Assert reset. */
809 HWRITE4(sc, base + 0x000c,
810 RK3288_CRU_PLL_RESET << 16 | RK3288_CRU_PLL_RESET);
811
812 /* Set PLL rate. */
813 HWRITE4(sc, base + 0x0000,
814 RK3288_CRU_PLL_CLKR_MASK << 16 |
815 (nr - 1) << RK3288_CRU_PLL_CLKR_SHIFT |
816 RK3288_CRU_PLL_CLKOD_MASK << 16 |
817 (no - 1) << RK3288_CRU_PLL_CLKOD_SHIFT);
818 HWRITE4(sc, base + 0x0004,
819 RK3288_CRU_PLL_CLKF_MASK << 16 |
820 (nf - 1) << RK3288_CRU_PLL_CLKF_SHIFT);
821
822 /* Deassert reset and wait. */
823 HWRITE4(sc, base + 0x000c,
824 RK3288_CRU_PLL_RESET << 16);
825 delay((nr * 500 / 24) + 1);
826
827 /* Switch back to normal mode. */
828 HWRITE4(sc, RK3288_CRU_MODE_CON,
829 (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 |
830 RK3288_CRU_MODE_PLL_WORK_MODE_NORMAL) << shift);
831
832 return 0;
833}
834
835uint32_t
836rk3288_get_frequency(void *cookie, uint32_t *cells)
837{
838 struct rkclock_softc *sc = cookie;
839 uint32_t idx = cells[0];
840 uint32_t reg, mux, div_con, aclk_div_con;
841
842 switch (idx) {
843 case RK3288_PLL_APLL:
844 return rk3288_get_pll(sc, RK3288_CRU_APLL_CON(0));
845 case RK3288_PLL_CPLL:
846 return rk3288_get_pll(sc, RK3288_CRU_CPLL_CON(0));
847 case RK3288_PLL_GPLL:
848 return rk3288_get_pll(sc, RK3288_CRU_GPLL_CON(0));
849 case RK3288_PLL_NPLL:
850 return rk3288_get_pll(sc, RK3288_CRU_NPLL_CON(0));
851 case RK3288_ARMCLK:
852 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(0));
853 mux = (reg >> 15) & 0x1;
854 div_con = (reg >> 8) & 0x1f;
855 idx = (mux == 0) ? RK3288_PLL_APLL : RK3288_PLL_GPLL;
856 return rk3288_get_frequency(sc, &idx) / (div_con + 1);
857 case RK3288_XIN24M:
858 return 24000000;
859 case RK3288_CLK_UART0:
860 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(13));
861 mux = (reg >> 8) & 0x3;
862 div_con = reg & 0x7f;
863 if (mux == 2)
864 return 24000000 / (div_con + 1);
865 break;
866 case RK3288_CLK_UART1:
867 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(14));
868 mux = (reg >> 8) & 0x3;
869 div_con = reg & 0x7f;
870 if (mux == 2)
871 return 24000000 / (div_con + 1);
872 break;
873 case RK3288_CLK_UART2:
874 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(15));
875 mux = (reg >> 8) & 0x3;
876 div_con = reg & 0x7f;
877 if (mux == 2)
878 return 24000000 / (div_con + 1);
879 break;
880 case RK3288_CLK_UART3:
881 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(16));
882 mux = (reg >> 8) & 0x3;
883 div_con = reg & 0x7f;
884 if (mux == 2)
885 return 24000000 / (div_con + 1);
886 break;
887 case RK3288_CLK_UART4:
888 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(3));
889 mux = (reg >> 8) & 0x3;
890 div_con = reg & 0x7f;
891 if (mux == 2)
892 return 24000000 / (div_con + 1);
893 break;
894 case RK3288_CLK_MAC:
895 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(21));
896 if (reg & 0x10)
897 return 125000000;
898 mux = (reg >> 0) & 0x3;
899 div_con = (reg >> 8) & 0x1f;
900 switch (mux) {
901 case 0:
902 idx = RK3288_PLL_NPLL;
903 break;
904 case 1:
905 idx = RK3288_PLL_CPLL;
906 break;
907 case 2:
908 idx = RK3288_PLL_GPLL;
909 break;
910 default:
911 return 0;
912 }
913 return rk3288_get_frequency(sc, &idx) / (div_con + 1);
914 case RK3288_PCLK_I2C0:
915 case RK3288_PCLK_I2C2:
916 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(1));
917 mux = (reg >> 15) & 0x1;
918 /* pd_bus_pclk_div_con */
919 div_con = (reg >> 12) & 0x7;
920 if (mux == 1)
921 idx = RK3288_PLL_GPLL;
922 else
923 idx = RK3288_PLL_CPLL;
924 return rk3288_get_frequency(sc, &idx) / (div_con + 1);
925 case RK3288_PCLK_I2C1:
926 case RK3288_PCLK_I2C3:
927 case RK3288_PCLK_I2C4:
928 case RK3288_PCLK_I2C5:
929 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(10));
930 mux = (reg >> 15) & 0x1;
931 /* peri_pclk_div_con */
932 div_con = (reg >> 12) & 0x3;
933 /* peri_aclk_div_con */
934 aclk_div_con = reg & 0xf;
935 if (mux == 1)
936 idx = RK3288_PLL_GPLL;
937 else
938 idx = RK3288_PLL_CPLL;
939 return (rk3288_get_frequency(sc, &idx) / (aclk_div_con + 1)) >>
940 div_con;
941 default:
942 break;
943 }
944
945 return rkclock_get_frequency(sc, idx);
946}
947
948int
949rk3288_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
950{
951 struct rkclock_softc *sc = cookie;
952 uint32_t idx = cells[0];
953 int error;
954
955 switch (idx) {
956 case RK3288_PLL_APLL:
957 return rk3288_set_pll(sc, RK3288_CRU_APLL_CON(0), freq);
958 case RK3288_ARMCLK:
959 idx = RK3288_PLL_APLL;
960 error = rk3288_set_frequency(sc, &idx, freq);
961 if (error == 0) {
962 HWRITE4(sc, RK3288_CRU_CLKSEL_CON(0),
963 ((1 << 15) | (0x1f << 8)) << 16);
964 }
965 return error;
966 default:
967 break;
968 }
969
970 return rkclock_set_frequency(sc, idx, freq);
971}
972
973void
974rk3288_enable(void *cookie, uint32_t *cells, int on)
975{
976 uint32_t idx = cells[0];
977
978 switch (idx) {
979 case RK3288_CLK_SDMMC:
980 case RK3288_CLK_TSADC:
981 case RK3288_CLK_UART0:
982 case RK3288_CLK_UART1:
983 case RK3288_CLK_UART2:
984 case RK3288_CLK_UART3:
985 case RK3288_CLK_UART4:
986 case RK3288_CLK_MAC_RX:
987 case RK3288_CLK_MAC_TX:
988 case RK3288_CLK_SDMMC_DRV:
989 case RK3288_CLK_SDMMC_SAMPLE:
990 case RK3288_CLK_MAC:
991 case RK3288_ACLK_GMAC:
992 case RK3288_PCLK_GMAC:
993 case RK3288_PCLK_I2C0:
994 case RK3288_PCLK_I2C1:
995 case RK3288_PCLK_I2C2:
996 case RK3288_PCLK_I2C3:
997 case RK3288_PCLK_I2C4:
998 case RK3288_PCLK_I2C5:
999 case RK3288_PCLK_TSADC:
1000 case RK3288_HCLK_HOST0:
1001 case RK3288_HCLK_SDMMC:
1002 /* Enabled by default. */
1003 break;
1004 default:
1005 printf("%s: 0x%08x\n", __func__, idx);
1006 break;
1007 }
1008}
1009
1010void
1011rk3288_reset(void *cookie, uint32_t *cells, int on)
1012{
1013 struct rkclock_softc *sc = cookie;
1014 uint32_t idx = cells[0];
1015 uint32_t mask = (1 << (idx % 16));
1016
1017 HWRITE4(sc, RK3288_CRU_SOFTRST_CON(idx / 16),
1018 mask << 16 | (on ? mask : 0));
1019}
1020
1021/*
1022 * Rockchip RK3308
1023 */
1024
1025const struct rkclock rk3308_clocks[] = {
1026 {
1027 RK3308_CLK_RTC32K, RK3308_CRU_CLKSEL_CON(2),
1028 SEL(10, 9), 0,
1029 { RK3308_PLL_VPLL0, RK3308_PLL_VPLL1 }
1030 },
1031 {
1032 RK3308_CLK_UART0, RK3308_CRU_CLKSEL_CON(10),
1033 SEL(15, 13), DIV(4, 0),
1034 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1035 RK3308_USB480M, RK3308_XIN24M }
1036 },
1037 {
1038 RK3308_CLK_UART1, RK3308_CRU_CLKSEL_CON(13),
1039 SEL(15, 13), DIV(4, 0),
1040 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1041 RK3308_USB480M, RK3308_XIN24M }
1042 },
1043 {
1044 RK3308_CLK_UART2, RK3308_CRU_CLKSEL_CON(16),
1045 SEL(15, 13), DIV(4, 0),
1046 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1047 RK3308_USB480M, RK3308_XIN24M }
1048 },
1049 {
1050 RK3308_CLK_UART3, RK3308_CRU_CLKSEL_CON(19),
1051 SEL(15, 13), DIV(4, 0),
1052 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1053 RK3308_USB480M, RK3308_XIN24M }
1054 },
1055 {
1056 RK3308_CLK_UART4, RK3308_CRU_CLKSEL_CON(22),
1057 SEL(15, 13), DIV(4, 0),
1058 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1059 RK3308_USB480M, RK3308_XIN24M }
1060 },
1061 {
1062 RK3308_CLK_PWM0, RK3308_CRU_CLKSEL_CON(29),
1063 SEL(15, 14), DIV(6, 0),
1064 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_XIN24M }
1065 },
1066 {
1067 RK3308_CLK_SPI0, RK3308_CRU_CLKSEL_CON(30),
1068 SEL(15, 14), DIV(6, 0),
1069 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_XIN24M }
1070 },
1071 {
1072 RK3308_CLK_SPI1, RK3308_CRU_CLKSEL_CON(31),
1073 SEL(15, 14), DIV(6, 0),
1074 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_XIN24M }
1075 },
1076 {
1077 RK3308_CLK_SPI2, RK3308_CRU_CLKSEL_CON(32),
1078 SEL(15, 14), DIV(6, 0),
1079 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_XIN24M }
1080 },
1081 {
1082 RK3308_CLK_TSADC, RK3308_CRU_CLKSEL_CON(33),
1083 0, DIV(10, 0),
1084 { RK3308_XIN24M }
1085 },
1086 {
1087 RK3308_CLK_SARADC, RK3308_CRU_CLKSEL_CON(34),
1088 0, DIV(10, 0),
1089 { RK3308_XIN24M }
1090 },
1091 {
1092 RK3308_CLK_CRYPTO, RK3308_CRU_CLKSEL_CON(7),
1093 SEL(7, 6), DIV(4, 0),
1094 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
1095 },
1096 {
1097 RK3308_CLK_CRYPTO_APK, RK3308_CRU_CLKSEL_CON(7),
1098 SEL(15, 14), DIV(12, 8),
1099 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
1100 },
1101 {
1102 RK3308_CLK_SDMMC, RK3308_CRU_CLKSEL_CON(39),
1103 SEL(9, 8), DIV(7, 0),
1104 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1105 RK3308_XIN24M }
1106 },
1107 {
1108 RK3308_CLK_SDIO, RK3308_CRU_CLKSEL_CON(40),
1109 SEL(9, 8), DIV(7, 0),
1110 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1111 RK3308_XIN24M }
1112 },
1113 {
1114 RK3308_CLK_EMMC, RK3308_CRU_CLKSEL_CON(41),
1115 SEL(9, 8), DIV(7, 0),
1116 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1,
1117 RK3308_XIN24M }
1118 },
1119 {
1120 RK3308_CLK_MAC_SRC, RK3308_CRU_CLKSEL_CON(43),
1121 SEL(7, 6), DIV(4, 0),
1122 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
1123 },
1124 {
1125 RK3308_CLK_MAC, RK3308_CRU_CLKSEL_CON(43),
1126 SEL(14, 13), 0,
1127 { RK3308_CLK_MAC_SRC, 0 },
1128 SET_PARENT
1129 },
1130 {
1131 RK3308_ACLK_PERI_SRC, RK3308_CRU_CLKSEL_CON(36),
1132 SEL(7, 6), 0,
1133 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 }
1134 },
1135 {
1136 RK3308_PCLK_PERI, RK3308_CRU_CLKSEL_CON(37),
1137 0, DIV(12, 8),
1138 { RK3308_ACLK_PERI_SRC }
1139 },
1140 {
1141 RK3308_PCLK_MAC, 0, 0, 0,
1142 { RK3308_PCLK_PERI }
1143 },
1144
1145 {
1146 /* Sentinel */
1147 }
1148};
1149
1150void
1151rk3308_init(struct rkclock_softc *sc)
1152{
1153 int i;
1154
1155 /* The code below assumes all clocks are enabled. Check this!. */
1156 for (i = 0; i <= 14; i++) {
1157 if (HREAD4(sc, RK3308_CRU_CLKGATE_CON(i)) != 0x00000000) {
1158 printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1159 HREAD4(sc, RK3308_CRU_CLKGATE_CON(i)));
1160 }
1161 }
1162 sc->sc_clocks = rk3308_clocks;
1163}
1164
1165uint32_t
1166rk3308_armclk_parent(uint32_t mux)
1167{
1168 switch (mux) {
1169 case 0:
1170 return RK3308_PLL_APLL;
1171 case 1:
1172 return RK3308_PLL_VPLL0;
1173 case 2:
1174 return RK3308_PLL_VPLL1;
1175 }
1176
1177 return 0;
1178}
1179
1180uint32_t
1181rk3308_get_armclk(struct rkclock_softc *sc)
1182{
1183 uint32_t reg, mux, div_con;
1184 uint32_t idx;
1185
1186 reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(0));
1187 mux = (reg & RK3308_CRU_CORE_CLK_PLL_SEL_MASK) >>
1188 RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT;
1189 div_con = (reg & RK3308_CRU_CLK_CORE_DIV_CON_MASK) >>
1190 RK3308_CRU_CLK_CORE_DIV_CON_SHIFT;
1191 idx = rk3308_armclk_parent(mux);
1192
1193 return rk3308_get_frequency(sc, &idx) / (div_con + 1);
1194}
1195
1196int
1197rk3308_set_armclk(struct rkclock_softc *sc, uint32_t freq)
1198{
1199 uint32_t reg, mux;
1200 uint32_t old_freq, div;
1201 uint32_t idx;
1202
1203 old_freq = rk3308_get_armclk(sc);
1204 if (freq == old_freq)
1205 return 0;
1206
1207 reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(0));
1208 mux = (reg & RK3308_CRU_CORE_CLK_PLL_SEL_MASK) >>
1209 RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT;
1210
1211 /* Keep the pclk_dbg clock at or below 300 MHz. */
1212 div = 1;
1213 while (freq / (div + 1) > 300000000)
1214 div++;
1215 /* and make sure we use an odd divider. */
1216 if ((div % 2) == 0)
1217 div++;
1218
1219 /* When ramping up, set clock dividers first. */
1220 if (freq > old_freq) {
1221 HWRITE4(sc, RK3308_CRU_CLKSEL_CON(0),
1222 RK3308_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1223 0 << RK3308_CRU_CLK_CORE_DIV_CON_SHIFT |
1224 RK3308_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1225 1 << RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT |
1226 RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1227 div << RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1228 }
1229
1230 /* We always use VPLL1 and force the switch below if needed. */
1231 idx = RK3308_PLL_VPLL1;
1232 rk3308_set_frequency(sc, &idx, freq);
1233
1234 /* When ramping down, set clock dividers last. */
1235 if (freq < old_freq || mux != 2) {
1236 HWRITE4(sc, RK3308_CRU_CLKSEL_CON(0),
1237 RK3308_CRU_CORE_CLK_PLL_SEL_MASK << 16 |
1238 2 << RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT |
1239 RK3308_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1240 0 << RK3308_CRU_CLK_CORE_DIV_CON_SHIFT |
1241 RK3308_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1242 1 << RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT |
1243 RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1244 div << RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1245 }
1246
1247 return 0;
1248}
1249
1250uint32_t
1251rk3308_get_pll(struct rkclock_softc *sc, bus_size_t base)
1252{
1253 uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1254 uint32_t dsmpd, fracdiv;
1255 uint64_t frac = 0;
1256 uint32_t reg;
1257
1258 reg = HREAD4(sc, base + 0x0000);
1259 postdiv1 = (reg & RK3308_CRU_PLL_POSTDIV1_MASK) >>
1260 RK3308_CRU_PLL_POSTDIV1_SHIFT;
1261 fbdiv = (reg & RK3308_CRU_PLL_FBDIV_MASK) >>
1262 RK3308_CRU_PLL_FBDIV_SHIFT;
1263 reg = HREAD4(sc, base + 0x0004);
1264 dsmpd = (reg & RK3308_CRU_PLL_DSMPD);
1265 postdiv2 = (reg & RK3308_CRU_PLL_POSTDIV2_MASK) >>
1266 RK3308_CRU_PLL_POSTDIV2_SHIFT;
1267 refdiv = (reg & RK3308_CRU_PLL_REFDIV_MASK) >>
1268 RK3308_CRU_PLL_REFDIV_SHIFT;
1269 reg = HREAD4(sc, base + 0x0008);
1270 fracdiv = (reg & RK3308_CRU_PLL_FRACDIV_MASK) >>
1271 RK3308_CRU_PLL_FRACDIV_SHIFT;
1272
1273 if (dsmpd == 0)
1274 frac = (24000000ULL * fracdiv / refdiv) >> 24;
1275 return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2;
1276}
1277
1278int
1279rk3308_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1280{
1281 uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1282 int mode_shift = -1;
1283
1284 switch (base) {
1285 case RK3308_CRU_APLL_CON(0):
1286 mode_shift = 0;
1287 break;
1288 case RK3308_CRU_DPLL_CON(0):
1289 mode_shift = 2;
1290 break;
1291 case RK3308_CRU_VPLL0_CON(0):
1292 mode_shift = 4;
1293 break;
1294 case RK3308_CRU_VPLL1_CON(0):
1295 mode_shift = 6;
1296 break;
1297 }
1298 KASSERT(mode_shift != -1);
1299
1300 /*
1301 * It is not clear whether all combinations of the clock
1302 * dividers result in a stable clock. Therefore this function
1303 * only supports a limited set of PLL clock rates. For now
1304 * this set covers all the CPU frequencies supported by the
1305 * Linux kernel.
1306 */
1307 switch (freq) {
1308 case 1608000000U:
1309 case 1584000000U:
1310 case 1560000000U:
1311 case 1536000000U:
1312 case 1512000000U:
1313 case 1488000000U:
1314 case 1464000000U:
1315 case 1440000000U:
1316 case 1416000000U:
1317 case 1392000000U:
1318 case 1368000000U:
1319 case 1344000000U:
1320 case 1320000000U:
1321 case 1296000000U:
1322 case 1272000000U:
1323 case 1248000000U:
1324 case 1200000000U:
1325 case 1104000000U:
1326 postdiv1 = postdiv2 = refdiv = 1;
1327 break;
1328 case 1188000000U:
1329 refdiv = 2; postdiv1 = postdiv2 = 1;
1330 break;
1331 case 1100000000U:
1332 refdiv = 12; postdiv1 = postdiv2 = 1;
1333 break;
1334 case 1000000000U:
1335 refdiv = 6; postdiv1 = postdiv2 = 1;
1336 break;
1337 case 1008000000U:
1338 case 984000000U:
1339 case 960000000U:
1340 case 936000000U:
1341 case 912000000U:
1342 case 888000000U:
1343 case 864000000U:
1344 case 840000000U:
1345 case 816000000U:
1346 case 696000000U:
1347 case 624000000U:
1348 postdiv1 = 2; postdiv2 = refdiv = 1;
1349 break;
1350 case 900000000U:
1351 refdiv = 4; postdiv1 = 2; postdiv2 = 1;
1352 break;
1353 case 800000000U:
1354 case 700000000U:
1355 case 500000000U:
1356 refdiv = 6; postdiv1 = 2; postdiv2 = 1;
1357 break;
1358 case 600000000U:
1359 case 504000000U:
1360 postdiv1 = 3; postdiv2 = refdiv = 1;
1361 break;
1362 case 594000000U:
1363 refdiv = 2; postdiv1 = 2; postdiv2 = 1;
1364 break;
1365 case 408000000U:
1366 case 312000000U:
1367 postdiv1 = postdiv2 = 2; refdiv = 1;
1368 break;
1369 case 216000000U:
1370 postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1371 break;
1372 case 96000000U:
1373 postdiv1 = postdiv2 = 4; refdiv = 1;
1374 break;
1375 default:
1376 printf("%s: %u Hz\n", __func__, freq);
1377 return -1;
1378 }
1379
1380 /* Calculate feedback divider. */
1381 fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1382
1383 /*
1384 * Select slow mode to guarantee a stable clock while we're
1385 * adjusting the PLL.
1386 */
1387 HWRITE4(sc, RK3308_CRU_CRU_MODE,
1388 (RK3308_CRU_CRU_MODE_MASK << 16 |
1389 RK3308_CRU_CRU_MODE_SLOW) << mode_shift);
1390
1391 /* Set PLL rate. */
1392 HWRITE4(sc, base + 0x0000,
1393 RK3308_CRU_PLL_POSTDIV1_MASK << 16 |
1394 postdiv1 << RK3308_CRU_PLL_POSTDIV1_SHIFT |
1395 RK3308_CRU_PLL_FBDIV_MASK << 16 |
1396 fbdiv << RK3308_CRU_PLL_FBDIV_SHIFT);
1397 HWRITE4(sc, base + 0x0004,
1398 RK3308_CRU_PLL_DSMPD << 16 | RK3308_CRU_PLL_DSMPD |
1399 RK3308_CRU_PLL_POSTDIV2_MASK << 16 |
1400 postdiv2 << RK3308_CRU_PLL_POSTDIV2_SHIFT |
1401 RK3308_CRU_PLL_REFDIV_MASK << 16 |
1402 refdiv << RK3308_CRU_PLL_REFDIV_SHIFT);
1403
1404 /* Wait for PLL to stabilize. */
1405 while ((HREAD4(sc, base + 0x0004) & RK3308_CRU_PLL_PLL_LOCK) == 0)
1406 delay(10);
1407
1408 /* Switch back to normal mode. */
1409 HWRITE4(sc, RK3308_CRU_CRU_MODE,
1410 (RK3308_CRU_CRU_MODE_MASK << 16 |
1411 RK3308_CRU_CRU_MODE_NORMAL) << mode_shift);
1412
1413 return 0;
1414}
1415
1416uint32_t
1417rk3308_get_rtc32k(struct rkclock_softc *sc)
1418{
1419 uint32_t reg, mux, pll, div_con;
1420
1421 reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(2));
1422 mux = (reg & 0x300) >> 8;
1423 if (mux != 3) {
1424 printf("%s: RTC32K not using clk_32k_div\n", __func__);
1425 return 0;
1426 }
1427
1428 if ((reg >> 10) & 1)
1429 pll = RK3308_PLL_VPLL1;
1430 else
1431 pll = RK3308_PLL_VPLL0;
1432
1433 div_con = HREAD4(sc, RK3308_CRU_CLKSEL_CON(4)) & 0xffff;
1434 return rk3308_get_frequency(sc, &pll) / (div_con + 1);
1435}
1436
1437int
1438rk3308_set_rtc32k(struct rkclock_softc *sc, uint32_t freq)
1439{
1440 const struct rkclock *clk;
1441 uint32_t vpll0_freq, vpll1_freq, mux, div_con;
1442
1443 clk = rkclock_lookup(sc, RK3308_CLK_RTC32K);
1444 vpll0_freq = rkclock_freq(sc, clk, 0, freq);
1445 vpll1_freq = rkclock_freq(sc, clk, 1, freq);
1446 mux = 0;
1447 freq = vpll0_freq;
1448
1449 if ((vpll1_freq > vpll0_freq && vpll1_freq <= freq) ||
1450 (vpll1_freq < vpll0_freq && vpll1_freq >= freq)) {
1451 mux = 1;
1452 freq = vpll1_freq;
1453 }
1454
1455 div_con = rkclock_div_con(sc, clk, mux, freq);
1456 HWRITE4(sc, RK3308_CRU_CLKSEL_CON(2), 1 << 26 | (mux << 10));
1457 HWRITE4(sc, RK3308_CRU_CLKSEL_CON(4), 0xffff0000 | div_con);
1458 return 0;
1459}
1460
1461uint32_t
1462rk3308_get_frequency(void *cookie, uint32_t *cells)
1463{
1464 struct rkclock_softc *sc = cookie;
1465 uint32_t idx = cells[0];
1466
1467 switch (idx) {
1468 case RK3308_PLL_APLL:
1469 return rk3308_get_pll(sc, RK3308_CRU_APLL_CON(0));
1470 case RK3308_PLL_DPLL:
1471 return rk3308_get_pll(sc, RK3308_CRU_DPLL_CON(0));
1472 case RK3308_PLL_VPLL0:
1473 return rk3308_get_pll(sc, RK3308_CRU_VPLL0_CON(0));
1474 case RK3308_PLL_VPLL1:
1475 return rk3308_get_pll(sc, RK3308_CRU_VPLL1_CON(0));
1476 case RK3308_ARMCLK:
1477 return rk3308_get_armclk(sc);
1478 case RK3308_XIN24M:
1479 return 24000000;
1480 case RK3308_CLK_RTC32K:
1481 return rk3308_get_rtc32k(sc);
1482
1483 /*
1484 * XXX The USB480M clock is external. Returning zero here will cause
1485 * it to be ignored for reparenting purposes.
1486 */
1487 case RK3308_USB480M:
1488 return 0;
1489 default:
1490 break;
1491 }
1492
1493 return rkclock_get_frequency(sc, idx);
1494}
1495
1496int
1497rk3308_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
1498{
1499 struct rkclock_softc *sc = cookie;
1500 uint32_t idx = cells[0];
1501
1502 switch (idx) {
1503 case RK3308_PLL_APLL:
1504 return rk3308_set_pll(sc, RK3308_CRU_APLL_CON(0), freq);
1505 case RK3308_PLL_DPLL:
1506 return rk3308_set_pll(sc, RK3308_CRU_DPLL_CON(0), freq);
1507 case RK3308_PLL_VPLL0:
1508 return rk3308_set_pll(sc, RK3308_CRU_VPLL0_CON(0), freq);
1509 case RK3308_PLL_VPLL1:
1510 return rk3308_set_pll(sc, RK3308_CRU_VPLL1_CON(0), freq);
1511 case RK3308_ARMCLK:
1512 return rk3308_set_armclk(sc, freq);
1513 case RK3308_CLK_RTC32K:
1514 return rk3308_set_rtc32k(sc, freq);
1515 default:
1516 break;
1517 }
1518
1519 return rkclock_set_frequency(sc, idx, freq);
1520}
1521
1522
1523int
1524rk3308_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
1525{
1526 struct rkclock_softc *sc = cookie;
1527
1528 if (pcells[0] != sc->sc_phandle)
1529 return -1;
1530
1531 return rkclock_set_parent(sc, cells[0], pcells[1]);
1532}
1533
1534void
1535rk3308_enable(void *cookie, uint32_t *cells, int on)
1536{
1537 uint32_t idx = cells[0];
1538
1539 /*
1540 * All clocks are enabled by default, so there is nothing for
1541 * us to do until we start disabling clocks.
1542 */
1543 if (!on)
1544 printf("%s: 0x%08x\n", __func__, idx);
1545}
1546
1547void
1548rk3308_reset(void *cookie, uint32_t *cells, int on)
1549{
1550 struct rkclock_softc *sc = cookie;
1551 uint32_t idx = cells[0];
1552 uint32_t mask = (1 << (idx % 16));
1553
1554 HWRITE4(sc, RK3308_CRU_SOFTRST_CON(idx / 16),
1555 mask << 16 | (on ? mask : 0));
1556}
1557
1558
1559/*
1560 * Rockchip RK3328
1561 */
1562
1563const struct rkclock rk3328_clocks[] = {
1564 {
1565 RK3328_CLK_RTC32K, RK3328_CRU_CLKSEL_CON(38),
1566 SEL(15, 14), DIV(13, 0),
1567 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M }
1568 },
1569 {
1570 RK3328_CLK_SPI, RK3328_CRU_CLKSEL_CON(24),
1571 SEL(7, 7), DIV(6, 0),
1572 { RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1573 },
1574 {
1575 RK3328_CLK_SDMMC, RK3328_CRU_CLKSEL_CON(30),
1576 SEL(9, 8), DIV(7, 0),
1577 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
1578 RK3328_USB480M }
1579 },
1580 {
1581 RK3328_CLK_SDIO, RK3328_CRU_CLKSEL_CON(31),
1582 SEL(9, 8), DIV(7, 0),
1583 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
1584 RK3328_USB480M }
1585 },
1586 {
1587 RK3328_CLK_EMMC, RK3328_CRU_CLKSEL_CON(32),
1588 SEL(9, 8), DIV(7, 0),
1589 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M,
1590 RK3328_USB480M }
1591 },
1592 {
1593 RK3328_CLK_TSADC, RK3328_CRU_CLKSEL_CON(22),
1594 0, DIV(9, 0),
1595 { RK3328_CLK_24M }
1596 },
1597 {
1598 RK3328_CLK_UART0, RK3328_CRU_CLKSEL_CON(14),
1599 SEL(9, 8), 0,
1600 { 0, 0, RK3328_XIN24M, RK3328_XIN24M }
1601 },
1602 {
1603 RK3328_CLK_UART1, RK3328_CRU_CLKSEL_CON(16),
1604 SEL(9, 8), 0,
1605 { 0, 0, RK3328_XIN24M, RK3328_XIN24M }
1606 },
1607 {
1608 RK3328_CLK_UART2, RK3328_CRU_CLKSEL_CON(18),
1609 SEL(9, 8), 0,
1610 { 0, 0, RK3328_XIN24M, RK3328_XIN24M }
1611 },
1612 {
1613 RK3328_CLK_WIFI, RK3328_CRU_CLKSEL_CON(52),
1614 SEL(7, 6), DIV(5, 0),
1615 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_USB480M }
1616 },
1617 {
1618 RK3328_CLK_I2C0, RK3328_CRU_CLKSEL_CON(34),
1619 SEL(7, 7), DIV(6, 0),
1620 { RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1621 },
1622 {
1623 RK3328_CLK_I2C1, RK3328_CRU_CLKSEL_CON(34),
1624 SEL(15, 15), DIV(14, 8),
1625 { RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1626 },
1627 {
1628 RK3328_CLK_I2C2, RK3328_CRU_CLKSEL_CON(35),
1629 SEL(7, 7), DIV(6, 0),
1630 { RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1631 },
1632 {
1633 RK3328_CLK_I2C3, RK3328_CRU_CLKSEL_CON(35),
1634 SEL(15, 15), DIV(14, 8),
1635 { RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1636 },
1637 {
1638 RK3328_CLK_CRYPTO, RK3328_CRU_CLKSEL_CON(20),
1639 SEL(7, 7), DIV(4, 0),
1640 { RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1641 },
1642 {
1643 RK3328_CLK_PDM, RK3328_CRU_CLKSEL_CON(20),
1644 SEL(15, 14), DIV(12, 8),
1645 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_PLL_APLL },
1646 FIXED_PARENT | SET_PARENT
1647 },
1648 {
1649 RK3328_CLK_VDEC_CABAC, RK3328_CRU_CLKSEL_CON(48),
1650 SEL(15, 14), DIV(12, 8),
1651 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1652 RK3328_USB480M }
1653 },
1654 {
1655 RK3328_CLK_VDEC_CORE, RK3328_CRU_CLKSEL_CON(49),
1656 SEL(7, 6), DIV(4, 0),
1657 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1658 RK3328_USB480M }
1659 },
1660 {
1661 RK3328_CLK_VENC_DSP, RK3328_CRU_CLKSEL_CON(52),
1662 SEL(15, 14), DIV(12, 8),
1663 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1664 RK3328_USB480M }
1665 },
1666 {
1667 RK3328_CLK_VENC_CORE, RK3328_CRU_CLKSEL_CON(51),
1668 SEL(15, 14), DIV(12, 8),
1669 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1670 RK3328_USB480M }
1671 },
1672 {
1673 RK3328_CLK_TSP, RK3328_CRU_CLKSEL_CON(21),
1674 SEL(15, 15), DIV(12, 8),
1675 { RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1676 },
1677 {
1678 RK3328_CLK_MAC2IO_SRC, RK3328_CRU_CLKSEL_CON(27),
1679 SEL(7, 7), DIV(4, 0),
1680 { RK3328_PLL_CPLL, RK3328_PLL_GPLL }
1681 },
1682 {
1683 RK3328_DCLK_LCDC, RK3328_CRU_CLKSEL_CON(40),
1684 SEL(1, 1), 0,
1685 { RK3328_HDMIPHY, RK3328_DCLK_LCDC_SRC }
1686 },
1687 {
1688 RK3328_ACLK_VOP_PRE, RK3328_CRU_CLKSEL_CON(39),
1689 SEL(7, 6), DIV(4, 0),
1690 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1691 RK3328_USB480M }
1692 },
1693 {
1694 RK3328_ACLK_RGA_PRE, RK3328_CRU_CLKSEL_CON(36),
1695 SEL(15, 14), DIV(12, 8),
1696 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1697 RK3328_USB480M }
1698 },
1699 {
1700 RK3328_ACLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(0),
1701 SEL(14, 13), DIV(12, 8),
1702 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
1703 },
1704 {
1705 RK3328_ACLK_PERI_PRE, RK3328_CRU_CLKSEL_CON(28),
1706 SEL(7, 6), DIV(4, 0),
1707 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY }
1708 },
1709 {
1710 RK3328_ACLK_RKVDEC_PRE, RK3328_CRU_CLKSEL_CON(48),
1711 SEL(7, 6), DIV(4, 0),
1712 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1713 RK3328_USB480M }
1714 },
1715 {
1716 RK3328_ACLK_RKVENC, RK3328_CRU_CLKSEL_CON(51),
1717 SEL(7, 6), DIV(4, 0),
1718 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1719 RK3328_USB480M }
1720 },
1721 {
1722 RK3328_ACLK_VPU_PRE, RK3328_CRU_CLKSEL_CON(50),
1723 SEL(7, 6), DIV(4, 0),
1724 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1725 RK3328_USB480M }
1726 },
1727 {
1728 RK3328_ACLK_VIO_PRE, RK3328_CRU_CLKSEL_CON(37),
1729 SEL(7, 6), DIV(4, 0),
1730 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY,
1731 RK3328_USB480M }
1732 },
1733 {
1734 RK3328_PCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
1735 0, DIV(14, 12),
1736 { RK3328_ACLK_BUS_PRE }
1737 },
1738 {
1739 RK3328_HCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1),
1740 0, DIV(9, 8),
1741 { RK3328_ACLK_BUS_PRE }
1742 },
1743 {
1744 RK3328_PCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
1745 0, DIV(6, 4),
1746 { RK3328_ACLK_PERI_PRE }
1747 },
1748 {
1749 RK3328_HCLK_PERI, RK3328_CRU_CLKSEL_CON(29),
1750 0, DIV(1, 0),
1751 { RK3328_ACLK_PERI_PRE }
1752 },
1753 {
1754 RK3328_CLK_24M, RK3328_CRU_CLKSEL_CON(2),
1755 0, DIV(12, 8),
1756 { RK3328_XIN24M }
1757 },
1758 {
1759 /* Sentinel */
1760 }
1761};
1762
1763void
1764rk3328_init(struct rkclock_softc *sc)
1765{
1766 int i;
1767
1768 /* The code below assumes all clocks are enabled. Check this!. */
1769 for (i = 0; i <= 28; i++) {
1770 if (HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)) != 0x00000000) {
1771 printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
1772 HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)));
1773 }
1774 }
1775
1776 sc->sc_clocks = rk3328_clocks;
1777}
1778
1779uint32_t
1780rk3328_armclk_parent(uint32_t mux)
1781{
1782 switch (mux) {
1783 case 0:
1784 return RK3328_PLL_APLL;
1785 case 1:
1786 return RK3328_PLL_GPLL;
1787 case 2:
1788 return RK3328_PLL_DPLL;
1789 case 3:
1790 return RK3328_PLL_NPLL;
1791 }
1792
1793 return 0;
1794}
1795
1796uint32_t
1797rk3328_get_armclk(struct rkclock_softc *sc)
1798{
1799 uint32_t reg, mux, div_con;
1800 uint32_t idx;
1801
1802 reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1803 mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1804 RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1805 div_con = (reg & RK3328_CRU_CLK_CORE_DIV_CON_MASK) >>
1806 RK3328_CRU_CLK_CORE_DIV_CON_SHIFT;
1807 idx = rk3328_armclk_parent(mux);
1808
1809 return rk3328_get_frequency(sc, &idx) / (div_con + 1);
1810}
1811
1812int
1813rk3328_set_armclk(struct rkclock_softc *sc, uint32_t freq)
1814{
1815 uint32_t reg, mux;
1816 uint32_t old_freq, div;
1817 uint32_t idx;
1818
1819 old_freq = rk3328_get_armclk(sc);
1820 if (freq == old_freq)
1821 return 0;
1822
1823 reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0));
1824 mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >>
1825 RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT;
1826
1827 /* Keep the pclk_dbg clock at or below 300 MHz. */
1828 div = 1;
1829 while (freq / (div + 1) > 300000000)
1830 div++;
1831 /* and make sure we use an odd divider. */
1832 if ((div % 2) == 0)
1833 div++;
1834
1835 /* When ramping up, set clock dividers first. */
1836 if (freq > old_freq) {
1837 HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1838 RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1839 0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1840 HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1841 RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1842 1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1843 RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1844 div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1845 }
1846
1847 /* We always use NPLL and force the switch below if needed. */
1848 idx = RK3328_PLL_NPLL;
1849 rk3328_set_frequency(sc, &idx, freq);
1850
1851 /* When ramping down, set clock dividers last. */
1852 if (freq < old_freq || mux != 3) {
1853 HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0),
1854 RK3328_CRU_CORE_CLK_PLL_SEL_MASK << 16 |
1855 3 << RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT |
1856 RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 |
1857 0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT);
1858 HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1),
1859 RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 |
1860 1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT |
1861 RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 |
1862 div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT);
1863 }
1864
1865 return 0;
1866}
1867
1868uint32_t
1869rk3328_get_pll(struct rkclock_softc *sc, bus_size_t base)
1870{
1871 uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1872 uint32_t dsmpd, fracdiv;
1873 uint64_t frac = 0;
1874 uint32_t reg;
1875
1876 reg = HREAD4(sc, base + 0x0000);
1877 postdiv1 = (reg & RK3328_CRU_PLL_POSTDIV1_MASK) >>
1878 RK3328_CRU_PLL_POSTDIV1_SHIFT;
1879 fbdiv = (reg & RK3328_CRU_PLL_FBDIV_MASK) >>
1880 RK3328_CRU_PLL_FBDIV_SHIFT;
1881 reg = HREAD4(sc, base + 0x0004);
1882 dsmpd = (reg & RK3328_CRU_PLL_DSMPD);
1883 postdiv2 = (reg & RK3328_CRU_PLL_POSTDIV2_MASK) >>
1884 RK3328_CRU_PLL_POSTDIV2_SHIFT;
1885 refdiv = (reg & RK3328_CRU_PLL_REFDIV_MASK) >>
1886 RK3328_CRU_PLL_REFDIV_SHIFT;
1887 reg = HREAD4(sc, base + 0x0008);
1888 fracdiv = (reg & RK3328_CRU_PLL_FRACDIV_MASK) >>
1889 RK3328_CRU_PLL_FRACDIV_SHIFT;
1890
1891 if (dsmpd == 0)
1892 frac = (24000000ULL * fracdiv / refdiv) >> 24;
1893 return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2;
1894}
1895
1896int
1897rk3328_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
1898{
1899 uint32_t fbdiv, postdiv1, postdiv2, refdiv;
1900 int mode_shift = -1;
1901
1902 switch (base) {
1903 case RK3328_CRU_APLL_CON(0):
1904 mode_shift = 0;
1905 break;
1906 case RK3328_CRU_DPLL_CON(0):
1907 mode_shift = 4;
1908 break;
1909 case RK3328_CRU_CPLL_CON(0):
1910 mode_shift = 8;
1911 break;
1912 case RK3328_CRU_GPLL_CON(0):
1913 mode_shift = 12;
1914 break;
1915 case RK3328_CRU_NPLL_CON(0):
1916 mode_shift = 1;
1917 break;
1918 }
1919 KASSERT(mode_shift != -1);
1920
1921 /*
1922 * It is not clear whether all combinations of the clock
1923 * dividers result in a stable clock. Therefore this function
1924 * only supports a limited set of PLL clock rates. For now
1925 * this set covers all the CPU frequencies supported by the
1926 * Linux kernel.
1927 */
1928 switch (freq) {
1929 case 1800000000U:
1930 case 1704000000U:
1931 case 1608000000U:
1932 case 1512000000U:
1933 case 1488000000U:
1934 case 1416000000U:
1935 case 1392000000U:
1936 case 1296000000U:
1937 case 1200000000U:
1938 case 1104000000U:
1939 postdiv1 = postdiv2 = refdiv = 1;
1940 break;
1941 case 1008000000U:
1942 case 912000000U:
1943 case 816000000U:
1944 case 696000000U:
1945 postdiv1 = 2; postdiv2 = refdiv = 1;
1946 break;
1947 case 600000000U:
1948 postdiv1 = 3; postdiv2 = refdiv = 1;
1949 break;
1950 case 408000000U:
1951 case 312000000U:
1952 postdiv1 = postdiv2 = 2; refdiv = 1;
1953 break;
1954 case 216000000U:
1955 postdiv1 = 4; postdiv2 = 2; refdiv = 1;
1956 break;
1957 case 96000000U:
1958 postdiv1 = postdiv2 = 4; refdiv = 1;
1959 break;
1960 default:
1961 printf("%s: %u Hz\n", __func__, freq);
1962 return -1;
1963 }
1964
1965 /* Calculate feedback divider. */
1966 fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
1967
1968 /*
1969 * Select slow mode to guarantee a stable clock while we're
1970 * adjusting the PLL.
1971 */
1972 HWRITE4(sc, RK3328_CRU_CRU_MODE,
1973 (RK3328_CRU_CRU_MODE_MASK << 16 |
1974 RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
1975
1976 /* Set PLL rate. */
1977 HWRITE4(sc, base + 0x0000,
1978 RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
1979 postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
1980 RK3328_CRU_PLL_FBDIV_MASK << 16 |
1981 fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
1982 HWRITE4(sc, base + 0x0004,
1983 RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD |
1984 RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
1985 postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
1986 RK3328_CRU_PLL_REFDIV_MASK << 16 |
1987 refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
1988
1989 /* Wait for PLL to stabilize. */
1990 while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
1991 delay(10);
1992
1993 /* Switch back to normal mode. */
1994 HWRITE4(sc, RK3328_CRU_CRU_MODE,
1995 (RK3328_CRU_CRU_MODE_MASK << 16 |
1996 RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
1997
1998 return 0;
1999}
2000
2001int
2002rk3328_set_frac_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
2003{
2004 uint32_t fbdiv, postdiv1, postdiv2, refdiv, fracdiv;
2005 int mode_shift = -1;
2006 uint32_t reg;
2007
2008 switch (base) {
2009 case RK3328_CRU_APLL_CON(0):
2010 mode_shift = 0;
2011 break;
2012 case RK3328_CRU_DPLL_CON(0):
2013 mode_shift = 4;
2014 break;
2015 case RK3328_CRU_CPLL_CON(0):
2016 mode_shift = 8;
2017 break;
2018 case RK3328_CRU_GPLL_CON(0):
2019 mode_shift = 12;
2020 break;
2021 case RK3328_CRU_NPLL_CON(0):
2022 mode_shift = 1;
2023 break;
2024 }
2025 KASSERT(mode_shift != -1);
2026
2027 /*
2028 * It is not clear whether all combinations of the clock
2029 * dividers result in a stable clock. Therefore this function
2030 * only supports a limited set of PLL clock rates. This set
2031 * set covers all the fractional PLL frequencies supported by
2032 * the Linux kernel.
2033 */
2034 switch (freq) {
2035 case 1016064000U:
2036 postdiv1 = postdiv2 = 1; refdiv = 3; fracdiv = 134217;
2037 break;
2038 case 983040000U:
2039 postdiv1 = postdiv2 = 1; refdiv = 24; fracdiv = 671088;
2040 break;
2041 case 491520000U:
2042 postdiv1 = 2; postdiv2 = 1; refdiv = 24; fracdiv = 671088;
2043 break;
2044 case 61440000U:
2045 postdiv1 = 7; postdiv2 = 2; refdiv = 6; fracdiv = 671088;
2046 break;
2047 case 56448000U:
2048 postdiv1 = postdiv2 = 4; refdiv = 12; fracdiv = 9797894;
2049 break;
2050 case 40960000U:
2051 postdiv1 = 4; postdiv2 = 5; refdiv = 12; fracdiv = 10066239;
2052 break;
2053 default:
2054 printf("%s: %u Hz\n", __func__, freq);
2055 return -1;
2056 }
2057
2058 /* Calculate feedback divider. */
2059 fbdiv = (uint64_t)freq * postdiv1 * postdiv2 * refdiv / 24000000;
2060
2061 /*
2062 * Select slow mode to guarantee a stable clock while we're
2063 * adjusting the PLL.
2064 */
2065 HWRITE4(sc, RK3328_CRU_CRU_MODE,
2066 (RK3328_CRU_CRU_MODE_MASK << 16 |
2067 RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
2068
2069 /* Set PLL rate. */
2070 HWRITE4(sc, base + 0x0000,
2071 RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
2072 postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
2073 RK3328_CRU_PLL_FBDIV_MASK << 16 |
2074 fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
2075 HWRITE4(sc, base + 0x0004,
2076 RK3328_CRU_PLL_DSMPD << 16 |
2077 RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
2078 postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
2079 RK3328_CRU_PLL_REFDIV_MASK << 16 |
2080 refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
2081 reg = HREAD4(sc, base + 0x0008);
2082 reg &= ~RK3328_CRU_PLL_FRACDIV_MASK;
2083 reg |= fracdiv << RK3328_CRU_PLL_FRACDIV_SHIFT;
2084 HWRITE4(sc, base + 0x0008, reg);
2085
2086 /* Wait for PLL to stabilize. */
2087 while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
2088 delay(10);
2089
2090 /* Switch back to normal mode. */
2091 HWRITE4(sc, RK3328_CRU_CRU_MODE,
2092 (RK3328_CRU_CRU_MODE_MASK << 16 |
2093 RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
2094
2095 return 0;
2096}
2097
2098uint32_t
2099rk3328_get_frequency(void *cookie, uint32_t *cells)
2100{
2101 struct rkclock_softc *sc = cookie;
2102 uint32_t idx = cells[0];
2103 uint32_t reg;
2104
2105 switch (idx) {
2106 case RK3328_PLL_APLL:
2107 return rk3328_get_pll(sc, RK3328_CRU_APLL_CON(0));
2108 case RK3328_PLL_DPLL:
2109 return rk3328_get_pll(sc, RK3328_CRU_DPLL_CON(0));
2110 case RK3328_PLL_CPLL:
2111 return rk3328_get_pll(sc, RK3328_CRU_CPLL_CON(0));
2112 case RK3328_PLL_GPLL:
2113 return rk3328_get_pll(sc, RK3328_CRU_GPLL_CON(0));
2114 case RK3328_PLL_NPLL:
2115 return rk3328_get_pll(sc, RK3328_CRU_NPLL_CON(0));
2116 case RK3328_ARMCLK:
2117 return rk3328_get_armclk(sc);
2118 case RK3328_XIN24M:
2119 return 24000000;
2120 case RK3328_GMAC_CLKIN:
2121 return 125000000;
2122 /*
2123 * XXX The HDMIPHY and USB480M clocks are external. Returning
2124 * zero here will cause them to be ignored for reparenting
2125 * purposes.
2126 */
2127 case RK3328_HDMIPHY:
2128 return 0;
2129 case RK3328_USB480M:
2130 return 0;
2131 case RK3328_CLK_MAC2IO:
2132 reg = regmap_read_4(sc->sc_grf, RK3328_GRF_MAC_CON1);
2133 if (reg & RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL)
2134 idx = RK3328_GMAC_CLKIN;
2135 else
2136 idx = RK3328_CLK_MAC2IO_SRC;
2137 return rk3328_get_frequency(sc, &idx);
2138 default:
2139 break;
2140 }
2141
2142 return rkclock_get_frequency(sc, idx);
2143}
2144
2145int
2146rk3328_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2147{
2148 struct rkclock_softc *sc = cookie;
2149 uint32_t idx = cells[0];
2150 uint32_t reg, mux;
2151
2152 switch (idx) {
2153 case RK3328_PLL_APLL:
2154 return rk3328_set_frac_pll(sc, RK3328_CRU_APLL_CON(0), freq);
2155 case RK3328_PLL_DPLL:
2156 return rk3328_set_pll(sc, RK3328_CRU_DPLL_CON(0), freq);
2157 case RK3328_PLL_CPLL:
2158 return rk3328_set_pll(sc, RK3328_CRU_CPLL_CON(0), freq);
2159 case RK3328_PLL_GPLL:
2160 return rk3328_set_frac_pll(sc, RK3328_CRU_GPLL_CON(0), freq);
2161 case RK3328_PLL_NPLL:
2162 return rk3328_set_pll(sc, RK3328_CRU_NPLL_CON(0), freq);
2163 case RK3328_ARMCLK:
2164 return rk3328_set_armclk(sc, freq);
2165 case RK3328_CLK_UART0:
2166 case RK3328_CLK_UART1:
2167 case RK3328_CLK_UART2:
2168 if (freq == rk3328_get_frequency(sc, &idx))
2169 return 0;
2170 break;
2171 case RK3328_DCLK_LCDC:
2172 reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(40));
2173 mux = (reg & RK3328_CRU_VOP_DCLK_SRC_SEL_MASK) >>
2174 RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT;
2175 idx = (mux == 0) ? RK3328_HDMIPHY : RK3328_DCLK_LCDC_SRC;
2176 return rk3328_set_frequency(sc, &idx, freq);
2177 case RK3328_HCLK_CRYPTO_SLV:
2178 idx = RK3328_HCLK_BUS_PRE;
2179 return rk3328_set_frequency(sc, &idx, freq);
2180 default:
2181 break;
2182 }
2183
2184 return rkclock_set_frequency(sc, idx, freq);
2185}
2186
2187int
2188rk3328_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
2189{
2190 struct rkclock_softc *sc = cookie;
2191 uint32_t idx = cells[0];
2192 uint32_t parent;
2193
2194 if (pcells[0] == sc->sc_phandle)
2195 parent = pcells[1];
2196 else {
2197 char name[32];
2198 int node;
2199
2200 node = OF_getnodebyphandle(pcells[0]);
2201 if (node == 0)
2202 return -1;
2203 name[0] = 0;
2204 OF_getprop(node, "clock-output-names", name, sizeof(name));
2205 name[sizeof(name) - 1] = 0;
2206 if (strcmp(name, "xin24m") == 0)
2207 parent = RK3328_XIN24M;
2208 else if (strcmp(name, "gmac_clkin") == 0)
2209 parent = RK3328_GMAC_CLKIN;
2210 else
2211 return -1;
2212 }
2213
2214 switch (idx) {
2215 case RK3328_CLK_MAC2IO:
2216 if (parent == RK3328_GMAC_CLKIN) {
2217 regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
2218 RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16 |
2219 RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL);
2220 } else {
2221 regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1,
2222 RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16);
2223 }
2224 return 0;
2225 case RK3328_CLK_MAC2IO_EXT:
2226 if (parent == RK3328_GMAC_CLKIN) {
2227 regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
2228 RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16 |
2229 RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN);
2230 } else {
2231 regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4,
2232 RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16);
2233 }
2234 return 0;
2235 }
2236
2237 return rkclock_set_parent(sc, idx, parent);
2238}
2239
2240void
2241rk3328_enable(void *cookie, uint32_t *cells, int on)
2242{
2243 uint32_t idx = cells[0];
2244
2245 /*
2246 * All clocks are enabled by default, so there is nothing for
2247 * us to do until we start disabling clocks.
2248 */
2249 if (!on)
2250 printf("%s: 0x%08x\n", __func__, idx);
2251}
2252
2253void
2254rk3328_reset(void *cookie, uint32_t *cells, int on)
2255{
2256 struct rkclock_softc *sc = cookie;
2257 uint32_t idx = cells[0];
2258 uint32_t mask = (1 << (idx % 16));
2259
2260 HWRITE4(sc, RK3328_CRU_SOFTRST_CON(idx / 16),
2261 mask << 16 | (on ? mask : 0));
2262}
2263
2264/*
2265 * Rockchip RK3399
2266 */
2267
2268const struct rkclock rk3399_clocks[] = {
2269 {
2270 RK3399_CLK_I2C1, RK3399_CRU_CLKSEL_CON(61),
2271 SEL(7, 7), DIV(6, 0),
2272 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2273 },
2274 {
2275 RK3399_CLK_I2C2, RK3399_CRU_CLKSEL_CON(62),
2276 SEL(7, 7), DIV(6, 0),
2277 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2278 },
2279 {
2280 RK3399_CLK_I2C3, RK3399_CRU_CLKSEL_CON(63),
2281 SEL(7, 7), DIV(6, 0),
2282 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2283 },
2284 {
2285 RK3399_CLK_I2C5, RK3399_CRU_CLKSEL_CON(61),
2286 SEL(15, 15), DIV(14, 8),
2287 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2288 },
2289 {
2290 RK3399_CLK_I2C6, RK3399_CRU_CLKSEL_CON(62),
2291 SEL(15, 15), DIV(14, 8),
2292 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2293 },
2294 {
2295 RK3399_CLK_I2C7, RK3399_CRU_CLKSEL_CON(63),
2296 SEL(15, 15), DIV(14, 8),
2297 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2298 },
2299 {
2300 RK3399_CLK_SPI0, RK3399_CRU_CLKSEL_CON(59),
2301 SEL(7, 7), DIV(6, 0),
2302 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2303 },
2304 {
2305 RK3399_CLK_SPI1, RK3399_CRU_CLKSEL_CON(59),
2306 SEL(15, 15), DIV(14, 8),
2307 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2308 },
2309 {
2310 RK3399_CLK_SPI2, RK3399_CRU_CLKSEL_CON(60),
2311 SEL(7, 7), DIV(6, 0),
2312 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2313 },
2314 {
2315 RK3399_CLK_SPI4, RK3399_CRU_CLKSEL_CON(60),
2316 SEL(15, 15), DIV(14, 8),
2317 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2318 },
2319 {
2320 RK3399_CLK_SPI5, RK3399_CRU_CLKSEL_CON(58),
2321 SEL(15, 15), DIV(14, 8),
2322 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2323 },
2324 {
2325 RK3399_CLK_SDMMC, RK3399_CRU_CLKSEL_CON(16),
2326 SEL(10, 8), DIV(6, 0),
2327 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2328 /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
2329 RK3399_XIN24M }
2330 },
2331 {
2332 RK3399_CLK_SDIO, RK3399_CRU_CLKSEL_CON(15),
2333 SEL(10, 8), DIV(6, 0),
2334 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2335 /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0,
2336 RK3399_XIN24M }
2337 },
2338 {
2339 RK3399_CLK_EMMC, RK3399_CRU_CLKSEL_CON(22),
2340 SEL(10, 8), DIV(6, 0),
2341 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2342 /* RK3399_USB_480M */ 0, RK3399_XIN24M }
2343 },
2344 {
2345 RK3399_CLK_TSADC, RK3399_CRU_CLKSEL_CON(27),
2346 SEL(15, 15), DIV(9, 0),
2347 { RK3399_XIN24M, RK3399_CLK_32K }
2348 },
2349 {
2350 RK3399_CLK_UART0, RK3399_CRU_CLKSEL_CON(33),
2351 SEL(9, 8), 0,
2352 { 0, 0, RK3399_XIN24M }
2353 },
2354 {
2355 RK3399_CLK_UART1, RK3399_CRU_CLKSEL_CON(34),
2356 SEL(9, 8), 0,
2357 { 0, 0, RK3399_XIN24M }
2358 },
2359 {
2360 RK3399_CLK_UART2, RK3399_CRU_CLKSEL_CON(35),
2361 SEL(9, 8), 0,
2362 { 0, 0, RK3399_XIN24M }
2363 },
2364 {
2365 RK3399_CLK_UART3, RK3399_CRU_CLKSEL_CON(36),
2366 SEL(9, 8), 0,
2367 { 0, 0, RK3399_XIN24M }
2368 },
2369 {
2370 RK3399_CLK_I2S0_8CH, RK3399_CRU_CLKSEL_CON(28),
2371 SEL(9, 8), 0,
2372 { RK3399_CLK_I2S0_DIV, RK3399_CLK_I2S0_FRAC, 0, RK3399_XIN12M },
2373 SET_PARENT
2374 },
2375 {
2376 RK3399_CLK_I2S1_8CH, RK3399_CRU_CLKSEL_CON(29),
2377 SEL(9, 8), 0,
2378 { RK3399_CLK_I2S1_DIV, RK3399_CLK_I2S1_FRAC, 0, RK3399_XIN12M },
2379 SET_PARENT
2380 },
2381 {
2382 RK3399_CLK_I2S2_8CH, RK3399_CRU_CLKSEL_CON(30),
2383 SEL(9, 8), 0,
2384 { RK3399_CLK_I2S2_DIV, RK3399_CLK_I2S2_FRAC, 0, RK3399_XIN12M },
2385 SET_PARENT
2386 },
2387 {
2388 RK3399_CLK_I2S_8CH_OUT, RK3399_CRU_CLKSEL_CON(31),
2389 SEL(2, 2), 0,
2390 { RK3399_CLK_I2SOUT_SRC, RK3399_XIN12M },
2391 SET_PARENT
2392 },
2393 {
2394 RK3399_CLK_MAC, RK3399_CRU_CLKSEL_CON(20),
2395 SEL(15, 14), DIV(12, 8),
2396 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL }
2397 },
2398 {
2399 RK3399_CLK_UPHY0_TCPDCORE, RK3399_CRU_CLKSEL_CON(64),
2400 SEL(7, 6), DIV(4, 0),
2401 { RK3399_XIN24M, RK3399_CLK_32K, RK3399_PLL_CPLL,
2402 RK3399_PLL_GPLL }
2403 },
2404 {
2405 RK3399_CLK_UPHY1_TCPDCORE, RK3399_CRU_CLKSEL_CON(65),
2406 SEL(7, 6), DIV(4, 0),
2407 { RK3399_XIN24M, RK3399_CLK_32K, RK3399_PLL_CPLL,
2408 RK3399_PLL_GPLL }
2409 },
2410 {
2411 RK3399_CLK_PCIEPHY_REF, RK3399_CRU_CLKSEL_CON(18),
2412 SEL(10, 10), 0,
2413 { RK3399_XIN24M, RK3399_CLK_PCIEPHY_REF100M },
2414 SET_PARENT
2415 },
2416 {
2417 RK3399_CLK_PCIEPHY_REF100M, RK3399_CRU_CLKSEL_CON(18),
2418 0, DIV(15, 11),
2419 { RK3399_PLL_NPLL }
2420 },
2421 {
2422 RK3399_DCLK_VOP0, RK3399_CRU_CLKSEL_CON(49),
2423 SEL(11, 11), 0,
2424 { RK3399_DCLK_VOP0_DIV, RK3399_DCLK_VOP0_FRAC },
2425 SET_PARENT
2426 },
2427 {
2428 RK3399_DCLK_VOP1, RK3399_CRU_CLKSEL_CON(50),
2429 SEL(11, 11), 0,
2430 { RK3399_DCLK_VOP1_DIV, RK3399_DCLK_VOP1_FRAC },
2431 SET_PARENT
2432 },
2433 {
2434 RK3399_DCLK_VOP0_DIV, RK3399_CRU_CLKSEL_CON(49),
2435 SEL(9, 8), DIV(7, 0),
2436 { RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2437 },
2438 {
2439 RK3399_DCLK_VOP1_DIV, RK3399_CRU_CLKSEL_CON(50),
2440 SEL(9, 8), DIV(7, 0),
2441 { RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2442 },
2443 {
2444 RK3399_ACLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
2445 SEL(7, 7), DIV(4, 0),
2446 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2447 },
2448 {
2449 RK3399_ACLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
2450 SEL(7, 7), DIV(4, 0),
2451 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2452 },
2453 {
2454 RK3399_ACLK_VIO, RK3399_CRU_CLKSEL_CON(42),
2455 SEL(7, 6), DIV(4, 0),
2456 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
2457 },
2458 {
2459 RK3399_ACLK_CCI, RK3399_CRU_CLKSEL_CON(5),
2460 SEL(7, 6), DIV(4, 0),
2461 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL,
2462 RK3399_PLL_VPLL }
2463 },
2464 {
2465 RK3399_ACLK_VOP0, RK3399_CRU_CLKSEL_CON(47),
2466 SEL(7, 6), DIV(4, 0),
2467 { RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL,
2468 RK3399_PLL_NPLL }
2469 },
2470 {
2471 RK3399_ACLK_VOP1, RK3399_CRU_CLKSEL_CON(48),
2472 SEL(7, 6), DIV(4, 0),
2473 { RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL,
2474 RK3399_PLL_NPLL }
2475 },
2476 {
2477 RK3399_ACLK_HDCP, RK3399_CRU_CLKSEL_CON(42),
2478 SEL(15, 14), DIV(12, 8),
2479 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ }
2480 },
2481 {
2482 RK3399_ACLK_GIC_PRE, RK3399_CRU_CLKSEL_CON(56),
2483 SEL(15, 15), DIV(12, 8),
2484 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2485 },
2486 {
2487 RK3399_PCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
2488 0, DIV(14, 12),
2489 { RK3399_ACLK_PERIPH }
2490 },
2491 {
2492 RK3399_PCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
2493 0, DIV(14, 12),
2494 { RK3399_ACLK_PERILP0 }
2495 },
2496 {
2497 RK3399_PCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
2498 0, DIV(10, 8),
2499 { RK3399_HCLK_PERILP1 }
2500 },
2501 {
2502 RK3399_PCLK_DDR, RK3399_CRU_CLKSEL_CON(6),
2503 SEL(15, 15), DIV(12, 8),
2504 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2505 },
2506 {
2507 RK3399_PCLK_WDT, RK3399_CRU_CLKSEL_CON(57),
2508 0, DIV(4, 0),
2509 { RK3399_PLL_GPLL }
2510 },
2511 {
2512 RK3399_HCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14),
2513 0, DIV(9, 8),
2514 { RK3399_ACLK_PERIPH }
2515 },
2516 {
2517 RK3399_HCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23),
2518 0, DIV(9, 8),
2519 { RK3399_ACLK_PERILP0 }
2520 },
2521 {
2522 RK3399_HCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25),
2523 SEL(7, 7), DIV(4, 0),
2524 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2525 },
2526 {
2527 RK3399_HCLK_SDMMC, RK3399_CRU_CLKSEL_CON(13),
2528 SEL(15, 15), DIV(12, 8),
2529 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2530 },
2531 {
2532 RK3399_HCLK_VOP0, RK3399_CRU_CLKSEL_CON(47),
2533 0, DIV(12, 8),
2534 { RK3399_ACLK_VOP0 }
2535 },
2536 {
2537 RK3399_HCLK_VOP1, RK3399_CRU_CLKSEL_CON(48),
2538 0, DIV(12, 8),
2539 { RK3399_ACLK_VOP1 }
2540 },
2541 {
2542 RK3399_CLK_I2S0_DIV, RK3399_CRU_CLKSEL_CON(28),
2543 SEL(7, 7), DIV(6, 0),
2544 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2545 },
2546 {
2547 RK3399_CLK_I2S1_DIV, RK3399_CRU_CLKSEL_CON(29),
2548 SEL(7, 7), DIV(6, 0),
2549 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2550 },
2551 {
2552 RK3399_CLK_I2S2_DIV, RK3399_CRU_CLKSEL_CON(30),
2553 SEL(7, 7), DIV(6, 0),
2554 { RK3399_PLL_CPLL, RK3399_PLL_GPLL }
2555 },
2556 {
2557 RK3399_CLK_I2SOUT_SRC, RK3399_CRU_CLKSEL_CON(31),
2558 SEL(1, 0), 0,
2559 { RK3399_CLK_I2S0_8CH, RK3399_CLK_I2S1_8CH,
2560 RK3399_CLK_I2S2_8CH },
2561 SET_PARENT
2562 },
2563 {
2564 /* Sentinel */
2565 }
2566};
2567
2568/* Some of our parent clocks live in the PMUCRU. */
2569struct rkclock_softc *rk3399_pmucru_sc;
2570
2571void
2572rk3399_init(struct rkclock_softc *sc)
2573{
2574 int i;
2575
2576 /* PMUCRU instance should attach before us. */
2577 KASSERT(rk3399_pmucru_sc != NULL);
2578
2579 /*
2580 * The U-Boot shipped on the Theobroma Systems RK3399-Q7
2581 * module is buggy and sets the parent of the clock for the
2582 * "big" cluster to LPLL. Undo that mistake here such that
2583 * the clocks of both clusters are independent.
2584 */
2585 HWRITE4(sc, RK3399_CRU_CLKSEL_CON(2),
2586 RK3399_CRU_CORE_PLL_SEL_MASK << 16 |
2587 RK3399_CRU_CORE_PLL_SEL_BPLL);
2588
2589 /* The code below assumes all clocks are enabled. Check this!. */
2590 for (i = 0; i <= 34; i++) {
2591 if (HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)) != 0x00000000) {
2592 printf("CRU_CLKGATE_CON%d: 0x%08x\n", i,
2593 HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)));
2594 }
2595 }
2596
2597 sc->sc_clocks = rk3399_clocks;
2598}
2599
2600uint32_t
2601rk3399_get_pll(struct rkclock_softc *sc, bus_size_t base)
2602{
2603 uint32_t fbdiv, postdiv1, postdiv2, refdiv;
2604 uint32_t pll_work_mode;
2605 uint32_t reg;
2606
2607 reg = HREAD4(sc, base + 0x000c);
2608 pll_work_mode = reg & RK3399_CRU_PLL_PLL_WORK_MODE_MASK;
2609 if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_SLOW)
2610 return 24000000;
2611 if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW)
2612 return 32768;
2613
2614 reg = HREAD4(sc, base + 0x0000);
2615 fbdiv = (reg & RK3399_CRU_PLL_FBDIV_MASK) >>
2616 RK3399_CRU_PLL_FBDIV_SHIFT;
2617 reg = HREAD4(sc, base + 0x0004);
2618 postdiv2 = (reg & RK3399_CRU_PLL_POSTDIV2_MASK) >>
2619 RK3399_CRU_PLL_POSTDIV2_SHIFT;
2620 postdiv1 = (reg & RK3399_CRU_PLL_POSTDIV1_MASK) >>
2621 RK3399_CRU_PLL_POSTDIV1_SHIFT;
2622 refdiv = (reg & RK3399_CRU_PLL_REFDIV_MASK) >>
2623 RK3399_CRU_PLL_REFDIV_SHIFT;
2624 return 24000000ULL * fbdiv / refdiv / postdiv1 / postdiv2;
2625}
2626
2627int
2628rk3399_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
2629{
2630 uint32_t fbdiv, postdiv1, postdiv2, refdiv;
2631
2632 /*
2633 * It is not clear whether all combinations of the clock
2634 * dividers result in a stable clock. Therefore this function
2635 * only supports a limited set of PLL clock rates. For now
2636 * this set covers all the CPU frequencies supported by the
2637 * Linux kernel.
2638 */
2639 switch (freq) {
2640 case 2208000000U:
2641 case 2184000000U:
2642 case 2088000000U:
2643 case 2040000000U:
2644 case 2016000000U:
2645 case 1992000000U:
2646 case 1896000000U:
2647 case 1800000000U:
2648 case 1704000000U:
2649 case 1608000000U:
2650 case 1512000000U:
2651 case 1488000000U:
2652 case 1416000000U:
2653 case 1200000000U:
2654 postdiv1 = postdiv2 = refdiv = 1;
2655 break;
2656 case 1008000000U:
2657 case 816000000U:
2658 case 696000000U:
2659 postdiv1 = 2; postdiv2 = refdiv = 1;
2660 break;
2661 case 676000000U:
2662 postdiv1 = 2; postdiv2 = 1; refdiv = 3;
2663 break;
2664 case 1000000000U:
2665 case 800000000U:
2666 case 600000000U:
2667 postdiv1 = 3; postdiv2 = refdiv = 1;
2668 break;
2669 case 594000000U:
2670 postdiv1 = 4; postdiv2 = refdiv = 1;
2671 break;
2672 case 408000000U:
2673 postdiv1 = postdiv2 = 2; refdiv = 1;
2674 break;
2675 case 297000000U:
2676 case 216000000U:
2677 postdiv1 = 4; postdiv2 = 2; refdiv = 1;
2678 break;
2679 case 148500000U:
2680 case 96000000U:
2681 postdiv1 = postdiv2 = 4; refdiv = 1;
2682 break;
2683 case 74250000U:
2684 postdiv1 = postdiv2 = 4; refdiv = 2;
2685 break;
2686 case 65000000U:
2687 case 54000000U:
2688 case 27000000U:
2689 postdiv1 = 6; postdiv2 = 4; refdiv = 1;
2690 break;
2691 default:
2692 printf("%s: %d Hz\n", __func__, freq);
2693 return -1;
2694 }
2695
2696 /* Calculate feedback divider. */
2697 fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
2698
2699 /*
2700 * Select slow mode to guarantee a stable clock while we're
2701 * adjusting the PLL.
2702 */
2703 HWRITE4(sc, base + 0x000c,
2704 RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
2705 RK3399_CRU_PLL_PLL_WORK_MODE_SLOW);
2706
2707 /* Set PLL rate. */
2708 HWRITE4(sc, base + 0x0000,
2709 RK3399_CRU_PLL_FBDIV_MASK << 16 |
2710 fbdiv << RK3399_CRU_PLL_FBDIV_SHIFT);
2711 HWRITE4(sc, base + 0x0004,
2712 RK3399_CRU_PLL_POSTDIV2_MASK << 16 |
2713 postdiv2 << RK3399_CRU_PLL_POSTDIV2_SHIFT |
2714 RK3399_CRU_PLL_POSTDIV1_MASK << 16 |
2715 postdiv1 << RK3399_CRU_PLL_POSTDIV1_SHIFT |
2716 RK3399_CRU_PLL_REFDIV_MASK << 16 |
2717 refdiv << RK3399_CRU_PLL_REFDIV_SHIFT);
2718
2719 /* Wait for PLL to stabilize. */
2720 while ((HREAD4(sc, base + 0x0008) & RK3399_CRU_PLL_PLL_LOCK) == 0)
2721 delay(10);
2722
2723 /* Switch back to normal mode. */
2724 HWRITE4(sc, base + 0x000c,
2725 RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 |
2726 RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL);
2727
2728 return 0;
2729}
2730
2731uint32_t
2732rk3399_armclk_parent(uint32_t mux)
2733{
2734 switch (mux) {
2735 case 0:
2736 return RK3399_PLL_ALPLL;
2737 case 1:
2738 return RK3399_PLL_ABPLL;
2739 case 2:
2740 return RK3399_PLL_DPLL;
2741 case 3:
2742 return RK3399_PLL_GPLL;
2743 }
2744
2745 return 0;
2746}
2747
2748uint32_t
2749rk3399_get_armclk(struct rkclock_softc *sc, bus_size_t clksel)
2750{
2751 uint32_t reg, mux, div_con;
2752 uint32_t idx;
2753
2754 reg = HREAD4(sc, clksel);
2755 mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
2756 RK3399_CRU_CORE_PLL_SEL_SHIFT;
2757 div_con = (reg & RK3399_CRU_CLK_CORE_DIV_CON_MASK) >>
2758 RK3399_CRU_CLK_CORE_DIV_CON_SHIFT;
2759 idx = rk3399_armclk_parent(mux);
2760
2761 return rk3399_get_frequency(sc, &idx) / (div_con + 1);
2762}
2763
2764int
2765rk3399_set_armclk(struct rkclock_softc *sc, bus_size_t clksel, uint32_t freq)
2766{
2767 uint32_t reg, mux;
2768 uint32_t old_freq, div;
2769 uint32_t idx;
2770
2771 old_freq = rk3399_get_armclk(sc, clksel);
2772 if (freq == old_freq)
2773 return 0;
2774
2775 reg = HREAD4(sc, clksel);
2776 mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >>
2777 RK3399_CRU_CORE_PLL_SEL_SHIFT;
2778 idx = rk3399_armclk_parent(mux);
2779
2780 /* Keep the atclk_core and pclk_dbg clocks at or below 200 MHz. */
2781 div = 1;
2782 while (freq / (div + 1) > 200000000)
2783 div++;
2784
2785 /* When ramping up, set clock dividers first. */
2786 if (freq > old_freq) {
2787 HWRITE4(sc, clksel,
2788 RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
2789 0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
2790 RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
2791 1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
2792 HWRITE4(sc, clksel + 0x0004,
2793 RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
2794 div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
2795 RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
2796 div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
2797 }
2798
2799 rk3399_set_frequency(sc, &idx, freq);
2800
2801 /* When ramping down, set clock dividers last. */
2802 if (freq < old_freq) {
2803 HWRITE4(sc, clksel,
2804 RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 |
2805 0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT |
2806 RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 |
2807 1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT);
2808 HWRITE4(sc, clksel + 0x0004,
2809 RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 |
2810 div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT |
2811 RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 |
2812 div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT);
2813 }
2814
2815 return 0;
2816}
2817
2818uint32_t
2819rk3399_get_frac(struct rkclock_softc *sc, uint32_t parent, bus_size_t base)
2820{
2821 uint32_t parent_freq, frac;
2822 uint16_t n, d;
2823
2824 frac = HREAD4(sc, base);
2825 n = frac >> 16;
2826 d = frac & 0xffff;
2827 if (n == 0 || d == 0)
2828 n = d = 1;
2829 parent_freq = sc->sc_cd.cd_get_frequency(sc, &parent);
2830 return ((uint64_t)parent_freq * n) / d;
2831}
2832
2833int
2834rk3399_set_frac(struct rkclock_softc *sc, uint32_t parent, bus_size_t base,
2835 uint32_t freq)
2836{
2837 uint32_t n, d;
2838 uint32_t p0, p1, p2;
2839 uint32_t q0, q1, q2;
2840 uint32_t a, tmp;
2841
2842 n = freq;
2843 d = sc->sc_cd.cd_get_frequency(sc, &parent);
2844
2845 /*
2846 * The denominator needs to be at least 20 times the numerator
2847 * for a stable clock.
2848 */
2849 if (n == 0 || d == 0 || d < 20 * n)
2850 return -1;
2851
2852 /*
2853 * This is a simplified implementation of the algorithm to
2854 * calculate the best rational approximation using continued
2855 * fractions.
2856 */
2857
2858 p0 = q1 = 0;
2859 p1 = q0 = 1;
2860
2861 while (d != 0) {
2862 /*
2863 * Calculate next coefficient in the continued
2864 * fraction and keep track of the remainder.
2865 */
2866 tmp = d;
2867 a = n / d;
2868 d = n % d;
2869 n = tmp;
2870
2871 /*
2872 * Calculate next approximation in the series based on
2873 * the current coefficient.
2874 */
2875 p2 = p0 + a * p1;
2876 q2 = q0 + a * q1;
2877
2878 /*
2879 * Terminate if we reached the maximum allowed
2880 * denominator.
2881 */
2882 if (q2 > 0xffff)
2883 break;
2884
2885 p0 = p1; p1 = p2;
2886 q0 = q1; q1 = q2;
2887 }
2888
2889 HWRITE4(sc, base, p1 << 16 | q1);
2890 return 0;
2891}
2892
2893uint32_t
2894rk3399_get_frequency(void *cookie, uint32_t *cells)
2895{
2896 struct rkclock_softc *sc = cookie;
2897 uint32_t idx = cells[0];
2898
2899 switch (idx) {
2900 case RK3399_PLL_ALPLL:
2901 return rk3399_get_pll(sc, RK3399_CRU_LPLL_CON(0));
2902 case RK3399_PLL_ABPLL:
2903 return rk3399_get_pll(sc, RK3399_CRU_BPLL_CON(0));
2904 case RK3399_PLL_DPLL:
2905 return rk3399_get_pll(sc, RK3399_CRU_DPLL_CON(0));
2906 case RK3399_PLL_CPLL:
2907 return rk3399_get_pll(sc, RK3399_CRU_CPLL_CON(0));
2908 case RK3399_PLL_GPLL:
2909 return rk3399_get_pll(sc, RK3399_CRU_GPLL_CON(0));
2910 case RK3399_PLL_NPLL:
2911 return rk3399_get_pll(sc, RK3399_CRU_NPLL_CON(0));
2912 case RK3399_PLL_VPLL:
2913 return rk3399_get_pll(sc, RK3399_CRU_VPLL_CON(0));
2914 case RK3399_ARMCLKL:
2915 return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(0));
2916 case RK3399_ARMCLKB:
2917 return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(2));
2918 case RK3399_XIN24M:
2919 return 24000000;
2920 case RK3399_CLK_32K:
2921 return 32768;
2922 case RK3399_XIN12M:
2923 return 12000000;
2924 case RK3399_CLK_I2S0_FRAC:
2925 return rk3399_get_frac(sc, RK3399_CLK_I2S0_DIV,
2926 RK3399_CRU_CLKSEL_CON(96));
2927 case RK3399_CLK_I2S1_FRAC:
2928 return rk3399_get_frac(sc, RK3399_CLK_I2S1_DIV,
2929 RK3399_CRU_CLKSEL_CON(97));
2930 case RK3399_CLK_I2S2_FRAC:
2931 return rk3399_get_frac(sc, RK3399_CLK_I2S2_DIV,
2932 RK3399_CRU_CLKSEL_CON(98));
2933 default:
2934 break;
2935 }
2936
2937 return rkclock_get_frequency(sc, idx);
2938}
2939
2940int
2941rk3399_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
2942{
2943 struct rkclock_softc *sc = cookie;
2944 uint32_t idx = cells[0];
2945
2946 switch (idx) {
2947 case RK3399_PLL_ALPLL:
2948 return rk3399_set_pll(sc, RK3399_CRU_LPLL_CON(0), freq);
2949 case RK3399_PLL_ABPLL:
2950 return rk3399_set_pll(sc, RK3399_CRU_BPLL_CON(0), freq);
2951 case RK3399_PLL_CPLL:
2952 return rk3399_set_pll(sc, RK3399_CRU_CPLL_CON(0), freq);
2953 case RK3399_PLL_GPLL:
2954 return rk3399_set_pll(sc, RK3399_CRU_GPLL_CON(0), freq);
2955 case RK3399_PLL_NPLL:
2956 return rk3399_set_pll(sc, RK3399_CRU_NPLL_CON(0), freq);
2957 case RK3399_PLL_VPLL:
2958 return rk3399_set_pll(sc, RK3399_CRU_VPLL_CON(0), freq);
2959 case RK3399_ARMCLKL:
2960 return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(0), freq);
2961 case RK3399_ARMCLKB:
2962 return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(2), freq);
2963 case RK3399_CLK_I2S0_8CH:
2964 rkclock_set_parent(sc, idx, RK3399_CLK_I2S0_FRAC);
2965 return rkclock_set_frequency(sc, idx, freq);
2966 case RK3399_CLK_I2S1_8CH:
2967 rkclock_set_parent(sc, idx, RK3399_CLK_I2S1_FRAC);
2968 return rkclock_set_frequency(sc, idx, freq);
2969 case RK3399_CLK_I2S2_8CH:
2970 rkclock_set_parent(sc, idx, RK3399_CLK_I2S2_FRAC);
2971 return rkclock_set_frequency(sc, idx, freq);
2972 case RK3399_XIN12M:
2973 if (freq / (1000 * 1000) != 12)
2974 return -1;
2975 return 0;
2976 case RK3399_CLK_I2S0_FRAC:
2977 return rk3399_set_frac(sc, RK3399_CLK_I2S0_DIV,
2978 RK3399_CRU_CLKSEL_CON(96), freq);
2979 case RK3399_CLK_I2S1_FRAC:
2980 return rk3399_set_frac(sc, RK3399_CLK_I2S1_DIV,
2981 RK3399_CRU_CLKSEL_CON(97), freq);
2982 case RK3399_CLK_I2S2_FRAC:
2983 return rk3399_set_frac(sc, RK3399_CLK_I2S2_DIV,
2984 RK3399_CRU_CLKSEL_CON(98), freq);
2985 default:
2986 break;
2987 }
2988
2989 return rkclock_set_frequency(sc, idx, freq);
2990}
2991
2992
2993int
2994rk3399_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
2995{
2996 struct rkclock_softc *sc = cookie;
2997
2998 if (pcells[0] != sc->sc_phandle)
2999 return -1;
3000
3001 return rkclock_set_parent(sc, cells[0], pcells[1]);
3002}
3003
3004void
3005rk3399_enable(void *cookie, uint32_t *cells, int on)
3006{
3007 struct rkclock_softc *sc = cookie;
3008 uint32_t idx = cells[0];
3009
3010 /*
3011 * All clocks are enabled upon hardware reset, but on some boards the
3012 * firmware will disable some of them. Handle those here.
3013 */
3014 if (!on) {
3015 printf("%s: 0x%08x\n", __func__, idx);
3016 return;
3017 }
3018
3019 switch (idx) {
3020 case RK3399_CLK_USB2PHY0_REF:
3021 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(6), (1 << 5) << 16);
3022 break;
3023 case RK3399_CLK_USB2PHY1_REF:
3024 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(6), (1 << 6) << 16);
3025 break;
3026 case RK3399_CLK_UPHY0_TCPDPHY_REF:
3027 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (1 << 4) << 16);
3028 break;
3029 case RK3399_CLK_UPHY0_TCPDCORE:
3030 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (1 << 5) << 16);
3031 break;
3032 case RK3399_CLK_UPHY1_TCPDPHY_REF:
3033 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (1 << 6) << 16);
3034 break;
3035 case RK3399_CLK_UPHY1_TCPDCORE:
3036 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (1 << 7) << 16);
3037 break;
3038 case RK3399_ACLK_GMAC:
3039 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(32), (1 << 0) << 16);
3040 break;
3041 case RK3399_PCLK_GMAC:
3042 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(32), (1 << 2) << 16);
3043 break;
3044 case RK3399_CLK_MAC:
3045 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(5), (1 << 5) << 16);
3046 break;
3047 case RK3399_CLK_MAC_RX:
3048 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(5), (1 << 8) << 16);
3049 break;
3050 case RK3399_CLK_MAC_TX:
3051 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(5), (1 << 9) << 16);
3052 break;
3053 }
3054}
3055
3056void
3057rk3399_reset(void *cookie, uint32_t *cells, int on)
3058{
3059 struct rkclock_softc *sc = cookie;
3060 uint32_t idx = cells[0];
3061 uint32_t mask = (1 << (idx % 16));
3062
3063 HWRITE4(sc, RK3399_CRU_SOFTRST_CON(idx / 16),
3064 mask << 16 | (on ? mask : 0));
3065}
3066
3067/* PMUCRU */
3068
3069const struct rkclock rk3399_pmu_clocks[] = {
3070 {
3071 RK3399_CLK_I2C0, RK3399_PMUCRU_CLKSEL_CON(2),
3072 0, DIV(6, 0),
3073 { RK3399_PLL_PPLL }
3074 },
3075 {
3076 RK3399_CLK_I2C4, RK3399_PMUCRU_CLKSEL_CON(3),
3077 0, DIV(6, 0),
3078 { RK3399_PLL_PPLL }
3079 },
3080 {
3081 RK3399_CLK_I2C8, RK3399_PMUCRU_CLKSEL_CON(2),
3082 0, DIV(14, 8),
3083 { RK3399_PLL_PPLL }
3084 },
3085 {
3086 RK3399_PCLK_RKPWM, RK3399_PMUCRU_CLKSEL_CON(0),
3087 0, DIV(6, 0),
3088 { RK3399_PLL_PPLL }
3089 },
3090 {
3091 /* Sentinel */
3092 }
3093};
3094
3095void
3096rk3399_pmu_init(struct rkclock_softc *sc)
3097{
3098 sc->sc_clocks = rk3399_pmu_clocks;
3099 rk3399_pmucru_sc = sc;
3100}
3101
3102uint32_t
3103rk3399_pmu_get_frequency(void *cookie, uint32_t *cells)
3104{
3105 struct rkclock_softc *sc = cookie;
3106 uint32_t idx = cells[0];
3107
3108 switch (idx) {
3109 case RK3399_PLL_PPLL:
3110 return rk3399_get_pll(sc, RK3399_PMUCRU_PPLL_CON(0));
3111 default:
3112 break;
3113 }
3114
3115 return rkclock_get_frequency(sc, idx);
3116}
3117
3118int
3119rk3399_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
3120{
3121 struct rkclock_softc *sc = cookie;
3122 uint32_t idx = cells[0];
3123
3124 switch (idx) {
3125 case RK3399_PLL_PPLL:
3126 return rk3399_set_pll(sc, RK3399_PMUCRU_PPLL_CON(0), freq);
3127 default:
3128 break;
3129 }
3130
3131 return rkclock_set_frequency(sc, idx, freq);
3132}
3133
3134void
3135rk3399_pmu_enable(void *cookie, uint32_t *cells, int on)
3136{
3137 uint32_t idx = cells[0];
3138
3139 switch (idx) {
3140 case RK3399_CLK_I2C0:
3141 case RK3399_CLK_I2C4:
3142 case RK3399_CLK_I2C8:
3143 case RK3399_PCLK_I2C0:
3144 case RK3399_PCLK_I2C4:
3145 case RK3399_PCLK_I2C8:
3146 case RK3399_PCLK_RKPWM:
3147 /* Enabled by default. */
3148 break;
3149 default:
3150 printf("%s: 0x%08x\n", __func__, idx);
3151 break;
3152 }
3153}
3154
3155void
3156rk3399_pmu_reset(void *cookie, uint32_t *cells, int on)
3157{
3158 uint32_t idx = cells[0];
3159
3160 printf("%s: 0x%08x\n", __func__, idx);
3161}
3162
3163/*
3164 * Rockchip RK3528
3165 */
3166
3167const struct rkclock rk3528_clocks[] = {
3168 {
3169 RK3528_CLK_MATRIX_50M_SRC, RK3528_CRU_CLKSEL_CON(0),
3170 0, DIV(6, 2),
3171 { RK3528_PLL_CPLL }
3172 },
3173 {
3174 RK3528_CLK_MATRIX_100M_SRC, RK3528_CRU_CLKSEL_CON(0),
3175 0, DIV(11, 7),
3176 { RK3528_PLL_CPLL }
3177 },
3178 {
3179 RK3528_CLK_MATRIX_200M_SRC, RK3528_CRU_CLKSEL_CON(1),
3180 0, DIV(9, 5),
3181 { RK3528_PLL_GPLL }
3182 },
3183 {
3184 RK3528_CLK_PWM0, RK3528_CRU_CLKSEL_CON(44),
3185 SEL(7, 6), 0,
3186 { RK3528_CLK_MATRIX_100M_SRC, RK3528_CLK_MATRIX_50M_SRC,
3187 RK3528_XIN24M }
3188 },
3189 {
3190 RK3528_CLK_PWM1, RK3528_CRU_CLKSEL_CON(44),
3191 SEL(9, 8), 0,
3192 { RK3528_CLK_MATRIX_100M_SRC, RK3528_CLK_MATRIX_50M_SRC,
3193 RK3528_XIN24M }
3194 },
3195 {
3196 RK3528_CLK_PPLL_125M_MATRIX, RK3528_CRU_CLKSEL_CON(60),
3197 0, DIV(14, 10),
3198 { RK3528_PLL_PPLL }
3199 },
3200 {
3201 RK3528_CCLK_SRC_EMMC, RK3528_CRU_CLKSEL_CON(62),
3202 SEL(7, 6), DIV(5, 0),
3203 { RK3528_PLL_GPLL, RK3528_PLL_CPLL, RK3528_XIN24M }
3204 },
3205 {
3206 RK3528_BCLK_EMMC, RK3528_CRU_CLKSEL_CON(62),
3207 SEL(9, 8), 0,
3208 { RK3528_CLK_MATRIX_200M_SRC, RK3528_CLK_MATRIX_100M_SRC,
3209 RK3528_CLK_MATRIX_50M_SRC, RK3528_XIN24M }
3210 },
3211 {
3212 RK3528_TCLK_EMMC, 0, 0, 0,
3213 { RK3528_XIN24M }
3214 },
3215 {
3216 RK3528_CLK_GMAC1_SRC_VPU, 0, 0, 0,
3217 { RK3528_CLK_PPLL_125M_MATRIX }
3218 },
3219 {
3220 RK3528_CLK_I2C1, RK3528_CRU_CLKSEL_CON(79),
3221 SEL(10, 9), 0,
3222 { RK3528_CLK_MATRIX_200M_SRC, RK3528_CLK_MATRIX_100M_SRC,
3223 RK3528_CLK_MATRIX_50M_SRC, RK3528_XIN24M }
3224 },
3225 {
3226 RK3528_CCLK_SRC_SDMMC0, RK3528_CRU_CLKSEL_CON(85),
3227 SEL(7, 6), DIV(5, 0),
3228 { RK3528_PLL_GPLL, RK3528_PLL_CPLL, RK3528_XIN24M }
3229 },
3230 {
3231 /* Sentinel */
3232 }
3233};
3234
3235void
3236rk3528_init(struct rkclock_softc *sc)
3237{
3238 int i;
3239
3240 /* The code below assumes all clocks are enabled. Check this!. */
3241 for (i = 0; i <= 46; i++) {
3242 if (HREAD4(sc, RK3528_CRU_GATE_CON(i)) != 0x00000000) {
3243 printf("CRU_GATE_CON%d: 0x%08x\n", i,
3244 HREAD4(sc, RK3528_CRU_GATE_CON(i)));
3245 }
3246 }
3247
3248 sc->sc_clocks = rk3528_clocks;
3249}
3250
3251uint32_t
3252rk3528_get_frequency(void *cookie, uint32_t *cells)
3253{
3254 struct rkclock_softc *sc = cookie;
3255 uint32_t idx = cells[0];
3256
3257 switch (idx) {
3258 case RK3528_PLL_CPLL:
3259 return rk3328_get_pll(sc, RK3528_CRU_PLL_CON(8));
3260 case RK3528_PLL_GPLL:
3261 return rk3328_get_pll(sc, RK3528_CRU_PLL_CON(24));
3262 case RK3528_PLL_PPLL:
3263 return rk3328_get_pll(sc, RK3528_PCIE_CRU_PLL_CON(32));
3264 case RK3528_XIN24M:
3265 return 24000000;
3266 default:
3267 break;
3268 }
3269
3270 return rkclock_get_frequency(sc, idx);
3271}
3272
3273int
3274rk3528_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
3275{
3276 struct rkclock_softc *sc = cookie;
3277 uint32_t idx = cells[0];
3278
3279 return rkclock_set_frequency(sc, idx, freq);
3280}
3281
3282int
3283rk3528_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
3284{
3285 struct rkclock_softc *sc = cookie;
3286
3287 return rkclock_set_parent(sc, cells[0], pcells[1]);
3288}
3289
3290void
3291rk3528_enable(void *cookie, uint32_t *cells, int on)
3292{
3293 uint32_t idx = cells[0];
3294
3295 /* All clocks are enabled upon hardware reset. */
3296 if (!on) {
3297 printf("%s: 0x%08x\n", __func__, idx);
3298 return;
3299 }
3300}
3301
3302void
3303rk3528_reset(void *cookie, uint32_t *cells, int on)
3304{
3305 struct rkclock_softc *sc = cookie;
3306 uint32_t idx = cells[0];
3307 uint32_t bit, mask, reg;
3308
3309 switch (idx) {
3310 case RK3528_SRST_C_EMMC:
3311 reg = RK3528_CRU_SOFTRST_CON(25);
3312 bit = 15;
3313 break;
3314 case RK3528_SRST_H_EMMC:
3315 reg = RK3528_CRU_SOFTRST_CON(26);
3316 bit = 0;
3317 break;
3318 case RK3528_SRST_A_EMMC:
3319 reg = RK3528_CRU_SOFTRST_CON(26);
3320 bit = 1;
3321 break;
3322 case RK3528_SRST_B_EMMC:
3323 reg = RK3528_CRU_SOFTRST_CON(26);
3324 bit = 2;
3325 break;
3326 case RK3528_SRST_T_EMMC:
3327 reg = RK3528_CRU_SOFTRST_CON(26);
3328 bit = 3;
3329 break;
3330 case RK3528_SRST_A_MAC:
3331 reg = RK3528_CRU_SOFTRST_CON(28);
3332 bit = 5;
3333 break;
3334 case RK3528_SRST_H_SDMMC0:
3335 reg = RK3528_CRU_SOFTRST_CON(42);
3336 bit = 9;
3337 break;
3338 default:
3339 printf("%s: 0x%08x\n", __func__, idx);
3340 return;
3341 }
3342
3343 mask = (1 << bit);
3344 HWRITE4(sc, reg, mask << 16 | (on ? mask : 0));
3345}
3346
3347/*
3348 * Rockchip RK3568
3349 */
3350
3351const struct rkclock rk3568_clocks[] = {
3352 {
3353 RK3568_BCLK_EMMC, RK3568_CRU_CLKSEL_CON(28),
3354 SEL(9, 8), 0,
3355 { RK3568_GPLL_200M, RK3568_GPLL_150M, RK3568_CPLL_125M }
3356 },
3357 {
3358 RK3568_CCLK_EMMC, RK3568_CRU_CLKSEL_CON(28),
3359 SEL(14, 12), 0,
3360 { RK3568_XIN24M, RK3568_GPLL_200M, RK3568_GPLL_150M,
3361 RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_375K }
3362 },
3363 {
3364 RK3568_TCLK_EMMC, 0, 0, 0,
3365 { RK3568_XIN24M }
3366 },
3367
3368 {
3369 RK3568_ACLK_PHP, RK3568_CRU_CLKSEL_CON(30),
3370 SEL(1, 0), 0,
3371 { RK3568_GPLL_300M, RK3568_GPLL_200M,
3372 RK3568_GPLL_100M, RK3568_XIN24M }
3373 },
3374 {
3375 RK3568_PCLK_PHP, RK3568_CRU_CLKSEL_CON(30),
3376 0, DIV(7, 4),
3377 { RK3568_ACLK_PHP }
3378 },
3379 {
3380 RK3568_CLK_SDMMC0, RK3568_CRU_CLKSEL_CON(30),
3381 SEL(10, 8), 0,
3382 { RK3568_XIN24M, RK3568_GPLL_400M, RK3568_GPLL_300M,
3383 RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_750K }
3384 },
3385 {
3386 RK3568_CLK_SDMMC1, RK3568_CRU_CLKSEL_CON(30),
3387 SEL(14, 12), 0,
3388 { RK3568_XIN24M, RK3568_GPLL_400M, RK3568_GPLL_300M,
3389 RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_750K }
3390 },
3391 {
3392 RK3568_CLK_SDMMC2, RK3568_CRU_CLKSEL_CON(32),
3393 SEL(10, 8), 0,
3394 { RK3568_XIN24M, RK3568_GPLL_400M, RK3568_GPLL_300M,
3395 RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_750K }
3396 },
3397 {
3398 RK3568_ACLK_GMAC0, 0, 0, 0,
3399 { RK3568_ACLK_PHP }
3400 },
3401 {
3402 RK3568_PCLK_GMAC0, 0, 0, 0,
3403 { RK3568_PCLK_PHP }
3404 },
3405 {
3406 RK3568_CLK_MAC0_2TOP, RK3568_CRU_CLKSEL_CON(31),
3407 SEL(9, 8), 0,
3408 { RK3568_CPLL_125M, RK3568_CPLL_50M,
3409 RK3568_CPLL_25M, RK3568_XIN24M }
3410 },
3411 {
3412 RK3568_CLK_MAC0_REFOUT, 0, 0, 0,
3413 { RK3568_CLK_MAC0_2TOP }
3414 },
3415 {
3416 RK3568_CLK_GMAC0_PTP_REF, RK3568_CRU_CLKSEL_CON(31),
3417 SEL(13, 12), 0,
3418 { RK3568_CPLL_62P5M, RK3568_GPLL_100M,
3419 RK3568_CPLL_50M, RK3568_XIN24M }
3420 },
3421 {
3422 RK3568_ACLK_USB, RK3568_CRU_CLKSEL_CON(32),
3423 SEL(1, 0), 0,
3424 { RK3568_GPLL_300M, RK3568_GPLL_200M,
3425 RK3568_GPLL_100M, RK3568_XIN24M }
3426 },
3427 {
3428 RK3568_PCLK_USB, RK3568_CRU_CLKSEL_CON(32),
3429 0, DIV(7, 4),
3430 { RK3568_ACLK_USB }
3431 },
3432 {
3433 RK3568_ACLK_GMAC1, 0, 0, 0,
3434 { RK3568_ACLK_USB }
3435 },
3436 {
3437 RK3568_PCLK_GMAC1, 0, 0, 0,
3438 { RK3568_PCLK_USB }
3439 },
3440 {
3441 RK3568_CLK_MAC1_2TOP, RK3568_CRU_CLKSEL_CON(33),
3442 SEL(9, 8), 0,
3443 { RK3568_CPLL_125M, RK3568_CPLL_50M,
3444 RK3568_CPLL_25M, RK3568_XIN24M }
3445 },
3446 {
3447 RK3568_CLK_MAC1_REFOUT, 0, 0, 0,
3448 { RK3568_CLK_MAC1_2TOP }
3449 },
3450 {
3451 RK3568_CLK_GMAC1_PTP_REF, RK3568_CRU_CLKSEL_CON(33),
3452 SEL(13, 12), 0,
3453 { RK3568_CPLL_62P5M, RK3568_GPLL_100M,
3454 RK3568_CPLL_50M, RK3568_XIN24M }
3455 },
3456 {
3457 RK3568_CLK_TSADC_TSEN, RK3568_CRU_CLKSEL_CON(51),
3458 SEL(5, 4), DIV(2, 0),
3459 { RK3568_XIN24M, RK3568_GPLL_100M, RK3568_CPLL_100M }
3460 },
3461 {
3462 RK3568_CLK_TSADC, RK3568_CRU_CLKSEL_CON(51),
3463 0, DIV(14, 8),
3464 { RK3568_CLK_TSADC_TSEN }
3465 },
3466 {
3467 RK3568_SCLK_UART1, RK3568_CRU_CLKSEL_CON(52),
3468 SEL(13, 12), 0,
3469 { 0, 0, RK3568_XIN24M }
3470 },
3471 {
3472 RK3568_SCLK_UART2, RK3568_CRU_CLKSEL_CON(54),
3473 SEL(13, 12), 0,
3474 { 0, 0, RK3568_XIN24M }
3475 },
3476 {
3477 RK3568_SCLK_UART3, RK3568_CRU_CLKSEL_CON(56),
3478 SEL(13, 12), 0,
3479 { 0, 0, RK3568_XIN24M }
3480 },
3481 {
3482 RK3568_SCLK_UART4, RK3568_CRU_CLKSEL_CON(58),
3483 SEL(13, 12), 0,
3484 { 0, 0, RK3568_XIN24M }
3485 },
3486 {
3487 RK3568_SCLK_UART5, RK3568_CRU_CLKSEL_CON(60),
3488 SEL(13, 12), 0,
3489 { 0, 0, RK3568_XIN24M }
3490 },
3491 {
3492 RK3568_SCLK_UART6, RK3568_CRU_CLKSEL_CON(62),
3493 SEL(13, 12), 0,
3494 { 0, 0, RK3568_XIN24M }
3495 },
3496 {
3497 RK3568_SCLK_UART7, RK3568_CRU_CLKSEL_CON(64),
3498 SEL(13, 12), 0,
3499 { 0, 0, RK3568_XIN24M }
3500 },
3501 {
3502 RK3568_SCLK_UART8, RK3568_CRU_CLKSEL_CON(66),
3503 SEL(13, 12), 0,
3504 { 0, 0, RK3568_XIN24M }
3505 },
3506 {
3507 RK3568_SCLK_UART9, RK3568_CRU_CLKSEL_CON(68),
3508 SEL(13, 12), 0,
3509 { 0, 0, RK3568_XIN24M }
3510 },
3511 {
3512 RK3568_CLK_I2C, RK3568_CRU_CLKSEL_CON(71),
3513 SEL(9, 8), 0,
3514 { 0, 0, RK3568_XIN24M }
3515 },
3516 {
3517 RK3568_CLK_I2C1, 0, 0, 0,
3518 { RK3568_CLK_I2C }
3519 },
3520 {
3521 RK3568_CLK_I2C2, 0, 0, 0,
3522 { RK3568_CLK_I2C }
3523 },
3524 {
3525 RK3568_CLK_I2C3, 0, 0, 0,
3526 { RK3568_CLK_I2C }
3527 },
3528 {
3529 RK3568_CLK_I2C4, 0, 0, 0,
3530 { RK3568_CLK_I2C }
3531 },
3532 {
3533 RK3568_CLK_I2C5, 0, 0, 0,
3534 { RK3568_CLK_I2C }
3535 },
3536 {
3537 RK3568_CLK_SPI0, RK3568_CRU_CLKSEL_CON(72),
3538 SEL(1, 0), 0,
3539 { RK3568_GPLL_200M, RK3568_XIN24M, RK3568_CPLL_100M }
3540 },
3541 {
3542 RK3568_CLK_SPI1, RK3568_CRU_CLKSEL_CON(72),
3543 SEL(3, 2), 0,
3544 { RK3568_GPLL_200M, RK3568_XIN24M, RK3568_CPLL_100M }
3545 },
3546 {
3547 RK3568_CLK_SPI2, RK3568_CRU_CLKSEL_CON(72),
3548 SEL(5, 4), 0,
3549 { RK3568_GPLL_200M, RK3568_XIN24M, RK3568_CPLL_100M }
3550 },
3551 {
3552 RK3568_CLK_SPI3, RK3568_CRU_CLKSEL_CON(72),
3553 SEL(7, 6), 0,
3554 { RK3568_GPLL_200M, RK3568_XIN24M, RK3568_CPLL_100M }
3555 },
3556 {
3557 RK3568_SCLK_GMAC0, RK3568_CRU_CLKSEL_CON(31),
3558 SEL(2, 2), 0,
3559 { RK3568_CLK_MAC0_2TOP, RK3568_GMAC0_CLKIN }
3560 },
3561 {
3562 RK3568_SCLK_GMAC0_RGMII_SPEED, RK3568_CRU_CLKSEL_CON(31),
3563 SEL(5, 4), 0,
3564 { RK3568_SCLK_GMAC0, RK3568_SCLK_GMAC0,
3565 RK3568_SCLK_GMAC0_DIV_50, RK3568_SCLK_GMAC0_DIV_5 }
3566 },
3567 {
3568 RK3568_SCLK_GMAC0_RMII_SPEED, RK3568_CRU_CLKSEL_CON(31),
3569 SEL(3, 3), 0,
3570 { RK3568_SCLK_GMAC0_DIV_20, RK3568_SCLK_GMAC0_DIV_2 }
3571 },
3572 {
3573 RK3568_SCLK_GMAC0_RX_TX, RK3568_CRU_CLKSEL_CON(31),
3574 SEL(1, 0), 0,
3575 { RK3568_SCLK_GMAC0_RGMII_SPEED, RK3568_SCLK_GMAC0_RMII_SPEED }
3576 },
3577 {
3578 RK3568_SCLK_GMAC1, RK3568_CRU_CLKSEL_CON(33),
3579 SEL(2, 2), 0,
3580 { RK3568_CLK_MAC1_2TOP, RK3568_GMAC1_CLKIN }
3581 },
3582 {
3583 RK3568_SCLK_GMAC1_RGMII_SPEED, RK3568_CRU_CLKSEL_CON(33),
3584 SEL(5, 4), 0,
3585 { RK3568_SCLK_GMAC1, RK3568_SCLK_GMAC1,
3586 RK3568_SCLK_GMAC1_DIV_50, RK3568_SCLK_GMAC1_DIV_5 }
3587 },
3588 {
3589 RK3568_SCLK_GMAC1_RMII_SPEED, RK3568_CRU_CLKSEL_CON(33),
3590 SEL(3, 3), 0,
3591 { RK3568_SCLK_GMAC1_DIV_20, RK3568_SCLK_GMAC1_DIV_2 }
3592 },
3593 {
3594 RK3568_SCLK_GMAC1_RX_TX, RK3568_CRU_CLKSEL_CON(33),
3595 SEL(1, 0), 0,
3596 { RK3568_SCLK_GMAC1_RGMII_SPEED, RK3568_SCLK_GMAC1_RMII_SPEED }
3597 },
3598 {
3599 RK3568_CPLL_125M, RK3568_CRU_CLKSEL_CON(80),
3600 0, DIV(4, 0),
3601 { RK3568_PLL_CPLL }
3602 },
3603 {
3604 RK3568_CPLL_62P5M, RK3568_CRU_CLKSEL_CON(80),
3605 0, DIV(12, 8),
3606 { RK3568_PLL_CPLL }
3607 },
3608 {
3609 RK3568_CPLL_50M, RK3568_CRU_CLKSEL_CON(81),
3610 0, DIV(4, 0),
3611 { RK3568_PLL_CPLL }
3612 },
3613 {
3614 RK3568_CPLL_25M, RK3568_CRU_CLKSEL_CON(81),
3615 0, DIV(13, 8),
3616 { RK3568_PLL_CPLL }
3617 },
3618 {
3619 RK3568_CPLL_100M, RK3568_CRU_CLKSEL_CON(82),
3620 0, DIV(4, 0),
3621 { RK3568_PLL_CPLL }
3622 },
3623 {
3624 RK3568_GPLL_400M, RK3568_CRU_CLKSEL_CON(75),
3625 0, DIV(4, 0),
3626 { RK3568_PLL_GPLL }
3627 },
3628 {
3629 RK3568_GPLL_300M, RK3568_CRU_CLKSEL_CON(75),
3630 0, DIV(12, 8),
3631 { RK3568_PLL_GPLL }
3632 },
3633 {
3634 RK3568_GPLL_200M, RK3568_CRU_CLKSEL_CON(76),
3635 0, DIV(4, 0),
3636 { RK3568_PLL_GPLL }
3637 },
3638 {
3639 RK3568_GPLL_150M, RK3568_CRU_CLKSEL_CON(76),
3640 0, DIV(12, 5),
3641 { RK3568_PLL_GPLL }
3642 },
3643 {
3644 RK3568_GPLL_100M, RK3568_CRU_CLKSEL_CON(77),
3645 0, DIV(4, 0),
3646 { RK3568_PLL_GPLL }
3647 },
3648 {
3649 RK3568_CLK_OSC0_DIV_750K, RK3568_CRU_CLKSEL_CON(82),
3650 0, DIV(13, 8),
3651 { RK3568_XIN24M }
3652 },
3653 {
3654 /* Sentinel */
3655 }
3656};
3657
3658void
3659rk3568_init(struct rkclock_softc *sc)
3660{
3661 int i;
3662
3663 /* The code below assumes all clocks are enabled. Check this!. */
3664 for (i = 0; i <= 35; i++) {
3665 if (HREAD4(sc, RK3568_CRU_GATE_CON(i)) != 0x00000000) {
3666 printf("CRU_GATE_CON%d: 0x%08x\n", i,
3667 HREAD4(sc, RK3568_CRU_GATE_CON(i)));
3668 }
3669 }
3670
3671 sc->sc_clocks = rk3568_clocks;
3672}
3673
3674int
3675rk3568_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
3676{
3677 uint32_t fbdiv, postdiv1, postdiv2, refdiv;
3678 int mode_shift = -1;
3679
3680 switch (base) {
3681 case RK3568_CRU_APLL_CON(0):
3682 mode_shift = 0;
3683 break;
3684 case RK3568_CRU_DPLL_CON(0):
3685 mode_shift = 2;
3686 break;
3687 case RK3568_CRU_CPLL_CON(0):
3688 mode_shift = 4;
3689 break;
3690 case RK3568_CRU_GPLL_CON(0):
3691 mode_shift = 6;
3692 break;
3693 case RK3568_CRU_NPLL_CON(0):
3694 mode_shift = 10;
3695 break;
3696 case RK3568_CRU_VPLL_CON(0):
3697 mode_shift = 12;
3698 break;
3699 }
3700 KASSERT(mode_shift != -1);
3701
3702 /*
3703 * It is not clear whether all combinations of the clock
3704 * dividers result in a stable clock. Therefore this function
3705 * only supports a limited set of PLL clock rates.
3706 */
3707 switch (freq) {
3708 case 1200000000U:
3709 postdiv1 = 2; postdiv2 = refdiv = 1;
3710 break;
3711 default:
3712 printf("%s: %u Hz\n", __func__, freq);
3713 return -1;
3714 }
3715
3716 /* Calculate feedback divider. */
3717 fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
3718
3719 /*
3720 * Select slow mode to guarantee a stable clock while we're
3721 * adjusting the PLL.
3722 */
3723 HWRITE4(sc, RK3568_CRU_MODE_CON,
3724 (RK3328_CRU_CRU_MODE_MASK << 16 |
3725 RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
3726
3727 /* Set PLL rate. */
3728 HWRITE4(sc, base + 0x0000,
3729 RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
3730 postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
3731 RK3328_CRU_PLL_FBDIV_MASK << 16 |
3732 fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
3733 HWRITE4(sc, base + 0x0004,
3734 RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD |
3735 RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
3736 postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
3737 RK3328_CRU_PLL_REFDIV_MASK << 16 |
3738 refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
3739
3740 /* Wait for PLL to stabilize. */
3741 while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
3742 delay(10);
3743
3744 /* Switch back to normal mode. */
3745 HWRITE4(sc, RK3568_CRU_MODE_CON,
3746 (RK3328_CRU_CRU_MODE_MASK << 16 |
3747 RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
3748
3749 return 0;
3750}
3751
3752uint32_t
3753rk3568_get_frequency(void *cookie, uint32_t *cells)
3754{
3755 struct rkclock_softc *sc = cookie;
3756 uint32_t idx = cells[0];
3757
3758 switch (idx) {
3759 case RK3568_PLL_APLL:
3760 return rk3328_get_pll(sc, RK3568_CRU_APLL_CON(0));
3761 case RK3568_PLL_DPLL:
3762 return rk3328_get_pll(sc, RK3568_CRU_DPLL_CON(0));
3763 case RK3568_PLL_CPLL:
3764 return rk3328_get_pll(sc, RK3568_CRU_CPLL_CON(0));
3765 case RK3568_PLL_GPLL:
3766 return rk3328_get_pll(sc, RK3568_CRU_GPLL_CON(0));
3767 case RK3568_PLL_NPLL:
3768 return rk3328_get_pll(sc, RK3568_CRU_NPLL_CON(0));
3769 case RK3568_PLL_VPLL:
3770 return rk3328_get_pll(sc, RK3568_CRU_VPLL_CON(0));
3771 case RK3568_SCLK_GMAC0_DIV_50:
3772 idx = RK3568_SCLK_GMAC0;
3773 return rk3568_get_frequency(sc, &idx) / 50;
3774 case RK3568_SCLK_GMAC0_DIV_5:
3775 idx = RK3568_SCLK_GMAC0;
3776 return rk3568_get_frequency(sc, &idx) / 5;
3777 case RK3568_SCLK_GMAC0_DIV_20:
3778 idx = RK3568_SCLK_GMAC0;
3779 return rk3568_get_frequency(sc, &idx) / 20;
3780 case RK3568_SCLK_GMAC0_DIV_2:
3781 idx = RK3568_SCLK_GMAC0;
3782 return rk3568_get_frequency(sc, &idx) / 2;
3783 case RK3568_SCLK_GMAC1_DIV_50:
3784 idx = RK3568_SCLK_GMAC1;
3785 return rk3568_get_frequency(sc, &idx) / 50;
3786 case RK3568_SCLK_GMAC1_DIV_5:
3787 idx = RK3568_SCLK_GMAC1;
3788 return rk3568_get_frequency(sc, &idx) / 5;
3789 case RK3568_SCLK_GMAC1_DIV_20:
3790 idx = RK3568_SCLK_GMAC1;
3791 return rk3568_get_frequency(sc, &idx) / 20;
3792 case RK3568_SCLK_GMAC1_DIV_2:
3793 idx = RK3568_SCLK_GMAC1;
3794 return rk3568_get_frequency(sc, &idx) / 2;
3795 case RK3568_CLK_OSC0_DIV_375K:
3796 idx = RK3568_CLK_OSC0_DIV_750K;
3797 return rk3568_get_frequency(sc, &idx) / 2;
3798 case RK3568_GMAC0_CLKIN:
3799 return rkclock_external_frequency("gmac0_clkin");
3800 case RK3568_GMAC1_CLKIN:
3801 return rkclock_external_frequency("gmac1_clkin");
3802 case RK3568_XIN24M:
3803 return 24000000;
3804 default:
3805 break;
3806 }
3807
3808 return rkclock_get_frequency(sc, idx);
3809}
3810
3811int
3812rk3568_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
3813{
3814 struct rkclock_softc *sc = cookie;
3815 uint32_t idx = cells[0];
3816
3817 switch (idx) {
3818 case RK3568_PLL_GPLL:
3819 return rk3568_set_pll(sc, RK3568_CRU_GPLL_CON(0), freq);
3820 default:
3821 break;
3822 }
3823
3824 return rkclock_set_frequency(sc, idx, freq);
3825}
3826
3827int
3828rk3568_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells)
3829{
3830 struct rkclock_softc *sc = cookie;
3831 char buf[64] = {};
3832 int len, node;
3833
3834 if (pcells[0] != sc->sc_phandle) {
3835 node = OF_getnodebyphandle(pcells[0]);
3836 if (node == 0)
3837 return -1;
3838 len = OF_getproplen(node, "clock-output-names");
3839 if (len <= 0 || len > sizeof(buf))
3840 return -1;
3841 OF_getprop(node, "clock-output-names", buf, sizeof(buf));
3842
3843 if (strcmp(buf, "gmac0_clkin") == 0) {
3844 return rkclock_set_parent(sc, cells[0],
3845 RK3568_GMAC0_CLKIN);
3846 }
3847 if (strcmp(buf, "gmac1_clkin") == 0) {
3848 return rkclock_set_parent(sc, cells[0],
3849 RK3568_GMAC1_CLKIN);
3850 }
3851
3852 printf("%s: 0x%08x 0x%08x\n", __func__, cells[0], pcells[0]);
3853 return -1;
3854 }
3855
3856 return rkclock_set_parent(sc, cells[0], pcells[1]);
3857}
3858
3859void
3860rk3568_enable(void *cookie, uint32_t *cells, int on)
3861{
3862 uint32_t idx = cells[0];
3863
3864 /* All clocks are enabled upon hardware reset. */
3865 if (!on) {
3866 printf("%s: 0x%08x\n", __func__, idx);
3867 return;
3868 }
3869}
3870
3871void
3872rk3568_reset(void *cookie, uint32_t *cells, int on)
3873{
3874 struct rkclock_softc *sc = cookie;
3875 uint32_t idx = cells[0];
3876 uint32_t mask = (1 << (idx % 16));
3877
3878 HWRITE4(sc, RK3568_CRU_SOFTRST_CON(idx / 16),
3879 mask << 16 | (on ? mask : 0));
3880}
3881
3882/* PMUCRU */
3883
3884const struct rkclock rk3568_pmu_clocks[] = {
3885 {
3886 RK3568_CLK_RTC_32K, RK3568_PMUCRU_CLKSEL_CON(0),
3887 SEL(7, 6), 0,
3888 { 0, RK3568_XIN32K, RK3568_CLK_RTC32K_FRAC },
3889 SET_PARENT
3890 },
3891 {
3892 RK3568_CLK_I2C0, RK3568_PMUCRU_CLKSEL_CON(3),
3893 0, DIV(15, 7),
3894 { RK3568_CLK_PDPMU }
3895 },
3896 {
3897 RK3568_SCLK_UART0, RK3568_PMUCRU_CLKSEL_CON(4),
3898 SEL(11, 10), 0,
3899 { 0, 0, RK3568_XIN24M }
3900 },
3901 {
3902 RK3568_CLK_PCIEPHY0_OSC0, 0, 0, 0,
3903 { RK3568_XIN24M }
3904 },
3905 {
3906 RK3568_CLK_PCIEPHY0_DIV, RK3568_PMUCRU_CLKSEL_CON(9),
3907 0, DIV(2, 0),
3908 { RK3568_PPLL_PH0 }
3909 },
3910 {
3911 RK3568_CLK_PCIEPHY0_REF, RK3568_PMUCRU_CLKSEL_CON(9),
3912 SEL(3, 3), 0,
3913 { RK3568_CLK_PCIEPHY0_OSC0, RK3568_CLK_PCIEPHY0_DIV },
3914 SET_PARENT
3915 },
3916 {
3917 RK3568_CLK_PCIEPHY1_OSC0, 0, 0, 0,
3918 { RK3568_XIN24M }
3919 },
3920 {
3921 RK3568_CLK_PCIEPHY1_DIV, RK3568_PMUCRU_CLKSEL_CON(9),
3922 0, DIV(6, 4),
3923 { RK3568_PPLL_PH0 }
3924 },
3925 {
3926 RK3568_CLK_PCIEPHY1_REF, RK3568_PMUCRU_CLKSEL_CON(9),
3927 SEL(7, 7), 0,
3928 { RK3568_CLK_PCIEPHY1_OSC0, RK3568_CLK_PCIEPHY1_DIV },
3929 SET_PARENT
3930 },
3931 {
3932 RK3568_CLK_PCIEPHY2_OSC0, 0, 0, 0,
3933 { RK3568_XIN24M }
3934 },
3935 {
3936 RK3568_CLK_PCIEPHY2_DIV, RK3568_PMUCRU_CLKSEL_CON(9),
3937 0, DIV(10, 8),
3938 { RK3568_PPLL_PH0 }
3939 },
3940 {
3941 RK3568_CLK_PCIEPHY2_REF, RK3568_PMUCRU_CLKSEL_CON(9),
3942 SEL(11, 11), 0,
3943 { RK3568_CLK_PCIEPHY2_OSC0, RK3568_CLK_PCIEPHY2_DIV },
3944 SET_PARENT
3945 },
3946 {
3947 RK3568_CLK_PDPMU, RK3568_PMUCRU_CLKSEL_CON(2),
3948 SEL(15, 15), 0,
3949 { RK3568_PLL_PPLL, 0 }
3950 },
3951 {
3952 /* Sentinel */
3953 }
3954};
3955
3956void
3957rk3568_pmu_init(struct rkclock_softc *sc)
3958{
3959 int i;
3960
3961 /* The code below assumes all clocks are enabled. Check this!. */
3962 for (i = 0; i <= 2; i++) {
3963 if (HREAD4(sc, RK3568_PMUCRU_GATE_CON(i)) != 0x00000000) {
3964 printf("CRU_GATE_CON%d: 0x%08x\n", i,
3965 HREAD4(sc, RK3568_CRU_GATE_CON(i)));
3966 }
3967 }
3968
3969 sc->sc_clocks = rk3568_pmu_clocks;
3970}
3971
3972int
3973rk3568_pmu_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
3974{
3975 uint32_t fbdiv, postdiv1, postdiv2, refdiv;
3976 int mode_shift = -1;
3977
3978 switch (base) {
3979 case RK3568_PMUCRU_PPLL_CON(0):
3980 mode_shift = 0;
3981 break;
3982 case RK3568_PMUCRU_HPLL_CON(0):
3983 mode_shift = 2;
3984 break;
3985 }
3986 KASSERT(mode_shift != -1);
3987
3988 /*
3989 * It is not clear whether all combinations of the clock
3990 * dividers result in a stable clock. Therefore this function
3991 * only supports a limited set of PLL clock rates.
3992 */
3993 switch (freq) {
3994 case 200000000U:
3995 postdiv1 = 3; postdiv2 = 4; refdiv = 1;
3996 break;
3997 default:
3998 printf("%s: %u Hz\n", __func__, freq);
3999 return -1;
4000 }
4001
4002 /* Calculate feedback divider. */
4003 fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000;
4004
4005 /*
4006 * Select slow mode to guarantee a stable clock while we're
4007 * adjusting the PLL.
4008 */
4009 HWRITE4(sc, RK3568_PMUCRU_MODE_CON,
4010 (RK3328_CRU_CRU_MODE_MASK << 16 |
4011 RK3328_CRU_CRU_MODE_SLOW) << mode_shift);
4012
4013 /* Set PLL rate. */
4014 HWRITE4(sc, base + 0x0000,
4015 RK3328_CRU_PLL_POSTDIV1_MASK << 16 |
4016 postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT |
4017 RK3328_CRU_PLL_FBDIV_MASK << 16 |
4018 fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT);
4019 HWRITE4(sc, base + 0x0004,
4020 RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD |
4021 RK3328_CRU_PLL_POSTDIV2_MASK << 16 |
4022 postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT |
4023 RK3328_CRU_PLL_REFDIV_MASK << 16 |
4024 refdiv << RK3328_CRU_PLL_REFDIV_SHIFT);
4025
4026 /* Wait for PLL to stabilize. */
4027 while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0)
4028 delay(10);
4029
4030 /* Switch back to normal mode. */
4031 HWRITE4(sc, RK3568_PMUCRU_MODE_CON,
4032 (RK3328_CRU_CRU_MODE_MASK << 16 |
4033 RK3328_CRU_CRU_MODE_NORMAL) << mode_shift);
4034
4035 return 0;
4036}
4037
4038uint32_t
4039rk3568_pmu_get_frequency(void *cookie, uint32_t *cells)
4040{
4041 struct rkclock_softc *sc = cookie;
4042 uint32_t idx = cells[0];
4043
4044 switch (idx) {
4045 case RK3568_PLL_PPLL:
4046 return rk3328_get_pll(sc, RK3568_PMUCRU_PPLL_CON(0));
4047 case RK3568_PLL_HPLL:
4048 return rk3328_get_pll(sc, RK3568_PMUCRU_HPLL_CON(0));
4049 case RK3568_CLK_RTC32K_FRAC:
4050 return rk3399_get_frac(sc, RK3568_XIN24M,
4051 RK3568_PMUCRU_CLKSEL_CON(1));
4052 case RK3568_PPLL_PH0:
4053 idx = RK3568_PLL_PPLL;
4054 return rk3568_get_frequency(sc, &idx) / 2;
4055 case RK3568_XIN32K:
4056 return 32768;
4057 case RK3568_XIN24M:
4058 return 24000000;
4059 default:
4060 break;
4061 }
4062
4063 return rkclock_get_frequency(sc, idx);
4064}
4065
4066int
4067rk3568_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
4068{
4069 struct rkclock_softc *sc = cookie;
4070 uint32_t idx = cells[0];
4071
4072 switch (idx) {
4073 case RK3568_PLL_PPLL:
4074 return rk3568_pmu_set_pll(sc, RK3568_PMUCRU_PPLL_CON(0), freq);
4075 case RK3568_PLL_HPLL:
4076 return rk3568_pmu_set_pll(sc, RK3568_PMUCRU_HPLL_CON(0), freq);
4077 case RK3568_CLK_RTC32K_FRAC:
4078 return rk3399_set_frac(sc, RK3568_XIN24M,
4079 RK3568_PMUCRU_CLKSEL_CON(1), freq);
4080 default:
4081 break;
4082 }
4083
4084 return rkclock_set_frequency(sc, idx, freq);
4085}
4086
4087void
4088rk3568_pmu_enable(void *cookie, uint32_t *cells, int on)
4089{
4090 uint32_t idx = cells[0];
4091
4092 switch (idx) {
4093 case RK3568_CLK_USBPHY0_REF:
4094 case RK3568_CLK_USBPHY1_REF:
4095 case RK3568_CLK_PCIEPHY0_REF:
4096 case RK3568_CLK_PCIEPHY1_REF:
4097 case RK3568_CLK_PCIEPHY2_REF:
4098 case RK3568_CLK_PCIE30PHY_REF_M:
4099 case RK3568_CLK_PCIE30PHY_REF_N:
4100 case RK3568_CLK_I2C0:
4101 case RK3568_SCLK_UART0:
4102 case RK3568_PCLK_I2C0:
4103 /* Enabled by default. */
4104 break;
4105 default:
4106 printf("%s: 0x%08x\n", __func__, idx);
4107 break;
4108 }
4109}
4110
4111void
4112rk3568_pmu_reset(void *cookie, uint32_t *cells, int on)
4113{
4114 uint32_t idx = cells[0];
4115
4116 printf("%s: 0x%08x\n", __func__, idx);
4117}
4118
4119/*
4120 * Rockchip RK3588
4121 */
4122
4123const struct rkclock rk3588_clocks[] = {
4124 {
4125 RK3588_CLK_PWM1, RK3588_CRU_CLKSEL_CON(59),
4126 SEL(13, 12), 0,
4127 { RK3588_CLK_100M_SRC, RK3588_CLK_50M_SRC, RK3588_XIN24M },
4128 },
4129 {
4130 RK3588_CLK_PWM2, RK3588_CRU_CLKSEL_CON(59),
4131 SEL(15, 14), 0,
4132 { RK3588_CLK_100M_SRC, RK3588_CLK_50M_SRC, RK3588_XIN24M },
4133 },
4134 {
4135 RK3588_CLK_PWM3, RK3588_CRU_CLKSEL_CON(60),
4136 SEL(1, 0), 0,
4137 { RK3588_CLK_100M_SRC, RK3588_CLK_50M_SRC, RK3588_XIN24M },
4138 },
4139 {
4140 RK3588_ACLK_BUS_ROOT, RK3588_CRU_CLKSEL_CON(38),
4141 SEL(5, 5), DIV(4, 0),
4142 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4143 },
4144 {
4145 RK3588_CLK_I2C1, RK3588_CRU_CLKSEL_CON(38),
4146 SEL(6, 6), 0,
4147 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
4148 },
4149 {
4150 RK3588_CLK_I2C2, RK3588_CRU_CLKSEL_CON(38),
4151 SEL(7, 7), 0,
4152 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
4153 },
4154 {
4155 RK3588_CLK_I2C3, RK3588_CRU_CLKSEL_CON(38),
4156 SEL(8, 8), 0,
4157 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
4158 },
4159 {
4160 RK3588_CLK_I2C4, RK3588_CRU_CLKSEL_CON(38),
4161 SEL(9, 9), 0,
4162 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
4163 },
4164 {
4165 RK3588_CLK_I2C5, RK3588_CRU_CLKSEL_CON(38),
4166 SEL(10, 10), 0,
4167 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
4168 },
4169 {
4170 RK3588_CLK_I2C6, RK3588_CRU_CLKSEL_CON(38),
4171 SEL(11, 11), 0,
4172 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
4173 },
4174 {
4175 RK3588_CLK_I2C7, RK3588_CRU_CLKSEL_CON(38),
4176 SEL(12, 12), 0,
4177 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
4178 },
4179 {
4180 RK3588_CLK_I2C8, RK3588_CRU_CLKSEL_CON(38),
4181 SEL(13, 13), 0,
4182 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC },
4183 },
4184 {
4185 RK3588_CLK_SPI0, RK3588_CRU_CLKSEL_CON(59),
4186 SEL(3, 2), 0,
4187 { RK3588_CLK_200M_SRC, RK3588_CLK_150M_SRC, RK3588_XIN24M },
4188 },
4189 {
4190 RK3588_CLK_SPI1, RK3588_CRU_CLKSEL_CON(59),
4191 SEL(5, 4), 0,
4192 { RK3588_CLK_200M_SRC, RK3588_CLK_150M_SRC, RK3588_XIN24M },
4193 },
4194 {
4195 RK3588_CLK_SPI2, RK3588_CRU_CLKSEL_CON(59),
4196 SEL(7, 6), 0,
4197 { RK3588_CLK_200M_SRC, RK3588_CLK_150M_SRC, RK3588_XIN24M },
4198 },
4199 {
4200 RK3588_CLK_SPI3, RK3588_CRU_CLKSEL_CON(59),
4201 SEL(9, 8), 0,
4202 { RK3588_CLK_200M_SRC, RK3588_CLK_150M_SRC, RK3588_XIN24M },
4203 },
4204 {
4205 RK3588_CLK_SPI4, RK3588_CRU_CLKSEL_CON(59),
4206 SEL(11, 10), 0,
4207 { RK3588_CLK_200M_SRC, RK3588_CLK_150M_SRC, RK3588_XIN24M },
4208 },
4209 {
4210 RK3588_CLK_TSADC, RK3588_CRU_CLKSEL_CON(41),
4211 SEL(8, 8), DIV(7, 0),
4212 { RK3588_PLL_GPLL, RK3588_XIN24M },
4213 },
4214 {
4215 RK3588_CLK_UART1_SRC, RK3588_CRU_CLKSEL_CON(41),
4216 SEL(14, 14), DIV(13, 9),
4217 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4218 },
4219 {
4220 RK3588_CLK_UART1, RK3588_CRU_CLKSEL_CON(43),
4221 SEL(1, 0), 0,
4222 { RK3588_CLK_UART1_SRC, RK3588_CLK_UART1_FRAC, RK3588_XIN24M }
4223 },
4224 {
4225 RK3588_SCLK_UART1, 0, 0, 0,
4226 { RK3588_CLK_UART1 }
4227 },
4228 {
4229 RK3588_CLK_UART2_SRC, RK3588_CRU_CLKSEL_CON(43),
4230 SEL(7, 7), DIV(6, 2),
4231 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4232 },
4233 {
4234 RK3588_CLK_UART2, RK3588_CRU_CLKSEL_CON(45),
4235 SEL(1, 0), 0,
4236 { RK3588_CLK_UART2_SRC, RK3588_CLK_UART2_FRAC, RK3588_XIN24M }
4237 },
4238 {
4239 RK3588_SCLK_UART2, 0, 0, 0,
4240 { RK3588_CLK_UART2 }
4241 },
4242 {
4243 RK3588_CLK_UART3_SRC, RK3588_CRU_CLKSEL_CON(45),
4244 SEL(7, 7), DIV(6, 2),
4245 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4246 },
4247 {
4248 RK3588_CLK_UART3, RK3588_CRU_CLKSEL_CON(47),
4249 SEL(1, 0), 0,
4250 { RK3588_CLK_UART3_SRC, RK3588_CLK_UART3_FRAC, RK3588_XIN24M }
4251 },
4252 {
4253 RK3588_SCLK_UART3, 0, 0, 0,
4254 { RK3588_CLK_UART3 }
4255 },
4256 {
4257 RK3588_CLK_UART4_SRC, RK3588_CRU_CLKSEL_CON(47),
4258 SEL(7, 7), DIV(6, 2),
4259 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4260 },
4261 {
4262 RK3588_CLK_UART4, RK3588_CRU_CLKSEL_CON(49),
4263 SEL(1, 0), 0,
4264 { RK3588_CLK_UART4_SRC, RK3588_CLK_UART4_FRAC, RK3588_XIN24M }
4265 },
4266 {
4267 RK3588_SCLK_UART4, 0, 0, 0,
4268 { RK3588_CLK_UART4 }
4269 },
4270 {
4271 RK3588_CLK_UART5_SRC, RK3588_CRU_CLKSEL_CON(49),
4272 SEL(7, 7), DIV(6, 2),
4273 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4274 },
4275 {
4276 RK3588_CLK_UART5, RK3588_CRU_CLKSEL_CON(51),
4277 SEL(1, 0), 0,
4278 { RK3588_CLK_UART5_SRC, RK3588_CLK_UART5_FRAC, RK3588_XIN24M }
4279 },
4280 {
4281 RK3588_SCLK_UART5, 0, 0, 0,
4282 { RK3588_CLK_UART5 }
4283 },
4284 {
4285 RK3588_CLK_UART6_SRC, RK3588_CRU_CLKSEL_CON(51),
4286 SEL(7, 7), DIV(6, 2),
4287 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4288 },
4289 {
4290 RK3588_CLK_UART6, RK3588_CRU_CLKSEL_CON(53),
4291 SEL(1, 0), 0,
4292 { RK3588_CLK_UART6_SRC, RK3588_CLK_UART6_FRAC, RK3588_XIN24M }
4293 },
4294 {
4295 RK3588_SCLK_UART6, 0, 0, 0,
4296 { RK3588_CLK_UART6 }
4297 },
4298 {
4299 RK3588_CLK_UART7_SRC, RK3588_CRU_CLKSEL_CON(53),
4300 SEL(7, 7), DIV(6, 2),
4301 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4302 },
4303 {
4304 RK3588_CLK_UART7, RK3588_CRU_CLKSEL_CON(55),
4305 SEL(1, 0), 0,
4306 { RK3588_CLK_UART7_SRC, RK3588_CLK_UART7_FRAC, RK3588_XIN24M }
4307 },
4308 {
4309 RK3588_SCLK_UART7, 0, 0, 0,
4310 { RK3588_CLK_UART7 }
4311 },
4312 {
4313 RK3588_CLK_UART8_SRC, RK3588_CRU_CLKSEL_CON(55),
4314 SEL(7, 7), DIV(6, 2),
4315 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4316 },
4317 {
4318 RK3588_CLK_UART8, RK3588_CRU_CLKSEL_CON(57),
4319 SEL(1, 0), 0,
4320 { RK3588_CLK_UART8_SRC, RK3588_CLK_UART8_FRAC, RK3588_XIN24M }
4321 },
4322 {
4323 RK3588_SCLK_UART8, 0, 0, 0,
4324 { RK3588_CLK_UART8 }
4325 },
4326 {
4327 RK3588_CLK_UART9_SRC, RK3588_CRU_CLKSEL_CON(57),
4328 SEL(7, 7), DIV(6, 2),
4329 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4330 },
4331 {
4332 RK3588_CLK_UART9, RK3588_CRU_CLKSEL_CON(59),
4333 SEL(1, 0), 0,
4334 { RK3588_CLK_UART9_SRC, RK3588_CLK_UART9_FRAC, RK3588_XIN24M }
4335 },
4336 {
4337 RK3588_SCLK_UART9, 0, 0, 0,
4338 { RK3588_CLK_UART9 }
4339 },
4340 {
4341 RK3588_ACLK_CENTER_ROOT, RK3588_CRU_CLKSEL_CON(165),
4342 SEL(1, 0), 0,
4343 { RK3588_CLK_700M_SRC, RK3588_CLK_400M_SRC,
4344 RK3588_CLK_200M_SRC, RK3588_XIN24M }
4345 },
4346 {
4347 RK3588_ACLK_CENTER_LOW_ROOT, RK3588_CRU_CLKSEL_CON(165),
4348 SEL(3, 2), 0,
4349 { RK3588_CLK_500M_SRC, RK3588_CLK_250M_SRC,
4350 RK3588_CLK_100M_SRC, RK3588_XIN24M }
4351 },
4352 {
4353 RK3588_HCLK_CENTER_ROOT, RK3588_CRU_CLKSEL_CON(165),
4354 SEL(5, 4), 0,
4355 { RK3588_CLK_400M_SRC, RK3588_CLK_200M_SRC,
4356 RK3588_CLK_100M_SRC, RK3588_XIN24M }
4357 },
4358 {
4359 RK3588_CLK_50M_SRC, RK3588_CRU_CLKSEL_CON(0),
4360 SEL(5, 5), DIV(4, 0),
4361 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4362 },
4363 {
4364 RK3588_CLK_100M_SRC, RK3588_CRU_CLKSEL_CON(0),
4365 SEL(11, 11), DIV(10, 6),
4366 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4367 },
4368 {
4369 RK3588_CLK_150M_SRC, RK3588_CRU_CLKSEL_CON(1),
4370 SEL(5, 5), DIV(4, 0),
4371 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4372 },
4373 {
4374 RK3588_CLK_200M_SRC, RK3588_CRU_CLKSEL_CON(1),
4375 SEL(11, 11), DIV(10, 6),
4376 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4377 },
4378 {
4379 RK3588_CLK_250M_SRC, RK3588_CRU_CLKSEL_CON(2),
4380 SEL(5, 5), DIV(4, 0),
4381 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4382 },
4383 {
4384 RK3588_CLK_400M_SRC, RK3588_CRU_CLKSEL_CON(3),
4385 SEL(11, 11), DIV(10, 6),
4386 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4387 },
4388 {
4389 RK3588_CLK_500M_SRC, RK3588_CRU_CLKSEL_CON(4),
4390 SEL(11, 11), DIV(10, 6),
4391 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4392 },
4393 {
4394 RK3588_CLK_700M_SRC, RK3588_CRU_CLKSEL_CON(6),
4395 SEL(5, 5), DIV(4, 0),
4396 { RK3588_PLL_GPLL, RK3588_PLL_SPLL }
4397 },
4398 {
4399 RK3588_ACLK_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8),
4400 SEL(6, 5), 0,
4401 { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL }
4402 },
4403 {
4404 RK3588_PCLK_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8),
4405 SEL(8, 7), 0,
4406 { RK3588_CLK_100M_SRC, RK3588_CLK_50M_SRC, RK3588_XIN24M }
4407 },
4408 {
4409 RK3588_ACLK_LOW_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8),
4410 SEL(14, 14), DIV(13, 9),
4411 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4412 },
4413 {
4414 RK3588_CLK_GPU_SRC, RK3588_CRU_CLKSEL_CON(158),
4415 SEL(7, 5), DIV(4, 0),
4416 { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL,
4417 RK3588_PLL_NPLL, RK3588_PLL_SPLL }
4418 },
4419 {
4420 RK3588_CLK_GPU, 0, 0, 0,
4421 { RK3588_CLK_GPU_SRC },
4422 SET_PARENT
4423 },
4424 {
4425 RK3588_CCLK_EMMC, RK3588_CRU_CLKSEL_CON(77),
4426 SEL(15, 14), DIV(13, 8),
4427 { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_XIN24M }
4428 },
4429 {
4430 RK3588_BCLK_EMMC, RK3588_CRU_CLKSEL_CON(78),
4431 SEL(5, 5), DIV(4, 0),
4432 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4433 },
4434 {
4435 RK3588_TMCLK_EMMC, 0, 0, 0,
4436 { RK3588_XIN24M }
4437 },
4438 {
4439 RK3588_CLK_GMAC_125M, RK3588_CRU_CLKSEL_CON(83),
4440 SEL(15, 15), DIV(14, 8),
4441 { RK3588_PLL_GPLL, RK3588_PLL_CPLL }
4442 },
4443 {
4444 RK3588_CCLK_SRC_SDIO, RK3588_CRU_CLKSEL_CON(172),
4445 SEL(9, 8), DIV(7, 2),
4446 { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_XIN24M }
4447 },
4448 {
4449 RK3588_ACLK_VOP_ROOT, RK3588_CRU_CLKSEL_CON(110),
4450 SEL(7, 5), DIV(4, 0),
4451 { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL,
4452 RK3588_PLL_NPLL, RK3588_PLL_SPLL }
4453 },
4454 {
4455 RK3588_ACLK_VOP, 0, 0, 0,
4456 { RK3588_ACLK_VOP_SUB_SRC },
4457 SET_PARENT
4458 },
4459 {
4460 RK3588_ACLK_VOP_SUB_SRC, RK3588_CRU_CLKSEL_CON(115),
4461 SEL(9, 9), 0,
4462 { RK3588_ACLK_VOP_ROOT, 0 /* RK3588_ACLK_VOP_DIV2_SRC */ },
4463 SET_PARENT
4464 },
4465 {
4466 RK3588_CLK_I2C0, RK3588_CRU_CLKSEL_CON(3),
4467 SEL(6, 6), 0,
4468 { RK3588_CLK_PMU1_200M_SRC, RK3588_CLK_PMU1_100M_SRC },
4469 },
4470 {
4471 RK3588_CLK_PMU1_50M_SRC, RK3588_PMUCRU_CLKSEL_CON(0),
4472 0, DIV(3, 0),
4473 { RK3588_CLK_PMU1_400M_SRC }
4474 },
4475 {
4476 RK3588_CLK_PMU1_100M_SRC, RK3588_PMUCRU_CLKSEL_CON(0),
4477 0, DIV(6, 4),
4478 { RK3588_CLK_PMU1_400M_SRC }
4479 },
4480 {
4481 RK3588_CLK_PMU1_200M_SRC, RK3588_PMUCRU_CLKSEL_CON(0),
4482 0, DIV(9, 7),
4483 { RK3588_CLK_PMU1_400M_SRC }
4484 },
4485 {
4486 RK3588_CLK_PMU1_400M_SRC, RK3588_PMUCRU_CLKSEL_CON(1),
4487 SEL(5, 5), DIV(4, 0),
4488 { RK3588_CLK_400M_SRC, RK3588_XIN24M }
4489 },
4490 {
4491 RK3588_PCLK_PMU1_ROOT, RK3588_PMUCRU_CLKSEL_CON(1),
4492 SEL(9, 8), 0,
4493 { RK3588_CLK_PMU1_100M_SRC, RK3588_CLK_PMU1_50M_SRC,
4494 RK3588_XIN24M }
4495 },
4496 {
4497 RK3588_PCLK_PMU0_ROOT, 0, 0, 0,
4498 { RK3588_PCLK_PMU1_ROOT },
4499 SET_PARENT
4500 },
4501 {
4502 RK3588_HCLK_PMU_CM0_ROOT, RK3588_PMUCRU_CLKSEL_CON(1),
4503 SEL(11, 10), 0,
4504 { RK3588_CLK_PMU1_400M_SRC, RK3588_CLK_PMU1_200M_SRC,
4505 RK3588_CLK_PMU1_100M_SRC, RK3588_XIN24M }
4506 },
4507 {
4508 RK3588_CLK_PMU1PWM, RK3588_PMUCRU_CLKSEL_CON(2),
4509 SEL(10, 9), 0,
4510 { RK3588_CLK_PMU1_100M_SRC, RK3588_CLK_PMU1_50M_SRC,
4511 RK3588_XIN24M }
4512 },
4513 {
4514 RK3588_CLK_UART0_SRC, RK3588_PMUCRU_CLKSEL_CON(3),
4515 0, DIV(11, 7),
4516 { RK3588_PLL_CPLL }
4517 },
4518 {
4519 RK3588_CLK_UART0, RK3588_PMUCRU_CLKSEL_CON(5),
4520 SEL(1, 0), 0,
4521 { RK3588_CLK_UART0_SRC, RK3588_CLK_UART0_FRAC, RK3588_XIN24M }
4522 },
4523 {
4524 RK3588_SCLK_UART0, 0, 0, 0,
4525 { RK3588_CLK_UART0 }
4526 },
4527 {
4528 RK3588_CLK_USBDPPHY_MIPIDCPPHY_REF, RK3588_CRU_CLKSEL_CON(14),
4529 SEL(8, 7), DIV(6, 0),
4530 { RK3588_XIN24M, RK3588_PLL_PPLL, RK3588_PLL_SPLL }
4531 },
4532 {
4533 RK3588_CLK_REF_PIPE_PHY0_OSC_SRC, 0, 0, 0,
4534 { RK3588_XIN24M }
4535 },
4536 {
4537 RK3588_CLK_REF_PIPE_PHY1_OSC_SRC, 0, 0, 0,
4538 { RK3588_XIN24M }
4539 },
4540 {
4541 RK3588_CLK_REF_PIPE_PHY2_OSC_SRC, 0, 0, 0,
4542 { RK3588_XIN24M }
4543 },
4544 {
4545 RK3588_CLK_REF_PIPE_PHY0_PLL_SRC, RK3588_CRU_CLKSEL_CON(176),
4546 0, DIV(5, 0),
4547 { RK3588_PLL_PPLL }
4548 },
4549 {
4550 RK3588_CLK_REF_PIPE_PHY1_PLL_SRC, RK3588_CRU_CLKSEL_CON(176),
4551 0, DIV(11, 6),
4552 { RK3588_PLL_PPLL }
4553 },
4554 {
4555 RK3588_CLK_REF_PIPE_PHY2_PLL_SRC, RK3588_CRU_CLKSEL_CON(177),
4556 0, DIV(5, 0),
4557 { RK3588_PLL_PPLL }
4558 },
4559 {
4560 RK3588_CLK_REF_PIPE_PHY0, RK3588_CRU_CLKSEL_CON(177),
4561 SEL(6, 6), 0,
4562 { RK3588_CLK_REF_PIPE_PHY0_OSC_SRC,
4563 RK3588_CLK_REF_PIPE_PHY0_PLL_SRC },
4564 },
4565 {
4566 RK3588_CLK_REF_PIPE_PHY1, RK3588_CRU_CLKSEL_CON(177),
4567 SEL(7, 7), 0,
4568 { RK3588_CLK_REF_PIPE_PHY1_OSC_SRC,
4569 RK3588_CLK_REF_PIPE_PHY1_PLL_SRC },
4570 },
4571 {
4572 RK3588_CLK_REF_PIPE_PHY2, RK3588_CRU_CLKSEL_CON(177),
4573 SEL(8, 8), 0,
4574 { RK3588_CLK_REF_PIPE_PHY2_OSC_SRC,
4575 RK3588_CLK_REF_PIPE_PHY2_PLL_SRC },
4576 },
4577 {
4578 /* Sentinel */
4579 }
4580};
4581
4582/* Certain test clocks are disabled. */
4583const uint32_t rk3588_gates[78] = {
4584 [2] = 0x00000050,
4585 [22] = 0x00000200,
4586 [25] = 0x00000200,
4587 [29] = 0x00000004,
4588 [66] = 0x00000004,
4589};
4590
4591void
4592rk3588_init(struct rkclock_softc *sc)
4593{
4594 int i;
4595
4596 /* The code below assumes all clocks are enabled. Check this!. */
4597 for (i = 0; i < nitems(rk3588_gates); i++) {
4598 if (HREAD4(sc, RK3588_CRU_GATE_CON(i)) != rk3588_gates[i]) {
4599 printf("CRU_GATE_CON%d: 0x%08x\n", i,
4600 HREAD4(sc, RK3588_CRU_GATE_CON(i)));
4601 }
4602 }
4603
4604 sc->sc_clocks = rk3588_clocks;
4605}
4606
4607int
4608rk3588_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq)
4609{
4610 uint32_t p, m, s, k;
4611 int mode_shift = -1;
4612
4613 switch (base) {
4614 case RK3588_CRU_AUPLL_CON(0):
4615 mode_shift = 6;
4616 break;
4617 case RK3588_CRU_GPLL_CON(0):
4618 mode_shift = 2;
4619 break;
4620 case RK3588_CRU_NPLL_CON(0):
4621 mode_shift = 0;
4622 break;
4623 case RK3588_PHPTOPCRU_PPLL_CON(0):
4624 mode_shift = 10;
4625 break;
4626 }
4627 KASSERT(mode_shift != -1);
4628
4629 /*
4630 * It is not clear whether all combinations of the clock
4631 * dividers result in a stable clock. Therefore this function
4632 * only supports a limited set of PLL clock rates.
4633 */
4634 switch (freq) {
4635 case 1188000000U:
4636 p = 2; m = 198; s = 1; k = 0;
4637 break;
4638 case 1100000000U:
4639 p = 3; m = 550; s = 2; k = 0;
4640 break;
4641 case 850000000U:
4642 p = 3; m = 425; s = 2; k = 0;
4643 break;
4644 case 786432000U:
4645 p = 2; m = 262; s = 2; k = 9437;
4646 break;
4647 case 100000000U:
4648 p = 3; m = 400; s = 5; k = 0;
4649 break;
4650 default:
4651 printf("%s: %u Hz\n", __func__, freq);
4652 return -1;
4653 }
4654
4655 /*
4656 * Select slow mode to guarantee a stable clock while we're
4657 * adjusting the PLL.
4658 */
4659 HWRITE4(sc, RK3588_CRU_MODE_CON,
4660 (RK3588_CRU_MODE_MASK << 16 |RK3588_CRU_MODE_SLOW) << mode_shift);
4661
4662 /* Power down PLL. */
4663 HWRITE4(sc, base + 0x0004,
4664 RK3588_CRU_PLL_RESETB << 16 | RK3588_CRU_PLL_RESETB);
4665
4666 /* Set PLL rate. */
4667 HWRITE4(sc, base + 0x0000,
4668 RK3588_CRU_PLL_M_MASK << 16 | m << RK3588_CRU_PLL_M_SHIFT);
4669 HWRITE4(sc, base + 0x0004,
4670 RK3588_CRU_PLL_S_MASK << 16 | s << RK3588_CRU_PLL_S_SHIFT |
4671 RK3588_CRU_PLL_P_MASK << 16 | p << RK3588_CRU_PLL_P_SHIFT);
4672 HWRITE4(sc, base + 0x0008,
4673 RK3588_CRU_PLL_K_MASK << 16 | k << RK3588_CRU_PLL_K_SHIFT);
4674
4675 /* Power up PLL. */
4676 HWRITE4(sc, base + 0x0004, RK3588_CRU_PLL_RESETB << 16);
4677
4678 /* Wait for PLL to stabilize. */
4679 while ((HREAD4(sc, base + 0x0018) & RK3588_CRU_PLL_PLL_LOCK) == 0)
4680 delay(10);
4681
4682 /* Switch back to normal mode. */
4683 HWRITE4(sc, RK3588_CRU_MODE_CON,
4684 (RK3588_CRU_MODE_MASK << 16 | RK3588_CRU_MODE_NORMAL) << mode_shift);
4685
4686 return 0;
4687}
4688
4689uint32_t
4690rk3588_get_pll(struct rkclock_softc *sc, bus_size_t base)
4691{
4692 uint64_t freq, frac;
4693 uint32_t k, m, p, s;
4694 uint32_t reg;
4695
4696 reg = HREAD4(sc, base);
4697 m = (reg & RK3588_CRU_PLL_M_MASK) >> RK3588_CRU_PLL_M_SHIFT;
4698 reg = HREAD4(sc, base + 4);
4699 p = (reg & RK3588_CRU_PLL_P_MASK) >> RK3588_CRU_PLL_P_SHIFT;
4700 s = (reg & RK3588_CRU_PLL_S_MASK) >> RK3588_CRU_PLL_S_SHIFT;
4701 reg = HREAD4(sc, base + 8);
4702 k = (reg & RK3588_CRU_PLL_K_MASK) >> RK3588_CRU_PLL_K_SHIFT;
4703
4704 freq = (24000000ULL * m) / p;
4705 if (k) {
4706 frac = ((24000000ULL * k) / (p * 65535));
4707 freq += frac;
4708 }
4709
4710 return freq >> s;
4711}
4712
4713uint32_t
4714rk3588_get_frequency(void *cookie, uint32_t *cells)
4715{
4716 struct rkclock_softc *sc = cookie;
4717 uint32_t idx = cells[0];
4718 uint32_t freq;
4719
4720 switch (idx) {
4721 case RK3588_PLL_AUPLL:
4722 return rk3588_get_pll(sc, RK3588_CRU_AUPLL_CON(0));
4723 case RK3588_PLL_CPLL:
4724 return rk3588_get_pll(sc, RK3588_CRU_CPLL_CON(0));
4725 case RK3588_PLL_GPLL:
4726 return rk3588_get_pll(sc, RK3588_CRU_GPLL_CON(0));
4727 case RK3588_PLL_NPLL:
4728 return rk3588_get_pll(sc, RK3588_CRU_NPLL_CON(0));
4729 case RK3588_PLL_PPLL:
4730 return rk3588_get_pll(sc, RK3588_PHPTOPCRU_PPLL_CON(0));
4731 case RK3588_PLL_SPLL:
4732 return rkclock_external_frequency("spll");
4733 case RK3588_XIN24M:
4734 return 24000000;
4735 default:
4736 break;
4737 }
4738
4739 freq = rkclock_get_frequency(sc, idx);
4740 return freq;
4741}
4742
4743int
4744rk3588_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
4745{
4746 struct rkclock_softc *sc = cookie;
4747 uint32_t idx = cells[0];
4748
4749 switch (idx) {
4750 case RK3588_PLL_AUPLL:
4751 return rk3588_set_pll(sc, RK3588_CRU_AUPLL_CON(0), freq);
4752 case RK3588_PLL_GPLL:
4753 return rk3588_set_pll(sc, RK3588_CRU_GPLL_CON(0), freq);
4754 case RK3588_PLL_NPLL:
4755 return rk3588_set_pll(sc, RK3588_CRU_NPLL_CON(0), freq);
4756 case RK3588_PLL_PPLL:
4757 return rk3588_set_pll(sc, RK3588_PHPTOPCRU_PPLL_CON(0), freq);
4758 default:
4759 break;
4760 }
4761
4762 return rkclock_set_frequency(sc, idx, freq);
4763}
4764
4765void
4766rk3588_enable(void *cookie, uint32_t *cells, int on)
4767{
4768 uint32_t idx = cells[0];
4769
4770 /* All clocks are enabled upon hardware reset. */
4771 if (!on) {
4772 printf("%s: 0x%08x\n", __func__, idx);
4773 return;
4774 }
4775}
4776
4777void
4778rk3588_reset(void *cookie, uint32_t *cells, int on)
4779{
4780 struct rkclock_softc *sc = cookie;
4781 uint32_t idx = cells[0];
4782 uint32_t bit, mask, reg;
4783
4784 switch (idx) {
4785 case RK3588_SRST_USBDP_COMBO_PHY0_INIT:
4786 reg = RK3588_CRU_SOFTRST_CON(2);
4787 bit = 8;
4788 break;
4789 case RK3588_SRST_USBDP_COMBO_PHY0_CMN:
4790 reg = RK3588_CRU_SOFTRST_CON(2);
4791 bit = 9;
4792 break;
4793 case RK3588_SRST_USBDP_COMBO_PHY0_LANE:
4794 reg = RK3588_CRU_SOFTRST_CON(2);
4795 bit = 10;
4796 break;
4797 case RK3588_SRST_USBDP_COMBO_PHY0_PCS:
4798 reg = RK3588_CRU_SOFTRST_CON(2);
4799 bit = 11;
4800 break;
4801 case RK3588_SRST_USBDP_COMBO_PHY1_INIT:
4802 reg = RK3588_CRU_SOFTRST_CON(2);
4803 bit = 15;
4804 break;
4805 case RK3588_SRST_USBDP_COMBO_PHY1_CMN:
4806 reg = RK3588_CRU_SOFTRST_CON(3);
4807 bit = 0;
4808 break;
4809 case RK3588_SRST_USBDP_COMBO_PHY1_LANE:
4810 reg = RK3588_CRU_SOFTRST_CON(3);
4811 bit = 1;
4812 break;
4813 case RK3588_SRST_USBDP_COMBO_PHY1_PCS:
4814 reg = RK3588_CRU_SOFTRST_CON(3);
4815 bit = 2;
4816 break;
4817 case RK3588_SRST_P_TSADC:
4818 reg = RK3588_CRU_SOFTRST_CON(12);
4819 bit = 0;
4820 break;
4821 case RK3588_SRST_TSADC:
4822 reg = RK3588_CRU_SOFTRST_CON(12);
4823 bit = 1;
4824 break;
4825 case RK3588_SRST_H_EMMC:
4826 reg = RK3588_CRU_SOFTRST_CON(31);
4827 bit = 4;
4828 break;
4829 case RK3588_SRST_A_EMMC:
4830 reg = RK3588_CRU_SOFTRST_CON(31);
4831 bit = 5;
4832 break;
4833 case RK3588_SRST_C_EMMC:
4834 reg = RK3588_CRU_SOFTRST_CON(31);
4835 bit = 6;
4836 break;
4837 case RK3588_SRST_B_EMMC:
4838 reg = RK3588_CRU_SOFTRST_CON(31);
4839 bit = 7;
4840 break;
4841 case RK3588_SRST_T_EMMC:
4842 reg = RK3588_CRU_SOFTRST_CON(31);
4843 bit = 8;
4844 break;
4845 case RK3588_SRST_A_GMAC0:
4846 reg = RK3588_CRU_SOFTRST_CON(32);
4847 bit = 10;
4848 break;
4849 case RK3588_SRST_A_GMAC1:
4850 reg = RK3588_CRU_SOFTRST_CON(32);
4851 bit = 11;
4852 break;
4853 case RK3588_SRST_PCIE0_POWER_UP:
4854 reg = RK3588_CRU_SOFTRST_CON(32);
4855 bit = 13;
4856 break;
4857 case RK3588_SRST_PCIE1_POWER_UP:
4858 reg = RK3588_CRU_SOFTRST_CON(32);
4859 bit = 14;
4860 break;
4861 case RK3588_SRST_PCIE2_POWER_UP:
4862 reg = RK3588_CRU_SOFTRST_CON(32);
4863 bit = 15;
4864 break;
4865 case RK3588_SRST_PCIE3_POWER_UP:
4866 reg = RK3588_CRU_SOFTRST_CON(33);
4867 bit = 0;
4868 break;
4869 case RK3588_SRST_PCIE4_POWER_UP:
4870 reg = RK3588_CRU_SOFTRST_CON(33);
4871 bit = 1;
4872 break;
4873 case RK3588_SRST_P_PCIE0:
4874 reg = RK3588_CRU_SOFTRST_CON(33);
4875 bit = 12;
4876 break;
4877 case RK3588_SRST_P_PCIE1:
4878 reg = RK3588_CRU_SOFTRST_CON(33);
4879 bit = 13;
4880 break;
4881 case RK3588_SRST_P_PCIE2:
4882 reg = RK3588_CRU_SOFTRST_CON(33);
4883 bit = 14;
4884 break;
4885 case RK3588_SRST_P_PCIE3:
4886 reg = RK3588_CRU_SOFTRST_CON(33);
4887 bit = 15;
4888 break;
4889 case RK3588_SRST_P_PCIE4:
4890 reg = RK3588_CRU_SOFTRST_CON(34);
4891 bit = 0;
4892 break;
4893 case RK3588_SRST_A_USB3OTG2:
4894 reg = RK3588_CRU_SOFTRST_CON(35);
4895 bit = 7;
4896 break;
4897 case RK3588_SRST_A_USB3OTG0:
4898 reg = RK3588_CRU_SOFTRST_CON(42);
4899 bit = 4;
4900 break;
4901 case RK3588_SRST_A_USB3OTG1:
4902 reg = RK3588_CRU_SOFTRST_CON(42);
4903 bit = 7;
4904 break;
4905 case RK3588_SRST_P_USBDPGRF0:
4906 reg = RK3588_CRU_SOFTRST_CON(72);
4907 bit = 1;
4908 break;
4909 case RK3588_SRST_P_USBDPPHY0:
4910 reg = RK3588_CRU_SOFTRST_CON(72);
4911 bit = 2;
4912 break;
4913 case RK3588_SRST_P_USBDPGRF1:
4914 reg = RK3588_CRU_SOFTRST_CON(72);
4915 bit = 3;
4916 break;
4917 case RK3588_SRST_P_USBDPPHY1:
4918 reg = RK3588_CRU_SOFTRST_CON(72);
4919 bit = 4;
4920 break;
4921 case RK3588_SRST_REF_PIPE_PHY0:
4922 reg = RK3588_CRU_SOFTRST_CON(77);
4923 bit = 6;
4924 break;
4925 case RK3588_SRST_REF_PIPE_PHY1:
4926 reg = RK3588_CRU_SOFTRST_CON(77);
4927 bit = 7;
4928 break;
4929 case RK3588_SRST_REF_PIPE_PHY2:
4930 reg = RK3588_CRU_SOFTRST_CON(77);
4931 bit = 8;
4932 break;
4933 case RK3588_SRST_P_PCIE2_PHY0:
4934 reg = RK3588_PHPTOPCRU_SOFTRST_CON(0);
4935 bit = 5;
4936 break;
4937 case RK3588_SRST_P_PCIE2_PHY1:
4938 reg = RK3588_PHPTOPCRU_SOFTRST_CON(0);
4939 bit = 6;
4940 break;
4941 case RK3588_SRST_P_PCIE2_PHY2:
4942 reg = RK3588_PHPTOPCRU_SOFTRST_CON(0);
4943 bit = 7;
4944 break;
4945 case RK3588_SRST_PCIE30_PHY:
4946 reg = RK3588_PHPTOPCRU_SOFTRST_CON(0);
4947 bit = 10;
4948 break;
4949 default:
4950 printf("%s: 0x%08x\n", __func__, idx);
4951 return;
4952 }
4953
4954 mask = (1 << bit);
4955 HWRITE4(sc, reg, mask << 16 | (on ? mask : 0));
4956}