|  | /* | 
|  | * BCM2835 CPRMAN clock manager | 
|  | * | 
|  | * Copyright (c) 2020 Luc Michel <luc@lmichel.fr> | 
|  | * | 
|  | * SPDX-License-Identifier: GPL-2.0-or-later | 
|  | */ | 
|  |  | 
|  | #ifndef HW_MISC_BCM2835_CPRMAN_INTERNALS_H | 
|  | #define HW_MISC_BCM2835_CPRMAN_INTERNALS_H | 
|  |  | 
|  | #include "hw/registerfields.h" | 
|  | #include "hw/misc/bcm2835_cprman.h" | 
|  |  | 
|  | #define TYPE_CPRMAN_PLL "bcm2835-cprman-pll" | 
|  | #define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel" | 
|  | #define TYPE_CPRMAN_CLOCK_MUX "bcm2835-cprman-clock-mux" | 
|  | #define TYPE_CPRMAN_DSI0HSCK_MUX "bcm2835-cprman-dsi0hsck-mux" | 
|  |  | 
|  | DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL, | 
|  | TYPE_CPRMAN_PLL) | 
|  | DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL, | 
|  | TYPE_CPRMAN_PLL_CHANNEL) | 
|  | DECLARE_INSTANCE_CHECKER(CprmanClockMuxState, CPRMAN_CLOCK_MUX, | 
|  | TYPE_CPRMAN_CLOCK_MUX) | 
|  | DECLARE_INSTANCE_CHECKER(CprmanDsi0HsckMuxState, CPRMAN_DSI0HSCK_MUX, | 
|  | TYPE_CPRMAN_DSI0HSCK_MUX) | 
|  |  | 
|  | /* Register map */ | 
|  |  | 
|  | /* PLLs */ | 
|  | REG32(CM_PLLA, 0x104) | 
|  | FIELD(CM_PLLA, LOADDSI0, 0, 1) | 
|  | FIELD(CM_PLLA, HOLDDSI0, 1, 1) | 
|  | FIELD(CM_PLLA, LOADCCP2, 2, 1) | 
|  | FIELD(CM_PLLA, HOLDCCP2, 3, 1) | 
|  | FIELD(CM_PLLA, LOADCORE, 4, 1) | 
|  | FIELD(CM_PLLA, HOLDCORE, 5, 1) | 
|  | FIELD(CM_PLLA, LOADPER, 6, 1) | 
|  | FIELD(CM_PLLA, HOLDPER, 7, 1) | 
|  | FIELD(CM_PLLx, ANARST, 8, 1) | 
|  | REG32(CM_PLLC, 0x108) | 
|  | FIELD(CM_PLLC, LOADCORE0, 0, 1) | 
|  | FIELD(CM_PLLC, HOLDCORE0, 1, 1) | 
|  | FIELD(CM_PLLC, LOADCORE1, 2, 1) | 
|  | FIELD(CM_PLLC, HOLDCORE1, 3, 1) | 
|  | FIELD(CM_PLLC, LOADCORE2, 4, 1) | 
|  | FIELD(CM_PLLC, HOLDCORE2, 5, 1) | 
|  | FIELD(CM_PLLC, LOADPER, 6, 1) | 
|  | FIELD(CM_PLLC, HOLDPER, 7, 1) | 
|  | REG32(CM_PLLD, 0x10c) | 
|  | FIELD(CM_PLLD, LOADDSI0, 0, 1) | 
|  | FIELD(CM_PLLD, HOLDDSI0, 1, 1) | 
|  | FIELD(CM_PLLD, LOADDSI1, 2, 1) | 
|  | FIELD(CM_PLLD, HOLDDSI1, 3, 1) | 
|  | FIELD(CM_PLLD, LOADCORE, 4, 1) | 
|  | FIELD(CM_PLLD, HOLDCORE, 5, 1) | 
|  | FIELD(CM_PLLD, LOADPER, 6, 1) | 
|  | FIELD(CM_PLLD, HOLDPER, 7, 1) | 
|  | REG32(CM_PLLH, 0x110) | 
|  | FIELD(CM_PLLH, LOADPIX, 0, 1) | 
|  | FIELD(CM_PLLH, LOADAUX, 1, 1) | 
|  | FIELD(CM_PLLH, LOADRCAL, 2, 1) | 
|  | REG32(CM_PLLB, 0x170) | 
|  | FIELD(CM_PLLB, LOADARM, 0, 1) | 
|  | FIELD(CM_PLLB, HOLDARM, 1, 1) | 
|  |  | 
|  | REG32(A2W_PLLA_CTRL, 0x1100) | 
|  | FIELD(A2W_PLLx_CTRL, NDIV, 0, 10) | 
|  | FIELD(A2W_PLLx_CTRL, PDIV, 12, 3) | 
|  | FIELD(A2W_PLLx_CTRL, PWRDN, 16, 1) | 
|  | FIELD(A2W_PLLx_CTRL, PRST_DISABLE, 17, 1) | 
|  | REG32(A2W_PLLC_CTRL, 0x1120) | 
|  | REG32(A2W_PLLD_CTRL, 0x1140) | 
|  | REG32(A2W_PLLH_CTRL, 0x1160) | 
|  | REG32(A2W_PLLB_CTRL, 0x11e0) | 
|  |  | 
|  | REG32(A2W_PLLA_ANA0, 0x1010) | 
|  | REG32(A2W_PLLA_ANA1, 0x1014) | 
|  | FIELD(A2W_PLLx_ANA1, FB_PREDIV, 14, 1) | 
|  | REG32(A2W_PLLA_ANA2, 0x1018) | 
|  | REG32(A2W_PLLA_ANA3, 0x101c) | 
|  |  | 
|  | REG32(A2W_PLLC_ANA0, 0x1030) | 
|  | REG32(A2W_PLLC_ANA1, 0x1034) | 
|  | REG32(A2W_PLLC_ANA2, 0x1038) | 
|  | REG32(A2W_PLLC_ANA3, 0x103c) | 
|  |  | 
|  | REG32(A2W_PLLD_ANA0, 0x1050) | 
|  | REG32(A2W_PLLD_ANA1, 0x1054) | 
|  | REG32(A2W_PLLD_ANA2, 0x1058) | 
|  | REG32(A2W_PLLD_ANA3, 0x105c) | 
|  |  | 
|  | REG32(A2W_PLLH_ANA0, 0x1070) | 
|  | REG32(A2W_PLLH_ANA1, 0x1074) | 
|  | FIELD(A2W_PLLH_ANA1, FB_PREDIV, 11, 1) | 
|  | REG32(A2W_PLLH_ANA2, 0x1078) | 
|  | REG32(A2W_PLLH_ANA3, 0x107c) | 
|  |  | 
|  | REG32(A2W_PLLB_ANA0, 0x10f0) | 
|  | REG32(A2W_PLLB_ANA1, 0x10f4) | 
|  | REG32(A2W_PLLB_ANA2, 0x10f8) | 
|  | REG32(A2W_PLLB_ANA3, 0x10fc) | 
|  |  | 
|  | REG32(A2W_PLLA_FRAC, 0x1200) | 
|  | FIELD(A2W_PLLx_FRAC, FRAC, 0, 20) | 
|  | REG32(A2W_PLLC_FRAC, 0x1220) | 
|  | REG32(A2W_PLLD_FRAC, 0x1240) | 
|  | REG32(A2W_PLLH_FRAC, 0x1260) | 
|  | REG32(A2W_PLLB_FRAC, 0x12e0) | 
|  |  | 
|  | /* PLL channels */ | 
|  | REG32(A2W_PLLA_DSI0, 0x1300) | 
|  | FIELD(A2W_PLLx_CHANNELy, DIV, 0, 8) | 
|  | FIELD(A2W_PLLx_CHANNELy, DISABLE, 8, 1) | 
|  | REG32(A2W_PLLA_CORE, 0x1400) | 
|  | REG32(A2W_PLLA_PER, 0x1500) | 
|  | REG32(A2W_PLLA_CCP2, 0x1600) | 
|  |  | 
|  | REG32(A2W_PLLC_CORE2, 0x1320) | 
|  | REG32(A2W_PLLC_CORE1, 0x1420) | 
|  | REG32(A2W_PLLC_PER, 0x1520) | 
|  | REG32(A2W_PLLC_CORE0, 0x1620) | 
|  |  | 
|  | REG32(A2W_PLLD_DSI0, 0x1340) | 
|  | REG32(A2W_PLLD_CORE, 0x1440) | 
|  | REG32(A2W_PLLD_PER, 0x1540) | 
|  | REG32(A2W_PLLD_DSI1, 0x1640) | 
|  |  | 
|  | REG32(A2W_PLLH_AUX, 0x1360) | 
|  | REG32(A2W_PLLH_RCAL, 0x1460) | 
|  | REG32(A2W_PLLH_PIX, 0x1560) | 
|  | REG32(A2W_PLLH_STS, 0x1660) | 
|  |  | 
|  | REG32(A2W_PLLB_ARM, 0x13e0) | 
|  |  | 
|  | /* Clock muxes */ | 
|  | REG32(CM_GNRICCTL, 0x000) | 
|  | FIELD(CM_CLOCKx_CTL, SRC, 0, 4) | 
|  | FIELD(CM_CLOCKx_CTL, ENABLE, 4, 1) | 
|  | FIELD(CM_CLOCKx_CTL, KILL, 5, 1) | 
|  | FIELD(CM_CLOCKx_CTL, GATE, 6, 1) | 
|  | FIELD(CM_CLOCKx_CTL, BUSY, 7, 1) | 
|  | FIELD(CM_CLOCKx_CTL, BUSYD, 8, 1) | 
|  | FIELD(CM_CLOCKx_CTL, MASH, 9, 2) | 
|  | FIELD(CM_CLOCKx_CTL, FLIP, 11, 1) | 
|  | REG32(CM_GNRICDIV, 0x004) | 
|  | FIELD(CM_CLOCKx_DIV, FRAC, 0, 12) | 
|  | REG32(CM_VPUCTL, 0x008) | 
|  | REG32(CM_VPUDIV, 0x00c) | 
|  | REG32(CM_SYSCTL, 0x010) | 
|  | REG32(CM_SYSDIV, 0x014) | 
|  | REG32(CM_PERIACTL, 0x018) | 
|  | REG32(CM_PERIADIV, 0x01c) | 
|  | REG32(CM_PERIICTL, 0x020) | 
|  | REG32(CM_PERIIDIV, 0x024) | 
|  | REG32(CM_H264CTL, 0x028) | 
|  | REG32(CM_H264DIV, 0x02c) | 
|  | REG32(CM_ISPCTL, 0x030) | 
|  | REG32(CM_ISPDIV, 0x034) | 
|  | REG32(CM_V3DCTL, 0x038) | 
|  | REG32(CM_V3DDIV, 0x03c) | 
|  | REG32(CM_CAM0CTL, 0x040) | 
|  | REG32(CM_CAM0DIV, 0x044) | 
|  | REG32(CM_CAM1CTL, 0x048) | 
|  | REG32(CM_CAM1DIV, 0x04c) | 
|  | REG32(CM_CCP2CTL, 0x050) | 
|  | REG32(CM_CCP2DIV, 0x054) | 
|  | REG32(CM_DSI0ECTL, 0x058) | 
|  | REG32(CM_DSI0EDIV, 0x05c) | 
|  | REG32(CM_DSI0PCTL, 0x060) | 
|  | REG32(CM_DSI0PDIV, 0x064) | 
|  | REG32(CM_DPICTL, 0x068) | 
|  | REG32(CM_DPIDIV, 0x06c) | 
|  | REG32(CM_GP0CTL, 0x070) | 
|  | REG32(CM_GP0DIV, 0x074) | 
|  | REG32(CM_GP1CTL, 0x078) | 
|  | REG32(CM_GP1DIV, 0x07c) | 
|  | REG32(CM_GP2CTL, 0x080) | 
|  | REG32(CM_GP2DIV, 0x084) | 
|  | REG32(CM_HSMCTL, 0x088) | 
|  | REG32(CM_HSMDIV, 0x08c) | 
|  | REG32(CM_OTPCTL, 0x090) | 
|  | REG32(CM_OTPDIV, 0x094) | 
|  | REG32(CM_PCMCTL, 0x098) | 
|  | REG32(CM_PCMDIV, 0x09c) | 
|  | REG32(CM_PWMCTL, 0x0a0) | 
|  | REG32(CM_PWMDIV, 0x0a4) | 
|  | REG32(CM_SLIMCTL, 0x0a8) | 
|  | REG32(CM_SLIMDIV, 0x0ac) | 
|  | REG32(CM_SMICTL, 0x0b0) | 
|  | REG32(CM_SMIDIV, 0x0b4) | 
|  | REG32(CM_TCNTCTL, 0x0c0) | 
|  | REG32(CM_TCNTCNT, 0x0c4) | 
|  | REG32(CM_TECCTL, 0x0c8) | 
|  | REG32(CM_TECDIV, 0x0cc) | 
|  | REG32(CM_TD0CTL, 0x0d0) | 
|  | REG32(CM_TD0DIV, 0x0d4) | 
|  | REG32(CM_TD1CTL, 0x0d8) | 
|  | REG32(CM_TD1DIV, 0x0dc) | 
|  | REG32(CM_TSENSCTL, 0x0e0) | 
|  | REG32(CM_TSENSDIV, 0x0e4) | 
|  | REG32(CM_TIMERCTL, 0x0e8) | 
|  | REG32(CM_TIMERDIV, 0x0ec) | 
|  | REG32(CM_UARTCTL, 0x0f0) | 
|  | REG32(CM_UARTDIV, 0x0f4) | 
|  | REG32(CM_VECCTL, 0x0f8) | 
|  | REG32(CM_VECDIV, 0x0fc) | 
|  | REG32(CM_PULSECTL, 0x190) | 
|  | REG32(CM_PULSEDIV, 0x194) | 
|  | REG32(CM_SDCCTL, 0x1a8) | 
|  | REG32(CM_SDCDIV, 0x1ac) | 
|  | REG32(CM_ARMCTL, 0x1b0) | 
|  | REG32(CM_AVEOCTL, 0x1b8) | 
|  | REG32(CM_AVEODIV, 0x1bc) | 
|  | REG32(CM_EMMCCTL, 0x1c0) | 
|  | REG32(CM_EMMCDIV, 0x1c4) | 
|  | REG32(CM_EMMC2CTL, 0x1d0) | 
|  | REG32(CM_EMMC2DIV, 0x1d4) | 
|  |  | 
|  | /* misc registers */ | 
|  | REG32(CM_LOCK, 0x114) | 
|  | FIELD(CM_LOCK, FLOCKH, 12, 1) | 
|  | FIELD(CM_LOCK, FLOCKD, 11, 1) | 
|  | FIELD(CM_LOCK, FLOCKC, 10, 1) | 
|  | FIELD(CM_LOCK, FLOCKB, 9, 1) | 
|  | FIELD(CM_LOCK, FLOCKA, 8, 1) | 
|  |  | 
|  | REG32(CM_DSI0HSCK, 0x120) | 
|  | FIELD(CM_DSI0HSCK, SELPLLD, 0, 1) | 
|  |  | 
|  | /* | 
|  | * This field is common to all registers. Each register write value must match | 
|  | * the CPRMAN_PASSWORD magic value in its 8 MSB. | 
|  | */ | 
|  | FIELD(CPRMAN, PASSWORD, 24, 8) | 
|  | #define CPRMAN_PASSWORD 0x5a | 
|  |  | 
|  | /* PLL init info */ | 
|  | typedef struct PLLInitInfo { | 
|  | const char *name; | 
|  | size_t cm_offset; | 
|  | size_t a2w_ctrl_offset; | 
|  | size_t a2w_ana_offset; | 
|  | uint32_t prediv_mask; /* Prediv bit in ana[1] */ | 
|  | size_t a2w_frac_offset; | 
|  | } PLLInitInfo; | 
|  |  | 
|  | #define FILL_PLL_INIT_INFO(pll_)                \ | 
|  | .cm_offset = R_CM_ ## pll_,                 \ | 
|  | .a2w_ctrl_offset = R_A2W_ ## pll_ ## _CTRL, \ | 
|  | .a2w_ana_offset = R_A2W_ ## pll_ ## _ANA0,  \ | 
|  | .a2w_frac_offset = R_A2W_ ## pll_ ## _FRAC | 
|  |  | 
|  | static const PLLInitInfo PLL_INIT_INFO[] = { | 
|  | [CPRMAN_PLLA] = { | 
|  | .name = "plla", | 
|  | .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, | 
|  | FILL_PLL_INIT_INFO(PLLA), | 
|  | }, | 
|  | [CPRMAN_PLLC] = { | 
|  | .name = "pllc", | 
|  | .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, | 
|  | FILL_PLL_INIT_INFO(PLLC), | 
|  | }, | 
|  | [CPRMAN_PLLD] = { | 
|  | .name = "plld", | 
|  | .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, | 
|  | FILL_PLL_INIT_INFO(PLLD), | 
|  | }, | 
|  | [CPRMAN_PLLH] = { | 
|  | .name = "pllh", | 
|  | .prediv_mask = R_A2W_PLLH_ANA1_FB_PREDIV_MASK, | 
|  | FILL_PLL_INIT_INFO(PLLH), | 
|  | }, | 
|  | [CPRMAN_PLLB] = { | 
|  | .name = "pllb", | 
|  | .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, | 
|  | FILL_PLL_INIT_INFO(PLLB), | 
|  | }, | 
|  | }; | 
|  |  | 
|  | #undef FILL_PLL_CHANNEL_INIT_INFO | 
|  |  | 
|  | static inline void set_pll_init_info(BCM2835CprmanState *s, | 
|  | CprmanPllState *pll, | 
|  | CprmanPll id) | 
|  | { | 
|  | pll->id = id; | 
|  | pll->reg_cm = &s->regs[PLL_INIT_INFO[id].cm_offset]; | 
|  | pll->reg_a2w_ctrl = &s->regs[PLL_INIT_INFO[id].a2w_ctrl_offset]; | 
|  | pll->reg_a2w_ana = &s->regs[PLL_INIT_INFO[id].a2w_ana_offset]; | 
|  | pll->prediv_mask = PLL_INIT_INFO[id].prediv_mask; | 
|  | pll->reg_a2w_frac = &s->regs[PLL_INIT_INFO[id].a2w_frac_offset]; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* PLL channel init info */ | 
|  | typedef struct PLLChannelInitInfo { | 
|  | const char *name; | 
|  | CprmanPll parent; | 
|  | size_t cm_offset; | 
|  | uint32_t cm_hold_mask; | 
|  | uint32_t cm_load_mask; | 
|  | size_t a2w_ctrl_offset; | 
|  | unsigned int fixed_divider; | 
|  | } PLLChannelInitInfo; | 
|  |  | 
|  | #define FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_)            \ | 
|  | .parent = CPRMAN_ ## pll_,                                       \ | 
|  | .cm_offset = R_CM_ ## pll_,                                      \ | 
|  | .cm_load_mask = R_CM_ ## pll_ ## _ ## LOAD ## channel_ ## _MASK, \ | 
|  | .a2w_ctrl_offset = R_A2W_ ## pll_ ## _ ## channel_ | 
|  |  | 
|  | #define FILL_PLL_CHANNEL_INIT_INFO(pll_, channel_)                   \ | 
|  | FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_),               \ | 
|  | .cm_hold_mask = R_CM_ ## pll_ ## _ ## HOLD ## channel_ ## _MASK, \ | 
|  | .fixed_divider = 1 | 
|  |  | 
|  | #define FILL_PLL_CHANNEL_INIT_INFO_nohold(pll_, channel_) \ | 
|  | FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_),    \ | 
|  | .cm_hold_mask = 0 | 
|  |  | 
|  | static PLLChannelInitInfo PLL_CHANNEL_INIT_INFO[] = { | 
|  | [CPRMAN_PLLA_CHANNEL_DSI0] = { | 
|  | .name = "plla-dsi0", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLA, DSI0), | 
|  | }, | 
|  | [CPRMAN_PLLA_CHANNEL_CORE] = { | 
|  | .name = "plla-core", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLA, CORE), | 
|  | }, | 
|  | [CPRMAN_PLLA_CHANNEL_PER] = { | 
|  | .name = "plla-per", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLA, PER), | 
|  | }, | 
|  | [CPRMAN_PLLA_CHANNEL_CCP2] = { | 
|  | .name = "plla-ccp2", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLA, CCP2), | 
|  | }, | 
|  |  | 
|  | [CPRMAN_PLLC_CHANNEL_CORE2] = { | 
|  | .name = "pllc-core2", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE2), | 
|  | }, | 
|  | [CPRMAN_PLLC_CHANNEL_CORE1] = { | 
|  | .name = "pllc-core1", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE1), | 
|  | }, | 
|  | [CPRMAN_PLLC_CHANNEL_PER] = { | 
|  | .name = "pllc-per", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLC, PER), | 
|  | }, | 
|  | [CPRMAN_PLLC_CHANNEL_CORE0] = { | 
|  | .name = "pllc-core0", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE0), | 
|  | }, | 
|  |  | 
|  | [CPRMAN_PLLD_CHANNEL_DSI0] = { | 
|  | .name = "plld-dsi0", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI0), | 
|  | }, | 
|  | [CPRMAN_PLLD_CHANNEL_CORE] = { | 
|  | .name = "plld-core", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLD, CORE), | 
|  | }, | 
|  | [CPRMAN_PLLD_CHANNEL_PER] = { | 
|  | .name = "plld-per", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLD, PER), | 
|  | }, | 
|  | [CPRMAN_PLLD_CHANNEL_DSI1] = { | 
|  | .name = "plld-dsi1", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI1), | 
|  | }, | 
|  |  | 
|  | [CPRMAN_PLLH_CHANNEL_AUX] = { | 
|  | .name = "pllh-aux", | 
|  | .fixed_divider = 1, | 
|  | FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, AUX), | 
|  | }, | 
|  | [CPRMAN_PLLH_CHANNEL_RCAL] = { | 
|  | .name = "pllh-rcal", | 
|  | .fixed_divider = 10, | 
|  | FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, RCAL), | 
|  | }, | 
|  | [CPRMAN_PLLH_CHANNEL_PIX] = { | 
|  | .name = "pllh-pix", | 
|  | .fixed_divider = 10, | 
|  | FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, PIX), | 
|  | }, | 
|  |  | 
|  | [CPRMAN_PLLB_CHANNEL_ARM] = { | 
|  | .name = "pllb-arm", | 
|  | FILL_PLL_CHANNEL_INIT_INFO(PLLB, ARM), | 
|  | }, | 
|  | }; | 
|  |  | 
|  | #undef FILL_PLL_CHANNEL_INIT_INFO_nohold | 
|  | #undef FILL_PLL_CHANNEL_INIT_INFO | 
|  | #undef FILL_PLL_CHANNEL_INIT_INFO_common | 
|  |  | 
|  | static inline void set_pll_channel_init_info(BCM2835CprmanState *s, | 
|  | CprmanPllChannelState *channel, | 
|  | CprmanPllChannel id) | 
|  | { | 
|  | channel->id = id; | 
|  | channel->parent = PLL_CHANNEL_INIT_INFO[id].parent; | 
|  | channel->reg_cm = &s->regs[PLL_CHANNEL_INIT_INFO[id].cm_offset]; | 
|  | channel->hold_mask = PLL_CHANNEL_INIT_INFO[id].cm_hold_mask; | 
|  | channel->load_mask = PLL_CHANNEL_INIT_INFO[id].cm_load_mask; | 
|  | channel->reg_a2w_ctrl = &s->regs[PLL_CHANNEL_INIT_INFO[id].a2w_ctrl_offset]; | 
|  | channel->fixed_divider = PLL_CHANNEL_INIT_INFO[id].fixed_divider; | 
|  | } | 
|  |  | 
|  | /* Clock mux init info */ | 
|  | typedef struct ClockMuxInitInfo { | 
|  | const char *name; | 
|  | size_t cm_offset; /* cm_offset[0]->CM_CTL, cm_offset[1]->CM_DIV */ | 
|  | int int_bits; | 
|  | int frac_bits; | 
|  |  | 
|  | CprmanPllChannel src_mapping[CPRMAN_NUM_CLOCK_MUX_SRC]; | 
|  | } ClockMuxInitInfo; | 
|  |  | 
|  | /* | 
|  | * Each clock mux can have up to 10 sources. Sources 0 to 3 are always the | 
|  | * same (ground, xosc, td0, td1). Sources 4 to 9 are mux specific, and are not | 
|  | * always populated. The following macros catch all those cases. | 
|  | */ | 
|  |  | 
|  | /* Unknown mapping. Connect everything to ground */ | 
|  | #define SRC_MAPPING_INFO_unknown                          \ | 
|  | .src_mapping = {                                      \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, /* gnd */          \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, /* xosc */         \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 0 */ \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 1 */ \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll a */        \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c */        \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll d */        \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll h */        \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core1 */ \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core2 */ \ | 
|  | } | 
|  |  | 
|  | /* Only the oscillator and the two test debug clocks */ | 
|  | #define SRC_MAPPING_INFO_xosc          \ | 
|  | .src_mapping = {                   \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | } | 
|  |  | 
|  | /* All the PLL "core" channels */ | 
|  | #define SRC_MAPPING_INFO_core      \ | 
|  | .src_mapping = {               \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,   \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,   \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,   \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,   \ | 
|  | CPRMAN_PLLA_CHANNEL_CORE,  \ | 
|  | CPRMAN_PLLC_CHANNEL_CORE0, \ | 
|  | CPRMAN_PLLD_CHANNEL_CORE,  \ | 
|  | CPRMAN_PLLH_CHANNEL_AUX,   \ | 
|  | CPRMAN_PLLC_CHANNEL_CORE1, \ | 
|  | CPRMAN_PLLC_CHANNEL_CORE2, \ | 
|  | } | 
|  |  | 
|  | /* All the PLL "per" channels */ | 
|  | #define SRC_MAPPING_INFO_periph        \ | 
|  | .src_mapping = {                   \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_PLLA_CHANNEL_PER,       \ | 
|  | CPRMAN_PLLC_CHANNEL_PER,       \ | 
|  | CPRMAN_PLLD_CHANNEL_PER,       \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | } | 
|  |  | 
|  | /* | 
|  | * The DSI0 channels. This one got an intermediate mux between the PLL channels | 
|  | * and the clock input. | 
|  | */ | 
|  | #define SRC_MAPPING_INFO_dsi0          \ | 
|  | .src_mapping = {                   \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_DSI0HSCK,     \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | } | 
|  |  | 
|  | /* The DSI1 channel */ | 
|  | #define SRC_MAPPING_INFO_dsi1          \ | 
|  | .src_mapping = {                   \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_CLOCK_SRC_NORMAL,       \ | 
|  | CPRMAN_PLLD_CHANNEL_DSI1,      \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | CPRMAN_CLOCK_SRC_FORCE_GROUND, \ | 
|  | } | 
|  |  | 
|  | #define FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) \ | 
|  | SRC_MAPPING_INFO_ ## kind_ | 
|  |  | 
|  | #define FILL_CLOCK_MUX_INIT_INFO(clock_, kind_) \ | 
|  | .cm_offset = R_CM_ ## clock_ ## CTL,        \ | 
|  | FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) | 
|  |  | 
|  | static ClockMuxInitInfo CLOCK_MUX_INIT_INFO[] = { | 
|  | [CPRMAN_CLOCK_GNRIC] = { | 
|  | .name = "gnric", | 
|  | FILL_CLOCK_MUX_INIT_INFO(GNRIC, unknown), | 
|  | }, | 
|  | [CPRMAN_CLOCK_VPU] = { | 
|  | .name = "vpu", | 
|  | .int_bits = 12, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(VPU, core), | 
|  | }, | 
|  | [CPRMAN_CLOCK_SYS] = { | 
|  | .name = "sys", | 
|  | FILL_CLOCK_MUX_INIT_INFO(SYS, unknown), | 
|  | }, | 
|  | [CPRMAN_CLOCK_PERIA] = { | 
|  | .name = "peria", | 
|  | FILL_CLOCK_MUX_INIT_INFO(PERIA, unknown), | 
|  | }, | 
|  | [CPRMAN_CLOCK_PERII] = { | 
|  | .name = "perii", | 
|  | FILL_CLOCK_MUX_INIT_INFO(PERII, unknown), | 
|  | }, | 
|  | [CPRMAN_CLOCK_H264] = { | 
|  | .name = "h264", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(H264, core), | 
|  | }, | 
|  | [CPRMAN_CLOCK_ISP] = { | 
|  | .name = "isp", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(ISP, core), | 
|  | }, | 
|  | [CPRMAN_CLOCK_V3D] = { | 
|  | .name = "v3d", | 
|  | FILL_CLOCK_MUX_INIT_INFO(V3D, core), | 
|  | }, | 
|  | [CPRMAN_CLOCK_CAM0] = { | 
|  | .name = "cam0", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(CAM0, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_CAM1] = { | 
|  | .name = "cam1", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(CAM1, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_CCP2] = { | 
|  | .name = "ccp2", | 
|  | FILL_CLOCK_MUX_INIT_INFO(CCP2, unknown), | 
|  | }, | 
|  | [CPRMAN_CLOCK_DSI0E] = { | 
|  | .name = "dsi0e", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(DSI0E, dsi0), | 
|  | }, | 
|  | [CPRMAN_CLOCK_DSI0P] = { | 
|  | .name = "dsi0p", | 
|  | .int_bits = 0, | 
|  | .frac_bits = 0, | 
|  | FILL_CLOCK_MUX_INIT_INFO(DSI0P, dsi0), | 
|  | }, | 
|  | [CPRMAN_CLOCK_DPI] = { | 
|  | .name = "dpi", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(DPI, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_GP0] = { | 
|  | .name = "gp0", | 
|  | .int_bits = 12, | 
|  | .frac_bits = 12, | 
|  | FILL_CLOCK_MUX_INIT_INFO(GP0, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_GP1] = { | 
|  | .name = "gp1", | 
|  | .int_bits = 12, | 
|  | .frac_bits = 12, | 
|  | FILL_CLOCK_MUX_INIT_INFO(GP1, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_GP2] = { | 
|  | .name = "gp2", | 
|  | .int_bits = 12, | 
|  | .frac_bits = 12, | 
|  | FILL_CLOCK_MUX_INIT_INFO(GP2, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_HSM] = { | 
|  | .name = "hsm", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(HSM, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_OTP] = { | 
|  | .name = "otp", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 0, | 
|  | FILL_CLOCK_MUX_INIT_INFO(OTP, xosc), | 
|  | }, | 
|  | [CPRMAN_CLOCK_PCM] = { | 
|  | .name = "pcm", | 
|  | .int_bits = 12, | 
|  | .frac_bits = 12, | 
|  | FILL_CLOCK_MUX_INIT_INFO(PCM, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_PWM] = { | 
|  | .name = "pwm", | 
|  | .int_bits = 12, | 
|  | .frac_bits = 12, | 
|  | FILL_CLOCK_MUX_INIT_INFO(PWM, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_SLIM] = { | 
|  | .name = "slim", | 
|  | .int_bits = 12, | 
|  | .frac_bits = 12, | 
|  | FILL_CLOCK_MUX_INIT_INFO(SLIM, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_SMI] = { | 
|  | .name = "smi", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(SMI, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_TEC] = { | 
|  | .name = "tec", | 
|  | .int_bits = 6, | 
|  | .frac_bits = 0, | 
|  | FILL_CLOCK_MUX_INIT_INFO(TEC, xosc), | 
|  | }, | 
|  | [CPRMAN_CLOCK_TD0] = { | 
|  | .name = "td0", | 
|  | FILL_CLOCK_MUX_INIT_INFO(TD0, unknown), | 
|  | }, | 
|  | [CPRMAN_CLOCK_TD1] = { | 
|  | .name = "td1", | 
|  | FILL_CLOCK_MUX_INIT_INFO(TD1, unknown), | 
|  | }, | 
|  | [CPRMAN_CLOCK_TSENS] = { | 
|  | .name = "tsens", | 
|  | .int_bits = 5, | 
|  | .frac_bits = 0, | 
|  | FILL_CLOCK_MUX_INIT_INFO(TSENS, xosc), | 
|  | }, | 
|  | [CPRMAN_CLOCK_TIMER] = { | 
|  | .name = "timer", | 
|  | .int_bits = 6, | 
|  | .frac_bits = 12, | 
|  | FILL_CLOCK_MUX_INIT_INFO(TIMER, xosc), | 
|  | }, | 
|  | [CPRMAN_CLOCK_UART] = { | 
|  | .name = "uart", | 
|  | .int_bits = 10, | 
|  | .frac_bits = 12, | 
|  | FILL_CLOCK_MUX_INIT_INFO(UART, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_VEC] = { | 
|  | .name = "vec", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 0, | 
|  | FILL_CLOCK_MUX_INIT_INFO(VEC, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_PULSE] = { | 
|  | .name = "pulse", | 
|  | FILL_CLOCK_MUX_INIT_INFO(PULSE, xosc), | 
|  | }, | 
|  | [CPRMAN_CLOCK_SDC] = { | 
|  | .name = "sdram", | 
|  | .int_bits = 6, | 
|  | .frac_bits = 0, | 
|  | FILL_CLOCK_MUX_INIT_INFO(SDC, core), | 
|  | }, | 
|  | [CPRMAN_CLOCK_ARM] = { | 
|  | .name = "arm", | 
|  | FILL_CLOCK_MUX_INIT_INFO(ARM, unknown), | 
|  | }, | 
|  | [CPRMAN_CLOCK_AVEO] = { | 
|  | .name = "aveo", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 0, | 
|  | FILL_CLOCK_MUX_INIT_INFO(AVEO, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_EMMC] = { | 
|  | .name = "emmc", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(EMMC, periph), | 
|  | }, | 
|  | [CPRMAN_CLOCK_EMMC2] = { | 
|  | .name = "emmc2", | 
|  | .int_bits = 4, | 
|  | .frac_bits = 8, | 
|  | FILL_CLOCK_MUX_INIT_INFO(EMMC2, unknown), | 
|  | }, | 
|  | }; | 
|  |  | 
|  | #undef FILL_CLOCK_MUX_INIT_INFO | 
|  | #undef FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO | 
|  | #undef SRC_MAPPING_INFO_dsi1 | 
|  | #undef SRC_MAPPING_INFO_dsi0 | 
|  | #undef SRC_MAPPING_INFO_periph | 
|  | #undef SRC_MAPPING_INFO_core | 
|  | #undef SRC_MAPPING_INFO_xosc | 
|  | #undef SRC_MAPPING_INFO_unknown | 
|  |  | 
|  | static inline void set_clock_mux_init_info(BCM2835CprmanState *s, | 
|  | CprmanClockMuxState *mux, | 
|  | CprmanClockMux id) | 
|  | { | 
|  | mux->id = id; | 
|  | mux->reg_ctl = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset]; | 
|  | mux->reg_div = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset + 1]; | 
|  | mux->int_bits = CLOCK_MUX_INIT_INFO[id].int_bits; | 
|  | mux->frac_bits = CLOCK_MUX_INIT_INFO[id].frac_bits; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* | 
|  | * Object reset info | 
|  | * Those values have been dumped from a Raspberry Pi 3 Model B v1.2 using the | 
|  | * clk debugfs interface in Linux. | 
|  | */ | 
|  | typedef struct PLLResetInfo { | 
|  | uint32_t cm; | 
|  | uint32_t a2w_ctrl; | 
|  | uint32_t a2w_ana[4]; | 
|  | uint32_t a2w_frac; | 
|  | } PLLResetInfo; | 
|  |  | 
|  | static const PLLResetInfo PLL_RESET_INFO[] = { | 
|  | [CPRMAN_PLLA] = { | 
|  | .cm = 0x0000008a, | 
|  | .a2w_ctrl = 0x0002103a, | 
|  | .a2w_frac = 0x00098000, | 
|  | .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } | 
|  | }, | 
|  |  | 
|  | [CPRMAN_PLLC] = { | 
|  | .cm = 0x00000228, | 
|  | .a2w_ctrl = 0x0002103e, | 
|  | .a2w_frac = 0x00080000, | 
|  | .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } | 
|  | }, | 
|  |  | 
|  | [CPRMAN_PLLD] = { | 
|  | .cm = 0x0000020a, | 
|  | .a2w_ctrl = 0x00021034, | 
|  | .a2w_frac = 0x00015556, | 
|  | .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } | 
|  | }, | 
|  |  | 
|  | [CPRMAN_PLLH] = { | 
|  | .cm = 0x00000000, | 
|  | .a2w_ctrl = 0x0002102d, | 
|  | .a2w_frac = 0x00000000, | 
|  | .a2w_ana = { 0x00900000, 0x0000000c, 0x00000000, 0x00000000 } | 
|  | }, | 
|  |  | 
|  | [CPRMAN_PLLB] = { | 
|  | /* unknown */ | 
|  | .cm = 0x00000000, | 
|  | .a2w_ctrl = 0x00000000, | 
|  | .a2w_frac = 0x00000000, | 
|  | .a2w_ana = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 } | 
|  | } | 
|  | }; | 
|  |  | 
|  | typedef struct PLLChannelResetInfo { | 
|  | /* | 
|  | * Even though a PLL channel has a CM register, it shares it with its | 
|  | * parent PLL. The parent already takes care of the reset value. | 
|  | */ | 
|  | uint32_t a2w_ctrl; | 
|  | } PLLChannelResetInfo; | 
|  |  | 
|  | static const PLLChannelResetInfo PLL_CHANNEL_RESET_INFO[] = { | 
|  | [CPRMAN_PLLA_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 }, | 
|  | [CPRMAN_PLLA_CHANNEL_CORE] = { .a2w_ctrl = 0x00000003 }, | 
|  | [CPRMAN_PLLA_CHANNEL_PER] = { .a2w_ctrl = 0x00000000 }, /* unknown */ | 
|  | [CPRMAN_PLLA_CHANNEL_CCP2] = { .a2w_ctrl = 0x00000100 }, | 
|  |  | 
|  | [CPRMAN_PLLC_CHANNEL_CORE2] = { .a2w_ctrl = 0x00000100 }, | 
|  | [CPRMAN_PLLC_CHANNEL_CORE1] = { .a2w_ctrl = 0x00000100 }, | 
|  | [CPRMAN_PLLC_CHANNEL_PER] = { .a2w_ctrl = 0x00000002 }, | 
|  | [CPRMAN_PLLC_CHANNEL_CORE0] = { .a2w_ctrl = 0x00000002 }, | 
|  |  | 
|  | [CPRMAN_PLLD_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 }, | 
|  | [CPRMAN_PLLD_CHANNEL_CORE] = { .a2w_ctrl = 0x00000004 }, | 
|  | [CPRMAN_PLLD_CHANNEL_PER] = { .a2w_ctrl = 0x00000004 }, | 
|  | [CPRMAN_PLLD_CHANNEL_DSI1] = { .a2w_ctrl = 0x00000100 }, | 
|  |  | 
|  | [CPRMAN_PLLH_CHANNEL_AUX] = { .a2w_ctrl = 0x00000004 }, | 
|  | [CPRMAN_PLLH_CHANNEL_RCAL] = { .a2w_ctrl = 0x00000000 }, | 
|  | [CPRMAN_PLLH_CHANNEL_PIX] = { .a2w_ctrl = 0x00000000 }, | 
|  |  | 
|  | [CPRMAN_PLLB_CHANNEL_ARM] = { .a2w_ctrl = 0x00000000 }, /* unknown */ | 
|  | }; | 
|  |  | 
|  | typedef struct ClockMuxResetInfo { | 
|  | uint32_t cm_ctl; | 
|  | uint32_t cm_div; | 
|  | } ClockMuxResetInfo; | 
|  |  | 
|  | static const ClockMuxResetInfo CLOCK_MUX_RESET_INFO[] = { | 
|  | [CPRMAN_CLOCK_GNRIC] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_VPU] = { | 
|  | .cm_ctl = 0x00000245, | 
|  | .cm_div = 0x00003000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_SYS] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_PERIA] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_PERII] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_H264] = { | 
|  | .cm_ctl = 0x00000244, | 
|  | .cm_div = 0x00003000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_ISP] = { | 
|  | .cm_ctl = 0x00000244, | 
|  | .cm_div = 0x00003000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_V3D] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_CAM0] = { | 
|  | .cm_ctl = 0x00000000, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_CAM1] = { | 
|  | .cm_ctl = 0x00000000, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_CCP2] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_DSI0E] = { | 
|  | .cm_ctl = 0x00000000, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_DSI0P] = { | 
|  | .cm_ctl = 0x00000000, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_DPI] = { | 
|  | .cm_ctl = 0x00000000, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_GP0] = { | 
|  | .cm_ctl = 0x00000200, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_GP1] = { | 
|  | .cm_ctl = 0x00000096, | 
|  | .cm_div = 0x00014000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_GP2] = { | 
|  | .cm_ctl = 0x00000291, | 
|  | .cm_div = 0x00249f00, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_HSM] = { | 
|  | .cm_ctl = 0x00000000, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_OTP] = { | 
|  | .cm_ctl = 0x00000091, | 
|  | .cm_div = 0x00004000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_PCM] = { | 
|  | .cm_ctl = 0x00000200, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_PWM] = { | 
|  | .cm_ctl = 0x00000200, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_SLIM] = { | 
|  | .cm_ctl = 0x00000200, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_SMI] = { | 
|  | .cm_ctl = 0x00000000, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_TEC] = { | 
|  | .cm_ctl = 0x00000000, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_TD0] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_TD1] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_TSENS] = { | 
|  | .cm_ctl = 0x00000091, | 
|  | .cm_div = 0x0000a000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_TIMER] = { | 
|  | .cm_ctl = 0x00000291, | 
|  | .cm_div = 0x00013333, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_UART] = { | 
|  | .cm_ctl = 0x00000296, | 
|  | .cm_div = 0x0000a6ab, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_VEC] = { | 
|  | .cm_ctl = 0x00000097, | 
|  | .cm_div = 0x00002000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_PULSE] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_SDC] = { | 
|  | .cm_ctl = 0x00004006, | 
|  | .cm_div = 0x00003000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_ARM] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_AVEO] = { | 
|  | .cm_ctl = 0x00000000, | 
|  | .cm_div = 0x00000000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_EMMC] = { | 
|  | .cm_ctl = 0x00000295, | 
|  | .cm_div = 0x00006000, | 
|  | }, | 
|  |  | 
|  | [CPRMAN_CLOCK_EMMC2] = { | 
|  | .cm_ctl = 0, /* unknown */ | 
|  | .cm_div = 0 | 
|  | }, | 
|  | }; | 
|  |  | 
|  | #endif |