1fc14176bSLuc Michel /* 2fc14176bSLuc Michel * BCM2835 CPRMAN clock manager 3fc14176bSLuc Michel * 4fc14176bSLuc Michel * Copyright (c) 2020 Luc Michel <luc@lmichel.fr> 5fc14176bSLuc Michel * 6fc14176bSLuc Michel * SPDX-License-Identifier: GPL-2.0-or-later 7fc14176bSLuc Michel */ 8fc14176bSLuc Michel 9fc14176bSLuc Michel #ifndef HW_MISC_CPRMAN_INTERNALS_H 10fc14176bSLuc Michel #define HW_MISC_CPRMAN_INTERNALS_H 11fc14176bSLuc Michel 12fc14176bSLuc Michel #include "hw/registerfields.h" 13fc14176bSLuc Michel #include "hw/misc/bcm2835_cprman.h" 14fc14176bSLuc Michel 151e986e25SLuc Michel #define TYPE_CPRMAN_PLL "bcm2835-cprman-pll" 1609d56bbcSLuc Michel #define TYPE_CPRMAN_PLL_CHANNEL "bcm2835-cprman-pll-channel" 1772813624SLuc Michel #define TYPE_CPRMAN_CLOCK_MUX "bcm2835-cprman-clock-mux" 18502960caSLuc Michel #define TYPE_CPRMAN_DSI0HSCK_MUX "bcm2835-cprman-dsi0hsck-mux" 191e986e25SLuc Michel 201e986e25SLuc Michel DECLARE_INSTANCE_CHECKER(CprmanPllState, CPRMAN_PLL, 211e986e25SLuc Michel TYPE_CPRMAN_PLL) 2209d56bbcSLuc Michel DECLARE_INSTANCE_CHECKER(CprmanPllChannelState, CPRMAN_PLL_CHANNEL, 2309d56bbcSLuc Michel TYPE_CPRMAN_PLL_CHANNEL) 2472813624SLuc Michel DECLARE_INSTANCE_CHECKER(CprmanClockMuxState, CPRMAN_CLOCK_MUX, 2572813624SLuc Michel TYPE_CPRMAN_CLOCK_MUX) 26502960caSLuc Michel DECLARE_INSTANCE_CHECKER(CprmanDsi0HsckMuxState, CPRMAN_DSI0HSCK_MUX, 27502960caSLuc Michel TYPE_CPRMAN_DSI0HSCK_MUX) 281e986e25SLuc Michel 29fc14176bSLuc Michel /* Register map */ 30fc14176bSLuc Michel 311e986e25SLuc Michel /* PLLs */ 321e986e25SLuc Michel REG32(CM_PLLA, 0x104) 331e986e25SLuc Michel FIELD(CM_PLLA, LOADDSI0, 0, 1) 341e986e25SLuc Michel FIELD(CM_PLLA, HOLDDSI0, 1, 1) 351e986e25SLuc Michel FIELD(CM_PLLA, LOADCCP2, 2, 1) 361e986e25SLuc Michel FIELD(CM_PLLA, HOLDCCP2, 3, 1) 371e986e25SLuc Michel FIELD(CM_PLLA, LOADCORE, 4, 1) 381e986e25SLuc Michel FIELD(CM_PLLA, HOLDCORE, 5, 1) 391e986e25SLuc Michel FIELD(CM_PLLA, LOADPER, 6, 1) 401e986e25SLuc Michel FIELD(CM_PLLA, HOLDPER, 7, 1) 411e986e25SLuc Michel FIELD(CM_PLLx, ANARST, 8, 1) 421e986e25SLuc Michel REG32(CM_PLLC, 0x108) 431e986e25SLuc Michel FIELD(CM_PLLC, LOADCORE0, 0, 1) 441e986e25SLuc Michel FIELD(CM_PLLC, HOLDCORE0, 1, 1) 451e986e25SLuc Michel FIELD(CM_PLLC, LOADCORE1, 2, 1) 461e986e25SLuc Michel FIELD(CM_PLLC, HOLDCORE1, 3, 1) 471e986e25SLuc Michel FIELD(CM_PLLC, LOADCORE2, 4, 1) 481e986e25SLuc Michel FIELD(CM_PLLC, HOLDCORE2, 5, 1) 491e986e25SLuc Michel FIELD(CM_PLLC, LOADPER, 6, 1) 501e986e25SLuc Michel FIELD(CM_PLLC, HOLDPER, 7, 1) 511e986e25SLuc Michel REG32(CM_PLLD, 0x10c) 521e986e25SLuc Michel FIELD(CM_PLLD, LOADDSI0, 0, 1) 531e986e25SLuc Michel FIELD(CM_PLLD, HOLDDSI0, 1, 1) 541e986e25SLuc Michel FIELD(CM_PLLD, LOADDSI1, 2, 1) 551e986e25SLuc Michel FIELD(CM_PLLD, HOLDDSI1, 3, 1) 561e986e25SLuc Michel FIELD(CM_PLLD, LOADCORE, 4, 1) 571e986e25SLuc Michel FIELD(CM_PLLD, HOLDCORE, 5, 1) 581e986e25SLuc Michel FIELD(CM_PLLD, LOADPER, 6, 1) 591e986e25SLuc Michel FIELD(CM_PLLD, HOLDPER, 7, 1) 601e986e25SLuc Michel REG32(CM_PLLH, 0x110) 611e986e25SLuc Michel FIELD(CM_PLLH, LOADPIX, 0, 1) 621e986e25SLuc Michel FIELD(CM_PLLH, LOADAUX, 1, 1) 631e986e25SLuc Michel FIELD(CM_PLLH, LOADRCAL, 2, 1) 641e986e25SLuc Michel REG32(CM_PLLB, 0x170) 651e986e25SLuc Michel FIELD(CM_PLLB, LOADARM, 0, 1) 661e986e25SLuc Michel FIELD(CM_PLLB, HOLDARM, 1, 1) 671e986e25SLuc Michel 681e986e25SLuc Michel REG32(A2W_PLLA_CTRL, 0x1100) 691e986e25SLuc Michel FIELD(A2W_PLLx_CTRL, NDIV, 0, 10) 701e986e25SLuc Michel FIELD(A2W_PLLx_CTRL, PDIV, 12, 3) 711e986e25SLuc Michel FIELD(A2W_PLLx_CTRL, PWRDN, 16, 1) 721e986e25SLuc Michel FIELD(A2W_PLLx_CTRL, PRST_DISABLE, 17, 1) 731e986e25SLuc Michel REG32(A2W_PLLC_CTRL, 0x1120) 741e986e25SLuc Michel REG32(A2W_PLLD_CTRL, 0x1140) 751e986e25SLuc Michel REG32(A2W_PLLH_CTRL, 0x1160) 761e986e25SLuc Michel REG32(A2W_PLLB_CTRL, 0x11e0) 771e986e25SLuc Michel 781e986e25SLuc Michel REG32(A2W_PLLA_ANA0, 0x1010) 791e986e25SLuc Michel REG32(A2W_PLLA_ANA1, 0x1014) 801e986e25SLuc Michel FIELD(A2W_PLLx_ANA1, FB_PREDIV, 14, 1) 811e986e25SLuc Michel REG32(A2W_PLLA_ANA2, 0x1018) 821e986e25SLuc Michel REG32(A2W_PLLA_ANA3, 0x101c) 831e986e25SLuc Michel 841e986e25SLuc Michel REG32(A2W_PLLC_ANA0, 0x1030) 851e986e25SLuc Michel REG32(A2W_PLLC_ANA1, 0x1034) 861e986e25SLuc Michel REG32(A2W_PLLC_ANA2, 0x1038) 871e986e25SLuc Michel REG32(A2W_PLLC_ANA3, 0x103c) 881e986e25SLuc Michel 891e986e25SLuc Michel REG32(A2W_PLLD_ANA0, 0x1050) 901e986e25SLuc Michel REG32(A2W_PLLD_ANA1, 0x1054) 911e986e25SLuc Michel REG32(A2W_PLLD_ANA2, 0x1058) 921e986e25SLuc Michel REG32(A2W_PLLD_ANA3, 0x105c) 931e986e25SLuc Michel 941e986e25SLuc Michel REG32(A2W_PLLH_ANA0, 0x1070) 951e986e25SLuc Michel REG32(A2W_PLLH_ANA1, 0x1074) 961e986e25SLuc Michel FIELD(A2W_PLLH_ANA1, FB_PREDIV, 11, 1) 971e986e25SLuc Michel REG32(A2W_PLLH_ANA2, 0x1078) 981e986e25SLuc Michel REG32(A2W_PLLH_ANA3, 0x107c) 991e986e25SLuc Michel 1001e986e25SLuc Michel REG32(A2W_PLLB_ANA0, 0x10f0) 1011e986e25SLuc Michel REG32(A2W_PLLB_ANA1, 0x10f4) 1021e986e25SLuc Michel REG32(A2W_PLLB_ANA2, 0x10f8) 1031e986e25SLuc Michel REG32(A2W_PLLB_ANA3, 0x10fc) 1041e986e25SLuc Michel 1051e986e25SLuc Michel REG32(A2W_PLLA_FRAC, 0x1200) 1061e986e25SLuc Michel FIELD(A2W_PLLx_FRAC, FRAC, 0, 20) 1071e986e25SLuc Michel REG32(A2W_PLLC_FRAC, 0x1220) 1081e986e25SLuc Michel REG32(A2W_PLLD_FRAC, 0x1240) 1091e986e25SLuc Michel REG32(A2W_PLLH_FRAC, 0x1260) 1101e986e25SLuc Michel REG32(A2W_PLLB_FRAC, 0x12e0) 1111e986e25SLuc Michel 11209d56bbcSLuc Michel /* PLL channels */ 11309d56bbcSLuc Michel REG32(A2W_PLLA_DSI0, 0x1300) 11409d56bbcSLuc Michel FIELD(A2W_PLLx_CHANNELy, DIV, 0, 8) 11509d56bbcSLuc Michel FIELD(A2W_PLLx_CHANNELy, DISABLE, 8, 1) 11609d56bbcSLuc Michel REG32(A2W_PLLA_CORE, 0x1400) 11709d56bbcSLuc Michel REG32(A2W_PLLA_PER, 0x1500) 11809d56bbcSLuc Michel REG32(A2W_PLLA_CCP2, 0x1600) 11909d56bbcSLuc Michel 12009d56bbcSLuc Michel REG32(A2W_PLLC_CORE2, 0x1320) 12109d56bbcSLuc Michel REG32(A2W_PLLC_CORE1, 0x1420) 12209d56bbcSLuc Michel REG32(A2W_PLLC_PER, 0x1520) 12309d56bbcSLuc Michel REG32(A2W_PLLC_CORE0, 0x1620) 12409d56bbcSLuc Michel 12509d56bbcSLuc Michel REG32(A2W_PLLD_DSI0, 0x1340) 12609d56bbcSLuc Michel REG32(A2W_PLLD_CORE, 0x1440) 12709d56bbcSLuc Michel REG32(A2W_PLLD_PER, 0x1540) 12809d56bbcSLuc Michel REG32(A2W_PLLD_DSI1, 0x1640) 12909d56bbcSLuc Michel 13009d56bbcSLuc Michel REG32(A2W_PLLH_AUX, 0x1360) 13109d56bbcSLuc Michel REG32(A2W_PLLH_RCAL, 0x1460) 13209d56bbcSLuc Michel REG32(A2W_PLLH_PIX, 0x1560) 13309d56bbcSLuc Michel REG32(A2W_PLLH_STS, 0x1660) 13409d56bbcSLuc Michel 13509d56bbcSLuc Michel REG32(A2W_PLLB_ARM, 0x13e0) 13609d56bbcSLuc Michel 13772813624SLuc Michel /* Clock muxes */ 13872813624SLuc Michel REG32(CM_GNRICCTL, 0x000) 13972813624SLuc Michel FIELD(CM_CLOCKx_CTL, SRC, 0, 4) 14072813624SLuc Michel FIELD(CM_CLOCKx_CTL, ENABLE, 4, 1) 14172813624SLuc Michel FIELD(CM_CLOCKx_CTL, KILL, 5, 1) 14272813624SLuc Michel FIELD(CM_CLOCKx_CTL, GATE, 6, 1) 14372813624SLuc Michel FIELD(CM_CLOCKx_CTL, BUSY, 7, 1) 14472813624SLuc Michel FIELD(CM_CLOCKx_CTL, BUSYD, 8, 1) 14572813624SLuc Michel FIELD(CM_CLOCKx_CTL, MASH, 9, 2) 14672813624SLuc Michel FIELD(CM_CLOCKx_CTL, FLIP, 11, 1) 14772813624SLuc Michel REG32(CM_GNRICDIV, 0x004) 14872813624SLuc Michel FIELD(CM_CLOCKx_DIV, FRAC, 0, 12) 14972813624SLuc Michel REG32(CM_VPUCTL, 0x008) 15072813624SLuc Michel REG32(CM_VPUDIV, 0x00c) 15172813624SLuc Michel REG32(CM_SYSCTL, 0x010) 15272813624SLuc Michel REG32(CM_SYSDIV, 0x014) 15372813624SLuc Michel REG32(CM_PERIACTL, 0x018) 15472813624SLuc Michel REG32(CM_PERIADIV, 0x01c) 15572813624SLuc Michel REG32(CM_PERIICTL, 0x020) 15672813624SLuc Michel REG32(CM_PERIIDIV, 0x024) 15772813624SLuc Michel REG32(CM_H264CTL, 0x028) 15872813624SLuc Michel REG32(CM_H264DIV, 0x02c) 15972813624SLuc Michel REG32(CM_ISPCTL, 0x030) 16072813624SLuc Michel REG32(CM_ISPDIV, 0x034) 16172813624SLuc Michel REG32(CM_V3DCTL, 0x038) 16272813624SLuc Michel REG32(CM_V3DDIV, 0x03c) 16372813624SLuc Michel REG32(CM_CAM0CTL, 0x040) 16472813624SLuc Michel REG32(CM_CAM0DIV, 0x044) 16572813624SLuc Michel REG32(CM_CAM1CTL, 0x048) 16672813624SLuc Michel REG32(CM_CAM1DIV, 0x04c) 16772813624SLuc Michel REG32(CM_CCP2CTL, 0x050) 16872813624SLuc Michel REG32(CM_CCP2DIV, 0x054) 16972813624SLuc Michel REG32(CM_DSI0ECTL, 0x058) 17072813624SLuc Michel REG32(CM_DSI0EDIV, 0x05c) 17172813624SLuc Michel REG32(CM_DSI0PCTL, 0x060) 17272813624SLuc Michel REG32(CM_DSI0PDIV, 0x064) 17372813624SLuc Michel REG32(CM_DPICTL, 0x068) 17472813624SLuc Michel REG32(CM_DPIDIV, 0x06c) 17572813624SLuc Michel REG32(CM_GP0CTL, 0x070) 17672813624SLuc Michel REG32(CM_GP0DIV, 0x074) 17772813624SLuc Michel REG32(CM_GP1CTL, 0x078) 17872813624SLuc Michel REG32(CM_GP1DIV, 0x07c) 17972813624SLuc Michel REG32(CM_GP2CTL, 0x080) 18072813624SLuc Michel REG32(CM_GP2DIV, 0x084) 18172813624SLuc Michel REG32(CM_HSMCTL, 0x088) 18272813624SLuc Michel REG32(CM_HSMDIV, 0x08c) 18372813624SLuc Michel REG32(CM_OTPCTL, 0x090) 18472813624SLuc Michel REG32(CM_OTPDIV, 0x094) 18572813624SLuc Michel REG32(CM_PCMCTL, 0x098) 18672813624SLuc Michel REG32(CM_PCMDIV, 0x09c) 18772813624SLuc Michel REG32(CM_PWMCTL, 0x0a0) 18872813624SLuc Michel REG32(CM_PWMDIV, 0x0a4) 18972813624SLuc Michel REG32(CM_SLIMCTL, 0x0a8) 19072813624SLuc Michel REG32(CM_SLIMDIV, 0x0ac) 19172813624SLuc Michel REG32(CM_SMICTL, 0x0b0) 19272813624SLuc Michel REG32(CM_SMIDIV, 0x0b4) 19372813624SLuc Michel REG32(CM_TCNTCTL, 0x0c0) 19472813624SLuc Michel REG32(CM_TCNTCNT, 0x0c4) 19572813624SLuc Michel REG32(CM_TECCTL, 0x0c8) 19672813624SLuc Michel REG32(CM_TECDIV, 0x0cc) 19772813624SLuc Michel REG32(CM_TD0CTL, 0x0d0) 19872813624SLuc Michel REG32(CM_TD0DIV, 0x0d4) 19972813624SLuc Michel REG32(CM_TD1CTL, 0x0d8) 20072813624SLuc Michel REG32(CM_TD1DIV, 0x0dc) 20172813624SLuc Michel REG32(CM_TSENSCTL, 0x0e0) 20272813624SLuc Michel REG32(CM_TSENSDIV, 0x0e4) 20372813624SLuc Michel REG32(CM_TIMERCTL, 0x0e8) 20472813624SLuc Michel REG32(CM_TIMERDIV, 0x0ec) 20572813624SLuc Michel REG32(CM_UARTCTL, 0x0f0) 20672813624SLuc Michel REG32(CM_UARTDIV, 0x0f4) 20772813624SLuc Michel REG32(CM_VECCTL, 0x0f8) 20872813624SLuc Michel REG32(CM_VECDIV, 0x0fc) 20972813624SLuc Michel REG32(CM_PULSECTL, 0x190) 21072813624SLuc Michel REG32(CM_PULSEDIV, 0x194) 21172813624SLuc Michel REG32(CM_SDCCTL, 0x1a8) 21272813624SLuc Michel REG32(CM_SDCDIV, 0x1ac) 21372813624SLuc Michel REG32(CM_ARMCTL, 0x1b0) 21472813624SLuc Michel REG32(CM_AVEOCTL, 0x1b8) 21572813624SLuc Michel REG32(CM_AVEODIV, 0x1bc) 21672813624SLuc Michel REG32(CM_EMMCCTL, 0x1c0) 21772813624SLuc Michel REG32(CM_EMMCDIV, 0x1c4) 21872813624SLuc Michel REG32(CM_EMMC2CTL, 0x1d0) 21972813624SLuc Michel REG32(CM_EMMC2DIV, 0x1d4) 22072813624SLuc Michel 2216d2b874cSLuc Michel /* misc registers */ 2226d2b874cSLuc Michel REG32(CM_LOCK, 0x114) 2236d2b874cSLuc Michel FIELD(CM_LOCK, FLOCKH, 12, 1) 2246d2b874cSLuc Michel FIELD(CM_LOCK, FLOCKD, 11, 1) 2256d2b874cSLuc Michel FIELD(CM_LOCK, FLOCKC, 10, 1) 2266d2b874cSLuc Michel FIELD(CM_LOCK, FLOCKB, 9, 1) 2276d2b874cSLuc Michel FIELD(CM_LOCK, FLOCKA, 8, 1) 2286d2b874cSLuc Michel 229502960caSLuc Michel REG32(CM_DSI0HSCK, 0x120) 230502960caSLuc Michel FIELD(CM_DSI0HSCK, SELPLLD, 0, 1) 231502960caSLuc Michel 232fc14176bSLuc Michel /* 233fc14176bSLuc Michel * This field is common to all registers. Each register write value must match 234fc14176bSLuc Michel * the CPRMAN_PASSWORD magic value in its 8 MSB. 235fc14176bSLuc Michel */ 236fc14176bSLuc Michel FIELD(CPRMAN, PASSWORD, 24, 8) 237fc14176bSLuc Michel #define CPRMAN_PASSWORD 0x5a 238fc14176bSLuc Michel 2391e986e25SLuc Michel /* PLL init info */ 2401e986e25SLuc Michel typedef struct PLLInitInfo { 2411e986e25SLuc Michel const char *name; 2421e986e25SLuc Michel size_t cm_offset; 2431e986e25SLuc Michel size_t a2w_ctrl_offset; 2441e986e25SLuc Michel size_t a2w_ana_offset; 2451e986e25SLuc Michel uint32_t prediv_mask; /* Prediv bit in ana[1] */ 2461e986e25SLuc Michel size_t a2w_frac_offset; 2471e986e25SLuc Michel } PLLInitInfo; 2481e986e25SLuc Michel 2491e986e25SLuc Michel #define FILL_PLL_INIT_INFO(pll_) \ 2501e986e25SLuc Michel .cm_offset = R_CM_ ## pll_, \ 2511e986e25SLuc Michel .a2w_ctrl_offset = R_A2W_ ## pll_ ## _CTRL, \ 2521e986e25SLuc Michel .a2w_ana_offset = R_A2W_ ## pll_ ## _ANA0, \ 2531e986e25SLuc Michel .a2w_frac_offset = R_A2W_ ## pll_ ## _FRAC 2541e986e25SLuc Michel 2551e986e25SLuc Michel static const PLLInitInfo PLL_INIT_INFO[] = { 2561e986e25SLuc Michel [CPRMAN_PLLA] = { 2571e986e25SLuc Michel .name = "plla", 2581e986e25SLuc Michel .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, 2591e986e25SLuc Michel FILL_PLL_INIT_INFO(PLLA), 2601e986e25SLuc Michel }, 2611e986e25SLuc Michel [CPRMAN_PLLC] = { 2621e986e25SLuc Michel .name = "pllc", 2631e986e25SLuc Michel .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, 2641e986e25SLuc Michel FILL_PLL_INIT_INFO(PLLC), 2651e986e25SLuc Michel }, 2661e986e25SLuc Michel [CPRMAN_PLLD] = { 2671e986e25SLuc Michel .name = "plld", 2681e986e25SLuc Michel .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, 2691e986e25SLuc Michel FILL_PLL_INIT_INFO(PLLD), 2701e986e25SLuc Michel }, 2711e986e25SLuc Michel [CPRMAN_PLLH] = { 2721e986e25SLuc Michel .name = "pllh", 2731e986e25SLuc Michel .prediv_mask = R_A2W_PLLH_ANA1_FB_PREDIV_MASK, 2741e986e25SLuc Michel FILL_PLL_INIT_INFO(PLLH), 2751e986e25SLuc Michel }, 2761e986e25SLuc Michel [CPRMAN_PLLB] = { 2771e986e25SLuc Michel .name = "pllb", 2781e986e25SLuc Michel .prediv_mask = R_A2W_PLLx_ANA1_FB_PREDIV_MASK, 2791e986e25SLuc Michel FILL_PLL_INIT_INFO(PLLB), 2801e986e25SLuc Michel }, 2811e986e25SLuc Michel }; 2821e986e25SLuc Michel 2831e986e25SLuc Michel #undef FILL_PLL_CHANNEL_INIT_INFO 2841e986e25SLuc Michel 2851e986e25SLuc Michel static inline void set_pll_init_info(BCM2835CprmanState *s, 2861e986e25SLuc Michel CprmanPllState *pll, 2871e986e25SLuc Michel CprmanPll id) 2881e986e25SLuc Michel { 2891e986e25SLuc Michel pll->id = id; 2901e986e25SLuc Michel pll->reg_cm = &s->regs[PLL_INIT_INFO[id].cm_offset]; 2911e986e25SLuc Michel pll->reg_a2w_ctrl = &s->regs[PLL_INIT_INFO[id].a2w_ctrl_offset]; 2921e986e25SLuc Michel pll->reg_a2w_ana = &s->regs[PLL_INIT_INFO[id].a2w_ana_offset]; 2931e986e25SLuc Michel pll->prediv_mask = PLL_INIT_INFO[id].prediv_mask; 2941e986e25SLuc Michel pll->reg_a2w_frac = &s->regs[PLL_INIT_INFO[id].a2w_frac_offset]; 2951e986e25SLuc Michel } 2961e986e25SLuc Michel 29709d56bbcSLuc Michel 29809d56bbcSLuc Michel /* PLL channel init info */ 29909d56bbcSLuc Michel typedef struct PLLChannelInitInfo { 30009d56bbcSLuc Michel const char *name; 30109d56bbcSLuc Michel CprmanPll parent; 30209d56bbcSLuc Michel size_t cm_offset; 30309d56bbcSLuc Michel uint32_t cm_hold_mask; 30409d56bbcSLuc Michel uint32_t cm_load_mask; 30509d56bbcSLuc Michel size_t a2w_ctrl_offset; 30609d56bbcSLuc Michel unsigned int fixed_divider; 30709d56bbcSLuc Michel } PLLChannelInitInfo; 30809d56bbcSLuc Michel 30909d56bbcSLuc Michel #define FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_) \ 31009d56bbcSLuc Michel .parent = CPRMAN_ ## pll_, \ 31109d56bbcSLuc Michel .cm_offset = R_CM_ ## pll_, \ 31209d56bbcSLuc Michel .cm_load_mask = R_CM_ ## pll_ ## _ ## LOAD ## channel_ ## _MASK, \ 31309d56bbcSLuc Michel .a2w_ctrl_offset = R_A2W_ ## pll_ ## _ ## channel_ 31409d56bbcSLuc Michel 31509d56bbcSLuc Michel #define FILL_PLL_CHANNEL_INIT_INFO(pll_, channel_) \ 31609d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \ 31709d56bbcSLuc Michel .cm_hold_mask = R_CM_ ## pll_ ## _ ## HOLD ## channel_ ## _MASK, \ 31809d56bbcSLuc Michel .fixed_divider = 1 31909d56bbcSLuc Michel 32009d56bbcSLuc Michel #define FILL_PLL_CHANNEL_INIT_INFO_nohold(pll_, channel_) \ 32109d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO_common(pll_, channel_), \ 32209d56bbcSLuc Michel .cm_hold_mask = 0 32309d56bbcSLuc Michel 32409d56bbcSLuc Michel static PLLChannelInitInfo PLL_CHANNEL_INIT_INFO[] = { 32509d56bbcSLuc Michel [CPRMAN_PLLA_CHANNEL_DSI0] = { 32609d56bbcSLuc Michel .name = "plla-dsi0", 32709d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLA, DSI0), 32809d56bbcSLuc Michel }, 32909d56bbcSLuc Michel [CPRMAN_PLLA_CHANNEL_CORE] = { 33009d56bbcSLuc Michel .name = "plla-core", 33109d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLA, CORE), 33209d56bbcSLuc Michel }, 33309d56bbcSLuc Michel [CPRMAN_PLLA_CHANNEL_PER] = { 33409d56bbcSLuc Michel .name = "plla-per", 33509d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLA, PER), 33609d56bbcSLuc Michel }, 33709d56bbcSLuc Michel [CPRMAN_PLLA_CHANNEL_CCP2] = { 33809d56bbcSLuc Michel .name = "plla-ccp2", 33909d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLA, CCP2), 34009d56bbcSLuc Michel }, 34109d56bbcSLuc Michel 34209d56bbcSLuc Michel [CPRMAN_PLLC_CHANNEL_CORE2] = { 34309d56bbcSLuc Michel .name = "pllc-core2", 34409d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE2), 34509d56bbcSLuc Michel }, 34609d56bbcSLuc Michel [CPRMAN_PLLC_CHANNEL_CORE1] = { 34709d56bbcSLuc Michel .name = "pllc-core1", 34809d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE1), 34909d56bbcSLuc Michel }, 35009d56bbcSLuc Michel [CPRMAN_PLLC_CHANNEL_PER] = { 35109d56bbcSLuc Michel .name = "pllc-per", 35209d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLC, PER), 35309d56bbcSLuc Michel }, 35409d56bbcSLuc Michel [CPRMAN_PLLC_CHANNEL_CORE0] = { 35509d56bbcSLuc Michel .name = "pllc-core0", 35609d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLC, CORE0), 35709d56bbcSLuc Michel }, 35809d56bbcSLuc Michel 35909d56bbcSLuc Michel [CPRMAN_PLLD_CHANNEL_DSI0] = { 36009d56bbcSLuc Michel .name = "plld-dsi0", 36109d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI0), 36209d56bbcSLuc Michel }, 36309d56bbcSLuc Michel [CPRMAN_PLLD_CHANNEL_CORE] = { 36409d56bbcSLuc Michel .name = "plld-core", 36509d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLD, CORE), 36609d56bbcSLuc Michel }, 36709d56bbcSLuc Michel [CPRMAN_PLLD_CHANNEL_PER] = { 36809d56bbcSLuc Michel .name = "plld-per", 36909d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLD, PER), 37009d56bbcSLuc Michel }, 37109d56bbcSLuc Michel [CPRMAN_PLLD_CHANNEL_DSI1] = { 37209d56bbcSLuc Michel .name = "plld-dsi1", 37309d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLD, DSI1), 37409d56bbcSLuc Michel }, 37509d56bbcSLuc Michel 37609d56bbcSLuc Michel [CPRMAN_PLLH_CHANNEL_AUX] = { 37709d56bbcSLuc Michel .name = "pllh-aux", 37809d56bbcSLuc Michel .fixed_divider = 1, 37909d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, AUX), 38009d56bbcSLuc Michel }, 38109d56bbcSLuc Michel [CPRMAN_PLLH_CHANNEL_RCAL] = { 38209d56bbcSLuc Michel .name = "pllh-rcal", 38309d56bbcSLuc Michel .fixed_divider = 10, 38409d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, RCAL), 38509d56bbcSLuc Michel }, 38609d56bbcSLuc Michel [CPRMAN_PLLH_CHANNEL_PIX] = { 38709d56bbcSLuc Michel .name = "pllh-pix", 38809d56bbcSLuc Michel .fixed_divider = 10, 38909d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO_nohold(PLLH, PIX), 39009d56bbcSLuc Michel }, 39109d56bbcSLuc Michel 39209d56bbcSLuc Michel [CPRMAN_PLLB_CHANNEL_ARM] = { 39309d56bbcSLuc Michel .name = "pllb-arm", 39409d56bbcSLuc Michel FILL_PLL_CHANNEL_INIT_INFO(PLLB, ARM), 39509d56bbcSLuc Michel }, 39609d56bbcSLuc Michel }; 39709d56bbcSLuc Michel 39809d56bbcSLuc Michel #undef FILL_PLL_CHANNEL_INIT_INFO_nohold 39909d56bbcSLuc Michel #undef FILL_PLL_CHANNEL_INIT_INFO 40009d56bbcSLuc Michel #undef FILL_PLL_CHANNEL_INIT_INFO_common 40109d56bbcSLuc Michel 40209d56bbcSLuc Michel static inline void set_pll_channel_init_info(BCM2835CprmanState *s, 40309d56bbcSLuc Michel CprmanPllChannelState *channel, 40409d56bbcSLuc Michel CprmanPllChannel id) 40509d56bbcSLuc Michel { 40609d56bbcSLuc Michel channel->id = id; 40709d56bbcSLuc Michel channel->parent = PLL_CHANNEL_INIT_INFO[id].parent; 40809d56bbcSLuc Michel channel->reg_cm = &s->regs[PLL_CHANNEL_INIT_INFO[id].cm_offset]; 40909d56bbcSLuc Michel channel->hold_mask = PLL_CHANNEL_INIT_INFO[id].cm_hold_mask; 41009d56bbcSLuc Michel channel->load_mask = PLL_CHANNEL_INIT_INFO[id].cm_load_mask; 41109d56bbcSLuc Michel channel->reg_a2w_ctrl = &s->regs[PLL_CHANNEL_INIT_INFO[id].a2w_ctrl_offset]; 41209d56bbcSLuc Michel channel->fixed_divider = PLL_CHANNEL_INIT_INFO[id].fixed_divider; 41309d56bbcSLuc Michel } 41409d56bbcSLuc Michel 41572813624SLuc Michel /* Clock mux init info */ 41672813624SLuc Michel typedef struct ClockMuxInitInfo { 41772813624SLuc Michel const char *name; 41872813624SLuc Michel size_t cm_offset; /* cm_offset[0]->CM_CTL, cm_offset[1]->CM_DIV */ 41972813624SLuc Michel int int_bits; 42072813624SLuc Michel int frac_bits; 42172813624SLuc Michel 42272813624SLuc Michel CprmanPllChannel src_mapping[CPRMAN_NUM_CLOCK_MUX_SRC]; 42372813624SLuc Michel } ClockMuxInitInfo; 42472813624SLuc Michel 42572813624SLuc Michel /* 42672813624SLuc Michel * Each clock mux can have up to 10 sources. Sources 0 to 3 are always the 42772813624SLuc Michel * same (ground, xosc, td0, td1). Sources 4 to 9 are mux specific, and are not 42872813624SLuc Michel * always populated. The following macros catch all those cases. 42972813624SLuc Michel */ 43072813624SLuc Michel 43172813624SLuc Michel /* Unknown mapping. Connect everything to ground */ 43272813624SLuc Michel #define SRC_MAPPING_INFO_unknown \ 43372813624SLuc Michel .src_mapping = { \ 43472813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, /* gnd */ \ 43572813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, /* xosc */ \ 43672813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 0 */ \ 43772813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, /* test debug 1 */ \ 43872813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll a */ \ 43972813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c */ \ 44072813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll d */ \ 44172813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll h */ \ 44272813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core1 */ \ 44372813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, /* pll c, core2 */ \ 44472813624SLuc Michel } 44572813624SLuc Michel 44672813624SLuc Michel /* Only the oscillator and the two test debug clocks */ 44772813624SLuc Michel #define SRC_MAPPING_INFO_xosc \ 44872813624SLuc Michel .src_mapping = { \ 44972813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 45072813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 45172813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 45272813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 45372813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 45472813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 45572813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 45672813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 45772813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 45872813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 45972813624SLuc Michel } 46072813624SLuc Michel 46172813624SLuc Michel /* All the PLL "core" channels */ 46272813624SLuc Michel #define SRC_MAPPING_INFO_core \ 46372813624SLuc Michel .src_mapping = { \ 46472813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 46572813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 46672813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 46772813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 46872813624SLuc Michel CPRMAN_PLLA_CHANNEL_CORE, \ 46972813624SLuc Michel CPRMAN_PLLC_CHANNEL_CORE0, \ 47072813624SLuc Michel CPRMAN_PLLD_CHANNEL_CORE, \ 47172813624SLuc Michel CPRMAN_PLLH_CHANNEL_AUX, \ 47272813624SLuc Michel CPRMAN_PLLC_CHANNEL_CORE1, \ 47372813624SLuc Michel CPRMAN_PLLC_CHANNEL_CORE2, \ 47472813624SLuc Michel } 47572813624SLuc Michel 47672813624SLuc Michel /* All the PLL "per" channels */ 47772813624SLuc Michel #define SRC_MAPPING_INFO_periph \ 47872813624SLuc Michel .src_mapping = { \ 47972813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 48072813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 48172813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 48272813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 48372813624SLuc Michel CPRMAN_PLLA_CHANNEL_PER, \ 48472813624SLuc Michel CPRMAN_PLLC_CHANNEL_PER, \ 48572813624SLuc Michel CPRMAN_PLLD_CHANNEL_PER, \ 48672813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 48772813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 48872813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 48972813624SLuc Michel } 49072813624SLuc Michel 49172813624SLuc Michel /* 49272813624SLuc Michel * The DSI0 channels. This one got an intermediate mux between the PLL channels 49372813624SLuc Michel * and the clock input. 49472813624SLuc Michel */ 49572813624SLuc Michel #define SRC_MAPPING_INFO_dsi0 \ 49672813624SLuc Michel .src_mapping = { \ 49772813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 49872813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 49972813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 50072813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 50172813624SLuc Michel CPRMAN_CLOCK_SRC_DSI0HSCK, \ 50272813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 50372813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 50472813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 50572813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 50672813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 50772813624SLuc Michel } 50872813624SLuc Michel 50972813624SLuc Michel /* The DSI1 channel */ 51072813624SLuc Michel #define SRC_MAPPING_INFO_dsi1 \ 51172813624SLuc Michel .src_mapping = { \ 51272813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 51372813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 51472813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 51572813624SLuc Michel CPRMAN_CLOCK_SRC_NORMAL, \ 51672813624SLuc Michel CPRMAN_PLLD_CHANNEL_DSI1, \ 51772813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 51872813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 51972813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 52072813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 52172813624SLuc Michel CPRMAN_CLOCK_SRC_FORCE_GROUND, \ 52272813624SLuc Michel } 52372813624SLuc Michel 52472813624SLuc Michel #define FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) \ 52572813624SLuc Michel SRC_MAPPING_INFO_ ## kind_ 52672813624SLuc Michel 52772813624SLuc Michel #define FILL_CLOCK_MUX_INIT_INFO(clock_, kind_) \ 52872813624SLuc Michel .cm_offset = R_CM_ ## clock_ ## CTL, \ 52972813624SLuc Michel FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO(kind_) 53072813624SLuc Michel 53172813624SLuc Michel static ClockMuxInitInfo CLOCK_MUX_INIT_INFO[] = { 53272813624SLuc Michel [CPRMAN_CLOCK_GNRIC] = { 53372813624SLuc Michel .name = "gnric", 53472813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(GNRIC, unknown), 53572813624SLuc Michel }, 53672813624SLuc Michel [CPRMAN_CLOCK_VPU] = { 53772813624SLuc Michel .name = "vpu", 53872813624SLuc Michel .int_bits = 12, 53972813624SLuc Michel .frac_bits = 8, 54072813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(VPU, core), 54172813624SLuc Michel }, 54272813624SLuc Michel [CPRMAN_CLOCK_SYS] = { 54372813624SLuc Michel .name = "sys", 54472813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(SYS, unknown), 54572813624SLuc Michel }, 54672813624SLuc Michel [CPRMAN_CLOCK_PERIA] = { 54772813624SLuc Michel .name = "peria", 54872813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(PERIA, unknown), 54972813624SLuc Michel }, 55072813624SLuc Michel [CPRMAN_CLOCK_PERII] = { 55172813624SLuc Michel .name = "perii", 55272813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(PERII, unknown), 55372813624SLuc Michel }, 55472813624SLuc Michel [CPRMAN_CLOCK_H264] = { 55572813624SLuc Michel .name = "h264", 55672813624SLuc Michel .int_bits = 4, 55772813624SLuc Michel .frac_bits = 8, 55872813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(H264, core), 55972813624SLuc Michel }, 56072813624SLuc Michel [CPRMAN_CLOCK_ISP] = { 56172813624SLuc Michel .name = "isp", 56272813624SLuc Michel .int_bits = 4, 56372813624SLuc Michel .frac_bits = 8, 56472813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(ISP, core), 56572813624SLuc Michel }, 56672813624SLuc Michel [CPRMAN_CLOCK_V3D] = { 56772813624SLuc Michel .name = "v3d", 56872813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(V3D, core), 56972813624SLuc Michel }, 57072813624SLuc Michel [CPRMAN_CLOCK_CAM0] = { 57172813624SLuc Michel .name = "cam0", 57272813624SLuc Michel .int_bits = 4, 57372813624SLuc Michel .frac_bits = 8, 57472813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(CAM0, periph), 57572813624SLuc Michel }, 57672813624SLuc Michel [CPRMAN_CLOCK_CAM1] = { 57772813624SLuc Michel .name = "cam1", 57872813624SLuc Michel .int_bits = 4, 57972813624SLuc Michel .frac_bits = 8, 58072813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(CAM1, periph), 58172813624SLuc Michel }, 58272813624SLuc Michel [CPRMAN_CLOCK_CCP2] = { 58372813624SLuc Michel .name = "ccp2", 58472813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(CCP2, unknown), 58572813624SLuc Michel }, 58672813624SLuc Michel [CPRMAN_CLOCK_DSI0E] = { 58772813624SLuc Michel .name = "dsi0e", 58872813624SLuc Michel .int_bits = 4, 58972813624SLuc Michel .frac_bits = 8, 59072813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(DSI0E, dsi0), 59172813624SLuc Michel }, 59272813624SLuc Michel [CPRMAN_CLOCK_DSI0P] = { 59372813624SLuc Michel .name = "dsi0p", 59472813624SLuc Michel .int_bits = 0, 59572813624SLuc Michel .frac_bits = 0, 59672813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(DSI0P, dsi0), 59772813624SLuc Michel }, 59872813624SLuc Michel [CPRMAN_CLOCK_DPI] = { 59972813624SLuc Michel .name = "dpi", 60072813624SLuc Michel .int_bits = 4, 60172813624SLuc Michel .frac_bits = 8, 60272813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(DPI, periph), 60372813624SLuc Michel }, 60472813624SLuc Michel [CPRMAN_CLOCK_GP0] = { 60572813624SLuc Michel .name = "gp0", 60672813624SLuc Michel .int_bits = 12, 60772813624SLuc Michel .frac_bits = 12, 60872813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(GP0, periph), 60972813624SLuc Michel }, 61072813624SLuc Michel [CPRMAN_CLOCK_GP1] = { 61172813624SLuc Michel .name = "gp1", 61272813624SLuc Michel .int_bits = 12, 61372813624SLuc Michel .frac_bits = 12, 61472813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(GP1, periph), 61572813624SLuc Michel }, 61672813624SLuc Michel [CPRMAN_CLOCK_GP2] = { 61772813624SLuc Michel .name = "gp2", 61872813624SLuc Michel .int_bits = 12, 61972813624SLuc Michel .frac_bits = 12, 62072813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(GP2, periph), 62172813624SLuc Michel }, 62272813624SLuc Michel [CPRMAN_CLOCK_HSM] = { 62372813624SLuc Michel .name = "hsm", 62472813624SLuc Michel .int_bits = 4, 62572813624SLuc Michel .frac_bits = 8, 62672813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(HSM, periph), 62772813624SLuc Michel }, 62872813624SLuc Michel [CPRMAN_CLOCK_OTP] = { 62972813624SLuc Michel .name = "otp", 63072813624SLuc Michel .int_bits = 4, 63172813624SLuc Michel .frac_bits = 0, 63272813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(OTP, xosc), 63372813624SLuc Michel }, 63472813624SLuc Michel [CPRMAN_CLOCK_PCM] = { 63572813624SLuc Michel .name = "pcm", 63672813624SLuc Michel .int_bits = 12, 63772813624SLuc Michel .frac_bits = 12, 63872813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(PCM, periph), 63972813624SLuc Michel }, 64072813624SLuc Michel [CPRMAN_CLOCK_PWM] = { 64172813624SLuc Michel .name = "pwm", 64272813624SLuc Michel .int_bits = 12, 64372813624SLuc Michel .frac_bits = 12, 64472813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(PWM, periph), 64572813624SLuc Michel }, 64672813624SLuc Michel [CPRMAN_CLOCK_SLIM] = { 64772813624SLuc Michel .name = "slim", 64872813624SLuc Michel .int_bits = 12, 64972813624SLuc Michel .frac_bits = 12, 65072813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(SLIM, periph), 65172813624SLuc Michel }, 65272813624SLuc Michel [CPRMAN_CLOCK_SMI] = { 65372813624SLuc Michel .name = "smi", 65472813624SLuc Michel .int_bits = 4, 65572813624SLuc Michel .frac_bits = 8, 65672813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(SMI, periph), 65772813624SLuc Michel }, 65872813624SLuc Michel [CPRMAN_CLOCK_TEC] = { 65972813624SLuc Michel .name = "tec", 66072813624SLuc Michel .int_bits = 6, 66172813624SLuc Michel .frac_bits = 0, 66272813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(TEC, xosc), 66372813624SLuc Michel }, 66472813624SLuc Michel [CPRMAN_CLOCK_TD0] = { 66572813624SLuc Michel .name = "td0", 66672813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(TD0, unknown), 66772813624SLuc Michel }, 66872813624SLuc Michel [CPRMAN_CLOCK_TD1] = { 66972813624SLuc Michel .name = "td1", 67072813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(TD1, unknown), 67172813624SLuc Michel }, 67272813624SLuc Michel [CPRMAN_CLOCK_TSENS] = { 67372813624SLuc Michel .name = "tsens", 67472813624SLuc Michel .int_bits = 5, 67572813624SLuc Michel .frac_bits = 0, 67672813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(TSENS, xosc), 67772813624SLuc Michel }, 67872813624SLuc Michel [CPRMAN_CLOCK_TIMER] = { 67972813624SLuc Michel .name = "timer", 68072813624SLuc Michel .int_bits = 6, 68172813624SLuc Michel .frac_bits = 12, 68272813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(TIMER, xosc), 68372813624SLuc Michel }, 68472813624SLuc Michel [CPRMAN_CLOCK_UART] = { 68572813624SLuc Michel .name = "uart", 68672813624SLuc Michel .int_bits = 10, 68772813624SLuc Michel .frac_bits = 12, 68872813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(UART, periph), 68972813624SLuc Michel }, 69072813624SLuc Michel [CPRMAN_CLOCK_VEC] = { 69172813624SLuc Michel .name = "vec", 69272813624SLuc Michel .int_bits = 4, 69372813624SLuc Michel .frac_bits = 0, 69472813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(VEC, periph), 69572813624SLuc Michel }, 69672813624SLuc Michel [CPRMAN_CLOCK_PULSE] = { 69772813624SLuc Michel .name = "pulse", 69872813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(PULSE, xosc), 69972813624SLuc Michel }, 70072813624SLuc Michel [CPRMAN_CLOCK_SDC] = { 70172813624SLuc Michel .name = "sdram", 70272813624SLuc Michel .int_bits = 6, 70372813624SLuc Michel .frac_bits = 0, 70472813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(SDC, core), 70572813624SLuc Michel }, 70672813624SLuc Michel [CPRMAN_CLOCK_ARM] = { 70772813624SLuc Michel .name = "arm", 70872813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(ARM, unknown), 70972813624SLuc Michel }, 71072813624SLuc Michel [CPRMAN_CLOCK_AVEO] = { 71172813624SLuc Michel .name = "aveo", 71272813624SLuc Michel .int_bits = 4, 71372813624SLuc Michel .frac_bits = 0, 71472813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(AVEO, periph), 71572813624SLuc Michel }, 71672813624SLuc Michel [CPRMAN_CLOCK_EMMC] = { 71772813624SLuc Michel .name = "emmc", 71872813624SLuc Michel .int_bits = 4, 71972813624SLuc Michel .frac_bits = 8, 72072813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(EMMC, periph), 72172813624SLuc Michel }, 72272813624SLuc Michel [CPRMAN_CLOCK_EMMC2] = { 72372813624SLuc Michel .name = "emmc2", 72472813624SLuc Michel .int_bits = 4, 72572813624SLuc Michel .frac_bits = 8, 72672813624SLuc Michel FILL_CLOCK_MUX_INIT_INFO(EMMC2, unknown), 72772813624SLuc Michel }, 72872813624SLuc Michel }; 72972813624SLuc Michel 73072813624SLuc Michel #undef FILL_CLOCK_MUX_INIT_INFO 73172813624SLuc Michel #undef FILL_CLOCK_MUX_SRC_MAPPING_INIT_INFO 73272813624SLuc Michel #undef SRC_MAPPING_INFO_dsi1 73372813624SLuc Michel #undef SRC_MAPPING_INFO_dsi0 73472813624SLuc Michel #undef SRC_MAPPING_INFO_periph 73572813624SLuc Michel #undef SRC_MAPPING_INFO_core 73672813624SLuc Michel #undef SRC_MAPPING_INFO_xosc 73772813624SLuc Michel #undef SRC_MAPPING_INFO_unknown 73872813624SLuc Michel 73972813624SLuc Michel static inline void set_clock_mux_init_info(BCM2835CprmanState *s, 74072813624SLuc Michel CprmanClockMuxState *mux, 74172813624SLuc Michel CprmanClockMux id) 74272813624SLuc Michel { 74372813624SLuc Michel mux->id = id; 74472813624SLuc Michel mux->reg_ctl = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset]; 74572813624SLuc Michel mux->reg_div = &s->regs[CLOCK_MUX_INIT_INFO[id].cm_offset + 1]; 74672813624SLuc Michel mux->int_bits = CLOCK_MUX_INIT_INFO[id].int_bits; 74772813624SLuc Michel mux->frac_bits = CLOCK_MUX_INIT_INFO[id].frac_bits; 74872813624SLuc Michel } 74972813624SLuc Michel 750*83ad4695SLuc Michel 751*83ad4695SLuc Michel /* 752*83ad4695SLuc Michel * Object reset info 753*83ad4695SLuc Michel * Those values have been dumped from a Raspberry Pi 3 Model B v1.2 using the 754*83ad4695SLuc Michel * clk debugfs interface in Linux. 755*83ad4695SLuc Michel */ 756*83ad4695SLuc Michel typedef struct PLLResetInfo { 757*83ad4695SLuc Michel uint32_t cm; 758*83ad4695SLuc Michel uint32_t a2w_ctrl; 759*83ad4695SLuc Michel uint32_t a2w_ana[4]; 760*83ad4695SLuc Michel uint32_t a2w_frac; 761*83ad4695SLuc Michel } PLLResetInfo; 762*83ad4695SLuc Michel 763*83ad4695SLuc Michel static const PLLResetInfo PLL_RESET_INFO[] = { 764*83ad4695SLuc Michel [CPRMAN_PLLA] = { 765*83ad4695SLuc Michel .cm = 0x0000008a, 766*83ad4695SLuc Michel .a2w_ctrl = 0x0002103a, 767*83ad4695SLuc Michel .a2w_frac = 0x00098000, 768*83ad4695SLuc Michel .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } 769*83ad4695SLuc Michel }, 770*83ad4695SLuc Michel 771*83ad4695SLuc Michel [CPRMAN_PLLC] = { 772*83ad4695SLuc Michel .cm = 0x00000228, 773*83ad4695SLuc Michel .a2w_ctrl = 0x0002103e, 774*83ad4695SLuc Michel .a2w_frac = 0x00080000, 775*83ad4695SLuc Michel .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } 776*83ad4695SLuc Michel }, 777*83ad4695SLuc Michel 778*83ad4695SLuc Michel [CPRMAN_PLLD] = { 779*83ad4695SLuc Michel .cm = 0x0000020a, 780*83ad4695SLuc Michel .a2w_ctrl = 0x00021034, 781*83ad4695SLuc Michel .a2w_frac = 0x00015556, 782*83ad4695SLuc Michel .a2w_ana = { 0x00000000, 0x00144000, 0x00000000, 0x00000100 } 783*83ad4695SLuc Michel }, 784*83ad4695SLuc Michel 785*83ad4695SLuc Michel [CPRMAN_PLLH] = { 786*83ad4695SLuc Michel .cm = 0x00000000, 787*83ad4695SLuc Michel .a2w_ctrl = 0x0002102d, 788*83ad4695SLuc Michel .a2w_frac = 0x00000000, 789*83ad4695SLuc Michel .a2w_ana = { 0x00900000, 0x0000000c, 0x00000000, 0x00000000 } 790*83ad4695SLuc Michel }, 791*83ad4695SLuc Michel 792*83ad4695SLuc Michel [CPRMAN_PLLB] = { 793*83ad4695SLuc Michel /* unknown */ 794*83ad4695SLuc Michel .cm = 0x00000000, 795*83ad4695SLuc Michel .a2w_ctrl = 0x00000000, 796*83ad4695SLuc Michel .a2w_frac = 0x00000000, 797*83ad4695SLuc Michel .a2w_ana = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 } 798*83ad4695SLuc Michel } 799*83ad4695SLuc Michel }; 800*83ad4695SLuc Michel 801*83ad4695SLuc Michel typedef struct PLLChannelResetInfo { 802*83ad4695SLuc Michel /* 803*83ad4695SLuc Michel * Even though a PLL channel has a CM register, it shares it with its 804*83ad4695SLuc Michel * parent PLL. The parent already takes care of the reset value. 805*83ad4695SLuc Michel */ 806*83ad4695SLuc Michel uint32_t a2w_ctrl; 807*83ad4695SLuc Michel } PLLChannelResetInfo; 808*83ad4695SLuc Michel 809*83ad4695SLuc Michel static const PLLChannelResetInfo PLL_CHANNEL_RESET_INFO[] = { 810*83ad4695SLuc Michel [CPRMAN_PLLA_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 }, 811*83ad4695SLuc Michel [CPRMAN_PLLA_CHANNEL_CORE] = { .a2w_ctrl = 0x00000003 }, 812*83ad4695SLuc Michel [CPRMAN_PLLA_CHANNEL_PER] = { .a2w_ctrl = 0x00000000 }, /* unknown */ 813*83ad4695SLuc Michel [CPRMAN_PLLA_CHANNEL_CCP2] = { .a2w_ctrl = 0x00000100 }, 814*83ad4695SLuc Michel 815*83ad4695SLuc Michel [CPRMAN_PLLC_CHANNEL_CORE2] = { .a2w_ctrl = 0x00000100 }, 816*83ad4695SLuc Michel [CPRMAN_PLLC_CHANNEL_CORE1] = { .a2w_ctrl = 0x00000100 }, 817*83ad4695SLuc Michel [CPRMAN_PLLC_CHANNEL_PER] = { .a2w_ctrl = 0x00000002 }, 818*83ad4695SLuc Michel [CPRMAN_PLLC_CHANNEL_CORE0] = { .a2w_ctrl = 0x00000002 }, 819*83ad4695SLuc Michel 820*83ad4695SLuc Michel [CPRMAN_PLLD_CHANNEL_DSI0] = { .a2w_ctrl = 0x00000100 }, 821*83ad4695SLuc Michel [CPRMAN_PLLD_CHANNEL_CORE] = { .a2w_ctrl = 0x00000004 }, 822*83ad4695SLuc Michel [CPRMAN_PLLD_CHANNEL_PER] = { .a2w_ctrl = 0x00000004 }, 823*83ad4695SLuc Michel [CPRMAN_PLLD_CHANNEL_DSI1] = { .a2w_ctrl = 0x00000100 }, 824*83ad4695SLuc Michel 825*83ad4695SLuc Michel [CPRMAN_PLLH_CHANNEL_AUX] = { .a2w_ctrl = 0x00000004 }, 826*83ad4695SLuc Michel [CPRMAN_PLLH_CHANNEL_RCAL] = { .a2w_ctrl = 0x00000000 }, 827*83ad4695SLuc Michel [CPRMAN_PLLH_CHANNEL_PIX] = { .a2w_ctrl = 0x00000000 }, 828*83ad4695SLuc Michel 829*83ad4695SLuc Michel [CPRMAN_PLLB_CHANNEL_ARM] = { .a2w_ctrl = 0x00000000 }, /* unknown */ 830*83ad4695SLuc Michel }; 831*83ad4695SLuc Michel 832*83ad4695SLuc Michel typedef struct ClockMuxResetInfo { 833*83ad4695SLuc Michel uint32_t cm_ctl; 834*83ad4695SLuc Michel uint32_t cm_div; 835*83ad4695SLuc Michel } ClockMuxResetInfo; 836*83ad4695SLuc Michel 837*83ad4695SLuc Michel static const ClockMuxResetInfo CLOCK_MUX_RESET_INFO[] = { 838*83ad4695SLuc Michel [CPRMAN_CLOCK_GNRIC] = { 839*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 840*83ad4695SLuc Michel .cm_div = 0 841*83ad4695SLuc Michel }, 842*83ad4695SLuc Michel 843*83ad4695SLuc Michel [CPRMAN_CLOCK_VPU] = { 844*83ad4695SLuc Michel .cm_ctl = 0x00000245, 845*83ad4695SLuc Michel .cm_div = 0x00003000, 846*83ad4695SLuc Michel }, 847*83ad4695SLuc Michel 848*83ad4695SLuc Michel [CPRMAN_CLOCK_SYS] = { 849*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 850*83ad4695SLuc Michel .cm_div = 0 851*83ad4695SLuc Michel }, 852*83ad4695SLuc Michel 853*83ad4695SLuc Michel [CPRMAN_CLOCK_PERIA] = { 854*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 855*83ad4695SLuc Michel .cm_div = 0 856*83ad4695SLuc Michel }, 857*83ad4695SLuc Michel 858*83ad4695SLuc Michel [CPRMAN_CLOCK_PERII] = { 859*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 860*83ad4695SLuc Michel .cm_div = 0 861*83ad4695SLuc Michel }, 862*83ad4695SLuc Michel 863*83ad4695SLuc Michel [CPRMAN_CLOCK_H264] = { 864*83ad4695SLuc Michel .cm_ctl = 0x00000244, 865*83ad4695SLuc Michel .cm_div = 0x00003000, 866*83ad4695SLuc Michel }, 867*83ad4695SLuc Michel 868*83ad4695SLuc Michel [CPRMAN_CLOCK_ISP] = { 869*83ad4695SLuc Michel .cm_ctl = 0x00000244, 870*83ad4695SLuc Michel .cm_div = 0x00003000, 871*83ad4695SLuc Michel }, 872*83ad4695SLuc Michel 873*83ad4695SLuc Michel [CPRMAN_CLOCK_V3D] = { 874*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 875*83ad4695SLuc Michel .cm_div = 0 876*83ad4695SLuc Michel }, 877*83ad4695SLuc Michel 878*83ad4695SLuc Michel [CPRMAN_CLOCK_CAM0] = { 879*83ad4695SLuc Michel .cm_ctl = 0x00000000, 880*83ad4695SLuc Michel .cm_div = 0x00000000, 881*83ad4695SLuc Michel }, 882*83ad4695SLuc Michel 883*83ad4695SLuc Michel [CPRMAN_CLOCK_CAM1] = { 884*83ad4695SLuc Michel .cm_ctl = 0x00000000, 885*83ad4695SLuc Michel .cm_div = 0x00000000, 886*83ad4695SLuc Michel }, 887*83ad4695SLuc Michel 888*83ad4695SLuc Michel [CPRMAN_CLOCK_CCP2] = { 889*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 890*83ad4695SLuc Michel .cm_div = 0 891*83ad4695SLuc Michel }, 892*83ad4695SLuc Michel 893*83ad4695SLuc Michel [CPRMAN_CLOCK_DSI0E] = { 894*83ad4695SLuc Michel .cm_ctl = 0x00000000, 895*83ad4695SLuc Michel .cm_div = 0x00000000, 896*83ad4695SLuc Michel }, 897*83ad4695SLuc Michel 898*83ad4695SLuc Michel [CPRMAN_CLOCK_DSI0P] = { 899*83ad4695SLuc Michel .cm_ctl = 0x00000000, 900*83ad4695SLuc Michel .cm_div = 0x00000000, 901*83ad4695SLuc Michel }, 902*83ad4695SLuc Michel 903*83ad4695SLuc Michel [CPRMAN_CLOCK_DPI] = { 904*83ad4695SLuc Michel .cm_ctl = 0x00000000, 905*83ad4695SLuc Michel .cm_div = 0x00000000, 906*83ad4695SLuc Michel }, 907*83ad4695SLuc Michel 908*83ad4695SLuc Michel [CPRMAN_CLOCK_GP0] = { 909*83ad4695SLuc Michel .cm_ctl = 0x00000200, 910*83ad4695SLuc Michel .cm_div = 0x00000000, 911*83ad4695SLuc Michel }, 912*83ad4695SLuc Michel 913*83ad4695SLuc Michel [CPRMAN_CLOCK_GP1] = { 914*83ad4695SLuc Michel .cm_ctl = 0x00000096, 915*83ad4695SLuc Michel .cm_div = 0x00014000, 916*83ad4695SLuc Michel }, 917*83ad4695SLuc Michel 918*83ad4695SLuc Michel [CPRMAN_CLOCK_GP2] = { 919*83ad4695SLuc Michel .cm_ctl = 0x00000291, 920*83ad4695SLuc Michel .cm_div = 0x00249f00, 921*83ad4695SLuc Michel }, 922*83ad4695SLuc Michel 923*83ad4695SLuc Michel [CPRMAN_CLOCK_HSM] = { 924*83ad4695SLuc Michel .cm_ctl = 0x00000000, 925*83ad4695SLuc Michel .cm_div = 0x00000000, 926*83ad4695SLuc Michel }, 927*83ad4695SLuc Michel 928*83ad4695SLuc Michel [CPRMAN_CLOCK_OTP] = { 929*83ad4695SLuc Michel .cm_ctl = 0x00000091, 930*83ad4695SLuc Michel .cm_div = 0x00004000, 931*83ad4695SLuc Michel }, 932*83ad4695SLuc Michel 933*83ad4695SLuc Michel [CPRMAN_CLOCK_PCM] = { 934*83ad4695SLuc Michel .cm_ctl = 0x00000200, 935*83ad4695SLuc Michel .cm_div = 0x00000000, 936*83ad4695SLuc Michel }, 937*83ad4695SLuc Michel 938*83ad4695SLuc Michel [CPRMAN_CLOCK_PWM] = { 939*83ad4695SLuc Michel .cm_ctl = 0x00000200, 940*83ad4695SLuc Michel .cm_div = 0x00000000, 941*83ad4695SLuc Michel }, 942*83ad4695SLuc Michel 943*83ad4695SLuc Michel [CPRMAN_CLOCK_SLIM] = { 944*83ad4695SLuc Michel .cm_ctl = 0x00000200, 945*83ad4695SLuc Michel .cm_div = 0x00000000, 946*83ad4695SLuc Michel }, 947*83ad4695SLuc Michel 948*83ad4695SLuc Michel [CPRMAN_CLOCK_SMI] = { 949*83ad4695SLuc Michel .cm_ctl = 0x00000000, 950*83ad4695SLuc Michel .cm_div = 0x00000000, 951*83ad4695SLuc Michel }, 952*83ad4695SLuc Michel 953*83ad4695SLuc Michel [CPRMAN_CLOCK_TEC] = { 954*83ad4695SLuc Michel .cm_ctl = 0x00000000, 955*83ad4695SLuc Michel .cm_div = 0x00000000, 956*83ad4695SLuc Michel }, 957*83ad4695SLuc Michel 958*83ad4695SLuc Michel [CPRMAN_CLOCK_TD0] = { 959*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 960*83ad4695SLuc Michel .cm_div = 0 961*83ad4695SLuc Michel }, 962*83ad4695SLuc Michel 963*83ad4695SLuc Michel [CPRMAN_CLOCK_TD1] = { 964*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 965*83ad4695SLuc Michel .cm_div = 0 966*83ad4695SLuc Michel }, 967*83ad4695SLuc Michel 968*83ad4695SLuc Michel [CPRMAN_CLOCK_TSENS] = { 969*83ad4695SLuc Michel .cm_ctl = 0x00000091, 970*83ad4695SLuc Michel .cm_div = 0x0000a000, 971*83ad4695SLuc Michel }, 972*83ad4695SLuc Michel 973*83ad4695SLuc Michel [CPRMAN_CLOCK_TIMER] = { 974*83ad4695SLuc Michel .cm_ctl = 0x00000291, 975*83ad4695SLuc Michel .cm_div = 0x00013333, 976*83ad4695SLuc Michel }, 977*83ad4695SLuc Michel 978*83ad4695SLuc Michel [CPRMAN_CLOCK_UART] = { 979*83ad4695SLuc Michel .cm_ctl = 0x00000296, 980*83ad4695SLuc Michel .cm_div = 0x0000a6ab, 981*83ad4695SLuc Michel }, 982*83ad4695SLuc Michel 983*83ad4695SLuc Michel [CPRMAN_CLOCK_VEC] = { 984*83ad4695SLuc Michel .cm_ctl = 0x00000097, 985*83ad4695SLuc Michel .cm_div = 0x00002000, 986*83ad4695SLuc Michel }, 987*83ad4695SLuc Michel 988*83ad4695SLuc Michel [CPRMAN_CLOCK_PULSE] = { 989*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 990*83ad4695SLuc Michel .cm_div = 0 991*83ad4695SLuc Michel }, 992*83ad4695SLuc Michel 993*83ad4695SLuc Michel [CPRMAN_CLOCK_SDC] = { 994*83ad4695SLuc Michel .cm_ctl = 0x00004006, 995*83ad4695SLuc Michel .cm_div = 0x00003000, 996*83ad4695SLuc Michel }, 997*83ad4695SLuc Michel 998*83ad4695SLuc Michel [CPRMAN_CLOCK_ARM] = { 999*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 1000*83ad4695SLuc Michel .cm_div = 0 1001*83ad4695SLuc Michel }, 1002*83ad4695SLuc Michel 1003*83ad4695SLuc Michel [CPRMAN_CLOCK_AVEO] = { 1004*83ad4695SLuc Michel .cm_ctl = 0x00000000, 1005*83ad4695SLuc Michel .cm_div = 0x00000000, 1006*83ad4695SLuc Michel }, 1007*83ad4695SLuc Michel 1008*83ad4695SLuc Michel [CPRMAN_CLOCK_EMMC] = { 1009*83ad4695SLuc Michel .cm_ctl = 0x00000295, 1010*83ad4695SLuc Michel .cm_div = 0x00006000, 1011*83ad4695SLuc Michel }, 1012*83ad4695SLuc Michel 1013*83ad4695SLuc Michel [CPRMAN_CLOCK_EMMC2] = { 1014*83ad4695SLuc Michel .cm_ctl = 0, /* unknown */ 1015*83ad4695SLuc Michel .cm_div = 0 1016*83ad4695SLuc Michel }, 1017*83ad4695SLuc Michel }; 1018*83ad4695SLuc Michel 1019fc14176bSLuc Michel #endif 1020