2 * BCM2835 CPRMAN clock manager
4 * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
6 * SPDX-License-Identifier: GPL-2.0-or-later
9 #ifndef HW_MISC_BCM2835_CPRMAN_INTERNALS_H
10 #define HW_MISC_BCM2835_CPRMAN_INTERNALS_H
12 #include "hw/registerfields.h"
13 #include "hw/misc/bcm2835_cprman.h"
15 #define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
16 #define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel"
17 #define TYPE_CPRMAN_CLOCK_MUX "bcm2835-cprman-clock-mux"
18 #define TYPE_CPRMAN_DSI0HSCK_MUX "bcm2835-cprman-dsi0hsck-mux"
20 DECLARE_INSTANCE_CHECKER(CprmanPllState
, CPRMAN_PLL
,
22 DECLARE_INSTANCE_CHECKER(CprmanPllChannelState
, CPRMAN_PLL_CHANNEL
,
23 TYPE_CPRMAN_PLL_CHANNEL
)
24 DECLARE_INSTANCE_CHECKER(CprmanClockMuxState
, CPRMAN_CLOCK_MUX
,
25 TYPE_CPRMAN_CLOCK_MUX
)
26 DECLARE_INSTANCE_CHECKER(CprmanDsi0HsckMuxState
, CPRMAN_DSI0HSCK_MUX
,
27 TYPE_CPRMAN_DSI0HSCK_MUX
)
33 FIELD(CM_PLLA
, LOADDSI0
, 0, 1)
34 FIELD(CM_PLLA
, HOLDDSI0
, 1, 1)
35 FIELD(CM_PLLA
, LOADCCP2
, 2, 1)
36 FIELD(CM_PLLA
, HOLDCCP2
, 3, 1)
37 FIELD(CM_PLLA
, LOADCORE
, 4, 1)
38 FIELD(CM_PLLA
, HOLDCORE
, 5, 1)
39 FIELD(CM_PLLA
, LOADPER
, 6, 1)
40 FIELD(CM_PLLA
, HOLDPER
, 7, 1)
41 FIELD(CM_PLLx
, ANARST
, 8, 1)
43 FIELD(CM_PLLC
, LOADCORE0
, 0, 1)
44 FIELD(CM_PLLC
, HOLDCORE0
, 1, 1)
45 FIELD(CM_PLLC
, LOADCORE1
, 2, 1)
46 FIELD(CM_PLLC
, HOLDCORE1
, 3, 1)
47 FIELD(CM_PLLC
, LOADCORE2
, 4, 1)
48 FIELD(CM_PLLC
, HOLDCORE2
, 5, 1)
49 FIELD(CM_PLLC
, LOADPER
, 6, 1)
50 FIELD(CM_PLLC
, HOLDPER
, 7, 1)
52 FIELD(CM_PLLD
, LOADDSI0
, 0, 1)
53 FIELD(CM_PLLD
, HOLDDSI0
, 1, 1)
54 FIELD(CM_PLLD
, LOADDSI1
, 2, 1)
55 FIELD(CM_PLLD
, HOLDDSI1
, 3, 1)
56 FIELD(CM_PLLD
, LOADCORE
, 4, 1)
57 FIELD(CM_PLLD
, HOLDCORE
, 5, 1)
58 FIELD(CM_PLLD
, LOADPER
, 6, 1)
59 FIELD(CM_PLLD
, HOLDPER
, 7, 1)
61 FIELD(CM_PLLH
, LOADPIX
, 0, 1)
62 FIELD(CM_PLLH
, LOADAUX
, 1, 1)
63 FIELD(CM_PLLH
, LOADRCAL
, 2, 1)
65 FIELD(CM_PLLB
, LOADARM
, 0, 1)
66 FIELD(CM_PLLB
, HOLDARM
, 1, 1)
68 REG32(A2W_PLLA_CTRL
, 0x1100)
69 FIELD(A2W_PLLx_CTRL
, NDIV
, 0, 10)
70 FIELD(A2W_PLLx_CTRL
, PDIV
, 12, 3)
71 FIELD(A2W_PLLx_CTRL
, PWRDN
, 16, 1)
72 FIELD(A2W_PLLx_CTRL
, PRST_DISABLE
, 17, 1)
73 REG32(A2W_PLLC_CTRL
, 0x1120)
74 REG32(A2W_PLLD_CTRL
, 0x1140)
75 REG32(A2W_PLLH_CTRL
, 0x1160)
76 REG32(A2W_PLLB_CTRL
, 0x11e0)
78 REG32(A2W_PLLA_ANA0
, 0x1010)
79 REG32(A2W_PLLA_ANA1
, 0x1014)
80 FIELD(A2W_PLLx_ANA1
, FB_PREDIV
, 14, 1)
81 REG32(A2W_PLLA_ANA2
, 0x1018)
82 REG32(A2W_PLLA_ANA3
, 0x101c)
84 REG32(A2W_PLLC_ANA0
, 0x1030)
85 REG32(A2W_PLLC_ANA1
, 0x1034)
86 REG32(A2W_PLLC_ANA2
, 0x1038)
87 REG32(A2W_PLLC_ANA3
, 0x103c)
89 REG32(A2W_PLLD_ANA0
, 0x1050)
90 REG32(A2W_PLLD_ANA1
, 0x1054)
91 REG32(A2W_PLLD_ANA2
, 0x1058)
92 REG32(A2W_PLLD_ANA3
, 0x105c)
94 REG32(A2W_PLLH_ANA0
, 0x1070)
95 REG32(A2W_PLLH_ANA1
, 0x1074)
96 FIELD(A2W_PLLH_ANA1
, FB_PREDIV
, 11, 1)
97 REG32(A2W_PLLH_ANA2
, 0x1078)
98 REG32(A2W_PLLH_ANA3
, 0x107c)
100 REG32(A2W_PLLB_ANA0
, 0x10f0)
101 REG32(A2W_PLLB_ANA1
, 0x10f4)
102 REG32(A2W_PLLB_ANA2
, 0x10f8)
103 REG32(A2W_PLLB_ANA3
, 0x10fc)
105 REG32(A2W_PLLA_FRAC
, 0x1200)
106 FIELD(A2W_PLLx_FRAC
, FRAC
, 0, 20)
107 REG32(A2W_PLLC_FRAC
, 0x1220)
108 REG32(A2W_PLLD_FRAC
, 0x1240)
109 REG32(A2W_PLLH_FRAC
, 0x1260)
110 REG32(A2W_PLLB_FRAC
, 0x12e0)
113 REG32(A2W_PLLA_DSI0
, 0x1300)
114 FIELD(A2W_PLLx_CHANNELy
, DIV
, 0, 8)
115 FIELD(A2W_PLLx_CHANNELy
, DISABLE
, 8, 1)
116 REG32(A2W_PLLA_CORE
, 0x1400)
117 REG32(A2W_PLLA_PER
, 0x1500)
118 REG32(A2W_PLLA_CCP2
, 0x1600)
120 REG32(A2W_PLLC_CORE2
, 0x1320)
121 REG32(A2W_PLLC_CORE1
, 0x1420)
122 REG32(A2W_PLLC_PER
, 0x1520)
123 REG32(A2W_PLLC_CORE0
, 0x1620)
125 REG32(A2W_PLLD_DSI0
, 0x1340)
126 REG32(A2W_PLLD_CORE
, 0x1440)
127 REG32(A2W_PLLD_PER
, 0x1540)
128 REG32(A2W_PLLD_DSI1
, 0x1640)
130 REG32(A2W_PLLH_AUX
, 0x1360)
131 REG32(A2W_PLLH_RCAL
, 0x1460)
132 REG32(A2W_PLLH_PIX
, 0x1560)
133 REG32(A2W_PLLH_STS
, 0x1660)
135 REG32(A2W_PLLB_ARM
, 0x13e0)
138 REG32(CM_GNRICCTL
, 0x000)
139 FIELD(CM_CLOCKx_CTL
, SRC
, 0, 4)
140 FIELD(CM_CLOCKx_CTL
, ENABLE
, 4, 1)
141 FIELD(CM_CLOCKx_CTL
, KILL
, 5, 1)
142 FIELD(CM_CLOCKx_CTL
, GATE
, 6, 1)
143 FIELD(CM_CLOCKx_CTL
, BUSY
, 7, 1)
144 FIELD(CM_CLOCKx_CTL
, BUSYD
, 8, 1)
145 FIELD(CM_CLOCKx_CTL
, MASH
, 9, 2)
146 FIELD(CM_CLOCKx_CTL
, FLIP
, 11, 1)
147 REG32(CM_GNRICDIV
, 0x004)
148 FIELD(CM_CLOCKx_DIV
, FRAC
, 0, 12)
149 REG32(CM_VPUCTL
, 0x008)
150 REG32(CM_VPUDIV
, 0x00c)
151 REG32(CM_SYSCTL
, 0x010)
152 REG32(CM_SYSDIV
, 0x014)
153 REG32(CM_PERIACTL
, 0x018)
154 REG32(CM_PERIADIV
, 0x01c)
155 REG32(CM_PERIICTL
, 0x020)
156 REG32(CM_PERIIDIV
, 0x024)
157 REG32(CM_H264CTL
, 0x028)
158 REG32(CM_H264DIV
, 0x02c)
159 REG32(CM_ISPCTL
, 0x030)
160 REG32(CM_ISPDIV
, 0x034)
161 REG32(CM_V3DCTL
, 0x038)
162 REG32(CM_V3DDIV
, 0x03c)
163 REG32(CM_CAM0CTL
, 0x040)
164 REG32(CM_CAM0DIV
, 0x044)
165 REG32(CM_CAM1CTL
, 0x048)
166 REG32(CM_CAM1DIV
, 0x04c)
167 REG32(CM_CCP2CTL
, 0x050)
168 REG32(CM_CCP2DIV
, 0x054)
169 REG32(CM_DSI0ECTL
, 0x058)
170 REG32(CM_DSI0EDIV
, 0x05c)
171 REG32(CM_DSI0PCTL
, 0x060)
172 REG32(CM_DSI0PDIV
, 0x064)
173 REG32(CM_DPICTL
, 0x068)
174 REG32(CM_DPIDIV
, 0x06c)
175 REG32(CM_GP0CTL
, 0x070)
176 REG32(CM_GP0DIV
, 0x074)
177 REG32(CM_GP1CTL
, 0x078)
178 REG32(CM_GP1DIV
, 0x07c)
179 REG32(CM_GP2CTL
, 0x080)
180 REG32(CM_GP2DIV
, 0x084)
181 REG32(CM_HSMCTL
, 0x088)
182 REG32(CM_HSMDIV
, 0x08c)
183 REG32(CM_OTPCTL
, 0x090)
184 REG32(CM_OTPDIV
, 0x094)
185 REG32(CM_PCMCTL
, 0x098)
186 REG32(CM_PCMDIV
, 0x09c)
187 REG32(CM_PWMCTL
, 0x0a0)
188 REG32(CM_PWMDIV
, 0x0a4)
189 REG32(CM_SLIMCTL
, 0x0a8)
190 REG32(CM_SLIMDIV
, 0x0ac)
191 REG32(CM_SMICTL
, 0x0b0)
192 REG32(CM_SMIDIV
, 0x0b4)
193 REG32(CM_TCNTCTL
, 0x0c0)
194 REG32(CM_TCNTCNT
, 0x0c4)
195 REG32(CM_TECCTL
, 0x0c8)
196 REG32(CM_TECDIV
, 0x0cc)
197 REG32(CM_TD0CTL
, 0x0d0)
198 REG32(CM_TD0DIV
, 0x0d4)
199 REG32(CM_TD1CTL
, 0x0d8)
200 REG32(CM_TD1DIV
, 0x0dc)
201 REG32(CM_TSENSCTL
, 0x0e0)
202 REG32(CM_TSENSDIV
, 0x0e4)
203 REG32(CM_TIMERCTL
, 0x0e8)
204 REG32(CM_TIMERDIV
, 0x0ec)
205 REG32(CM_UARTCTL
, 0x0f0)
206 REG32(CM_UARTDIV
, 0x0f4)
207 REG32(CM_VECCTL
, 0x0f8)
208 REG32(CM_VECDIV
, 0x0fc)
209 REG32(CM_PULSECTL
, 0x190)
210 REG32(CM_PULSEDIV
, 0x194)
211 REG32(CM_SDCCTL
, 0x1a8)
212 REG32(CM_SDCDIV
, 0x1ac)
213 REG32(CM_ARMCTL
, 0x1b0)
214 REG32(CM_AVEOCTL
, 0x1b8)
215 REG32(CM_AVEODIV
, 0x1bc)
216 REG32(CM_EMMCCTL
, 0x1c0)
217 REG32(CM_EMMCDIV
, 0x1c4)
218 REG32(CM_EMMC2CTL
, 0x1d0)
219 REG32(CM_EMMC2DIV
, 0x1d4)
222 REG32(CM_LOCK
, 0x114)
223 FIELD(CM_LOCK
, FLOCKH
, 12, 1)
224 FIELD(CM_LOCK
, FLOCKD
, 11, 1)
225 FIELD(CM_LOCK
, FLOCKC
, 10, 1)
226 FIELD(CM_LOCK
, FLOCKB
, 9, 1)
227 FIELD(CM_LOCK
, FLOCKA
, 8, 1)
229 REG32(CM_DSI0HSCK
, 0x120)
230 FIELD(CM_DSI0HSCK
, SELPLLD
, 0, 1)
233 * This field is common to all registers. Each register write value must match
234 * the CPRMAN_PASSWORD magic value in its 8 MSB.
236 FIELD(CPRMAN
, PASSWORD
, 24, 8)
237 #define CPRMAN_PASSWORD 0x5a
240 typedef struct PLLInitInfo
{
243 size_t a2w_ctrl_offset
;
244 size_t a2w_ana_offset
;
245 uint32_t prediv_mask
; /* Prediv bit in ana[1] */
246 size_t a2w_frac_offset
;
249 #define FILL_PLL_INIT_INFO(pll_) \
250 .cm_offset = R_CM_ ## pll_, \
251 .a2w_ctrl_offset = R_A2W_ ## pll_ ## _CTRL, \
252 .a2w_ana_offset = R_A2W_ ## pll_ ## _ANA0, \
253 .a2w_frac_offset = R_A2W_ ## pll_ ## _FRAC
255 static const PLLInitInfo PLL_INIT_INFO
[] = {
258 .prediv_mask
= R_A2W_PLLx_ANA1_FB_PREDIV_MASK
,
259 FILL_PLL_INIT_INFO(PLLA
),
263 .prediv_mask
= R_A2W_PLLx_ANA1_FB_PREDIV_MASK
,
264 FILL_PLL_INIT_INFO(PLLC
),
268 .prediv_mask
= R_A2W_PLLx_ANA1_FB_PREDIV_MASK
,
269 FILL_PLL_INIT_INFO(PLLD
),
273 .prediv_mask
= R_A2W_PLLH_ANA1_FB_PREDIV_MASK
,
274 FILL_PLL_INIT_INFO(PLLH
),
278 .prediv_mask
= R_A2W_PLLx_ANA1_FB_PREDIV_MASK
,
279 FILL_PLL_INIT_INFO(PLLB
),
283 #undef FILL_PLL_CHANNEL_INIT_INFO
285 static inline void set_pll_init_info(BCM2835CprmanState
*s
,
290 pll
->reg_cm
= &s
->regs
[PLL_INIT_INFO
[id
].cm_offset
];
291 pll
->reg_a2w_ctrl
= &s
->regs
[PLL_INIT_INFO
[id
].a2w_ctrl_offset
];
292 pll
->reg_a2w_ana
= &s
->regs
[PLL_INIT_INFO
[id
].a2w_ana_offset
];
293 pll
->prediv_mask
= PLL_INIT_INFO
[id
].prediv_mask
;
294 pll
->reg_a2w_frac
= &s
->regs
[PLL_INIT_INFO
[id
].a2w_frac_offset
];
298 /* PLL channel init info */
299 typedef struct PLLChannelInitInfo
{
303 uint32_t cm_hold_mask
;
304 uint32_t cm_load_mask
;
305 size_t a2w_ctrl_offset
;
306 unsigned int fixed_divider
;
307 } PLLChannelInitInfo
;
309 #define FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_) \
310 .parent = CPRMAN_ ## pll_, \
311 .cm_offset = R_CM_ ## pll_, \
312 .cm_load_mask = R_CM_ ## pll_ ## _ ## LOAD ## channel_ ## _MASK, \
313 .a2w_ctrl_offset = R_A2W_ ## pll_ ## _ ## channel_
315 #define FILL_PLL_CHANNEL_INIT_INFO(pll_, channel_) \
316 FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \
317 .cm_hold_mask = R_CM_ ## pll_ ## _ ## HOLD ## channel_ ## _MASK, \
320 #define FILL_PLL_CHANNEL_INIT_INFO_nohold(pll_, channel_) \
321 FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \
324 static PLLChannelInitInfo PLL_CHANNEL_INIT_INFO
[] = {
325 [CPRMAN_PLLA_CHANNEL_DSI0
] = {
327 FILL_PLL_CHANNEL_INIT_INFO(PLLA
, DSI0
),
329 [CPRMAN_PLLA_CHANNEL_CORE
] = {
331 FILL_PLL_CHANNEL_INIT_INFO(PLLA
, CORE
),
333 [CPRMAN_PLLA_CHANNEL_PER
] = {
335 FILL_PLL_CHANNEL_INIT_INFO(PLLA
, PER
),
337 [CPRMAN_PLLA_CHANNEL_CCP2
] = {
339 FILL_PLL_CHANNEL_INIT_INFO(PLLA
, CCP2
),
342 [CPRMAN_PLLC_CHANNEL_CORE2
] = {
343 .name
= "pllc-core2",
344 FILL_PLL_CHANNEL_INIT_INFO(PLLC
, CORE2
),
346 [CPRMAN_PLLC_CHANNEL_CORE1
] = {
347 .name
= "pllc-core1",
348 FILL_PLL_CHANNEL_INIT_INFO(PLLC
, CORE1
),
350 [CPRMAN_PLLC_CHANNEL_PER
] = {
352 FILL_PLL_CHANNEL_INIT_INFO(PLLC
, PER
),
354 [CPRMAN_PLLC_CHANNEL_CORE0
] = {
355 .name
= "pllc-core0",
356 FILL_PLL_CHANNEL_INIT_INFO(PLLC
, CORE0
),
359 [CPRMAN_PLLD_CHANNEL_DSI0
] = {
361 FILL_PLL_CHANNEL_INIT_INFO(PLLD
, DSI0
),
363 [CPRMAN_PLLD_CHANNEL_CORE
] = {
365 FILL_PLL_CHANNEL_INIT_INFO(PLLD
, CORE
),
367 [CPRMAN_PLLD_CHANNEL_PER
] = {
369 FILL_PLL_CHANNEL_INIT_INFO(PLLD
, PER
),
371 [CPRMAN_PLLD_CHANNEL_DSI1
] = {
373 FILL_PLL_CHANNEL_INIT_INFO(PLLD
, DSI1
),
376 [CPRMAN_PLLH_CHANNEL_AUX
] = {
379 FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH
, AUX
),
381 [CPRMAN_PLLH_CHANNEL_RCAL
] = {
384 FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH
, RCAL
),
386 [CPRMAN_PLLH_CHANNEL_PIX
] = {
389 FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH
, PIX
),
392 [CPRMAN_PLLB_CHANNEL_ARM
] = {
394 FILL_PLL_CHANNEL_INIT_INFO(PLLB
, ARM
),
398 #undef FILL_PLL_CHANNEL_INIT_INFO_nohold
399 #undef FILL_PLL_CHANNEL_INIT_INFO
400 #undef FILL_PLL_CHANNEL_INIT_INFO_common
402 static inline void set_pll_channel_init_info(BCM2835CprmanState
*s
,
403 CprmanPllChannelState
*channel
,
407 channel
->parent
= PLL_CHANNEL_INIT_INFO
[id
].parent
;
408 channel
->reg_cm
= &s
->regs
[PLL_CHANNEL_INIT_INFO
[id
].cm_offset
];
409 channel
->hold_mask
= PLL_CHANNEL_INIT_INFO
[id
].cm_hold_mask
;
410 channel
->load_mask
= PLL_CHANNEL_INIT_INFO
[id
].cm_load_mask
;
411 channel
->reg_a2w_ctrl
= &s
->regs
[PLL_CHANNEL_INIT_INFO
[id
].a2w_ctrl_offset
];
412 channel
->fixed_divider
= PLL_CHANNEL_INIT_INFO
[id
].fixed_divider
;
415 /* Clock mux init info */
416 typedef struct ClockMuxInitInfo
{
418 size_t cm_offset
; /* cm_offset[0]->CM_CTL, cm_offset[1]->CM_DIV */
422 CprmanPllChannel src_mapping
[CPRMAN_NUM_CLOCK_MUX_SRC
];
426 * Each clock mux can have up to 10 sources. Sources 0 to 3 are always the
427 * same (ground, xosc, td0, td1). Sources 4 to 9 are mux specific, and are not
428 * always populated. The following macros catch all those cases.
431 /* Unknown mapping. Connect everything to ground */
432 #define SRC_MAPPING_INFO_unknown \
434 CPRMAN_CLOCK_SRC_FORCE_GROUND, /* gnd */ \
435 CPRMAN_CLOCK_SRC_FORCE_GROUND, /* xosc */ \
436 CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 0 */ \
437 CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 1 */ \
438 CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll a */ \
439 CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c */ \
440 CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll d */ \
441 CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll h */ \
442 CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core1 */ \
443 CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core2 */ \
446 /* Only the oscillator and the two test debug clocks */
447 #define SRC_MAPPING_INFO_xosc \
449 CPRMAN_CLOCK_SRC_NORMAL, \
450 CPRMAN_CLOCK_SRC_NORMAL, \
451 CPRMAN_CLOCK_SRC_NORMAL, \
452 CPRMAN_CLOCK_SRC_NORMAL, \
453 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
454 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
455 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
456 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
457 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
458 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
461 /* All the PLL "core" channels */
462 #define SRC_MAPPING_INFO_core \
464 CPRMAN_CLOCK_SRC_NORMAL, \
465 CPRMAN_CLOCK_SRC_NORMAL, \
466 CPRMAN_CLOCK_SRC_NORMAL, \
467 CPRMAN_CLOCK_SRC_NORMAL, \
468 CPRMAN_PLLA_CHANNEL_CORE, \
469 CPRMAN_PLLC_CHANNEL_CORE0, \
470 CPRMAN_PLLD_CHANNEL_CORE, \
471 CPRMAN_PLLH_CHANNEL_AUX, \
472 CPRMAN_PLLC_CHANNEL_CORE1, \
473 CPRMAN_PLLC_CHANNEL_CORE2, \
476 /* All the PLL "per" channels */
477 #define SRC_MAPPING_INFO_periph \
479 CPRMAN_CLOCK_SRC_NORMAL, \
480 CPRMAN_CLOCK_SRC_NORMAL, \
481 CPRMAN_CLOCK_SRC_NORMAL, \
482 CPRMAN_CLOCK_SRC_NORMAL, \
483 CPRMAN_PLLA_CHANNEL_PER, \
484 CPRMAN_PLLC_CHANNEL_PER, \
485 CPRMAN_PLLD_CHANNEL_PER, \
486 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
487 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
488 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
492 * The DSI0 channels. This one got an intermediate mux between the PLL channels
493 * and the clock input.
495 #define SRC_MAPPING_INFO_dsi0 \
497 CPRMAN_CLOCK_SRC_NORMAL, \
498 CPRMAN_CLOCK_SRC_NORMAL, \
499 CPRMAN_CLOCK_SRC_NORMAL, \
500 CPRMAN_CLOCK_SRC_NORMAL, \
501 CPRMAN_CLOCK_SRC_DSI0HSCK, \
502 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
503 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
504 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
505 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
506 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
509 /* The DSI1 channel */
510 #define SRC_MAPPING_INFO_dsi1 \
512 CPRMAN_CLOCK_SRC_NORMAL, \
513 CPRMAN_CLOCK_SRC_NORMAL, \
514 CPRMAN_CLOCK_SRC_NORMAL, \
515 CPRMAN_CLOCK_SRC_NORMAL, \
516 CPRMAN_PLLD_CHANNEL_DSI1, \
517 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
518 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
519 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
520 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
521 CPRMAN_CLOCK_SRC_FORCE_GROUND, \
524 #define FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) \
525 SRC_MAPPING_INFO_ ## kind_
527 #define FILL_CLOCK_MUX_INIT_INFO(clock_, kind_) \
528 .cm_offset = R_CM_ ## clock_ ## CTL, \
529 FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_)
531 static ClockMuxInitInfo CLOCK_MUX_INIT_INFO
[] = {
532 [CPRMAN_CLOCK_GNRIC
] = {
534 FILL_CLOCK_MUX_INIT_INFO(GNRIC
, unknown
),
536 [CPRMAN_CLOCK_VPU
] = {
540 FILL_CLOCK_MUX_INIT_INFO(VPU
, core
),
542 [CPRMAN_CLOCK_SYS
] = {
544 FILL_CLOCK_MUX_INIT_INFO(SYS
, unknown
),
546 [CPRMAN_CLOCK_PERIA
] = {
548 FILL_CLOCK_MUX_INIT_INFO(PERIA
, unknown
),
550 [CPRMAN_CLOCK_PERII
] = {
552 FILL_CLOCK_MUX_INIT_INFO(PERII
, unknown
),
554 [CPRMAN_CLOCK_H264
] = {
558 FILL_CLOCK_MUX_INIT_INFO(H264
, core
),
560 [CPRMAN_CLOCK_ISP
] = {
564 FILL_CLOCK_MUX_INIT_INFO(ISP
, core
),
566 [CPRMAN_CLOCK_V3D
] = {
568 FILL_CLOCK_MUX_INIT_INFO(V3D
, core
),
570 [CPRMAN_CLOCK_CAM0
] = {
574 FILL_CLOCK_MUX_INIT_INFO(CAM0
, periph
),
576 [CPRMAN_CLOCK_CAM1
] = {
580 FILL_CLOCK_MUX_INIT_INFO(CAM1
, periph
),
582 [CPRMAN_CLOCK_CCP2
] = {
584 FILL_CLOCK_MUX_INIT_INFO(CCP2
, unknown
),
586 [CPRMAN_CLOCK_DSI0E
] = {
590 FILL_CLOCK_MUX_INIT_INFO(DSI0E
, dsi0
),
592 [CPRMAN_CLOCK_DSI0P
] = {
596 FILL_CLOCK_MUX_INIT_INFO(DSI0P
, dsi0
),
598 [CPRMAN_CLOCK_DPI
] = {
602 FILL_CLOCK_MUX_INIT_INFO(DPI
, periph
),
604 [CPRMAN_CLOCK_GP0
] = {
608 FILL_CLOCK_MUX_INIT_INFO(GP0
, periph
),
610 [CPRMAN_CLOCK_GP1
] = {
614 FILL_CLOCK_MUX_INIT_INFO(GP1
, periph
),
616 [CPRMAN_CLOCK_GP2
] = {
620 FILL_CLOCK_MUX_INIT_INFO(GP2
, periph
),
622 [CPRMAN_CLOCK_HSM
] = {
626 FILL_CLOCK_MUX_INIT_INFO(HSM
, periph
),
628 [CPRMAN_CLOCK_OTP
] = {
632 FILL_CLOCK_MUX_INIT_INFO(OTP
, xosc
),
634 [CPRMAN_CLOCK_PCM
] = {
638 FILL_CLOCK_MUX_INIT_INFO(PCM
, periph
),
640 [CPRMAN_CLOCK_PWM
] = {
644 FILL_CLOCK_MUX_INIT_INFO(PWM
, periph
),
646 [CPRMAN_CLOCK_SLIM
] = {
650 FILL_CLOCK_MUX_INIT_INFO(SLIM
, periph
),
652 [CPRMAN_CLOCK_SMI
] = {
656 FILL_CLOCK_MUX_INIT_INFO(SMI
, periph
),
658 [CPRMAN_CLOCK_TEC
] = {
662 FILL_CLOCK_MUX_INIT_INFO(TEC
, xosc
),
664 [CPRMAN_CLOCK_TD0
] = {
666 FILL_CLOCK_MUX_INIT_INFO(TD0
, unknown
),
668 [CPRMAN_CLOCK_TD1
] = {
670 FILL_CLOCK_MUX_INIT_INFO(TD1
, unknown
),
672 [CPRMAN_CLOCK_TSENS
] = {
676 FILL_CLOCK_MUX_INIT_INFO(TSENS
, xosc
),
678 [CPRMAN_CLOCK_TIMER
] = {
682 FILL_CLOCK_MUX_INIT_INFO(TIMER
, xosc
),
684 [CPRMAN_CLOCK_UART
] = {
688 FILL_CLOCK_MUX_INIT_INFO(UART
, periph
),
690 [CPRMAN_CLOCK_VEC
] = {
694 FILL_CLOCK_MUX_INIT_INFO(VEC
, periph
),
696 [CPRMAN_CLOCK_PULSE
] = {
698 FILL_CLOCK_MUX_INIT_INFO(PULSE
, xosc
),
700 [CPRMAN_CLOCK_SDC
] = {
704 FILL_CLOCK_MUX_INIT_INFO(SDC
, core
),
706 [CPRMAN_CLOCK_ARM
] = {
708 FILL_CLOCK_MUX_INIT_INFO(ARM
, unknown
),
710 [CPRMAN_CLOCK_AVEO
] = {
714 FILL_CLOCK_MUX_INIT_INFO(AVEO
, periph
),
716 [CPRMAN_CLOCK_EMMC
] = {
720 FILL_CLOCK_MUX_INIT_INFO(EMMC
, periph
),
722 [CPRMAN_CLOCK_EMMC2
] = {
726 FILL_CLOCK_MUX_INIT_INFO(EMMC2
, unknown
),
730 #undef FILL_CLOCK_MUX_INIT_INFO
731 #undef FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO
732 #undef SRC_MAPPING_INFO_dsi1
733 #undef SRC_MAPPING_INFO_dsi0
734 #undef SRC_MAPPING_INFO_periph
735 #undef SRC_MAPPING_INFO_core
736 #undef SRC_MAPPING_INFO_xosc
737 #undef SRC_MAPPING_INFO_unknown
739 static inline void set_clock_mux_init_info(BCM2835CprmanState
*s
,
740 CprmanClockMuxState
*mux
,
744 mux
->reg_ctl
= &s
->regs
[CLOCK_MUX_INIT_INFO
[id
].cm_offset
];
745 mux
->reg_div
= &s
->regs
[CLOCK_MUX_INIT_INFO
[id
].cm_offset
+ 1];
746 mux
->int_bits
= CLOCK_MUX_INIT_INFO
[id
].int_bits
;
747 mux
->frac_bits
= CLOCK_MUX_INIT_INFO
[id
].frac_bits
;
753 * Those values have been dumped from a Raspberry Pi 3 Model B v1.2 using the
754 * clk debugfs interface in Linux.
756 typedef struct PLLResetInfo
{
763 static const PLLResetInfo PLL_RESET_INFO
[] = {
766 .a2w_ctrl
= 0x0002103a,
767 .a2w_frac
= 0x00098000,
768 .a2w_ana
= { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
773 .a2w_ctrl
= 0x0002103e,
774 .a2w_frac
= 0x00080000,
775 .a2w_ana
= { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
780 .a2w_ctrl
= 0x00021034,
781 .a2w_frac
= 0x00015556,
782 .a2w_ana
= { 0x00000000, 0x00144000, 0x00000000, 0x00000100 }
787 .a2w_ctrl
= 0x0002102d,
788 .a2w_frac
= 0x00000000,
789 .a2w_ana
= { 0x00900000, 0x0000000c, 0x00000000, 0x00000000 }
795 .a2w_ctrl
= 0x00000000,
796 .a2w_frac
= 0x00000000,
797 .a2w_ana
= { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }
801 typedef struct PLLChannelResetInfo
{
803 * Even though a PLL channel has a CM register, it shares it with its
804 * parent PLL. The parent already takes care of the reset value.
807 } PLLChannelResetInfo
;
809 static const PLLChannelResetInfo PLL_CHANNEL_RESET_INFO
[] = {
810 [CPRMAN_PLLA_CHANNEL_DSI0
] = { .a2w_ctrl
= 0x00000100 },
811 [CPRMAN_PLLA_CHANNEL_CORE
] = { .a2w_ctrl
= 0x00000003 },
812 [CPRMAN_PLLA_CHANNEL_PER
] = { .a2w_ctrl
= 0x00000000 }, /* unknown */
813 [CPRMAN_PLLA_CHANNEL_CCP2
] = { .a2w_ctrl
= 0x00000100 },
815 [CPRMAN_PLLC_CHANNEL_CORE2
] = { .a2w_ctrl
= 0x00000100 },
816 [CPRMAN_PLLC_CHANNEL_CORE1
] = { .a2w_ctrl
= 0x00000100 },
817 [CPRMAN_PLLC_CHANNEL_PER
] = { .a2w_ctrl
= 0x00000002 },
818 [CPRMAN_PLLC_CHANNEL_CORE0
] = { .a2w_ctrl
= 0x00000002 },
820 [CPRMAN_PLLD_CHANNEL_DSI0
] = { .a2w_ctrl
= 0x00000100 },
821 [CPRMAN_PLLD_CHANNEL_CORE
] = { .a2w_ctrl
= 0x00000004 },
822 [CPRMAN_PLLD_CHANNEL_PER
] = { .a2w_ctrl
= 0x00000004 },
823 [CPRMAN_PLLD_CHANNEL_DSI1
] = { .a2w_ctrl
= 0x00000100 },
825 [CPRMAN_PLLH_CHANNEL_AUX
] = { .a2w_ctrl
= 0x00000004 },
826 [CPRMAN_PLLH_CHANNEL_RCAL
] = { .a2w_ctrl
= 0x00000000 },
827 [CPRMAN_PLLH_CHANNEL_PIX
] = { .a2w_ctrl
= 0x00000000 },
829 [CPRMAN_PLLB_CHANNEL_ARM
] = { .a2w_ctrl
= 0x00000000 }, /* unknown */
832 typedef struct ClockMuxResetInfo
{
837 static const ClockMuxResetInfo CLOCK_MUX_RESET_INFO
[] = {
838 [CPRMAN_CLOCK_GNRIC
] = {
839 .cm_ctl
= 0, /* unknown */
843 [CPRMAN_CLOCK_VPU
] = {
844 .cm_ctl
= 0x00000245,
845 .cm_div
= 0x00003000,
848 [CPRMAN_CLOCK_SYS
] = {
849 .cm_ctl
= 0, /* unknown */
853 [CPRMAN_CLOCK_PERIA
] = {
854 .cm_ctl
= 0, /* unknown */
858 [CPRMAN_CLOCK_PERII
] = {
859 .cm_ctl
= 0, /* unknown */
863 [CPRMAN_CLOCK_H264
] = {
864 .cm_ctl
= 0x00000244,
865 .cm_div
= 0x00003000,
868 [CPRMAN_CLOCK_ISP
] = {
869 .cm_ctl
= 0x00000244,
870 .cm_div
= 0x00003000,
873 [CPRMAN_CLOCK_V3D
] = {
874 .cm_ctl
= 0, /* unknown */
878 [CPRMAN_CLOCK_CAM0
] = {
879 .cm_ctl
= 0x00000000,
880 .cm_div
= 0x00000000,
883 [CPRMAN_CLOCK_CAM1
] = {
884 .cm_ctl
= 0x00000000,
885 .cm_div
= 0x00000000,
888 [CPRMAN_CLOCK_CCP2
] = {
889 .cm_ctl
= 0, /* unknown */
893 [CPRMAN_CLOCK_DSI0E
] = {
894 .cm_ctl
= 0x00000000,
895 .cm_div
= 0x00000000,
898 [CPRMAN_CLOCK_DSI0P
] = {
899 .cm_ctl
= 0x00000000,
900 .cm_div
= 0x00000000,
903 [CPRMAN_CLOCK_DPI
] = {
904 .cm_ctl
= 0x00000000,
905 .cm_div
= 0x00000000,
908 [CPRMAN_CLOCK_GP0
] = {
909 .cm_ctl
= 0x00000200,
910 .cm_div
= 0x00000000,
913 [CPRMAN_CLOCK_GP1
] = {
914 .cm_ctl
= 0x00000096,
915 .cm_div
= 0x00014000,
918 [CPRMAN_CLOCK_GP2
] = {
919 .cm_ctl
= 0x00000291,
920 .cm_div
= 0x00249f00,
923 [CPRMAN_CLOCK_HSM
] = {
924 .cm_ctl
= 0x00000000,
925 .cm_div
= 0x00000000,
928 [CPRMAN_CLOCK_OTP
] = {
929 .cm_ctl
= 0x00000091,
930 .cm_div
= 0x00004000,
933 [CPRMAN_CLOCK_PCM
] = {
934 .cm_ctl
= 0x00000200,
935 .cm_div
= 0x00000000,
938 [CPRMAN_CLOCK_PWM
] = {
939 .cm_ctl
= 0x00000200,
940 .cm_div
= 0x00000000,
943 [CPRMAN_CLOCK_SLIM
] = {
944 .cm_ctl
= 0x00000200,
945 .cm_div
= 0x00000000,
948 [CPRMAN_CLOCK_SMI
] = {
949 .cm_ctl
= 0x00000000,
950 .cm_div
= 0x00000000,
953 [CPRMAN_CLOCK_TEC
] = {
954 .cm_ctl
= 0x00000000,
955 .cm_div
= 0x00000000,
958 [CPRMAN_CLOCK_TD0
] = {
959 .cm_ctl
= 0, /* unknown */
963 [CPRMAN_CLOCK_TD1
] = {
964 .cm_ctl
= 0, /* unknown */
968 [CPRMAN_CLOCK_TSENS
] = {
969 .cm_ctl
= 0x00000091,
970 .cm_div
= 0x0000a000,
973 [CPRMAN_CLOCK_TIMER
] = {
974 .cm_ctl
= 0x00000291,
975 .cm_div
= 0x00013333,
978 [CPRMAN_CLOCK_UART
] = {
979 .cm_ctl
= 0x00000296,
980 .cm_div
= 0x0000a6ab,
983 [CPRMAN_CLOCK_VEC
] = {
984 .cm_ctl
= 0x00000097,
985 .cm_div
= 0x00002000,
988 [CPRMAN_CLOCK_PULSE
] = {
989 .cm_ctl
= 0, /* unknown */
993 [CPRMAN_CLOCK_SDC
] = {
994 .cm_ctl
= 0x00004006,
995 .cm_div
= 0x00003000,
998 [CPRMAN_CLOCK_ARM
] = {
999 .cm_ctl
= 0, /* unknown */
1003 [CPRMAN_CLOCK_AVEO
] = {
1004 .cm_ctl
= 0x00000000,
1005 .cm_div
= 0x00000000,
1008 [CPRMAN_CLOCK_EMMC
] = {
1009 .cm_ctl
= 0x00000295,
1010 .cm_div
= 0x00006000,
1013 [CPRMAN_CLOCK_EMMC2
] = {
1014 .cm_ctl
= 0, /* unknown */