xref: /qemu/include/hw/misc/bcm2835_cprman_internals.h (revision 09d56bbc9bc2f40865764b06b9830a9504bd3f9a)
1 /*
2  * BCM2835 CPRMAN clock manager
3  *
4  * Copyright (c) 2020 Luc Michel <luc@lmichel.fr>
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #ifndef HW_MISC_CPRMAN_INTERNALS_H
10 #define HW_MISC_CPRMAN_INTERNALS_H
11 
12 #include "hw/registerfields.h"
13 #include "hw/misc/bcm2835_cprman.h"
14 
15 #define TYPE_CPRMAN_PLL "bcm2835-cprman-pll"
16 #define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel"
17 
18 DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL,
19                          TYPE_CPRMAN_PLL)
20 DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL,
21                          TYPE_CPRMAN_PLL_CHANNEL)
22 
23 /* Register map */
24 
25 /* PLLs */
26 REG32(CM_PLLA, 0x104)
27     FIELD(CM_PLLA, LOADDSI0, 0, 1)
28     FIELD(CM_PLLA, HOLDDSI0, 1, 1)
29     FIELD(CM_PLLA, LOADCCP2, 2, 1)
30     FIELD(CM_PLLA, HOLDCCP2, 3, 1)
31     FIELD(CM_PLLA, LOADCORE, 4, 1)
32     FIELD(CM_PLLA, HOLDCORE, 5, 1)
33     FIELD(CM_PLLA, LOADPER, 6, 1)
34     FIELD(CM_PLLA, HOLDPER, 7, 1)
35     FIELD(CM_PLLx, ANARST, 8, 1)
36 REG32(CM_PLLC, 0x108)
37     FIELD(CM_PLLC, LOADCORE0, 0, 1)
38     FIELD(CM_PLLC, HOLDCORE0, 1, 1)
39     FIELD(CM_PLLC, LOADCORE1, 2, 1)
40     FIELD(CM_PLLC, HOLDCORE1, 3, 1)
41     FIELD(CM_PLLC, LOADCORE2, 4, 1)
42     FIELD(CM_PLLC, HOLDCORE2, 5, 1)
43     FIELD(CM_PLLC, LOADPER, 6, 1)
44     FIELD(CM_PLLC, HOLDPER, 7, 1)
45 REG32(CM_PLLD, 0x10c)
46     FIELD(CM_PLLD, LOADDSI0, 0, 1)
47     FIELD(CM_PLLD, HOLDDSI0, 1, 1)
48     FIELD(CM_PLLD, LOADDSI1, 2, 1)
49     FIELD(CM_PLLD, HOLDDSI1, 3, 1)
50     FIELD(CM_PLLD, LOADCORE, 4, 1)
51     FIELD(CM_PLLD, HOLDCORE, 5, 1)
52     FIELD(CM_PLLD, LOADPER, 6, 1)
53     FIELD(CM_PLLD, HOLDPER, 7, 1)
54 REG32(CM_PLLH, 0x110)
55     FIELD(CM_PLLH, LOADPIX, 0, 1)
56     FIELD(CM_PLLH, LOADAUX, 1, 1)
57     FIELD(CM_PLLH, LOADRCAL, 2, 1)
58 REG32(CM_PLLB, 0x170)
59     FIELD(CM_PLLB, LOADARM, 0, 1)
60     FIELD(CM_PLLB, HOLDARM, 1, 1)
61 
62 REG32(A2W_PLLA_CTRL, 0x1100)
63     FIELD(A2W_PLLx_CTRL, NDIV, 0, 10)
64     FIELD(A2W_PLLx_CTRL, PDIV, 12, 3)
65     FIELD(A2W_PLLx_CTRL, PWRDN, 16, 1)
66     FIELD(A2W_PLLx_CTRL, PRST_DISABLE, 17, 1)
67 REG32(A2W_PLLC_CTRL, 0x1120)
68 REG32(A2W_PLLD_CTRL, 0x1140)
69 REG32(A2W_PLLH_CTRL, 0x1160)
70 REG32(A2W_PLLB_CTRL, 0x11e0)
71 
72 REG32(A2W_PLLA_ANA0, 0x1010)
73 REG32(A2W_PLLA_ANA1, 0x1014)
74     FIELD(A2W_PLLx_ANA1, FB_PREDIV, 14, 1)
75 REG32(A2W_PLLA_ANA2, 0x1018)
76 REG32(A2W_PLLA_ANA3, 0x101c)
77 
78 REG32(A2W_PLLC_ANA0, 0x1030)
79 REG32(A2W_PLLC_ANA1, 0x1034)
80 REG32(A2W_PLLC_ANA2, 0x1038)
81 REG32(A2W_PLLC_ANA3, 0x103c)
82 
83 REG32(A2W_PLLD_ANA0, 0x1050)
84 REG32(A2W_PLLD_ANA1, 0x1054)
85 REG32(A2W_PLLD_ANA2, 0x1058)
86 REG32(A2W_PLLD_ANA3, 0x105c)
87 
88 REG32(A2W_PLLH_ANA0, 0x1070)
89 REG32(A2W_PLLH_ANA1, 0x1074)
90     FIELD(A2W_PLLH_ANA1, FB_PREDIV, 11, 1)
91 REG32(A2W_PLLH_ANA2, 0x1078)
92 REG32(A2W_PLLH_ANA3, 0x107c)
93 
94 REG32(A2W_PLLB_ANA0, 0x10f0)
95 REG32(A2W_PLLB_ANA1, 0x10f4)
96 REG32(A2W_PLLB_ANA2, 0x10f8)
97 REG32(A2W_PLLB_ANA3, 0x10fc)
98 
99 REG32(A2W_PLLA_FRAC, 0x1200)
100     FIELD(A2W_PLLx_FRAC, FRAC, 0, 20)
101 REG32(A2W_PLLC_FRAC, 0x1220)
102 REG32(A2W_PLLD_FRAC, 0x1240)
103 REG32(A2W_PLLH_FRAC, 0x1260)
104 REG32(A2W_PLLB_FRAC, 0x12e0)
105 
106 /* PLL channels */
107 REG32(A2W_PLLA_DSI0, 0x1300)
108     FIELD(A2W_PLLx_CHANNELy, DIV, 0, 8)
109     FIELD(A2W_PLLx_CHANNELy, DISABLE, 8, 1)
110 REG32(A2W_PLLA_CORE, 0x1400)
111 REG32(A2W_PLLA_PER, 0x1500)
112 REG32(A2W_PLLA_CCP2, 0x1600)
113 
114 REG32(A2W_PLLC_CORE2, 0x1320)
115 REG32(A2W_PLLC_CORE1, 0x1420)
116 REG32(A2W_PLLC_PER, 0x1520)
117 REG32(A2W_PLLC_CORE0, 0x1620)
118 
119 REG32(A2W_PLLD_DSI0, 0x1340)
120 REG32(A2W_PLLD_CORE, 0x1440)
121 REG32(A2W_PLLD_PER, 0x1540)
122 REG32(A2W_PLLD_DSI1, 0x1640)
123 
124 REG32(A2W_PLLH_AUX, 0x1360)
125 REG32(A2W_PLLH_RCAL, 0x1460)
126 REG32(A2W_PLLH_PIX, 0x1560)
127 REG32(A2W_PLLH_STS, 0x1660)
128 
129 REG32(A2W_PLLB_ARM, 0x13e0)
130 
131 /* misc registers */
132 REG32(CM_LOCK, 0x114)
133     FIELD(CM_LOCK, FLOCKH, 12, 1)
134     FIELD(CM_LOCK, FLOCKD, 11, 1)
135     FIELD(CM_LOCK, FLOCKC, 10, 1)
136     FIELD(CM_LOCK, FLOCKB, 9, 1)
137     FIELD(CM_LOCK, FLOCKA, 8, 1)
138 
139 /*
140  * This field is common to all registers. Each register write value must match
141  * the CPRMAN_PASSWORD magic value in its 8 MSB.
142  */
143 FIELD(CPRMAN, PASSWORD, 24, 8)
144 #define CPRMAN_PASSWORD 0x5a
145 
146 /* PLL init info */
147 typedef struct PLLInitInfo {
148     const char *name;
149     size_t cm_offset;
150     size_t a2w_ctrl_offset;
151     size_t a2w_ana_offset;
152     uint32_t prediv_mask; /* Prediv bit in ana[1] */
153     size_t a2w_frac_offset;
154 } PLLInitInfo;
155 
156 #define FILL_PLL_INIT_INFO(pll_)                \
157     .cm_offset = R_CM_ ## pll_,                 \
158     .a2w_ctrl_offset = R_A2W_ ## pll_ ## _CTRL, \
159     .a2w_ana_offset = R_A2W_ ## pll_ ## _ANA0,  \
160     .a2w_frac_offset = R_A2W_ ## pll_ ## _FRAC
161 
162 static const PLLInitInfo PLL_INIT_INFO[] = {
163     [CPRMAN_PLLA] = {
164         .name = "plla",
165         .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
166         FILL_PLL_INIT_INFO(PLLA),
167     },
168     [CPRMAN_PLLC] = {
169         .name = "pllc",
170         .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
171         FILL_PLL_INIT_INFO(PLLC),
172     },
173     [CPRMAN_PLLD] = {
174         .name = "plld",
175         .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
176         FILL_PLL_INIT_INFO(PLLD),
177     },
178     [CPRMAN_PLLH] = {
179         .name = "pllh",
180         .prediv_mask = R_A2W_PLLH_ANA1_FB_PREDIV_MASK,
181         FILL_PLL_INIT_INFO(PLLH),
182     },
183     [CPRMAN_PLLB] = {
184         .name = "pllb",
185         .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK,
186         FILL_PLL_INIT_INFO(PLLB),
187     },
188 };
189 
190 #undef FILL_PLL_CHANNEL_INIT_INFO
191 
192 static inline void set_pll_init_info(BCM2835CprmanState *s,
193                                      CprmanPllState *pll,
194                                      CprmanPll id)
195 {
196     pll->id = id;
197     pll->reg_cm = &s->regs[PLL_INIT_INFO[id].cm_offset];
198     pll->reg_a2w_ctrl = &s->regs[PLL_INIT_INFO[id].a2w_ctrl_offset];
199     pll->reg_a2w_ana = &s->regs[PLL_INIT_INFO[id].a2w_ana_offset];
200     pll->prediv_mask = PLL_INIT_INFO[id].prediv_mask;
201     pll->reg_a2w_frac = &s->regs[PLL_INIT_INFO[id].a2w_frac_offset];
202 }
203 
204 
205 /* PLL channel init info */
206 typedef struct PLLChannelInitInfo {
207     const char *name;
208     CprmanPll parent;
209     size_t cm_offset;
210     uint32_t cm_hold_mask;
211     uint32_t cm_load_mask;
212     size_t a2w_ctrl_offset;
213     unsigned int fixed_divider;
214 } PLLChannelInitInfo;
215 
216 #define FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_)            \
217     .parent = CPRMAN_ ## pll_,                                       \
218     .cm_offset = R_CM_ ## pll_,                                      \
219     .cm_load_mask = R_CM_ ## pll_ ## _ ## LOAD ## channel_ ## _MASK, \
220     .a2w_ctrl_offset = R_A2W_ ## pll_ ## _ ## channel_
221 
222 #define FILL_PLL_CHANNEL_INIT_INFO(pll_, channel_)                   \
223     FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_),               \
224     .cm_hold_mask = R_CM_ ## pll_ ## _ ## HOLD ## channel_ ## _MASK, \
225     .fixed_divider = 1
226 
227 #define FILL_PLL_CHANNEL_INIT_INFO_nohold(pll_, channel_) \
228     FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_),    \
229     .cm_hold_mask = 0
230 
231 static PLLChannelInitInfo PLL_CHANNEL_INIT_INFO[] = {
232     [CPRMAN_PLLA_CHANNEL_DSI0] = {
233         .name = "plla-dsi0",
234         FILL_PLL_CHANNEL_INIT_INFO(PLLA, DSI0),
235     },
236     [CPRMAN_PLLA_CHANNEL_CORE] = {
237         .name = "plla-core",
238         FILL_PLL_CHANNEL_INIT_INFO(PLLA, CORE),
239     },
240     [CPRMAN_PLLA_CHANNEL_PER] = {
241         .name = "plla-per",
242         FILL_PLL_CHANNEL_INIT_INFO(PLLA, PER),
243     },
244     [CPRMAN_PLLA_CHANNEL_CCP2] = {
245         .name = "plla-ccp2",
246         FILL_PLL_CHANNEL_INIT_INFO(PLLA, CCP2),
247     },
248 
249     [CPRMAN_PLLC_CHANNEL_CORE2] = {
250         .name = "pllc-core2",
251         FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE2),
252     },
253     [CPRMAN_PLLC_CHANNEL_CORE1] = {
254         .name = "pllc-core1",
255         FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE1),
256     },
257     [CPRMAN_PLLC_CHANNEL_PER] = {
258         .name = "pllc-per",
259         FILL_PLL_CHANNEL_INIT_INFO(PLLC, PER),
260     },
261     [CPRMAN_PLLC_CHANNEL_CORE0] = {
262         .name = "pllc-core0",
263         FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE0),
264     },
265 
266     [CPRMAN_PLLD_CHANNEL_DSI0] = {
267         .name = "plld-dsi0",
268         FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI0),
269     },
270     [CPRMAN_PLLD_CHANNEL_CORE] = {
271         .name = "plld-core",
272         FILL_PLL_CHANNEL_INIT_INFO(PLLD, CORE),
273     },
274     [CPRMAN_PLLD_CHANNEL_PER] = {
275         .name = "plld-per",
276         FILL_PLL_CHANNEL_INIT_INFO(PLLD, PER),
277     },
278     [CPRMAN_PLLD_CHANNEL_DSI1] = {
279         .name = "plld-dsi1",
280         FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI1),
281     },
282 
283     [CPRMAN_PLLH_CHANNEL_AUX] = {
284         .name = "pllh-aux",
285         .fixed_divider = 1,
286         FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, AUX),
287     },
288     [CPRMAN_PLLH_CHANNEL_RCAL] = {
289         .name = "pllh-rcal",
290         .fixed_divider = 10,
291         FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, RCAL),
292     },
293     [CPRMAN_PLLH_CHANNEL_PIX] = {
294         .name = "pllh-pix",
295         .fixed_divider = 10,
296         FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, PIX),
297     },
298 
299     [CPRMAN_PLLB_CHANNEL_ARM] = {
300         .name = "pllb-arm",
301         FILL_PLL_CHANNEL_INIT_INFO(PLLB, ARM),
302     },
303 };
304 
305 #undef FILL_PLL_CHANNEL_INIT_INFO_nohold
306 #undef FILL_PLL_CHANNEL_INIT_INFO
307 #undef FILL_PLL_CHANNEL_INIT_INFO_common
308 
309 static inline void set_pll_channel_init_info(BCM2835CprmanState *s,
310                                              CprmanPllChannelState *channel,
311                                              CprmanPllChannel id)
312 {
313     channel->id = id;
314     channel->parent = PLL_CHANNEL_INIT_INFO[id].parent;
315     channel->reg_cm = &s->regs[PLL_CHANNEL_INIT_INFO[id].cm_offset];
316     channel->hold_mask = PLL_CHANNEL_INIT_INFO[id].cm_hold_mask;
317     channel->load_mask = PLL_CHANNEL_INIT_INFO[id].cm_load_mask;
318     channel->reg_a2w_ctrl = &s->regs[PLL_CHANNEL_INIT_INFO[id].a2w_ctrl_offset];
319     channel->fixed_divider = PLL_CHANNEL_INIT_INFO[id].fixed_divider;
320 }
321 
322 #endif
323