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