hw/misc/bcm2835_cprman: add a PLL channel skeleton implementation
[qemu.git] / hw / misc / bcm2835_cprman.c
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 /*
10 * This peripheral is roughly divided into 3 main parts:
11 * - the PLLs
12 * - the PLL channels
13 * - the clock muxes
14 *
15 * A main oscillator (xosc) feeds all the PLLs. Each PLLs has one or more
16 * channels. Those channel are then connected to the clock muxes. Each mux has
17 * multiples sources (usually the xosc, some of the PLL channels and some "test
18 * debug" clocks). A mux is configured to select a given source through its
19 * control register. Each mux has one output clock that also goes out of the
20 * CPRMAN. This output clock usually connects to another peripheral in the SoC
21 * (so a given mux is dedicated to a peripheral).
22 *
23 * At each level (PLL, channel and mux), the clock can be altered through
24 * dividers (and multipliers in case of the PLLs), and can be disabled (in this
25 * case, the next levels see no clock).
26 *
27 * This can be sum-up as follows (this is an example and not the actual BCM2835
28 * clock tree):
29 *
30 * /-->[PLL]-|->[PLL channel]--... [mux]--> to peripherals
31 * | |->[PLL channel] muxes takes [mux]
32 * | \->[PLL channel] inputs from [mux]
33 * | some channels [mux]
34 * [xosc]---|-->[PLL]-|->[PLL channel] and other srcs [mux]
35 * | \->[PLL channel] ...-->[mux]
36 * | [mux]
37 * \-->[PLL]--->[PLL channel] [mux]
38 *
39 * The page at https://elinux.org/The_Undocumented_Pi gives the actual clock
40 * tree configuration.
41 */
42
43 #include "qemu/osdep.h"
44 #include "qemu/log.h"
45 #include "migration/vmstate.h"
46 #include "hw/qdev-properties.h"
47 #include "hw/misc/bcm2835_cprman.h"
48 #include "hw/misc/bcm2835_cprman_internals.h"
49 #include "trace.h"
50
51 /* PLL */
52
53 static bool pll_is_locked(const CprmanPllState *pll)
54 {
55 return !FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PWRDN)
56 && !FIELD_EX32(*pll->reg_cm, CM_PLLx, ANARST);
57 }
58
59 static void pll_update(CprmanPllState *pll)
60 {
61 uint64_t freq, ndiv, fdiv, pdiv;
62
63 if (!pll_is_locked(pll)) {
64 clock_update(pll->out, 0);
65 return;
66 }
67
68 pdiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, PDIV);
69
70 if (!pdiv) {
71 clock_update(pll->out, 0);
72 return;
73 }
74
75 ndiv = FIELD_EX32(*pll->reg_a2w_ctrl, A2W_PLLx_CTRL, NDIV);
76 fdiv = FIELD_EX32(*pll->reg_a2w_frac, A2W_PLLx_FRAC, FRAC);
77
78 if (pll->reg_a2w_ana[1] & pll->prediv_mask) {
79 /* The prescaler doubles the parent frequency */
80 ndiv *= 2;
81 fdiv *= 2;
82 }
83
84 /*
85 * We have a multiplier with an integer part (ndiv) and a fractional part
86 * (fdiv), and a divider (pdiv).
87 */
88 freq = clock_get_hz(pll->xosc_in) *
89 ((ndiv << R_A2W_PLLx_FRAC_FRAC_LENGTH) + fdiv);
90 freq /= pdiv;
91 freq >>= R_A2W_PLLx_FRAC_FRAC_LENGTH;
92
93 clock_update_hz(pll->out, freq);
94 }
95
96 static void pll_xosc_update(void *opaque)
97 {
98 pll_update(CPRMAN_PLL(opaque));
99 }
100
101 static void pll_init(Object *obj)
102 {
103 CprmanPllState *s = CPRMAN_PLL(obj);
104
105 s->xosc_in = qdev_init_clock_in(DEVICE(s), "xosc-in", pll_xosc_update, s);
106 s->out = qdev_init_clock_out(DEVICE(s), "out");
107 }
108
109 static const VMStateDescription pll_vmstate = {
110 .name = TYPE_CPRMAN_PLL,
111 .version_id = 1,
112 .minimum_version_id = 1,
113 .fields = (VMStateField[]) {
114 VMSTATE_CLOCK(xosc_in, CprmanPllState),
115 VMSTATE_END_OF_LIST()
116 }
117 };
118
119 static void pll_class_init(ObjectClass *klass, void *data)
120 {
121 DeviceClass *dc = DEVICE_CLASS(klass);
122
123 dc->vmsd = &pll_vmstate;
124 }
125
126 static const TypeInfo cprman_pll_info = {
127 .name = TYPE_CPRMAN_PLL,
128 .parent = TYPE_DEVICE,
129 .instance_size = sizeof(CprmanPllState),
130 .class_init = pll_class_init,
131 .instance_init = pll_init,
132 };
133
134
135 /* PLL channel */
136
137 static void pll_channel_update(CprmanPllChannelState *channel)
138 {
139 clock_update(channel->out, 0);
140 }
141
142 /* Update a PLL and all its channels */
143 static void pll_update_all_channels(BCM2835CprmanState *s,
144 CprmanPllState *pll)
145 {
146 size_t i;
147
148 pll_update(pll);
149
150 for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
151 CprmanPllChannelState *channel = &s->channels[i];
152 if (channel->parent == pll->id) {
153 pll_channel_update(channel);
154 }
155 }
156 }
157
158 static void pll_channel_pll_in_update(void *opaque)
159 {
160 pll_channel_update(CPRMAN_PLL_CHANNEL(opaque));
161 }
162
163 static void pll_channel_init(Object *obj)
164 {
165 CprmanPllChannelState *s = CPRMAN_PLL_CHANNEL(obj);
166
167 s->pll_in = qdev_init_clock_in(DEVICE(s), "pll-in",
168 pll_channel_pll_in_update, s);
169 s->out = qdev_init_clock_out(DEVICE(s), "out");
170 }
171
172 static const VMStateDescription pll_channel_vmstate = {
173 .name = TYPE_CPRMAN_PLL_CHANNEL,
174 .version_id = 1,
175 .minimum_version_id = 1,
176 .fields = (VMStateField[]) {
177 VMSTATE_CLOCK(pll_in, CprmanPllChannelState),
178 VMSTATE_END_OF_LIST()
179 }
180 };
181
182 static void pll_channel_class_init(ObjectClass *klass, void *data)
183 {
184 DeviceClass *dc = DEVICE_CLASS(klass);
185
186 dc->vmsd = &pll_channel_vmstate;
187 }
188
189 static const TypeInfo cprman_pll_channel_info = {
190 .name = TYPE_CPRMAN_PLL_CHANNEL,
191 .parent = TYPE_DEVICE,
192 .instance_size = sizeof(CprmanPllChannelState),
193 .class_init = pll_channel_class_init,
194 .instance_init = pll_channel_init,
195 };
196
197
198 /* CPRMAN "top level" model */
199
200 static uint32_t get_cm_lock(const BCM2835CprmanState *s)
201 {
202 static const int CM_LOCK_MAPPING[CPRMAN_NUM_PLL] = {
203 [CPRMAN_PLLA] = R_CM_LOCK_FLOCKA_SHIFT,
204 [CPRMAN_PLLC] = R_CM_LOCK_FLOCKC_SHIFT,
205 [CPRMAN_PLLD] = R_CM_LOCK_FLOCKD_SHIFT,
206 [CPRMAN_PLLH] = R_CM_LOCK_FLOCKH_SHIFT,
207 [CPRMAN_PLLB] = R_CM_LOCK_FLOCKB_SHIFT,
208 };
209
210 uint32_t r = 0;
211 size_t i;
212
213 for (i = 0; i < CPRMAN_NUM_PLL; i++) {
214 r |= pll_is_locked(&s->plls[i]) << CM_LOCK_MAPPING[i];
215 }
216
217 return r;
218 }
219
220 static uint64_t cprman_read(void *opaque, hwaddr offset,
221 unsigned size)
222 {
223 BCM2835CprmanState *s = CPRMAN(opaque);
224 uint64_t r = 0;
225 size_t idx = offset / sizeof(uint32_t);
226
227 switch (idx) {
228 case R_CM_LOCK:
229 r = get_cm_lock(s);
230 break;
231
232 default:
233 r = s->regs[idx];
234 }
235
236 trace_bcm2835_cprman_read(offset, r);
237 return r;
238 }
239
240 static inline void update_pll_and_channels_from_cm(BCM2835CprmanState *s,
241 size_t idx)
242 {
243 size_t i;
244
245 for (i = 0; i < CPRMAN_NUM_PLL; i++) {
246 if (PLL_INIT_INFO[i].cm_offset == idx) {
247 pll_update_all_channels(s, &s->plls[i]);
248 return;
249 }
250 }
251 }
252
253 static inline void update_channel_from_a2w(BCM2835CprmanState *s, size_t idx)
254 {
255 size_t i;
256
257 for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
258 if (PLL_CHANNEL_INIT_INFO[i].a2w_ctrl_offset == idx) {
259 pll_channel_update(&s->channels[i]);
260 return;
261 }
262 }
263 }
264
265 #define CASE_PLL_A2W_REGS(pll_) \
266 case R_A2W_ ## pll_ ## _CTRL: \
267 case R_A2W_ ## pll_ ## _ANA0: \
268 case R_A2W_ ## pll_ ## _ANA1: \
269 case R_A2W_ ## pll_ ## _ANA2: \
270 case R_A2W_ ## pll_ ## _ANA3: \
271 case R_A2W_ ## pll_ ## _FRAC
272
273 static void cprman_write(void *opaque, hwaddr offset,
274 uint64_t value, unsigned size)
275 {
276 BCM2835CprmanState *s = CPRMAN(opaque);
277 size_t idx = offset / sizeof(uint32_t);
278
279 if (FIELD_EX32(value, CPRMAN, PASSWORD) != CPRMAN_PASSWORD) {
280 trace_bcm2835_cprman_write_invalid_magic(offset, value);
281 return;
282 }
283
284 value &= ~R_CPRMAN_PASSWORD_MASK;
285
286 trace_bcm2835_cprman_write(offset, value);
287 s->regs[idx] = value;
288
289 switch (idx) {
290 case R_CM_PLLA ... R_CM_PLLH:
291 case R_CM_PLLB:
292 /*
293 * A given CM_PLLx register is shared by both the PLL and the channels
294 * of this PLL.
295 */
296 update_pll_and_channels_from_cm(s, idx);
297 break;
298
299 CASE_PLL_A2W_REGS(PLLA) :
300 pll_update(&s->plls[CPRMAN_PLLA]);
301 break;
302
303 CASE_PLL_A2W_REGS(PLLC) :
304 pll_update(&s->plls[CPRMAN_PLLC]);
305 break;
306
307 CASE_PLL_A2W_REGS(PLLD) :
308 pll_update(&s->plls[CPRMAN_PLLD]);
309 break;
310
311 CASE_PLL_A2W_REGS(PLLH) :
312 pll_update(&s->plls[CPRMAN_PLLH]);
313 break;
314
315 CASE_PLL_A2W_REGS(PLLB) :
316 pll_update(&s->plls[CPRMAN_PLLB]);
317 break;
318
319 case R_A2W_PLLA_DSI0:
320 case R_A2W_PLLA_CORE:
321 case R_A2W_PLLA_PER:
322 case R_A2W_PLLA_CCP2:
323 case R_A2W_PLLC_CORE2:
324 case R_A2W_PLLC_CORE1:
325 case R_A2W_PLLC_PER:
326 case R_A2W_PLLC_CORE0:
327 case R_A2W_PLLD_DSI0:
328 case R_A2W_PLLD_CORE:
329 case R_A2W_PLLD_PER:
330 case R_A2W_PLLD_DSI1:
331 case R_A2W_PLLH_AUX:
332 case R_A2W_PLLH_RCAL:
333 case R_A2W_PLLH_PIX:
334 case R_A2W_PLLB_ARM:
335 update_channel_from_a2w(s, idx);
336 break;
337 }
338 }
339
340 #undef CASE_PLL_A2W_REGS
341
342 static const MemoryRegionOps cprman_ops = {
343 .read = cprman_read,
344 .write = cprman_write,
345 .endianness = DEVICE_LITTLE_ENDIAN,
346 .valid = {
347 /*
348 * Although this hasn't been checked against real hardware, nor the
349 * information can be found in a datasheet, it seems reasonable because
350 * of the "PASSWORD" magic value found in every registers.
351 */
352 .min_access_size = 4,
353 .max_access_size = 4,
354 .unaligned = false,
355 },
356 .impl = {
357 .max_access_size = 4,
358 },
359 };
360
361 static void cprman_reset(DeviceState *dev)
362 {
363 BCM2835CprmanState *s = CPRMAN(dev);
364 size_t i;
365
366 memset(s->regs, 0, sizeof(s->regs));
367
368 for (i = 0; i < CPRMAN_NUM_PLL; i++) {
369 device_cold_reset(DEVICE(&s->plls[i]));
370 }
371
372 for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
373 device_cold_reset(DEVICE(&s->channels[i]));
374 }
375
376 clock_update_hz(s->xosc, s->xosc_freq);
377 }
378
379 static void cprman_init(Object *obj)
380 {
381 BCM2835CprmanState *s = CPRMAN(obj);
382 size_t i;
383
384 for (i = 0; i < CPRMAN_NUM_PLL; i++) {
385 object_initialize_child(obj, PLL_INIT_INFO[i].name,
386 &s->plls[i], TYPE_CPRMAN_PLL);
387 set_pll_init_info(s, &s->plls[i], i);
388 }
389
390 for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
391 object_initialize_child(obj, PLL_CHANNEL_INIT_INFO[i].name,
392 &s->channels[i],
393 TYPE_CPRMAN_PLL_CHANNEL);
394 set_pll_channel_init_info(s, &s->channels[i], i);
395 }
396
397 s->xosc = clock_new(obj, "xosc");
398
399 memory_region_init_io(&s->iomem, obj, &cprman_ops,
400 s, "bcm2835-cprman", 0x2000);
401 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
402 }
403
404 static void cprman_realize(DeviceState *dev, Error **errp)
405 {
406 BCM2835CprmanState *s = CPRMAN(dev);
407 size_t i;
408
409 for (i = 0; i < CPRMAN_NUM_PLL; i++) {
410 CprmanPllState *pll = &s->plls[i];
411
412 clock_set_source(pll->xosc_in, s->xosc);
413
414 if (!qdev_realize(DEVICE(pll), NULL, errp)) {
415 return;
416 }
417 }
418
419 for (i = 0; i < CPRMAN_NUM_PLL_CHANNEL; i++) {
420 CprmanPllChannelState *channel = &s->channels[i];
421 CprmanPll parent = PLL_CHANNEL_INIT_INFO[i].parent;
422 Clock *parent_clk = s->plls[parent].out;
423
424 clock_set_source(channel->pll_in, parent_clk);
425
426 if (!qdev_realize(DEVICE(channel), NULL, errp)) {
427 return;
428 }
429 }
430 }
431
432 static const VMStateDescription cprman_vmstate = {
433 .name = TYPE_BCM2835_CPRMAN,
434 .version_id = 1,
435 .minimum_version_id = 1,
436 .fields = (VMStateField[]) {
437 VMSTATE_UINT32_ARRAY(regs, BCM2835CprmanState, CPRMAN_NUM_REGS),
438 VMSTATE_END_OF_LIST()
439 }
440 };
441
442 static Property cprman_properties[] = {
443 DEFINE_PROP_UINT32("xosc-freq-hz", BCM2835CprmanState, xosc_freq, 19200000),
444 DEFINE_PROP_END_OF_LIST()
445 };
446
447 static void cprman_class_init(ObjectClass *klass, void *data)
448 {
449 DeviceClass *dc = DEVICE_CLASS(klass);
450
451 dc->realize = cprman_realize;
452 dc->reset = cprman_reset;
453 dc->vmsd = &cprman_vmstate;
454 device_class_set_props(dc, cprman_properties);
455 }
456
457 static const TypeInfo cprman_info = {
458 .name = TYPE_BCM2835_CPRMAN,
459 .parent = TYPE_SYS_BUS_DEVICE,
460 .instance_size = sizeof(BCM2835CprmanState),
461 .class_init = cprman_class_init,
462 .instance_init = cprman_init,
463 };
464
465 static void cprman_register_types(void)
466 {
467 type_register_static(&cprman_info);
468 type_register_static(&cprman_pll_info);
469 type_register_static(&cprman_pll_channel_info);
470 }
471
472 type_init(cprman_register_types);