1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2020-2021 SiFive, Inc. 4 * Wesley Terpstra 5 * Paul Walmsley 6 * Zong Li 7 * Pragnesh Patel 8 */ 9 10 #ifndef __SIFIVE_CLK_SIFIVE_PRCI_H 11 #define __SIFIVE_CLK_SIFIVE_PRCI_H 12 13 #include <clk.h> 14 #include <linux/clk/analogbits-wrpll-cln28hpc.h> 15 16 /* 17 * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects: 18 * hfclk and rtcclk 19 */ 20 #define EXPECTED_CLK_PARENT_COUNT 2 21 22 /* 23 * Register offsets and bitmasks 24 */ 25 26 /* COREPLLCFG0 */ 27 #define PRCI_COREPLLCFG0_OFFSET 0x4 28 #define PRCI_COREPLLCFG0_DIVR_SHIFT 0 29 #define PRCI_COREPLLCFG0_DIVR_MASK (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT) 30 #define PRCI_COREPLLCFG0_DIVF_SHIFT 6 31 #define PRCI_COREPLLCFG0_DIVF_MASK (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT) 32 #define PRCI_COREPLLCFG0_DIVQ_SHIFT 15 33 #define PRCI_COREPLLCFG0_DIVQ_MASK (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT) 34 #define PRCI_COREPLLCFG0_RANGE_SHIFT 18 35 #define PRCI_COREPLLCFG0_RANGE_MASK (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT) 36 #define PRCI_COREPLLCFG0_BYPASS_SHIFT 24 37 #define PRCI_COREPLLCFG0_BYPASS_MASK (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT) 38 #define PRCI_COREPLLCFG0_FSE_SHIFT 25 39 #define PRCI_COREPLLCFG0_FSE_MASK (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT) 40 #define PRCI_COREPLLCFG0_LOCK_SHIFT 31 41 #define PRCI_COREPLLCFG0_LOCK_MASK (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT) 42 43 /* COREPLLCFG1 */ 44 #define PRCI_COREPLLCFG1_OFFSET 0x8 45 #define PRCI_COREPLLCFG1_CKE_SHIFT 31 46 #define PRCI_COREPLLCFG1_CKE_MASK (0x1 << PRCI_COREPLLCFG1_CKE_SHIFT) 47 48 /* DDRPLLCFG0 */ 49 #define PRCI_DDRPLLCFG0_OFFSET 0xc 50 #define PRCI_DDRPLLCFG0_DIVR_SHIFT 0 51 #define PRCI_DDRPLLCFG0_DIVR_MASK (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT) 52 #define PRCI_DDRPLLCFG0_DIVF_SHIFT 6 53 #define PRCI_DDRPLLCFG0_DIVF_MASK (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT) 54 #define PRCI_DDRPLLCFG0_DIVQ_SHIFT 15 55 #define PRCI_DDRPLLCFG0_DIVQ_MASK (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT) 56 #define PRCI_DDRPLLCFG0_RANGE_SHIFT 18 57 #define PRCI_DDRPLLCFG0_RANGE_MASK (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT) 58 #define PRCI_DDRPLLCFG0_BYPASS_SHIFT 24 59 #define PRCI_DDRPLLCFG0_BYPASS_MASK (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT) 60 #define PRCI_DDRPLLCFG0_FSE_SHIFT 25 61 #define PRCI_DDRPLLCFG0_FSE_MASK (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT) 62 #define PRCI_DDRPLLCFG0_LOCK_SHIFT 31 63 #define PRCI_DDRPLLCFG0_LOCK_MASK (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT) 64 65 /* DDRPLLCFG1 */ 66 #define PRCI_DDRPLLCFG1_OFFSET 0x10 67 #define PRCI_DDRPLLCFG1_CKE_SHIFT 31 68 #define PRCI_DDRPLLCFG1_CKE_MASK (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT) 69 70 /* PCIEAUXCFG1 */ 71 #define PRCI_PCIEAUXCFG1_OFFSET 0x14 72 #define PRCI_PCIEAUXCFG1_SHIFT 0 73 #define PRCI_PCIEAUXCFG1_MASK (0x1 << PRCI_PCIEAUXCFG1_SHIFT) 74 75 /* GEMGXLPLLCFG0 */ 76 #define PRCI_GEMGXLPLLCFG0_OFFSET 0x1c 77 #define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT 0 78 #define PRCI_GEMGXLPLLCFG0_DIVR_MASK \ 79 (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT) 80 #define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT 6 81 #define PRCI_GEMGXLPLLCFG0_DIVF_MASK \ 82 (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT) 83 #define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT 15 84 #define PRCI_GEMGXLPLLCFG0_DIVQ_MASK (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT) 85 #define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT 18 86 #define PRCI_GEMGXLPLLCFG0_RANGE_MASK \ 87 (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT) 88 #define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT 24 89 #define PRCI_GEMGXLPLLCFG0_BYPASS_MASK \ 90 (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT) 91 #define PRCI_GEMGXLPLLCFG0_FSE_SHIFT 25 92 #define PRCI_GEMGXLPLLCFG0_FSE_MASK \ 93 (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT) 94 #define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT 31 95 #define PRCI_GEMGXLPLLCFG0_LOCK_MASK (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT) 96 97 /* GEMGXLPLLCFG1 */ 98 #define PRCI_GEMGXLPLLCFG1_OFFSET 0x20 99 #define PRCI_GEMGXLPLLCFG1_CKE_SHIFT 31 100 #define PRCI_GEMGXLPLLCFG1_CKE_MASK (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT) 101 102 /* CORECLKSEL */ 103 #define PRCI_CORECLKSEL_OFFSET 0x24 104 #define PRCI_CORECLKSEL_CORECLKSEL_SHIFT 0 105 #define PRCI_CORECLKSEL_CORECLKSEL_MASK \ 106 (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT) 107 108 /* DEVICESRESETREG */ 109 #define PRCI_DEVICESRESETREG_OFFSET 0x28 110 #define PRCI_DEVICERESETCNT 6 111 112 /* CLKMUXSTATUSREG */ 113 #define PRCI_CLKMUXSTATUSREG_OFFSET 0x2c 114 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1 115 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ 116 (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT) 117 118 /* CLTXPLLCFG0 */ 119 #define PRCI_CLTXPLLCFG0_OFFSET 0x30 120 #define PRCI_CLTXPLLCFG0_DIVR_SHIFT 0 121 #define PRCI_CLTXPLLCFG0_DIVR_MASK (0x3f << PRCI_CLTXPLLCFG0_DIVR_SHIFT) 122 #define PRCI_CLTXPLLCFG0_DIVF_SHIFT 6 123 #define PRCI_CLTXPLLCFG0_DIVF_MASK (0x1ff << PRCI_CLTXPLLCFG0_DIVF_SHIFT) 124 #define PRCI_CLTXPLLCFG0_DIVQ_SHIFT 15 125 #define PRCI_CLTXPLLCFG0_DIVQ_MASK (0x7 << PRCI_CLTXPLLCFG0_DIVQ_SHIFT) 126 #define PRCI_CLTXPLLCFG0_RANGE_SHIFT 18 127 #define PRCI_CLTXPLLCFG0_RANGE_MASK (0x7 << PRCI_CLTXPLLCFG0_RANGE_SHIFT) 128 #define PRCI_CLTXPLLCFG0_BYPASS_SHIFT 24 129 #define PRCI_CLTXPLLCFG0_BYPASS_MASK (0x1 << PRCI_CLTXPLLCFG0_BYPASS_SHIFT) 130 #define PRCI_CLTXPLLCFG0_FSE_SHIFT 25 131 #define PRCI_CLTXPLLCFG0_FSE_MASK (0x1 << PRCI_CLTXPLLCFG0_FSE_SHIFT) 132 #define PRCI_CLTXPLLCFG0_LOCK_SHIFT 31 133 #define PRCI_CLTXPLLCFG0_LOCK_MASK (0x1 << PRCI_CLTXPLLCFG0_LOCK_SHIFT) 134 135 /* CLTXPLLCFG1 */ 136 #define PRCI_CLTXPLLCFG1_OFFSET 0x34 137 #define PRCI_CLTXPLLCFG1_CKE_SHIFT 24 138 #define PRCI_CLTXPLLCFG1_CKE_MASK (0x1 << PRCI_CLTXPLLCFG1_CKE_SHIFT) 139 140 /* DVFSCOREPLLCFG0 */ 141 #define PRCI_DVFSCOREPLLCFG0_OFFSET 0x38 142 143 /* DVFSCOREPLLCFG1 */ 144 #define PRCI_DVFSCOREPLLCFG1_OFFSET 0x3c 145 #define PRCI_DVFSCOREPLLCFG1_CKE_SHIFT 24 146 #define PRCI_DVFSCOREPLLCFG1_CKE_MASK (0x1 << PRCI_DVFSCOREPLLCFG1_CKE_SHIFT) 147 148 /* COREPLLSEL */ 149 #define PRCI_COREPLLSEL_OFFSET 0x40 150 #define PRCI_COREPLLSEL_COREPLLSEL_SHIFT 0 151 #define PRCI_COREPLLSEL_COREPLLSEL_MASK \ 152 (0x1 << PRCI_COREPLLSEL_COREPLLSEL_SHIFT) 153 154 /* HFPCLKPLLCFG0 */ 155 #define PRCI_HFPCLKPLLCFG0_OFFSET 0x50 156 #define PRCI_HFPCLKPLL_CFG0_DIVR_SHIFT 0 157 #define PRCI_HFPCLKPLL_CFG0_DIVR_MASK \ 158 (0x3f << PRCI_HFPCLKPLLCFG0_DIVR_SHIFT) 159 #define PRCI_HFPCLKPLL_CFG0_DIVF_SHIFT 6 160 #define PRCI_HFPCLKPLL_CFG0_DIVF_MASK \ 161 (0x1ff << PRCI_HFPCLKPLLCFG0_DIVF_SHIFT) 162 #define PRCI_HFPCLKPLL_CFG0_DIVQ_SHIFT 15 163 #define PRCI_HFPCLKPLL_CFG0_DIVQ_MASK \ 164 (0x7 << PRCI_HFPCLKPLLCFG0_DIVQ_SHIFT) 165 #define PRCI_HFPCLKPLL_CFG0_RANGE_SHIFT 18 166 #define PRCI_HFPCLKPLL_CFG0_RANGE_MASK \ 167 (0x7 << PRCI_HFPCLKPLLCFG0_RANGE_SHIFT) 168 #define PRCI_HFPCLKPLL_CFG0_BYPASS_SHIFT 24 169 #define PRCI_HFPCLKPLL_CFG0_BYPASS_MASK \ 170 (0x1 << PRCI_HFPCLKPLLCFG0_BYPASS_SHIFT) 171 #define PRCI_HFPCLKPLL_CFG0_FSE_SHIFT 25 172 #define PRCI_HFPCLKPLL_CFG0_FSE_MASK \ 173 (0x1 << PRCI_HFPCLKPLLCFG0_FSE_SHIFT) 174 #define PRCI_HFPCLKPLL_CFG0_LOCK_SHIFT 31 175 #define PRCI_HFPCLKPLL_CFG0_LOCK_MASK \ 176 (0x1 << PRCI_HFPCLKPLLCFG0_LOCK_SHIFT) 177 178 /* HFPCLKPLLCFG1 */ 179 #define PRCI_HFPCLKPLLCFG1_OFFSET 0x54 180 #define PRCI_HFPCLKPLLCFG1_CKE_SHIFT 24 181 #define PRCI_HFPCLKPLLCFG1_CKE_MASK \ 182 (0x1 << PRCI_HFPCLKPLLCFG1_CKE_SHIFT) 183 184 /* HFPCLKPLLSEL */ 185 #define PRCI_HFPCLKPLLSEL_OFFSET 0x58 186 #define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT 0 187 #define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK \ 188 (0x1 << PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT) 189 190 /* HFPCLKPLLDIV */ 191 #define PRCI_HFPCLKPLLDIV_OFFSET 0x5c 192 193 /* PRCIPLL */ 194 #define PRCI_PRCIPLL_OFFSET 0xe0 195 196 #define PRCI_PRCIPLL_CLTXPLL (0x1 << 0) 197 #define PRCI_PRCIPLL_GEMGXLPLL (0x1 << 1) 198 #define PRCI_PRCIPLL_DDRPLL (0x1 << 2) 199 #define PRCI_PRCIPLL_HFPCLKPLL (0x1 << 3) 200 #define PRCI_PRCIPLL_DVFSCOREPLL (0x1 << 4) 201 #define PRCI_PRCIPLL_COREPLL (0x1 << 5) 202 203 /* PROCMONCFG */ 204 #define PRCI_PROCMONCFG_OFFSET 0xF0 205 #define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 206 #define PRCI_PROCMONCFG_CORE_CLOCK_MASK \ 207 (0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT) 208 209 /* 210 * Private structures 211 */ 212 213 /** 214 * struct __prci_data - per-device-instance data 215 * @va: base virtual address of the PRCI IP block 216 * @parent: parent clk instance 217 * 218 * PRCI per-device instance data 219 */ 220 struct __prci_data { 221 void *va; 222 struct clk parent_hfclk; 223 struct clk parent_rtcclk; 224 }; 225 226 /** 227 * struct __prci_wrpll_data - WRPLL configuration and integration data 228 * @c: WRPLL current configuration record 229 * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL) 230 * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL) 231 * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address 232 * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address 233 * @release_reset: fn ptr to code to release clock reset 234 * 235 * @enable_bypass and @disable_bypass are used for WRPLL instances 236 * that contain a separate external glitchless clock mux downstream 237 * from the PLL. The WRPLL internal bypass mux is not glitchless. 238 */ 239 struct __prci_wrpll_data { 240 struct wrpll_cfg c; 241 void (*enable_bypass)(struct __prci_data *pd); 242 void (*disable_bypass)(struct __prci_data *pd); 243 u8 cfg0_offs; 244 u8 cfg1_offs; 245 void (*release_reset)(struct __prci_data *pd); 246 }; 247 248 /** 249 * struct __prci_clock - describes a clock device managed by PRCI 250 * @name: user-readable clock name string - should match the manual 251 * @parent_name: parent name for this clock 252 * @ops: struct __prci_clock_ops for control 253 * @pwd: WRPLL-specific data, associated with this clock (if not NULL) 254 * @pd: PRCI-specific data associated with this clock (if not NULL) 255 * 256 * PRCI clock data. Used by the PRCI driver to register PRCI-provided 257 * clocks to the Linux clock infrastructure. 258 */ 259 struct __prci_clock { 260 const char *name; 261 const char *parent_name; 262 const struct __prci_clock_ops *ops; 263 struct __prci_wrpll_data *pwd; 264 struct __prci_data *pd; 265 }; 266 267 /* struct __prci_clock_ops - clock operations */ 268 struct __prci_clock_ops { 269 int (*set_rate)(struct __prci_clock *pc, 270 unsigned long rate, 271 unsigned long parent_rate); 272 unsigned long (*round_rate)(struct __prci_clock *pc, 273 unsigned long rate, 274 unsigned long *parent_rate); 275 unsigned long (*recalc_rate)(struct __prci_clock *pc, 276 unsigned long parent_rate); 277 int (*enable_clk)(struct __prci_clock *pc, bool enable); 278 }; 279 280 /* 281 * struct prci_clk_desc - describes the information of clocks of each SoCs 282 * @clks: point to a array of __prci_clock 283 * @num_clks: the number of element of clks 284 */ 285 struct prci_clk_desc { 286 struct __prci_clock *clks; 287 size_t num_clks; 288 }; 289 290 void sifive_prci_ethernet_release_reset(struct __prci_data *pd); 291 void sifive_prci_ddr_release_reset(struct __prci_data *pd); 292 void sifive_prci_cltx_release_reset(struct __prci_data *pd); 293 294 /* Core clock mux control */ 295 void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd); 296 void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd); 297 void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd); 298 void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd); 299 void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd); 300 void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd); 301 void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd); 302 303 unsigned long sifive_prci_wrpll_round_rate(struct __prci_clock *pc, 304 unsigned long rate, 305 unsigned long *parent_rate); 306 307 /* Linux clock framework integration */ 308 int sifive_prci_wrpll_set_rate(struct __prci_clock *pc, 309 unsigned long rate, 310 unsigned long parent_rate); 311 312 unsigned long sifive_prci_wrpll_recalc_rate(struct __prci_clock *pc, 313 unsigned long parent_rate); 314 315 unsigned long sifive_prci_tlclksel_recalc_rate(struct __prci_clock *pc, 316 unsigned long parent_rate); 317 318 unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct __prci_clock *pc, 319 unsigned long parent_rate); 320 321 int sifive_prci_clock_enable(struct __prci_clock *pc, bool enable); 322 323 #endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */ 324