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 /* CPRMAN "top level" model */ 136 137 static uint32_t get_cm_lock(const BCM2835CprmanState *s) 138 { 139 static const int CM_LOCK_MAPPING[CPRMAN_NUM_PLL] = { 140 [CPRMAN_PLLA] = R_CM_LOCK_FLOCKA_SHIFT, 141 [CPRMAN_PLLC] = R_CM_LOCK_FLOCKC_SHIFT, 142 [CPRMAN_PLLD] = R_CM_LOCK_FLOCKD_SHIFT, 143 [CPRMAN_PLLH] = R_CM_LOCK_FLOCKH_SHIFT, 144 [CPRMAN_PLLB] = R_CM_LOCK_FLOCKB_SHIFT, 145 }; 146 147 uint32_t r = 0; 148 size_t i; 149 150 for (i = 0; i < CPRMAN_NUM_PLL; i++) { 151 r |= pll_is_locked(&s->plls[i]) << CM_LOCK_MAPPING[i]; 152 } 153 154 return r; 155 } 156 157 static uint64_t cprman_read(void *opaque, hwaddr offset, 158 unsigned size) 159 { 160 BCM2835CprmanState *s = CPRMAN(opaque); 161 uint64_t r = 0; 162 size_t idx = offset / sizeof(uint32_t); 163 164 switch (idx) { 165 case R_CM_LOCK: 166 r = get_cm_lock(s); 167 break; 168 169 default: 170 r = s->regs[idx]; 171 } 172 173 trace_bcm2835_cprman_read(offset, r); 174 return r; 175 } 176 177 #define CASE_PLL_REGS(pll_) \ 178 case R_CM_ ## pll_: \ 179 case R_A2W_ ## pll_ ## _CTRL: \ 180 case R_A2W_ ## pll_ ## _ANA0: \ 181 case R_A2W_ ## pll_ ## _ANA1: \ 182 case R_A2W_ ## pll_ ## _ANA2: \ 183 case R_A2W_ ## pll_ ## _ANA3: \ 184 case R_A2W_ ## pll_ ## _FRAC 185 186 static void cprman_write(void *opaque, hwaddr offset, 187 uint64_t value, unsigned size) 188 { 189 BCM2835CprmanState *s = CPRMAN(opaque); 190 size_t idx = offset / sizeof(uint32_t); 191 192 if (FIELD_EX32(value, CPRMAN, PASSWORD) != CPRMAN_PASSWORD) { 193 trace_bcm2835_cprman_write_invalid_magic(offset, value); 194 return; 195 } 196 197 value &= ~R_CPRMAN_PASSWORD_MASK; 198 199 trace_bcm2835_cprman_write(offset, value); 200 s->regs[idx] = value; 201 202 switch (idx) { 203 CASE_PLL_REGS(PLLA) : 204 pll_update(&s->plls[CPRMAN_PLLA]); 205 break; 206 207 CASE_PLL_REGS(PLLC) : 208 pll_update(&s->plls[CPRMAN_PLLC]); 209 break; 210 211 CASE_PLL_REGS(PLLD) : 212 pll_update(&s->plls[CPRMAN_PLLD]); 213 break; 214 215 CASE_PLL_REGS(PLLH) : 216 pll_update(&s->plls[CPRMAN_PLLH]); 217 break; 218 219 CASE_PLL_REGS(PLLB) : 220 pll_update(&s->plls[CPRMAN_PLLB]); 221 break; 222 } 223 } 224 225 #undef CASE_PLL_REGS 226 227 static const MemoryRegionOps cprman_ops = { 228 .read = cprman_read, 229 .write = cprman_write, 230 .endianness = DEVICE_LITTLE_ENDIAN, 231 .valid = { 232 /* 233 * Although this hasn't been checked against real hardware, nor the 234 * information can be found in a datasheet, it seems reasonable because 235 * of the "PASSWORD" magic value found in every registers. 236 */ 237 .min_access_size = 4, 238 .max_access_size = 4, 239 .unaligned = false, 240 }, 241 .impl = { 242 .max_access_size = 4, 243 }, 244 }; 245 246 static void cprman_reset(DeviceState *dev) 247 { 248 BCM2835CprmanState *s = CPRMAN(dev); 249 size_t i; 250 251 memset(s->regs, 0, sizeof(s->regs)); 252 253 for (i = 0; i < CPRMAN_NUM_PLL; i++) { 254 device_cold_reset(DEVICE(&s->plls[i])); 255 } 256 257 clock_update_hz(s->xosc, s->xosc_freq); 258 } 259 260 static void cprman_init(Object *obj) 261 { 262 BCM2835CprmanState *s = CPRMAN(obj); 263 size_t i; 264 265 for (i = 0; i < CPRMAN_NUM_PLL; i++) { 266 object_initialize_child(obj, PLL_INIT_INFO[i].name, 267 &s->plls[i], TYPE_CPRMAN_PLL); 268 set_pll_init_info(s, &s->plls[i], i); 269 } 270 271 s->xosc = clock_new(obj, "xosc"); 272 273 memory_region_init_io(&s->iomem, obj, &cprman_ops, 274 s, "bcm2835-cprman", 0x2000); 275 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); 276 } 277 278 static void cprman_realize(DeviceState *dev, Error **errp) 279 { 280 BCM2835CprmanState *s = CPRMAN(dev); 281 size_t i; 282 283 for (i = 0; i < CPRMAN_NUM_PLL; i++) { 284 CprmanPllState *pll = &s->plls[i]; 285 286 clock_set_source(pll->xosc_in, s->xosc); 287 288 if (!qdev_realize(DEVICE(pll), NULL, errp)) { 289 return; 290 } 291 } 292 } 293 294 static const VMStateDescription cprman_vmstate = { 295 .name = TYPE_BCM2835_CPRMAN, 296 .version_id = 1, 297 .minimum_version_id = 1, 298 .fields = (VMStateField[]) { 299 VMSTATE_UINT32_ARRAY(regs, BCM2835CprmanState, CPRMAN_NUM_REGS), 300 VMSTATE_END_OF_LIST() 301 } 302 }; 303 304 static Property cprman_properties[] = { 305 DEFINE_PROP_UINT32("xosc-freq-hz", BCM2835CprmanState, xosc_freq, 19200000), 306 DEFINE_PROP_END_OF_LIST() 307 }; 308 309 static void cprman_class_init(ObjectClass *klass, void *data) 310 { 311 DeviceClass *dc = DEVICE_CLASS(klass); 312 313 dc->realize = cprman_realize; 314 dc->reset = cprman_reset; 315 dc->vmsd = &cprman_vmstate; 316 device_class_set_props(dc, cprman_properties); 317 } 318 319 static const TypeInfo cprman_info = { 320 .name = TYPE_BCM2835_CPRMAN, 321 .parent = TYPE_SYS_BUS_DEVICE, 322 .instance_size = sizeof(BCM2835CprmanState), 323 .class_init = cprman_class_init, 324 .instance_init = cprman_init, 325 }; 326 327 static void cprman_register_types(void) 328 { 329 type_register_static(&cprman_info); 330 type_register_static(&cprman_pll_info); 331 } 332 333 type_init(cprman_register_types); 334