313 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * Copyright (C) 2018-2019 SiFive, Inc.4 * Wesley Terpstra5 * Paul Walmsley6 * Zong Li7 */8 9#ifndef __SIFIVE_CLK_SIFIVE_PRCI_H10#define __SIFIVE_CLK_SIFIVE_PRCI_H11 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 rtcclk20 */21#define EXPECTED_CLK_PARENT_COUNT 222 23/*24 * Register offsets and bitmasks25 */26 27/* COREPLLCFG0 */28#define PRCI_COREPLLCFG0_OFFSET 0x429#define PRCI_COREPLLCFG0_DIVR_SHIFT 030#define PRCI_COREPLLCFG0_DIVR_MASK (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)31#define PRCI_COREPLLCFG0_DIVF_SHIFT 632#define PRCI_COREPLLCFG0_DIVF_MASK (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)33#define PRCI_COREPLLCFG0_DIVQ_SHIFT 1534#define PRCI_COREPLLCFG0_DIVQ_MASK (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)35#define PRCI_COREPLLCFG0_RANGE_SHIFT 1836#define PRCI_COREPLLCFG0_RANGE_MASK (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)37#define PRCI_COREPLLCFG0_BYPASS_SHIFT 2438#define PRCI_COREPLLCFG0_BYPASS_MASK (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)39#define PRCI_COREPLLCFG0_FSE_SHIFT 2540#define PRCI_COREPLLCFG0_FSE_MASK (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)41#define PRCI_COREPLLCFG0_LOCK_SHIFT 3142#define PRCI_COREPLLCFG0_LOCK_MASK (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)43 44/* COREPLLCFG1 */45#define PRCI_COREPLLCFG1_OFFSET 0x846#define PRCI_COREPLLCFG1_CKE_SHIFT 3147#define PRCI_COREPLLCFG1_CKE_MASK (0x1 << PRCI_COREPLLCFG1_CKE_SHIFT)48 49/* DDRPLLCFG0 */50#define PRCI_DDRPLLCFG0_OFFSET 0xc51#define PRCI_DDRPLLCFG0_DIVR_SHIFT 052#define PRCI_DDRPLLCFG0_DIVR_MASK (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)53#define PRCI_DDRPLLCFG0_DIVF_SHIFT 654#define PRCI_DDRPLLCFG0_DIVF_MASK (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)55#define PRCI_DDRPLLCFG0_DIVQ_SHIFT 1556#define PRCI_DDRPLLCFG0_DIVQ_MASK (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)57#define PRCI_DDRPLLCFG0_RANGE_SHIFT 1858#define PRCI_DDRPLLCFG0_RANGE_MASK (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)59#define PRCI_DDRPLLCFG0_BYPASS_SHIFT 2460#define PRCI_DDRPLLCFG0_BYPASS_MASK (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)61#define PRCI_DDRPLLCFG0_FSE_SHIFT 2562#define PRCI_DDRPLLCFG0_FSE_MASK (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)63#define PRCI_DDRPLLCFG0_LOCK_SHIFT 3164#define PRCI_DDRPLLCFG0_LOCK_MASK (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)65 66/* DDRPLLCFG1 */67#define PRCI_DDRPLLCFG1_OFFSET 0x1068#define PRCI_DDRPLLCFG1_CKE_SHIFT 3169#define PRCI_DDRPLLCFG1_CKE_MASK (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)70 71/* PCIEAUX */72#define PRCI_PCIE_AUX_OFFSET 0x1473#define PRCI_PCIE_AUX_EN_SHIFT 074#define PRCI_PCIE_AUX_EN_MASK (0x1 << PRCI_PCIE_AUX_EN_SHIFT)75 76/* GEMGXLPLLCFG0 */77#define PRCI_GEMGXLPLLCFG0_OFFSET 0x1c78#define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT 079#define PRCI_GEMGXLPLLCFG0_DIVR_MASK (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)80#define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT 681#define PRCI_GEMGXLPLLCFG0_DIVF_MASK (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)82#define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT 1583#define PRCI_GEMGXLPLLCFG0_DIVQ_MASK (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)84#define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT 1885#define PRCI_GEMGXLPLLCFG0_RANGE_MASK (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)86#define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT 2487#define PRCI_GEMGXLPLLCFG0_BYPASS_MASK (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)88#define PRCI_GEMGXLPLLCFG0_FSE_SHIFT 2589#define PRCI_GEMGXLPLLCFG0_FSE_MASK (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)90#define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT 3191#define PRCI_GEMGXLPLLCFG0_LOCK_MASK (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)92 93/* GEMGXLPLLCFG1 */94#define PRCI_GEMGXLPLLCFG1_OFFSET 0x2095#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT 3196#define PRCI_GEMGXLPLLCFG1_CKE_MASK (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)97 98/* CORECLKSEL */99#define PRCI_CORECLKSEL_OFFSET 0x24100#define PRCI_CORECLKSEL_CORECLKSEL_SHIFT 0101#define PRCI_CORECLKSEL_CORECLKSEL_MASK \102 (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)103 104/* DEVICESRESETREG */105#define PRCI_DEVICESRESETREG_OFFSET 0x28106#define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT 0107#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 1110#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 2113#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 3116#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 5119#define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK \120 (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)121#define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT 6122#define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_MASK \123 (0x1 << PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT)124 125#define PRCI_RST_NR 7126 127/* CLKMUXSTATUSREG */128#define PRCI_CLKMUXSTATUSREG_OFFSET 0x2c129#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1130#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \131 (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)132 133/* CLTXPLLCFG0 */134#define PRCI_CLTXPLLCFG0_OFFSET 0x30135#define PRCI_CLTXPLLCFG0_DIVR_SHIFT 0136#define PRCI_CLTXPLLCFG0_DIVR_MASK (0x3f << PRCI_CLTXPLLCFG0_DIVR_SHIFT)137#define PRCI_CLTXPLLCFG0_DIVF_SHIFT 6138#define PRCI_CLTXPLLCFG0_DIVF_MASK (0x1ff << PRCI_CLTXPLLCFG0_DIVF_SHIFT)139#define PRCI_CLTXPLLCFG0_DIVQ_SHIFT 15140#define PRCI_CLTXPLLCFG0_DIVQ_MASK (0x7 << PRCI_CLTXPLLCFG0_DIVQ_SHIFT)141#define PRCI_CLTXPLLCFG0_RANGE_SHIFT 18142#define PRCI_CLTXPLLCFG0_RANGE_MASK (0x7 << PRCI_CLTXPLLCFG0_RANGE_SHIFT)143#define PRCI_CLTXPLLCFG0_BYPASS_SHIFT 24144#define PRCI_CLTXPLLCFG0_BYPASS_MASK (0x1 << PRCI_CLTXPLLCFG0_BYPASS_SHIFT)145#define PRCI_CLTXPLLCFG0_FSE_SHIFT 25146#define PRCI_CLTXPLLCFG0_FSE_MASK (0x1 << PRCI_CLTXPLLCFG0_FSE_SHIFT)147#define PRCI_CLTXPLLCFG0_LOCK_SHIFT 31148#define PRCI_CLTXPLLCFG0_LOCK_MASK (0x1 << PRCI_CLTXPLLCFG0_LOCK_SHIFT)149 150/* CLTXPLLCFG1 */151#define PRCI_CLTXPLLCFG1_OFFSET 0x34152#define PRCI_CLTXPLLCFG1_CKE_SHIFT 31153#define PRCI_CLTXPLLCFG1_CKE_MASK (0x1 << PRCI_CLTXPLLCFG1_CKE_SHIFT)154 155/* DVFSCOREPLLCFG0 */156#define PRCI_DVFSCOREPLLCFG0_OFFSET 0x38157 158/* DVFSCOREPLLCFG1 */159#define PRCI_DVFSCOREPLLCFG1_OFFSET 0x3c160#define PRCI_DVFSCOREPLLCFG1_CKE_SHIFT 31161#define PRCI_DVFSCOREPLLCFG1_CKE_MASK (0x1 << PRCI_DVFSCOREPLLCFG1_CKE_SHIFT)162 163/* COREPLLSEL */164#define PRCI_COREPLLSEL_OFFSET 0x40165#define PRCI_COREPLLSEL_COREPLLSEL_SHIFT 0166#define PRCI_COREPLLSEL_COREPLLSEL_MASK \167 (0x1 << PRCI_COREPLLSEL_COREPLLSEL_SHIFT)168 169/* HFPCLKPLLCFG0 */170#define PRCI_HFPCLKPLLCFG0_OFFSET 0x50171#define PRCI_HFPCLKPLL_CFG0_DIVR_SHIFT 0172#define PRCI_HFPCLKPLL_CFG0_DIVR_MASK \173 (0x3f << PRCI_HFPCLKPLLCFG0_DIVR_SHIFT)174#define PRCI_HFPCLKPLL_CFG0_DIVF_SHIFT 6175#define PRCI_HFPCLKPLL_CFG0_DIVF_MASK \176 (0x1ff << PRCI_HFPCLKPLLCFG0_DIVF_SHIFT)177#define PRCI_HFPCLKPLL_CFG0_DIVQ_SHIFT 15178#define PRCI_HFPCLKPLL_CFG0_DIVQ_MASK \179 (0x7 << PRCI_HFPCLKPLLCFG0_DIVQ_SHIFT)180#define PRCI_HFPCLKPLL_CFG0_RANGE_SHIFT 18181#define PRCI_HFPCLKPLL_CFG0_RANGE_MASK \182 (0x7 << PRCI_HFPCLKPLLCFG0_RANGE_SHIFT)183#define PRCI_HFPCLKPLL_CFG0_BYPASS_SHIFT 24184#define PRCI_HFPCLKPLL_CFG0_BYPASS_MASK \185 (0x1 << PRCI_HFPCLKPLLCFG0_BYPASS_SHIFT)186#define PRCI_HFPCLKPLL_CFG0_FSE_SHIFT 25187#define PRCI_HFPCLKPLL_CFG0_FSE_MASK \188 (0x1 << PRCI_HFPCLKPLLCFG0_FSE_SHIFT)189#define PRCI_HFPCLKPLL_CFG0_LOCK_SHIFT 31190#define PRCI_HFPCLKPLL_CFG0_LOCK_MASK \191 (0x1 << PRCI_HFPCLKPLLCFG0_LOCK_SHIFT)192 193/* HFPCLKPLLCFG1 */194#define PRCI_HFPCLKPLLCFG1_OFFSET 0x54195#define PRCI_HFPCLKPLLCFG1_CKE_SHIFT 31196#define PRCI_HFPCLKPLLCFG1_CKE_MASK \197 (0x1 << PRCI_HFPCLKPLLCFG1_CKE_SHIFT)198 199/* HFPCLKPLLSEL */200#define PRCI_HFPCLKPLLSEL_OFFSET 0x58201#define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT 0202#define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK \203 (0x1 << PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT)204 205/* HFPCLKPLLDIV */206#define PRCI_HFPCLKPLLDIV_OFFSET 0x5c207 208/* PRCIPLL */209#define PRCI_PRCIPLL_OFFSET 0xe0210 211/* PROCMONCFG */212#define PRCI_PROCMONCFG_OFFSET 0xf0213 214/*215 * Private structures216 */217 218/**219 * struct __prci_data - per-device-instance data220 * @va: base virtual address of the PRCI IP block221 * @hw_clks: encapsulates struct clk_hw records222 *223 * PRCI per-device instance data224 */225struct __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 data233 * @c: WRPLL current configuration record234 * @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 address237 * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address238 *239 * @enable_bypass and @disable_bypass are used for WRPLL instances240 * that contain a separate external glitchless clock mux downstream241 * from the PLL. The WRPLL internal bypass mux is not glitchless.242 */243struct __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 PRCI253 * @name: user-readable clock name string - should match the manual254 * @parent_name: parent name for this clock255 * @ops: struct clk_ops for the Linux clock framework to use for control256 * @hw: Linux-private clock data257 * @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-provided261 * clocks to the Linux clock infrastructure.262 */263struct __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 SoCs276 * @clks: point to a array of __prci_clock277 * @num_clks: the number of element of clks278 */279struct prci_clk_desc {280 struct __prci_clock *clks;281 size_t num_clks;282};283 284/* Core clock mux control */285void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd);286void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd);287void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd);288void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd);289void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd);290void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd);291void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd);292 293/* Linux clock framework integration */294long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate,295 unsigned long *parent_rate);296int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate,297 unsigned long parent_rate);298int sifive_clk_is_enabled(struct clk_hw *hw);299int sifive_prci_clock_enable(struct clk_hw *hw);300void sifive_prci_clock_disable(struct clk_hw *hw);301unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,302 unsigned long parent_rate);303unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,304 unsigned long parent_rate);305unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw,306 unsigned long parent_rate);307 308int sifive_prci_pcie_aux_clock_is_enabled(struct clk_hw *hw);309int sifive_prci_pcie_aux_clock_enable(struct clk_hw *hw);310void sifive_prci_pcie_aux_clock_disable(struct clk_hw *hw);311 312#endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */313