1*c816e1ddSZong Li /* SPDX-License-Identifier: GPL-2.0 */ 2*c816e1ddSZong Li /* 3*c816e1ddSZong Li * Copyright (C) 2018-2019 SiFive, Inc. 4*c816e1ddSZong Li * Wesley Terpstra 5*c816e1ddSZong Li * Paul Walmsley 6*c816e1ddSZong Li * Zong Li 7*c816e1ddSZong Li */ 8*c816e1ddSZong Li 9*c816e1ddSZong Li #ifndef __SIFIVE_CLK_SIFIVE_PRCI_H 10*c816e1ddSZong Li #define __SIFIVE_CLK_SIFIVE_PRCI_H 11*c816e1ddSZong Li 12*c816e1ddSZong Li #include <linux/clk/analogbits-wrpll-cln28hpc.h> 13*c816e1ddSZong Li #include <linux/clk-provider.h> 14*c816e1ddSZong Li #include <linux/platform_device.h> 15*c816e1ddSZong Li 16*c816e1ddSZong Li /* 17*c816e1ddSZong Li * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects: 18*c816e1ddSZong Li * hfclk and rtcclk 19*c816e1ddSZong Li */ 20*c816e1ddSZong Li #define EXPECTED_CLK_PARENT_COUNT 2 21*c816e1ddSZong Li 22*c816e1ddSZong Li /* 23*c816e1ddSZong Li * Register offsets and bitmasks 24*c816e1ddSZong Li */ 25*c816e1ddSZong Li 26*c816e1ddSZong Li /* COREPLLCFG0 */ 27*c816e1ddSZong Li #define PRCI_COREPLLCFG0_OFFSET 0x4 28*c816e1ddSZong Li #define PRCI_COREPLLCFG0_DIVR_SHIFT 0 29*c816e1ddSZong Li #define PRCI_COREPLLCFG0_DIVR_MASK (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT) 30*c816e1ddSZong Li #define PRCI_COREPLLCFG0_DIVF_SHIFT 6 31*c816e1ddSZong Li #define PRCI_COREPLLCFG0_DIVF_MASK (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT) 32*c816e1ddSZong Li #define PRCI_COREPLLCFG0_DIVQ_SHIFT 15 33*c816e1ddSZong Li #define PRCI_COREPLLCFG0_DIVQ_MASK (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT) 34*c816e1ddSZong Li #define PRCI_COREPLLCFG0_RANGE_SHIFT 18 35*c816e1ddSZong Li #define PRCI_COREPLLCFG0_RANGE_MASK (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT) 36*c816e1ddSZong Li #define PRCI_COREPLLCFG0_BYPASS_SHIFT 24 37*c816e1ddSZong Li #define PRCI_COREPLLCFG0_BYPASS_MASK (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT) 38*c816e1ddSZong Li #define PRCI_COREPLLCFG0_FSE_SHIFT 25 39*c816e1ddSZong Li #define PRCI_COREPLLCFG0_FSE_MASK (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT) 40*c816e1ddSZong Li #define PRCI_COREPLLCFG0_LOCK_SHIFT 31 41*c816e1ddSZong Li #define PRCI_COREPLLCFG0_LOCK_MASK (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT) 42*c816e1ddSZong Li 43*c816e1ddSZong Li /* DDRPLLCFG0 */ 44*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_OFFSET 0xc 45*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_DIVR_SHIFT 0 46*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_DIVR_MASK (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT) 47*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_DIVF_SHIFT 6 48*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_DIVF_MASK (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT) 49*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_DIVQ_SHIFT 15 50*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_DIVQ_MASK (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT) 51*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_RANGE_SHIFT 18 52*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_RANGE_MASK (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT) 53*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_BYPASS_SHIFT 24 54*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_BYPASS_MASK (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT) 55*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_FSE_SHIFT 25 56*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_FSE_MASK (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT) 57*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_LOCK_SHIFT 31 58*c816e1ddSZong Li #define PRCI_DDRPLLCFG0_LOCK_MASK (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT) 59*c816e1ddSZong Li 60*c816e1ddSZong Li /* DDRPLLCFG1 */ 61*c816e1ddSZong Li #define PRCI_DDRPLLCFG1_OFFSET 0x10 62*c816e1ddSZong Li #define PRCI_DDRPLLCFG1_CKE_SHIFT 24 63*c816e1ddSZong Li #define PRCI_DDRPLLCFG1_CKE_MASK (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT) 64*c816e1ddSZong Li 65*c816e1ddSZong Li /* GEMGXLPLLCFG0 */ 66*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_OFFSET 0x1c 67*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT 0 68*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_DIVR_MASK (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT) 69*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT 6 70*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_DIVF_MASK (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT) 71*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT 15 72*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_DIVQ_MASK (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT) 73*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT 18 74*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_RANGE_MASK (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT) 75*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT 24 76*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_BYPASS_MASK (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT) 77*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_FSE_SHIFT 25 78*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_FSE_MASK (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT) 79*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT 31 80*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG0_LOCK_MASK (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT) 81*c816e1ddSZong Li 82*c816e1ddSZong Li /* GEMGXLPLLCFG1 */ 83*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG1_OFFSET 0x20 84*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG1_CKE_SHIFT 24 85*c816e1ddSZong Li #define PRCI_GEMGXLPLLCFG1_CKE_MASK (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT) 86*c816e1ddSZong Li 87*c816e1ddSZong Li /* CORECLKSEL */ 88*c816e1ddSZong Li #define PRCI_CORECLKSEL_OFFSET 0x24 89*c816e1ddSZong Li #define PRCI_CORECLKSEL_CORECLKSEL_SHIFT 0 90*c816e1ddSZong Li #define PRCI_CORECLKSEL_CORECLKSEL_MASK \ 91*c816e1ddSZong Li (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT) 92*c816e1ddSZong Li 93*c816e1ddSZong Li /* DEVICESRESETREG */ 94*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_OFFSET 0x28 95*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT 0 96*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK \ 97*c816e1ddSZong Li (0x1 << PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT) 98*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT 1 99*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK \ 100*c816e1ddSZong Li (0x1 << PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT) 101*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT 2 102*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK \ 103*c816e1ddSZong Li (0x1 << PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT) 104*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT 3 105*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK \ 106*c816e1ddSZong Li (0x1 << PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT) 107*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT 5 108*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK \ 109*c816e1ddSZong Li (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT) 110*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT 6 111*c816e1ddSZong Li #define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_MASK \ 112*c816e1ddSZong Li (0x1 << PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT) 113*c816e1ddSZong Li 114*c816e1ddSZong Li /* CLKMUXSTATUSREG */ 115*c816e1ddSZong Li #define PRCI_CLKMUXSTATUSREG_OFFSET 0x2c 116*c816e1ddSZong Li #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1 117*c816e1ddSZong Li #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ 118*c816e1ddSZong Li (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT) 119*c816e1ddSZong Li 120*c816e1ddSZong Li /* 121*c816e1ddSZong Li * Private structures 122*c816e1ddSZong Li */ 123*c816e1ddSZong Li 124*c816e1ddSZong Li /** 125*c816e1ddSZong Li * struct __prci_data - per-device-instance data 126*c816e1ddSZong Li * @va: base virtual address of the PRCI IP block 127*c816e1ddSZong Li * @hw_clks: encapsulates struct clk_hw records 128*c816e1ddSZong Li * 129*c816e1ddSZong Li * PRCI per-device instance data 130*c816e1ddSZong Li */ 131*c816e1ddSZong Li struct __prci_data { 132*c816e1ddSZong Li void __iomem *va; 133*c816e1ddSZong Li struct clk_hw_onecell_data hw_clks; 134*c816e1ddSZong Li }; 135*c816e1ddSZong Li 136*c816e1ddSZong Li /** 137*c816e1ddSZong Li * struct __prci_wrpll_data - WRPLL configuration and integration data 138*c816e1ddSZong Li * @c: WRPLL current configuration record 139*c816e1ddSZong Li * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL) 140*c816e1ddSZong Li * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL) 141*c816e1ddSZong Li * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address 142*c816e1ddSZong Li * 143*c816e1ddSZong Li * @enable_bypass and @disable_bypass are used for WRPLL instances 144*c816e1ddSZong Li * that contain a separate external glitchless clock mux downstream 145*c816e1ddSZong Li * from the PLL. The WRPLL internal bypass mux is not glitchless. 146*c816e1ddSZong Li */ 147*c816e1ddSZong Li struct __prci_wrpll_data { 148*c816e1ddSZong Li struct wrpll_cfg c; 149*c816e1ddSZong Li void (*enable_bypass)(struct __prci_data *pd); 150*c816e1ddSZong Li void (*disable_bypass)(struct __prci_data *pd); 151*c816e1ddSZong Li u8 cfg0_offs; 152*c816e1ddSZong Li }; 153*c816e1ddSZong Li 154*c816e1ddSZong Li /** 155*c816e1ddSZong Li * struct __prci_clock - describes a clock device managed by PRCI 156*c816e1ddSZong Li * @name: user-readable clock name string - should match the manual 157*c816e1ddSZong Li * @parent_name: parent name for this clock 158*c816e1ddSZong Li * @ops: struct clk_ops for the Linux clock framework to use for control 159*c816e1ddSZong Li * @hw: Linux-private clock data 160*c816e1ddSZong Li * @pwd: WRPLL-specific data, associated with this clock (if not NULL) 161*c816e1ddSZong Li * @pd: PRCI-specific data associated with this clock (if not NULL) 162*c816e1ddSZong Li * 163*c816e1ddSZong Li * PRCI clock data. Used by the PRCI driver to register PRCI-provided 164*c816e1ddSZong Li * clocks to the Linux clock infrastructure. 165*c816e1ddSZong Li */ 166*c816e1ddSZong Li struct __prci_clock { 167*c816e1ddSZong Li const char *name; 168*c816e1ddSZong Li const char *parent_name; 169*c816e1ddSZong Li const struct clk_ops *ops; 170*c816e1ddSZong Li struct clk_hw hw; 171*c816e1ddSZong Li struct __prci_wrpll_data *pwd; 172*c816e1ddSZong Li struct __prci_data *pd; 173*c816e1ddSZong Li }; 174*c816e1ddSZong Li 175*c816e1ddSZong Li #define clk_hw_to_prci_clock(pwd) container_of(pwd, struct __prci_clock, hw) 176*c816e1ddSZong Li 177*c816e1ddSZong Li /* 178*c816e1ddSZong Li * struct prci_clk_desc - describes the information of clocks of each SoCs 179*c816e1ddSZong Li * @clks: point to a array of __prci_clock 180*c816e1ddSZong Li * @num_clks: the number of element of clks 181*c816e1ddSZong Li */ 182*c816e1ddSZong Li struct prci_clk_desc { 183*c816e1ddSZong Li struct __prci_clock *clks; 184*c816e1ddSZong Li size_t num_clks; 185*c816e1ddSZong Li }; 186*c816e1ddSZong Li 187*c816e1ddSZong Li /* Core clock mux control */ 188*c816e1ddSZong Li void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd); 189*c816e1ddSZong Li void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd); 190*c816e1ddSZong Li 191*c816e1ddSZong Li /* Linux clock framework integration */ 192*c816e1ddSZong Li long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate, 193*c816e1ddSZong Li unsigned long *parent_rate); 194*c816e1ddSZong Li int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate, 195*c816e1ddSZong Li unsigned long parent_rate); 196*c816e1ddSZong Li unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw, 197*c816e1ddSZong Li unsigned long parent_rate); 198*c816e1ddSZong Li unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw, 199*c816e1ddSZong Li unsigned long parent_rate); 200*c816e1ddSZong Li 201*c816e1ddSZong Li #endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */ 202