bcm2835_cprman_internals.h (28347B)
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#define TYPE_CPRMAN_CLOCK_MUX "bcm2835-cprman-clock-mux" 18#define TYPE_CPRMAN_DSI0HSCK_MUX "bcm2835-cprman-dsi0hsck-mux" 19 20DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL, 21 TYPE_CPRMAN_PLL) 22DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL, 23 TYPE_CPRMAN_PLL_CHANNEL) 24DECLARE_INSTANCE_CHECKER(CprmanClockMuxState, CPRMAN_CLOCK_MUX, 25 TYPE_CPRMAN_CLOCK_MUX) 26DECLARE_INSTANCE_CHECKER(CprmanDsi0HsckMuxState, CPRMAN_DSI0HSCK_MUX, 27 TYPE_CPRMAN_DSI0HSCK_MUX) 28 29/* Register map */ 30 31/* PLLs */ 32REG32(CM_PLLA, 0x104) 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) 42REG32(CM_PLLC, 0x108) 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) 51REG32(CM_PLLD, 0x10c) 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) 60REG32(CM_PLLH, 0x110) 61 FIELD(CM_PLLH, LOADPIX, 0, 1) 62 FIELD(CM_PLLH, LOADAUX, 1, 1) 63 FIELD(CM_PLLH, LOADRCAL, 2, 1) 64REG32(CM_PLLB, 0x170) 65 FIELD(CM_PLLB, LOADARM, 0, 1) 66 FIELD(CM_PLLB, HOLDARM, 1, 1) 67 68REG32(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) 73REG32(A2W_PLLC_CTRL, 0x1120) 74REG32(A2W_PLLD_CTRL, 0x1140) 75REG32(A2W_PLLH_CTRL, 0x1160) 76REG32(A2W_PLLB_CTRL, 0x11e0) 77 78REG32(A2W_PLLA_ANA0, 0x1010) 79REG32(A2W_PLLA_ANA1, 0x1014) 80 FIELD(A2W_PLLx_ANA1, FB_PREDIV, 14, 1) 81REG32(A2W_PLLA_ANA2, 0x1018) 82REG32(A2W_PLLA_ANA3, 0x101c) 83 84REG32(A2W_PLLC_ANA0, 0x1030) 85REG32(A2W_PLLC_ANA1, 0x1034) 86REG32(A2W_PLLC_ANA2, 0x1038) 87REG32(A2W_PLLC_ANA3, 0x103c) 88 89REG32(A2W_PLLD_ANA0, 0x1050) 90REG32(A2W_PLLD_ANA1, 0x1054) 91REG32(A2W_PLLD_ANA2, 0x1058) 92REG32(A2W_PLLD_ANA3, 0x105c) 93 94REG32(A2W_PLLH_ANA0, 0x1070) 95REG32(A2W_PLLH_ANA1, 0x1074) 96 FIELD(A2W_PLLH_ANA1, FB_PREDIV, 11, 1) 97REG32(A2W_PLLH_ANA2, 0x1078) 98REG32(A2W_PLLH_ANA3, 0x107c) 99 100REG32(A2W_PLLB_ANA0, 0x10f0) 101REG32(A2W_PLLB_ANA1, 0x10f4) 102REG32(A2W_PLLB_ANA2, 0x10f8) 103REG32(A2W_PLLB_ANA3, 0x10fc) 104 105REG32(A2W_PLLA_FRAC, 0x1200) 106 FIELD(A2W_PLLx_FRAC, FRAC, 0, 20) 107REG32(A2W_PLLC_FRAC, 0x1220) 108REG32(A2W_PLLD_FRAC, 0x1240) 109REG32(A2W_PLLH_FRAC, 0x1260) 110REG32(A2W_PLLB_FRAC, 0x12e0) 111 112/* PLL channels */ 113REG32(A2W_PLLA_DSI0, 0x1300) 114 FIELD(A2W_PLLx_CHANNELy, DIV, 0, 8) 115 FIELD(A2W_PLLx_CHANNELy, DISABLE, 8, 1) 116REG32(A2W_PLLA_CORE, 0x1400) 117REG32(A2W_PLLA_PER, 0x1500) 118REG32(A2W_PLLA_CCP2, 0x1600) 119 120REG32(A2W_PLLC_CORE2, 0x1320) 121REG32(A2W_PLLC_CORE1, 0x1420) 122REG32(A2W_PLLC_PER, 0x1520) 123REG32(A2W_PLLC_CORE0, 0x1620) 124 125REG32(A2W_PLLD_DSI0, 0x1340) 126REG32(A2W_PLLD_CORE, 0x1440) 127REG32(A2W_PLLD_PER, 0x1540) 128REG32(A2W_PLLD_DSI1, 0x1640) 129 130REG32(A2W_PLLH_AUX, 0x1360) 131REG32(A2W_PLLH_RCAL, 0x1460) 132REG32(A2W_PLLH_PIX, 0x1560) 133REG32(A2W_PLLH_STS, 0x1660) 134 135REG32(A2W_PLLB_ARM, 0x13e0) 136 137/* Clock muxes */ 138REG32(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) 147REG32(CM_GNRICDIV, 0x004) 148 FIELD(CM_CLOCKx_DIV, FRAC, 0, 12) 149REG32(CM_VPUCTL, 0x008) 150REG32(CM_VPUDIV, 0x00c) 151REG32(CM_SYSCTL, 0x010) 152REG32(CM_SYSDIV, 0x014) 153REG32(CM_PERIACTL, 0x018) 154REG32(CM_PERIADIV, 0x01c) 155REG32(CM_PERIICTL, 0x020) 156REG32(CM_PERIIDIV, 0x024) 157REG32(CM_H264CTL, 0x028) 158REG32(CM_H264DIV, 0x02c) 159REG32(CM_ISPCTL, 0x030) 160REG32(CM_ISPDIV, 0x034) 161REG32(CM_V3DCTL, 0x038) 162REG32(CM_V3DDIV, 0x03c) 163REG32(CM_CAM0CTL, 0x040) 164REG32(CM_CAM0DIV, 0x044) 165REG32(CM_CAM1CTL, 0x048) 166REG32(CM_CAM1DIV, 0x04c) 167REG32(CM_CCP2CTL, 0x050) 168REG32(CM_CCP2DIV, 0x054) 169REG32(CM_DSI0ECTL, 0x058) 170REG32(CM_DSI0EDIV, 0x05c) 171REG32(CM_DSI0PCTL, 0x060) 172REG32(CM_DSI0PDIV, 0x064) 173REG32(CM_DPICTL, 0x068) 174REG32(CM_DPIDIV, 0x06c) 175REG32(CM_GP0CTL, 0x070) 176REG32(CM_GP0DIV, 0x074) 177REG32(CM_GP1CTL, 0x078) 178REG32(CM_GP1DIV, 0x07c) 179REG32(CM_GP2CTL, 0x080) 180REG32(CM_GP2DIV, 0x084) 181REG32(CM_HSMCTL, 0x088) 182REG32(CM_HSMDIV, 0x08c) 183REG32(CM_OTPCTL, 0x090) 184REG32(CM_OTPDIV, 0x094) 185REG32(CM_PCMCTL, 0x098) 186REG32(CM_PCMDIV, 0x09c) 187REG32(CM_PWMCTL, 0x0a0) 188REG32(CM_PWMDIV, 0x0a4) 189REG32(CM_SLIMCTL, 0x0a8) 190REG32(CM_SLIMDIV, 0x0ac) 191REG32(CM_SMICTL, 0x0b0) 192REG32(CM_SMIDIV, 0x0b4) 193REG32(CM_TCNTCTL, 0x0c0) 194REG32(CM_TCNTCNT, 0x0c4) 195REG32(CM_TECCTL, 0x0c8) 196REG32(CM_TECDIV, 0x0cc) 197REG32(CM_TD0CTL, 0x0d0) 198REG32(CM_TD0DIV, 0x0d4) 199REG32(CM_TD1CTL, 0x0d8) 200REG32(CM_TD1DIV, 0x0dc) 201REG32(CM_TSENSCTL, 0x0e0) 202REG32(CM_TSENSDIV, 0x0e4) 203REG32(CM_TIMERCTL, 0x0e8) 204REG32(CM_TIMERDIV, 0x0ec) 205REG32(CM_UARTCTL, 0x0f0) 206REG32(CM_UARTDIV, 0x0f4) 207REG32(CM_VECCTL, 0x0f8) 208REG32(CM_VECDIV, 0x0fc) 209REG32(CM_PULSECTL, 0x190) 210REG32(CM_PULSEDIV, 0x194) 211REG32(CM_SDCCTL, 0x1a8) 212REG32(CM_SDCDIV, 0x1ac) 213REG32(CM_ARMCTL, 0x1b0) 214REG32(CM_AVEOCTL, 0x1b8) 215REG32(CM_AVEODIV, 0x1bc) 216REG32(CM_EMMCCTL, 0x1c0) 217REG32(CM_EMMCDIV, 0x1c4) 218REG32(CM_EMMC2CTL, 0x1d0) 219REG32(CM_EMMC2DIV, 0x1d4) 220 221/* misc registers */ 222REG32(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) 228 229REG32(CM_DSI0HSCK, 0x120) 230 FIELD(CM_DSI0HSCK, SELPLLD, 0, 1) 231 232/* 233 * This field is common to all registers. Each register write value must match 234 * the CPRMAN_PASSWORD magic value in its 8 MSB. 235 */ 236FIELD(CPRMAN, PASSWORD, 24, 8) 237#define CPRMAN_PASSWORD 0x5a 238 239/* PLL init info */ 240typedef struct PLLInitInfo { 241 const char *name; 242 size_t cm_offset; 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; 247} PLLInitInfo; 248 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 254 255static const PLLInitInfo PLL_INIT_INFO[] = { 256 [CPRMAN_PLLA] = { 257 .name = "plla", 258 .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, 259 FILL_PLL_INIT_INFO(PLLA), 260 }, 261 [CPRMAN_PLLC] = { 262 .name = "pllc", 263 .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, 264 FILL_PLL_INIT_INFO(PLLC), 265 }, 266 [CPRMAN_PLLD] = { 267 .name = "plld", 268 .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, 269 FILL_PLL_INIT_INFO(PLLD), 270 }, 271 [CPRMAN_PLLH] = { 272 .name = "pllh", 273 .prediv_mask = R_A2W_PLLH_ANA1_FB_PREDIV_MASK, 274 FILL_PLL_INIT_INFO(PLLH), 275 }, 276 [CPRMAN_PLLB] = { 277 .name = "pllb", 278 .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, 279 FILL_PLL_INIT_INFO(PLLB), 280 }, 281}; 282 283#undef FILL_PLL_CHANNEL_INIT_INFO 284 285static inline void set_pll_init_info(BCM2835CprmanState *s, 286 CprmanPllState *pll, 287 CprmanPll id) 288{ 289 pll->id = id; 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]; 295} 296 297 298/* PLL channel init info */ 299typedef struct PLLChannelInitInfo { 300 const char *name; 301 CprmanPll parent; 302 size_t cm_offset; 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; 308 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_ 314 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, \ 318 .fixed_divider = 1 319 320#define FILL_PLL_CHANNEL_INIT_INFO_nohold(pll_, channel_) \ 321 FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \ 322 .cm_hold_mask = 0 323 324static PLLChannelInitInfo PLL_CHANNEL_INIT_INFO[] = { 325 [CPRMAN_PLLA_CHANNEL_DSI0] = { 326 .name = "plla-dsi0", 327 FILL_PLL_CHANNEL_INIT_INFO(PLLA, DSI0), 328 }, 329 [CPRMAN_PLLA_CHANNEL_CORE] = { 330 .name = "plla-core", 331 FILL_PLL_CHANNEL_INIT_INFO(PLLA, CORE), 332 }, 333 [CPRMAN_PLLA_CHANNEL_PER] = { 334 .name = "plla-per", 335 FILL_PLL_CHANNEL_INIT_INFO(PLLA, PER), 336 }, 337 [CPRMAN_PLLA_CHANNEL_CCP2] = { 338 .name = "plla-ccp2", 339 FILL_PLL_CHANNEL_INIT_INFO(PLLA, CCP2), 340 }, 341 342 [CPRMAN_PLLC_CHANNEL_CORE2] = { 343 .name = "pllc-core2", 344 FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE2), 345 }, 346 [CPRMAN_PLLC_CHANNEL_CORE1] = { 347 .name = "pllc-core1", 348 FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE1), 349 }, 350 [CPRMAN_PLLC_CHANNEL_PER] = { 351 .name = "pllc-per", 352 FILL_PLL_CHANNEL_INIT_INFO(PLLC, PER), 353 }, 354 [CPRMAN_PLLC_CHANNEL_CORE0] = { 355 .name = "pllc-core0", 356 FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE0), 357 }, 358 359 [CPRMAN_PLLD_CHANNEL_DSI0] = { 360 .name = "plld-dsi0", 361 FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI0), 362 }, 363 [CPRMAN_PLLD_CHANNEL_CORE] = { 364 .name = "plld-core", 365 FILL_PLL_CHANNEL_INIT_INFO(PLLD, CORE), 366 }, 367 [CPRMAN_PLLD_CHANNEL_PER] = { 368 .name = "plld-per", 369 FILL_PLL_CHANNEL_INIT_INFO(PLLD, PER), 370 }, 371 [CPRMAN_PLLD_CHANNEL_DSI1] = { 372 .name = "plld-dsi1", 373 FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI1), 374 }, 375 376 [CPRMAN_PLLH_CHANNEL_AUX] = { 377 .name = "pllh-aux", 378 .fixed_divider = 1, 379 FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, AUX), 380 }, 381 [CPRMAN_PLLH_CHANNEL_RCAL] = { 382 .name = "pllh-rcal", 383 .fixed_divider = 10, 384 FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, RCAL), 385 }, 386 [CPRMAN_PLLH_CHANNEL_PIX] = { 387 .name = "pllh-pix", 388 .fixed_divider = 10, 389 FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, PIX), 390 }, 391 392 [CPRMAN_PLLB_CHANNEL_ARM] = { 393 .name = "pllb-arm", 394 FILL_PLL_CHANNEL_INIT_INFO(PLLB, ARM), 395 }, 396}; 397 398#undef FILL_PLL_CHANNEL_INIT_INFO_nohold 399#undef FILL_PLL_CHANNEL_INIT_INFO 400#undef FILL_PLL_CHANNEL_INIT_INFO_common 401 402static inline void set_pll_channel_init_info(BCM2835CprmanState *s, 403 CprmanPllChannelState *channel, 404 CprmanPllChannel id) 405{ 406 channel->id = id; 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; 413} 414 415/* Clock mux init info */ 416typedef struct ClockMuxInitInfo { 417 const char *name; 418 size_t cm_offset; /* cm_offset[0]->CM_CTL, cm_offset[1]->CM_DIV */ 419 int int_bits; 420 int frac_bits; 421 422 CprmanPllChannel src_mapping[CPRMAN_NUM_CLOCK_MUX_SRC]; 423} ClockMuxInitInfo; 424 425/* 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. 429 */ 430 431/* Unknown mapping. Connect everything to ground */ 432#define SRC_MAPPING_INFO_unknown \ 433 .src_mapping = { \ 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 */ \ 444 } 445 446/* Only the oscillator and the two test debug clocks */ 447#define SRC_MAPPING_INFO_xosc \ 448 .src_mapping = { \ 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, \ 459 } 460 461/* All the PLL "core" channels */ 462#define SRC_MAPPING_INFO_core \ 463 .src_mapping = { \ 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, \ 474 } 475 476/* All the PLL "per" channels */ 477#define SRC_MAPPING_INFO_periph \ 478 .src_mapping = { \ 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, \ 489 } 490 491/* 492 * The DSI0 channels. This one got an intermediate mux between the PLL channels 493 * and the clock input. 494 */ 495#define SRC_MAPPING_INFO_dsi0 \ 496 .src_mapping = { \ 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, \ 507 } 508 509/* The DSI1 channel */ 510#define SRC_MAPPING_INFO_dsi1 \ 511 .src_mapping = { \ 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, \ 522 } 523 524#define FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) \ 525 SRC_MAPPING_INFO_ ## kind_ 526 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_) 530 531static ClockMuxInitInfo CLOCK_MUX_INIT_INFO[] = { 532 [CPRMAN_CLOCK_GNRIC] = { 533 .name = "gnric", 534 FILL_CLOCK_MUX_INIT_INFO(GNRIC, unknown), 535 }, 536 [CPRMAN_CLOCK_VPU] = { 537 .name = "vpu", 538 .int_bits = 12, 539 .frac_bits = 8, 540 FILL_CLOCK_MUX_INIT_INFO(VPU, core), 541 }, 542 [CPRMAN_CLOCK_SYS] = { 543 .name = "sys", 544 FILL_CLOCK_MUX_INIT_INFO(SYS, unknown), 545 }, 546 [CPRMAN_CLOCK_PERIA] = { 547 .name = "peria", 548 FILL_CLOCK_MUX_INIT_INFO(PERIA, unknown), 549 }, 550 [CPRMAN_CLOCK_PERII] = { 551 .name = "perii", 552 FILL_CLOCK_MUX_INIT_INFO(PERII, unknown), 553 }, 554 [CPRMAN_CLOCK_H264] = { 555 .name = "h264", 556 .int_bits = 4, 557 .frac_bits = 8, 558 FILL_CLOCK_MUX_INIT_INFO(H264, core), 559 }, 560 [CPRMAN_CLOCK_ISP] = { 561 .name = "isp", 562 .int_bits = 4, 563 .frac_bits = 8, 564 FILL_CLOCK_MUX_INIT_INFO(ISP, core), 565 }, 566 [CPRMAN_CLOCK_V3D] = { 567 .name = "v3d", 568 FILL_CLOCK_MUX_INIT_INFO(V3D, core), 569 }, 570 [CPRMAN_CLOCK_CAM0] = { 571 .name = "cam0", 572 .int_bits = 4, 573 .frac_bits = 8, 574 FILL_CLOCK_MUX_INIT_INFO(CAM0, periph), 575 }, 576 [CPRMAN_CLOCK_CAM1] = { 577 .name = "cam1", 578 .int_bits = 4, 579 .frac_bits = 8, 580 FILL_CLOCK_MUX_INIT_INFO(CAM1, periph), 581 }, 582 [CPRMAN_CLOCK_CCP2] = { 583 .name = "ccp2", 584 FILL_CLOCK_MUX_INIT_INFO(CCP2, unknown), 585 }, 586 [CPRMAN_CLOCK_DSI0E] = { 587 .name = "dsi0e", 588 .int_bits = 4, 589 .frac_bits = 8, 590 FILL_CLOCK_MUX_INIT_INFO(DSI0E, dsi0), 591 }, 592 [CPRMAN_CLOCK_DSI0P] = { 593 .name = "dsi0p", 594 .int_bits = 0, 595 .frac_bits = 0, 596 FILL_CLOCK_MUX_INIT_INFO(DSI0P, dsi0), 597 }, 598 [CPRMAN_CLOCK_DPI] = { 599 .name = "dpi", 600 .int_bits = 4, 601 .frac_bits = 8, 602 FILL_CLOCK_MUX_INIT_INFO(DPI, periph), 603 }, 604 [CPRMAN_CLOCK_GP0] = { 605 .name = "gp0", 606 .int_bits = 12, 607 .frac_bits = 12, 608 FILL_CLOCK_MUX_INIT_INFO(GP0, periph), 609 }, 610 [CPRMAN_CLOCK_GP1] = { 611 .name = "gp1", 612 .int_bits = 12, 613 .frac_bits = 12, 614 FILL_CLOCK_MUX_INIT_INFO(GP1, periph), 615 }, 616 [CPRMAN_CLOCK_GP2] = { 617 .name = "gp2", 618 .int_bits = 12, 619 .frac_bits = 12, 620 FILL_CLOCK_MUX_INIT_INFO(GP2, periph), 621 }, 622 [CPRMAN_CLOCK_HSM] = { 623 .name = "hsm", 624 .int_bits = 4, 625 .frac_bits = 8, 626 FILL_CLOCK_MUX_INIT_INFO(HSM, periph), 627 }, 628 [CPRMAN_CLOCK_OTP] = { 629 .name = "otp", 630 .int_bits = 4, 631 .frac_bits = 0, 632 FILL_CLOCK_MUX_INIT_INFO(OTP, xosc), 633 }, 634 [CPRMAN_CLOCK_PCM] = { 635 .name = "pcm", 636 .int_bits = 12, 637 .frac_bits = 12, 638 FILL_CLOCK_MUX_INIT_INFO(PCM, periph), 639 }, 640 [CPRMAN_CLOCK_PWM] = { 641 .name = "pwm", 642 .int_bits = 12, 643 .frac_bits = 12, 644 FILL_CLOCK_MUX_INIT_INFO(PWM, periph), 645 }, 646 [CPRMAN_CLOCK_SLIM] = { 647 .name = "slim", 648 .int_bits = 12, 649 .frac_bits = 12, 650 FILL_CLOCK_MUX_INIT_INFO(SLIM, periph), 651 }, 652 [CPRMAN_CLOCK_SMI] = { 653 .name = "smi", 654 .int_bits = 4, 655 .frac_bits = 8, 656 FILL_CLOCK_MUX_INIT_INFO(SMI, periph), 657 }, 658 [CPRMAN_CLOCK_TEC] = { 659 .name = "tec", 660 .int_bits = 6, 661 .frac_bits = 0, 662 FILL_CLOCK_MUX_INIT_INFO(TEC, xosc), 663 }, 664 [CPRMAN_CLOCK_TD0] = { 665 .name = "td0", 666 FILL_CLOCK_MUX_INIT_INFO(TD0, unknown), 667 }, 668 [CPRMAN_CLOCK_TD1] = { 669 .name = "td1", 670 FILL_CLOCK_MUX_INIT_INFO(TD1, unknown), 671 }, 672 [CPRMAN_CLOCK_TSENS] = { 673 .name = "tsens", 674 .int_bits = 5, 675 .frac_bits = 0, 676 FILL_CLOCK_MUX_INIT_INFO(TSENS, xosc), 677 }, 678 [CPRMAN_CLOCK_TIMER] = { 679 .name = "timer", 680 .int_bits = 6, 681 .frac_bits = 12, 682 FILL_CLOCK_MUX_INIT_INFO(TIMER, xosc), 683 }, 684 [CPRMAN_CLOCK_UART] = { 685 .name = "uart", 686 .int_bits = 10, 687 .frac_bits = 12, 688 FILL_CLOCK_MUX_INIT_INFO(UART, periph), 689 }, 690 [CPRMAN_CLOCK_VEC] = { 691 .name = "vec", 692 .int_bits = 4, 693 .frac_bits = 0, 694 FILL_CLOCK_MUX_INIT_INFO(VEC, periph), 695 }, 696 [CPRMAN_CLOCK_PULSE] = { 697 .name = "pulse", 698 FILL_CLOCK_MUX_INIT_INFO(PULSE, xosc), 699 }, 700 [CPRMAN_CLOCK_SDC] = { 701 .name = "sdram", 702 .int_bits = 6, 703 .frac_bits = 0, 704 FILL_CLOCK_MUX_INIT_INFO(SDC, core), 705 }, 706 [CPRMAN_CLOCK_ARM] = { 707 .name = "arm", 708 FILL_CLOCK_MUX_INIT_INFO(ARM, unknown), 709 }, 710 [CPRMAN_CLOCK_AVEO] = { 711 .name = "aveo", 712 .int_bits = 4, 713 .frac_bits = 0, 714 FILL_CLOCK_MUX_INIT_INFO(AVEO, periph), 715 }, 716 [CPRMAN_CLOCK_EMMC] = { 717 .name = "emmc", 718 .int_bits = 4, 719 .frac_bits = 8, 720 FILL_CLOCK_MUX_INIT_INFO(EMMC, periph), 721 }, 722 [CPRMAN_CLOCK_EMMC2] = { 723 .name = "emmc2", 724 .int_bits = 4, 725 .frac_bits = 8, 726 FILL_CLOCK_MUX_INIT_INFO(EMMC2, unknown), 727 }, 728}; 729 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 738 739static inline void set_clock_mux_init_info(BCM2835CprmanState *s, 740 CprmanClockMuxState *mux, 741 CprmanClockMux id) 742{ 743 mux->id = id; 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; 748} 749 750 751/* 752 * Object reset info 753 * Those values have been dumped from a Raspberry Pi 3 Model B v1.2 using the 754 * clk debugfs interface in Linux. 755 */ 756typedef struct PLLResetInfo { 757 uint32_t cm; 758 uint32_t a2w_ctrl; 759 uint32_t a2w_ana[4]; 760 uint32_t a2w_frac; 761} PLLResetInfo; 762 763static const PLLResetInfo PLL_RESET_INFO[] = { 764 [CPRMAN_PLLA] = { 765 .cm = 0x0000008a, 766 .a2w_ctrl = 0x0002103a, 767 .a2w_frac = 0x00098000, 768 .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } 769 }, 770 771 [CPRMAN_PLLC] = { 772 .cm = 0x00000228, 773 .a2w_ctrl = 0x0002103e, 774 .a2w_frac = 0x00080000, 775 .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } 776 }, 777 778 [CPRMAN_PLLD] = { 779 .cm = 0x0000020a, 780 .a2w_ctrl = 0x00021034, 781 .a2w_frac = 0x00015556, 782 .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } 783 }, 784 785 [CPRMAN_PLLH] = { 786 .cm = 0x00000000, 787 .a2w_ctrl = 0x0002102d, 788 .a2w_frac = 0x00000000, 789 .a2w_ana = { 0x00900000, 0x0000000c, 0x00000000, 0x00000000 } 790 }, 791 792 [CPRMAN_PLLB] = { 793 /* unknown */ 794 .cm = 0x00000000, 795 .a2w_ctrl = 0x00000000, 796 .a2w_frac = 0x00000000, 797 .a2w_ana = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 } 798 } 799}; 800 801typedef struct PLLChannelResetInfo { 802 /* 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. 805 */ 806 uint32_t a2w_ctrl; 807} PLLChannelResetInfo; 808 809static 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 }, 814 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 }, 819 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 }, 824 825 [CPRMAN_PLLH_CHANNEL_AUX] = { .a2w_ctrl = 0x00000004 }, 826 [CPRMAN_PLLH_CHANNEL_RCAL] = { .a2w_ctrl = 0x00000000 }, 827 [CPRMAN_PLLH_CHANNEL_PIX] = { .a2w_ctrl = 0x00000000 }, 828 829 [CPRMAN_PLLB_CHANNEL_ARM] = { .a2w_ctrl = 0x00000000 }, /* unknown */ 830}; 831 832typedef struct ClockMuxResetInfo { 833 uint32_t cm_ctl; 834 uint32_t cm_div; 835} ClockMuxResetInfo; 836 837static const ClockMuxResetInfo CLOCK_MUX_RESET_INFO[] = { 838 [CPRMAN_CLOCK_GNRIC] = { 839 .cm_ctl = 0, /* unknown */ 840 .cm_div = 0 841 }, 842 843 [CPRMAN_CLOCK_VPU] = { 844 .cm_ctl = 0x00000245, 845 .cm_div = 0x00003000, 846 }, 847 848 [CPRMAN_CLOCK_SYS] = { 849 .cm_ctl = 0, /* unknown */ 850 .cm_div = 0 851 }, 852 853 [CPRMAN_CLOCK_PERIA] = { 854 .cm_ctl = 0, /* unknown */ 855 .cm_div = 0 856 }, 857 858 [CPRMAN_CLOCK_PERII] = { 859 .cm_ctl = 0, /* unknown */ 860 .cm_div = 0 861 }, 862 863 [CPRMAN_CLOCK_H264] = { 864 .cm_ctl = 0x00000244, 865 .cm_div = 0x00003000, 866 }, 867 868 [CPRMAN_CLOCK_ISP] = { 869 .cm_ctl = 0x00000244, 870 .cm_div = 0x00003000, 871 }, 872 873 [CPRMAN_CLOCK_V3D] = { 874 .cm_ctl = 0, /* unknown */ 875 .cm_div = 0 876 }, 877 878 [CPRMAN_CLOCK_CAM0] = { 879 .cm_ctl = 0x00000000, 880 .cm_div = 0x00000000, 881 }, 882 883 [CPRMAN_CLOCK_CAM1] = { 884 .cm_ctl = 0x00000000, 885 .cm_div = 0x00000000, 886 }, 887 888 [CPRMAN_CLOCK_CCP2] = { 889 .cm_ctl = 0, /* unknown */ 890 .cm_div = 0 891 }, 892 893 [CPRMAN_CLOCK_DSI0E] = { 894 .cm_ctl = 0x00000000, 895 .cm_div = 0x00000000, 896 }, 897 898 [CPRMAN_CLOCK_DSI0P] = { 899 .cm_ctl = 0x00000000, 900 .cm_div = 0x00000000, 901 }, 902 903 [CPRMAN_CLOCK_DPI] = { 904 .cm_ctl = 0x00000000, 905 .cm_div = 0x00000000, 906 }, 907 908 [CPRMAN_CLOCK_GP0] = { 909 .cm_ctl = 0x00000200, 910 .cm_div = 0x00000000, 911 }, 912 913 [CPRMAN_CLOCK_GP1] = { 914 .cm_ctl = 0x00000096, 915 .cm_div = 0x00014000, 916 }, 917 918 [CPRMAN_CLOCK_GP2] = { 919 .cm_ctl = 0x00000291, 920 .cm_div = 0x00249f00, 921 }, 922 923 [CPRMAN_CLOCK_HSM] = { 924 .cm_ctl = 0x00000000, 925 .cm_div = 0x00000000, 926 }, 927 928 [CPRMAN_CLOCK_OTP] = { 929 .cm_ctl = 0x00000091, 930 .cm_div = 0x00004000, 931 }, 932 933 [CPRMAN_CLOCK_PCM] = { 934 .cm_ctl = 0x00000200, 935 .cm_div = 0x00000000, 936 }, 937 938 [CPRMAN_CLOCK_PWM] = { 939 .cm_ctl = 0x00000200, 940 .cm_div = 0x00000000, 941 }, 942 943 [CPRMAN_CLOCK_SLIM] = { 944 .cm_ctl = 0x00000200, 945 .cm_div = 0x00000000, 946 }, 947 948 [CPRMAN_CLOCK_SMI] = { 949 .cm_ctl = 0x00000000, 950 .cm_div = 0x00000000, 951 }, 952 953 [CPRMAN_CLOCK_TEC] = { 954 .cm_ctl = 0x00000000, 955 .cm_div = 0x00000000, 956 }, 957 958 [CPRMAN_CLOCK_TD0] = { 959 .cm_ctl = 0, /* unknown */ 960 .cm_div = 0 961 }, 962 963 [CPRMAN_CLOCK_TD1] = { 964 .cm_ctl = 0, /* unknown */ 965 .cm_div = 0 966 }, 967 968 [CPRMAN_CLOCK_TSENS] = { 969 .cm_ctl = 0x00000091, 970 .cm_div = 0x0000a000, 971 }, 972 973 [CPRMAN_CLOCK_TIMER] = { 974 .cm_ctl = 0x00000291, 975 .cm_div = 0x00013333, 976 }, 977 978 [CPRMAN_CLOCK_UART] = { 979 .cm_ctl = 0x00000296, 980 .cm_div = 0x0000a6ab, 981 }, 982 983 [CPRMAN_CLOCK_VEC] = { 984 .cm_ctl = 0x00000097, 985 .cm_div = 0x00002000, 986 }, 987 988 [CPRMAN_CLOCK_PULSE] = { 989 .cm_ctl = 0, /* unknown */ 990 .cm_div = 0 991 }, 992 993 [CPRMAN_CLOCK_SDC] = { 994 .cm_ctl = 0x00004006, 995 .cm_div = 0x00003000, 996 }, 997 998 [CPRMAN_CLOCK_ARM] = { 999 .cm_ctl = 0, /* unknown */ 1000 .cm_div = 0 1001 }, 1002 1003 [CPRMAN_CLOCK_AVEO] = { 1004 .cm_ctl = 0x00000000, 1005 .cm_div = 0x00000000, 1006 }, 1007 1008 [CPRMAN_CLOCK_EMMC] = { 1009 .cm_ctl = 0x00000295, 1010 .cm_div = 0x00006000, 1011 }, 1012 1013 [CPRMAN_CLOCK_EMMC2] = { 1014 .cm_ctl = 0, /* unknown */ 1015 .cm_div = 0 1016 }, 1017}; 1018 1019#endif