1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2018-2019 SiFive, Inc. 4 * Wesley Terpstra 5 * Paul Walmsley 6 * Zong Li 7 */ 8 9 #ifndef __SIFIVE_CLK_SIFIVE_PRCI_H 10 #define __SIFIVE_CLK_SIFIVE_PRCI_H 11 12 #include <linux/clk/analogbits-wrpll-cln28hpc.h> 13 #include <linux/clk-provider.h> 14 #include <linux/platform_device.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 /* GEMGXLPLLCFG0 */ 71 #define PRCI_GEMGXLPLLCFG0_OFFSET 0x1c 72 #define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT 0 73 #define PRCI_GEMGXLPLLCFG0_DIVR_MASK (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT) 74 #define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT 6 75 #define PRCI_GEMGXLPLLCFG0_DIVF_MASK (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT) 76 #define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT 15 77 #define PRCI_GEMGXLPLLCFG0_DIVQ_MASK (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT) 78 #define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT 18 79 #define PRCI_GEMGXLPLLCFG0_RANGE_MASK (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT) 80 #define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT 24 81 #define PRCI_GEMGXLPLLCFG0_BYPASS_MASK (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT) 82 #define PRCI_GEMGXLPLLCFG0_FSE_SHIFT 25 83 #define PRCI_GEMGXLPLLCFG0_FSE_MASK (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT) 84 #define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT 31 85 #define PRCI_GEMGXLPLLCFG0_LOCK_MASK (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT) 86 87 /* GEMGXLPLLCFG1 */ 88 #define PRCI_GEMGXLPLLCFG1_OFFSET 0x20 89 #define PRCI_GEMGXLPLLCFG1_CKE_SHIFT 31 90 #define PRCI_GEMGXLPLLCFG1_CKE_MASK (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT) 91 92 /* CORECLKSEL */ 93 #define PRCI_CORECLKSEL_OFFSET 0x24 94 #define PRCI_CORECLKSEL_CORECLKSEL_SHIFT 0 95 #define PRCI_CORECLKSEL_CORECLKSEL_MASK \ 96 (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT) 97 98 /* DEVICESRESETREG */ 99 #define PRCI_DEVICESRESETREG_OFFSET 0x28 100 #define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT 0 101 #define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK \ 102 (0x1 << PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT) 103 #define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT 1 104 #define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK \ 105 (0x1 << PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT) 106 #define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT 2 107 #define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK \ 108 (0x1 << PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT) 109 #define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT 3 110 #define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK \ 111 (0x1 << PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT) 112 #define PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT 5 113 #define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK \ 114 (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT) 115 #define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT 6 116 #define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_MASK \ 117 (0x1 << PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT) 118 119 /* CLKMUXSTATUSREG */ 120 #define PRCI_CLKMUXSTATUSREG_OFFSET 0x2c 121 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1 122 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ 123 (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT) 124 125 /* CLTXPLLCFG0 */ 126 #define PRCI_CLTXPLLCFG0_OFFSET 0x30 127 #define PRCI_CLTXPLLCFG0_DIVR_SHIFT 0 128 #define PRCI_CLTXPLLCFG0_DIVR_MASK (0x3f << PRCI_CLTXPLLCFG0_DIVR_SHIFT) 129 #define PRCI_CLTXPLLCFG0_DIVF_SHIFT 6 130 #define PRCI_CLTXPLLCFG0_DIVF_MASK (0x1ff << PRCI_CLTXPLLCFG0_DIVF_SHIFT) 131 #define PRCI_CLTXPLLCFG0_DIVQ_SHIFT 15 132 #define PRCI_CLTXPLLCFG0_DIVQ_MASK (0x7 << PRCI_CLTXPLLCFG0_DIVQ_SHIFT) 133 #define PRCI_CLTXPLLCFG0_RANGE_SHIFT 18 134 #define PRCI_CLTXPLLCFG0_RANGE_MASK (0x7 << PRCI_CLTXPLLCFG0_RANGE_SHIFT) 135 #define PRCI_CLTXPLLCFG0_BYPASS_SHIFT 24 136 #define PRCI_CLTXPLLCFG0_BYPASS_MASK (0x1 << PRCI_CLTXPLLCFG0_BYPASS_SHIFT) 137 #define PRCI_CLTXPLLCFG0_FSE_SHIFT 25 138 #define PRCI_CLTXPLLCFG0_FSE_MASK (0x1 << PRCI_CLTXPLLCFG0_FSE_SHIFT) 139 #define PRCI_CLTXPLLCFG0_LOCK_SHIFT 31 140 #define PRCI_CLTXPLLCFG0_LOCK_MASK (0x1 << PRCI_CLTXPLLCFG0_LOCK_SHIFT) 141 142 /* CLTXPLLCFG1 */ 143 #define PRCI_CLTXPLLCFG1_OFFSET 0x34 144 #define PRCI_CLTXPLLCFG1_CKE_SHIFT 31 145 #define PRCI_CLTXPLLCFG1_CKE_MASK (0x1 << PRCI_CLTXPLLCFG1_CKE_SHIFT) 146 147 /* DVFSCOREPLLCFG0 */ 148 #define PRCI_DVFSCOREPLLCFG0_OFFSET 0x38 149 150 /* DVFSCOREPLLCFG1 */ 151 #define PRCI_DVFSCOREPLLCFG1_OFFSET 0x3c 152 #define PRCI_DVFSCOREPLLCFG1_CKE_SHIFT 31 153 #define PRCI_DVFSCOREPLLCFG1_CKE_MASK (0x1 << PRCI_DVFSCOREPLLCFG1_CKE_SHIFT) 154 155 /* COREPLLSEL */ 156 #define PRCI_COREPLLSEL_OFFSET 0x40 157 #define PRCI_COREPLLSEL_COREPLLSEL_SHIFT 0 158 #define PRCI_COREPLLSEL_COREPLLSEL_MASK \ 159 (0x1 << PRCI_COREPLLSEL_COREPLLSEL_SHIFT) 160 161 /* HFPCLKPLLCFG0 */ 162 #define PRCI_HFPCLKPLLCFG0_OFFSET 0x50 163 #define PRCI_HFPCLKPLL_CFG0_DIVR_SHIFT 0 164 #define PRCI_HFPCLKPLL_CFG0_DIVR_MASK \ 165 (0x3f << PRCI_HFPCLKPLLCFG0_DIVR_SHIFT) 166 #define PRCI_HFPCLKPLL_CFG0_DIVF_SHIFT 6 167 #define PRCI_HFPCLKPLL_CFG0_DIVF_MASK \ 168 (0x1ff << PRCI_HFPCLKPLLCFG0_DIVF_SHIFT) 169 #define PRCI_HFPCLKPLL_CFG0_DIVQ_SHIFT 15 170 #define PRCI_HFPCLKPLL_CFG0_DIVQ_MASK \ 171 (0x7 << PRCI_HFPCLKPLLCFG0_DIVQ_SHIFT) 172 #define PRCI_HFPCLKPLL_CFG0_RANGE_SHIFT 18 173 #define PRCI_HFPCLKPLL_CFG0_RANGE_MASK \ 174 (0x7 << PRCI_HFPCLKPLLCFG0_RANGE_SHIFT) 175 #define PRCI_HFPCLKPLL_CFG0_BYPASS_SHIFT 24 176 #define PRCI_HFPCLKPLL_CFG0_BYPASS_MASK \ 177 (0x1 << PRCI_HFPCLKPLLCFG0_BYPASS_SHIFT) 178 #define PRCI_HFPCLKPLL_CFG0_FSE_SHIFT 25 179 #define PRCI_HFPCLKPLL_CFG0_FSE_MASK \ 180 (0x1 << PRCI_HFPCLKPLLCFG0_FSE_SHIFT) 181 #define PRCI_HFPCLKPLL_CFG0_LOCK_SHIFT 31 182 #define PRCI_HFPCLKPLL_CFG0_LOCK_MASK \ 183 (0x1 << PRCI_HFPCLKPLLCFG0_LOCK_SHIFT) 184 185 /* HFPCLKPLLCFG1 */ 186 #define PRCI_HFPCLKPLLCFG1_OFFSET 0x54 187 #define PRCI_HFPCLKPLLCFG1_CKE_SHIFT 31 188 #define PRCI_HFPCLKPLLCFG1_CKE_MASK \ 189 (0x1 << PRCI_HFPCLKPLLCFG1_CKE_SHIFT) 190 191 /* HFPCLKPLLSEL */ 192 #define PRCI_HFPCLKPLLSEL_OFFSET 0x58 193 #define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT 0 194 #define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK \ 195 (0x1 << PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT) 196 197 /* HFPCLKPLLDIV */ 198 #define PRCI_HFPCLKPLLDIV_OFFSET 0x5c 199 200 /* PRCIPLL */ 201 #define PRCI_PRCIPLL_OFFSET 0xe0 202 203 /* PROCMONCFG */ 204 #define PRCI_PROCMONCFG_OFFSET 0xf0 205 206 /* 207 * Private structures 208 */ 209 210 /** 211 * struct __prci_data - per-device-instance data 212 * @va: base virtual address of the PRCI IP block 213 * @hw_clks: encapsulates struct clk_hw records 214 * 215 * PRCI per-device instance data 216 */ 217 struct __prci_data { 218 void __iomem *va; 219 struct clk_hw_onecell_data hw_clks; 220 }; 221 222 /** 223 * struct __prci_wrpll_data - WRPLL configuration and integration data 224 * @c: WRPLL current configuration record 225 * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL) 226 * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL) 227 * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address 228 * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address 229 * 230 * @enable_bypass and @disable_bypass are used for WRPLL instances 231 * that contain a separate external glitchless clock mux downstream 232 * from the PLL. The WRPLL internal bypass mux is not glitchless. 233 */ 234 struct __prci_wrpll_data { 235 struct wrpll_cfg c; 236 void (*enable_bypass)(struct __prci_data *pd); 237 void (*disable_bypass)(struct __prci_data *pd); 238 u8 cfg0_offs; 239 u8 cfg1_offs; 240 }; 241 242 /** 243 * struct __prci_clock - describes a clock device managed by PRCI 244 * @name: user-readable clock name string - should match the manual 245 * @parent_name: parent name for this clock 246 * @ops: struct clk_ops for the Linux clock framework to use for control 247 * @hw: Linux-private clock data 248 * @pwd: WRPLL-specific data, associated with this clock (if not NULL) 249 * @pd: PRCI-specific data associated with this clock (if not NULL) 250 * 251 * PRCI clock data. Used by the PRCI driver to register PRCI-provided 252 * clocks to the Linux clock infrastructure. 253 */ 254 struct __prci_clock { 255 const char *name; 256 const char *parent_name; 257 const struct clk_ops *ops; 258 struct clk_hw hw; 259 struct __prci_wrpll_data *pwd; 260 struct __prci_data *pd; 261 }; 262 263 #define clk_hw_to_prci_clock(pwd) container_of(pwd, struct __prci_clock, hw) 264 265 /* 266 * struct prci_clk_desc - describes the information of clocks of each SoCs 267 * @clks: point to a array of __prci_clock 268 * @num_clks: the number of element of clks 269 */ 270 struct prci_clk_desc { 271 struct __prci_clock *clks; 272 size_t num_clks; 273 }; 274 275 /* Core clock mux control */ 276 void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd); 277 void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd); 278 void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd); 279 void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd); 280 void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd); 281 void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd); 282 void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd); 283 284 /* Linux clock framework integration */ 285 long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate, 286 unsigned long *parent_rate); 287 int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate, 288 unsigned long parent_rate); 289 int sifive_clk_is_enabled(struct clk_hw *hw); 290 int sifive_prci_clock_enable(struct clk_hw *hw); 291 void sifive_prci_clock_disable(struct clk_hw *hw); 292 unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw, 293 unsigned long parent_rate); 294 unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw, 295 unsigned long parent_rate); 296 unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw, 297 unsigned long parent_rate); 298 299 #endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */ 300