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_H 10 #define HW_MISC_CPRMAN_H 11 12 #include "hw/sysbus.h" 13 #include "hw/qdev-clock.h" 14 15 #define TYPE_BCM2835_CPRMAN "bcm2835-cprman" 16 17 typedef struct BCM2835CprmanState BCM2835CprmanState; 18 19 DECLARE_INSTANCE_CHECKER(BCM2835CprmanState, CPRMAN, 20 TYPE_BCM2835_CPRMAN) 21 22 #define CPRMAN_NUM_REGS (0x2000 / sizeof(uint32_t)) 23 24 typedef enum CprmanPll { 25 CPRMAN_PLLA = 0, 26 CPRMAN_PLLC, 27 CPRMAN_PLLD, 28 CPRMAN_PLLH, 29 CPRMAN_PLLB, 30 31 CPRMAN_NUM_PLL 32 } CprmanPll; 33 34 typedef enum CprmanPllChannel { 35 CPRMAN_PLLA_CHANNEL_DSI0 = 0, 36 CPRMAN_PLLA_CHANNEL_CORE, 37 CPRMAN_PLLA_CHANNEL_PER, 38 CPRMAN_PLLA_CHANNEL_CCP2, 39 40 CPRMAN_PLLC_CHANNEL_CORE2, 41 CPRMAN_PLLC_CHANNEL_CORE1, 42 CPRMAN_PLLC_CHANNEL_PER, 43 CPRMAN_PLLC_CHANNEL_CORE0, 44 45 CPRMAN_PLLD_CHANNEL_DSI0, 46 CPRMAN_PLLD_CHANNEL_CORE, 47 CPRMAN_PLLD_CHANNEL_PER, 48 CPRMAN_PLLD_CHANNEL_DSI1, 49 50 CPRMAN_PLLH_CHANNEL_AUX, 51 CPRMAN_PLLH_CHANNEL_RCAL, 52 CPRMAN_PLLH_CHANNEL_PIX, 53 54 CPRMAN_PLLB_CHANNEL_ARM, 55 56 CPRMAN_NUM_PLL_CHANNEL, 57 58 /* Special values used when connecting clock sources to clocks */ 59 CPRMAN_CLOCK_SRC_NORMAL = -1, 60 CPRMAN_CLOCK_SRC_FORCE_GROUND = -2, 61 CPRMAN_CLOCK_SRC_DSI0HSCK = -3, 62 } CprmanPllChannel; 63 64 typedef enum CprmanClockMux { 65 CPRMAN_CLOCK_GNRIC, 66 CPRMAN_CLOCK_VPU, 67 CPRMAN_CLOCK_SYS, 68 CPRMAN_CLOCK_PERIA, 69 CPRMAN_CLOCK_PERII, 70 CPRMAN_CLOCK_H264, 71 CPRMAN_CLOCK_ISP, 72 CPRMAN_CLOCK_V3D, 73 CPRMAN_CLOCK_CAM0, 74 CPRMAN_CLOCK_CAM1, 75 CPRMAN_CLOCK_CCP2, 76 CPRMAN_CLOCK_DSI0E, 77 CPRMAN_CLOCK_DSI0P, 78 CPRMAN_CLOCK_DPI, 79 CPRMAN_CLOCK_GP0, 80 CPRMAN_CLOCK_GP1, 81 CPRMAN_CLOCK_GP2, 82 CPRMAN_CLOCK_HSM, 83 CPRMAN_CLOCK_OTP, 84 CPRMAN_CLOCK_PCM, 85 CPRMAN_CLOCK_PWM, 86 CPRMAN_CLOCK_SLIM, 87 CPRMAN_CLOCK_SMI, 88 CPRMAN_CLOCK_TEC, 89 CPRMAN_CLOCK_TD0, 90 CPRMAN_CLOCK_TD1, 91 CPRMAN_CLOCK_TSENS, 92 CPRMAN_CLOCK_TIMER, 93 CPRMAN_CLOCK_UART, 94 CPRMAN_CLOCK_VEC, 95 CPRMAN_CLOCK_PULSE, 96 CPRMAN_CLOCK_SDC, 97 CPRMAN_CLOCK_ARM, 98 CPRMAN_CLOCK_AVEO, 99 CPRMAN_CLOCK_EMMC, 100 CPRMAN_CLOCK_EMMC2, 101 102 CPRMAN_NUM_CLOCK_MUX 103 } CprmanClockMux; 104 105 typedef enum CprmanClockMuxSource { 106 CPRMAN_CLOCK_SRC_GND = 0, 107 CPRMAN_CLOCK_SRC_XOSC, 108 CPRMAN_CLOCK_SRC_TD0, 109 CPRMAN_CLOCK_SRC_TD1, 110 CPRMAN_CLOCK_SRC_PLLA, 111 CPRMAN_CLOCK_SRC_PLLC, 112 CPRMAN_CLOCK_SRC_PLLD, 113 CPRMAN_CLOCK_SRC_PLLH, 114 CPRMAN_CLOCK_SRC_PLLC_CORE1, 115 CPRMAN_CLOCK_SRC_PLLC_CORE2, 116 117 CPRMAN_NUM_CLOCK_MUX_SRC 118 } CprmanClockMuxSource; 119 120 typedef struct CprmanPllState { 121 /*< private >*/ 122 DeviceState parent_obj; 123 124 /*< public >*/ 125 CprmanPll id; 126 127 uint32_t *reg_cm; 128 uint32_t *reg_a2w_ctrl; 129 uint32_t *reg_a2w_ana; /* ANA[0] .. ANA[3] */ 130 uint32_t prediv_mask; /* prediv bit in ana[1] */ 131 uint32_t *reg_a2w_frac; 132 133 Clock *xosc_in; 134 Clock *out; 135 } CprmanPllState; 136 137 typedef struct CprmanPllChannelState { 138 /*< private >*/ 139 DeviceState parent_obj; 140 141 /*< public >*/ 142 CprmanPllChannel id; 143 CprmanPll parent; 144 145 uint32_t *reg_cm; 146 uint32_t hold_mask; 147 uint32_t load_mask; 148 uint32_t *reg_a2w_ctrl; 149 int fixed_divider; 150 151 Clock *pll_in; 152 Clock *out; 153 } CprmanPllChannelState; 154 155 typedef struct CprmanClockMuxState { 156 /*< private >*/ 157 DeviceState parent_obj; 158 159 /*< public >*/ 160 CprmanClockMux id; 161 162 uint32_t *reg_ctl; 163 uint32_t *reg_div; 164 int int_bits; 165 int frac_bits; 166 167 Clock *srcs[CPRMAN_NUM_CLOCK_MUX_SRC]; 168 Clock *out; 169 170 /* 171 * Used by clock srcs update callback to retrieve both the clock and the 172 * source number. 173 */ 174 struct CprmanClockMuxState *backref[CPRMAN_NUM_CLOCK_MUX_SRC]; 175 } CprmanClockMuxState; 176 177 typedef struct CprmanDsi0HsckMuxState { 178 /*< private >*/ 179 DeviceState parent_obj; 180 181 /*< public >*/ 182 CprmanClockMux id; 183 184 uint32_t *reg_cm; 185 186 Clock *plla_in; 187 Clock *plld_in; 188 Clock *out; 189 } CprmanDsi0HsckMuxState; 190 191 struct BCM2835CprmanState { 192 /*< private >*/ 193 SysBusDevice parent_obj; 194 195 /*< public >*/ 196 MemoryRegion iomem; 197 198 CprmanPllState plls[CPRMAN_NUM_PLL]; 199 CprmanPllChannelState channels[CPRMAN_NUM_PLL_CHANNEL]; 200 CprmanClockMuxState clock_muxes[CPRMAN_NUM_CLOCK_MUX]; 201 CprmanDsi0HsckMuxState dsi0hsck_mux; 202 203 uint32_t regs[CPRMAN_NUM_REGS]; 204 uint32_t xosc_freq; 205 206 Clock *xosc; 207 Clock *gnd; 208 }; 209 210 #endif 211