1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun #ifndef __MACH_MMP_CLK_H 3*4882a593Smuzhiyun #define __MACH_MMP_CLK_H 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun #include <linux/clk-provider.h> 6*4882a593Smuzhiyun #include <linux/pm_domain.h> 7*4882a593Smuzhiyun #include <linux/clkdev.h> 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #define APBC_NO_BUS_CTRL BIT(0) 10*4882a593Smuzhiyun #define APBC_POWER_CTRL BIT(1) 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun /* Clock type "factor" */ 14*4882a593Smuzhiyun struct mmp_clk_factor_masks { 15*4882a593Smuzhiyun unsigned int factor; 16*4882a593Smuzhiyun unsigned int num_mask; 17*4882a593Smuzhiyun unsigned int den_mask; 18*4882a593Smuzhiyun unsigned int num_shift; 19*4882a593Smuzhiyun unsigned int den_shift; 20*4882a593Smuzhiyun unsigned int enable_mask; 21*4882a593Smuzhiyun }; 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun struct mmp_clk_factor_tbl { 24*4882a593Smuzhiyun unsigned int num; 25*4882a593Smuzhiyun unsigned int den; 26*4882a593Smuzhiyun }; 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun struct mmp_clk_factor { 29*4882a593Smuzhiyun struct clk_hw hw; 30*4882a593Smuzhiyun void __iomem *base; 31*4882a593Smuzhiyun struct mmp_clk_factor_masks *masks; 32*4882a593Smuzhiyun struct mmp_clk_factor_tbl *ftbl; 33*4882a593Smuzhiyun unsigned int ftbl_cnt; 34*4882a593Smuzhiyun spinlock_t *lock; 35*4882a593Smuzhiyun }; 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun extern struct clk *mmp_clk_register_factor(const char *name, 38*4882a593Smuzhiyun const char *parent_name, unsigned long flags, 39*4882a593Smuzhiyun void __iomem *base, struct mmp_clk_factor_masks *masks, 40*4882a593Smuzhiyun struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt, 41*4882a593Smuzhiyun spinlock_t *lock); 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun /* Clock type "mix" */ 44*4882a593Smuzhiyun #define MMP_CLK_BITS_MASK(width, shift) \ 45*4882a593Smuzhiyun (((1 << (width)) - 1) << (shift)) 46*4882a593Smuzhiyun #define MMP_CLK_BITS_GET_VAL(data, width, shift) \ 47*4882a593Smuzhiyun ((data & MMP_CLK_BITS_MASK(width, shift)) >> (shift)) 48*4882a593Smuzhiyun #define MMP_CLK_BITS_SET_VAL(val, width, shift) \ 49*4882a593Smuzhiyun (((val) << (shift)) & MMP_CLK_BITS_MASK(width, shift)) 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun enum { 52*4882a593Smuzhiyun MMP_CLK_MIX_TYPE_V1, 53*4882a593Smuzhiyun MMP_CLK_MIX_TYPE_V2, 54*4882a593Smuzhiyun MMP_CLK_MIX_TYPE_V3, 55*4882a593Smuzhiyun }; 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun /* The register layout */ 58*4882a593Smuzhiyun struct mmp_clk_mix_reg_info { 59*4882a593Smuzhiyun void __iomem *reg_clk_ctrl; 60*4882a593Smuzhiyun void __iomem *reg_clk_sel; 61*4882a593Smuzhiyun u8 width_div; 62*4882a593Smuzhiyun u8 shift_div; 63*4882a593Smuzhiyun u8 width_mux; 64*4882a593Smuzhiyun u8 shift_mux; 65*4882a593Smuzhiyun u8 bit_fc; 66*4882a593Smuzhiyun }; 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun /* The suggested clock table from user. */ 69*4882a593Smuzhiyun struct mmp_clk_mix_clk_table { 70*4882a593Smuzhiyun unsigned long rate; 71*4882a593Smuzhiyun u8 parent_index; 72*4882a593Smuzhiyun unsigned int divisor; 73*4882a593Smuzhiyun unsigned int valid; 74*4882a593Smuzhiyun }; 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun struct mmp_clk_mix_config { 77*4882a593Smuzhiyun struct mmp_clk_mix_reg_info reg_info; 78*4882a593Smuzhiyun struct mmp_clk_mix_clk_table *table; 79*4882a593Smuzhiyun unsigned int table_size; 80*4882a593Smuzhiyun u32 *mux_table; 81*4882a593Smuzhiyun struct clk_div_table *div_table; 82*4882a593Smuzhiyun u8 div_flags; 83*4882a593Smuzhiyun u8 mux_flags; 84*4882a593Smuzhiyun }; 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun struct mmp_clk_mix { 87*4882a593Smuzhiyun struct clk_hw hw; 88*4882a593Smuzhiyun struct mmp_clk_mix_reg_info reg_info; 89*4882a593Smuzhiyun struct mmp_clk_mix_clk_table *table; 90*4882a593Smuzhiyun u32 *mux_table; 91*4882a593Smuzhiyun struct clk_div_table *div_table; 92*4882a593Smuzhiyun unsigned int table_size; 93*4882a593Smuzhiyun u8 div_flags; 94*4882a593Smuzhiyun u8 mux_flags; 95*4882a593Smuzhiyun unsigned int type; 96*4882a593Smuzhiyun spinlock_t *lock; 97*4882a593Smuzhiyun }; 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun extern const struct clk_ops mmp_clk_mix_ops; 100*4882a593Smuzhiyun extern struct clk *mmp_clk_register_mix(struct device *dev, 101*4882a593Smuzhiyun const char *name, 102*4882a593Smuzhiyun const char * const *parent_names, 103*4882a593Smuzhiyun u8 num_parents, 104*4882a593Smuzhiyun unsigned long flags, 105*4882a593Smuzhiyun struct mmp_clk_mix_config *config, 106*4882a593Smuzhiyun spinlock_t *lock); 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun /* Clock type "gate". MMP private gate */ 110*4882a593Smuzhiyun #define MMP_CLK_GATE_NEED_DELAY BIT(0) 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun struct mmp_clk_gate { 113*4882a593Smuzhiyun struct clk_hw hw; 114*4882a593Smuzhiyun void __iomem *reg; 115*4882a593Smuzhiyun u32 mask; 116*4882a593Smuzhiyun u32 val_enable; 117*4882a593Smuzhiyun u32 val_disable; 118*4882a593Smuzhiyun unsigned int flags; 119*4882a593Smuzhiyun spinlock_t *lock; 120*4882a593Smuzhiyun }; 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun extern const struct clk_ops mmp_clk_gate_ops; 123*4882a593Smuzhiyun extern struct clk *mmp_clk_register_gate(struct device *dev, const char *name, 124*4882a593Smuzhiyun const char *parent_name, unsigned long flags, 125*4882a593Smuzhiyun void __iomem *reg, u32 mask, u32 val_enable, 126*4882a593Smuzhiyun u32 val_disable, unsigned int gate_flags, 127*4882a593Smuzhiyun spinlock_t *lock); 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun extern struct clk *mmp_clk_register_apbc(const char *name, 130*4882a593Smuzhiyun const char *parent_name, void __iomem *base, 131*4882a593Smuzhiyun unsigned int delay, unsigned int apbc_flags, spinlock_t *lock); 132*4882a593Smuzhiyun extern struct clk *mmp_clk_register_apmu(const char *name, 133*4882a593Smuzhiyun const char *parent_name, void __iomem *base, u32 enable_mask, 134*4882a593Smuzhiyun spinlock_t *lock); 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun struct mmp_clk_unit { 137*4882a593Smuzhiyun unsigned int nr_clks; 138*4882a593Smuzhiyun struct clk **clk_table; 139*4882a593Smuzhiyun struct clk_onecell_data clk_data; 140*4882a593Smuzhiyun }; 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun struct mmp_param_fixed_rate_clk { 143*4882a593Smuzhiyun unsigned int id; 144*4882a593Smuzhiyun char *name; 145*4882a593Smuzhiyun const char *parent_name; 146*4882a593Smuzhiyun unsigned long flags; 147*4882a593Smuzhiyun unsigned long fixed_rate; 148*4882a593Smuzhiyun }; 149*4882a593Smuzhiyun void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit, 150*4882a593Smuzhiyun struct mmp_param_fixed_rate_clk *clks, 151*4882a593Smuzhiyun int size); 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun struct mmp_param_fixed_factor_clk { 154*4882a593Smuzhiyun unsigned int id; 155*4882a593Smuzhiyun char *name; 156*4882a593Smuzhiyun const char *parent_name; 157*4882a593Smuzhiyun unsigned long mult; 158*4882a593Smuzhiyun unsigned long div; 159*4882a593Smuzhiyun unsigned long flags; 160*4882a593Smuzhiyun }; 161*4882a593Smuzhiyun void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit, 162*4882a593Smuzhiyun struct mmp_param_fixed_factor_clk *clks, 163*4882a593Smuzhiyun int size); 164*4882a593Smuzhiyun 165*4882a593Smuzhiyun struct mmp_param_general_gate_clk { 166*4882a593Smuzhiyun unsigned int id; 167*4882a593Smuzhiyun const char *name; 168*4882a593Smuzhiyun const char *parent_name; 169*4882a593Smuzhiyun unsigned long flags; 170*4882a593Smuzhiyun unsigned long offset; 171*4882a593Smuzhiyun u8 bit_idx; 172*4882a593Smuzhiyun u8 gate_flags; 173*4882a593Smuzhiyun spinlock_t *lock; 174*4882a593Smuzhiyun }; 175*4882a593Smuzhiyun void mmp_register_general_gate_clks(struct mmp_clk_unit *unit, 176*4882a593Smuzhiyun struct mmp_param_general_gate_clk *clks, 177*4882a593Smuzhiyun void __iomem *base, int size); 178*4882a593Smuzhiyun 179*4882a593Smuzhiyun struct mmp_param_gate_clk { 180*4882a593Smuzhiyun unsigned int id; 181*4882a593Smuzhiyun char *name; 182*4882a593Smuzhiyun const char *parent_name; 183*4882a593Smuzhiyun unsigned long flags; 184*4882a593Smuzhiyun unsigned long offset; 185*4882a593Smuzhiyun u32 mask; 186*4882a593Smuzhiyun u32 val_enable; 187*4882a593Smuzhiyun u32 val_disable; 188*4882a593Smuzhiyun unsigned int gate_flags; 189*4882a593Smuzhiyun spinlock_t *lock; 190*4882a593Smuzhiyun }; 191*4882a593Smuzhiyun void mmp_register_gate_clks(struct mmp_clk_unit *unit, 192*4882a593Smuzhiyun struct mmp_param_gate_clk *clks, 193*4882a593Smuzhiyun void __iomem *base, int size); 194*4882a593Smuzhiyun 195*4882a593Smuzhiyun struct mmp_param_mux_clk { 196*4882a593Smuzhiyun unsigned int id; 197*4882a593Smuzhiyun char *name; 198*4882a593Smuzhiyun const char * const *parent_name; 199*4882a593Smuzhiyun u8 num_parents; 200*4882a593Smuzhiyun unsigned long flags; 201*4882a593Smuzhiyun unsigned long offset; 202*4882a593Smuzhiyun u8 shift; 203*4882a593Smuzhiyun u8 width; 204*4882a593Smuzhiyun u8 mux_flags; 205*4882a593Smuzhiyun spinlock_t *lock; 206*4882a593Smuzhiyun }; 207*4882a593Smuzhiyun void mmp_register_mux_clks(struct mmp_clk_unit *unit, 208*4882a593Smuzhiyun struct mmp_param_mux_clk *clks, 209*4882a593Smuzhiyun void __iomem *base, int size); 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun struct mmp_param_div_clk { 212*4882a593Smuzhiyun unsigned int id; 213*4882a593Smuzhiyun char *name; 214*4882a593Smuzhiyun const char *parent_name; 215*4882a593Smuzhiyun unsigned long flags; 216*4882a593Smuzhiyun unsigned long offset; 217*4882a593Smuzhiyun u8 shift; 218*4882a593Smuzhiyun u8 width; 219*4882a593Smuzhiyun u8 div_flags; 220*4882a593Smuzhiyun spinlock_t *lock; 221*4882a593Smuzhiyun }; 222*4882a593Smuzhiyun void mmp_register_div_clks(struct mmp_clk_unit *unit, 223*4882a593Smuzhiyun struct mmp_param_div_clk *clks, 224*4882a593Smuzhiyun void __iomem *base, int size); 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun struct mmp_param_pll_clk { 227*4882a593Smuzhiyun unsigned int id; 228*4882a593Smuzhiyun char *name; 229*4882a593Smuzhiyun unsigned long default_rate; 230*4882a593Smuzhiyun unsigned long enable_offset; 231*4882a593Smuzhiyun u32 enable; 232*4882a593Smuzhiyun unsigned long offset; 233*4882a593Smuzhiyun u8 shift; 234*4882a593Smuzhiyun /* MMP3 specific: */ 235*4882a593Smuzhiyun unsigned long input_rate; 236*4882a593Smuzhiyun unsigned long postdiv_offset; 237*4882a593Smuzhiyun unsigned long postdiv_shift; 238*4882a593Smuzhiyun }; 239*4882a593Smuzhiyun void mmp_register_pll_clks(struct mmp_clk_unit *unit, 240*4882a593Smuzhiyun struct mmp_param_pll_clk *clks, 241*4882a593Smuzhiyun void __iomem *base, int size); 242*4882a593Smuzhiyun 243*4882a593Smuzhiyun #define DEFINE_MIX_REG_INFO(w_d, s_d, w_m, s_m, fc) \ 244*4882a593Smuzhiyun { \ 245*4882a593Smuzhiyun .width_div = (w_d), \ 246*4882a593Smuzhiyun .shift_div = (s_d), \ 247*4882a593Smuzhiyun .width_mux = (w_m), \ 248*4882a593Smuzhiyun .shift_mux = (s_m), \ 249*4882a593Smuzhiyun .bit_fc = (fc), \ 250*4882a593Smuzhiyun } 251*4882a593Smuzhiyun 252*4882a593Smuzhiyun void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, 253*4882a593Smuzhiyun int nr_clks); 254*4882a593Smuzhiyun void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id, 255*4882a593Smuzhiyun struct clk *clk); 256*4882a593Smuzhiyun 257*4882a593Smuzhiyun /* Power islands */ 258*4882a593Smuzhiyun #define MMP_PM_DOMAIN_NO_DISABLE BIT(0) 259*4882a593Smuzhiyun 260*4882a593Smuzhiyun struct generic_pm_domain *mmp_pm_domain_register(const char *name, 261*4882a593Smuzhiyun void __iomem *reg, 262*4882a593Smuzhiyun u32 power_on, u32 reset, u32 clock_enable, 263*4882a593Smuzhiyun unsigned int flags, spinlock_t *lock); 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun #endif 266