|  | /* SPDX-License-Identifier: GPL-2.0 */ | 
|  | #ifndef __MACH_MMP_CLK_H | 
|  | #define __MACH_MMP_CLK_H | 
|  |  | 
|  | #include <linux/clk-provider.h> | 
|  | #include <linux/clkdev.h> | 
|  |  | 
|  | #define APBC_NO_BUS_CTRL	BIT(0) | 
|  | #define APBC_POWER_CTRL		BIT(1) | 
|  |  | 
|  |  | 
|  | /* Clock type "factor" */ | 
|  | struct mmp_clk_factor_masks { | 
|  | unsigned int factor; | 
|  | unsigned int num_mask; | 
|  | unsigned int den_mask; | 
|  | unsigned int num_shift; | 
|  | unsigned int den_shift; | 
|  | }; | 
|  |  | 
|  | struct mmp_clk_factor_tbl { | 
|  | unsigned int num; | 
|  | unsigned int den; | 
|  | }; | 
|  |  | 
|  | struct mmp_clk_factor { | 
|  | struct clk_hw hw; | 
|  | void __iomem *base; | 
|  | struct mmp_clk_factor_masks *masks; | 
|  | struct mmp_clk_factor_tbl *ftbl; | 
|  | unsigned int ftbl_cnt; | 
|  | spinlock_t *lock; | 
|  | }; | 
|  |  | 
|  | extern struct clk *mmp_clk_register_factor(const char *name, | 
|  | const char *parent_name, unsigned long flags, | 
|  | void __iomem *base, struct mmp_clk_factor_masks *masks, | 
|  | struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt, | 
|  | spinlock_t *lock); | 
|  |  | 
|  | /* Clock type "mix" */ | 
|  | #define MMP_CLK_BITS_MASK(width, shift)			\ | 
|  | (((1 << (width)) - 1) << (shift)) | 
|  | #define MMP_CLK_BITS_GET_VAL(data, width, shift)	\ | 
|  | ((data & MMP_CLK_BITS_MASK(width, shift)) >> (shift)) | 
|  | #define MMP_CLK_BITS_SET_VAL(val, width, shift)		\ | 
|  | (((val) << (shift)) & MMP_CLK_BITS_MASK(width, shift)) | 
|  |  | 
|  | enum { | 
|  | MMP_CLK_MIX_TYPE_V1, | 
|  | MMP_CLK_MIX_TYPE_V2, | 
|  | MMP_CLK_MIX_TYPE_V3, | 
|  | }; | 
|  |  | 
|  | /* The register layout */ | 
|  | struct mmp_clk_mix_reg_info { | 
|  | void __iomem *reg_clk_ctrl; | 
|  | void __iomem *reg_clk_sel; | 
|  | u8 width_div; | 
|  | u8 shift_div; | 
|  | u8 width_mux; | 
|  | u8 shift_mux; | 
|  | u8 bit_fc; | 
|  | }; | 
|  |  | 
|  | /* The suggested clock table from user. */ | 
|  | struct mmp_clk_mix_clk_table { | 
|  | unsigned long rate; | 
|  | u8 parent_index; | 
|  | unsigned int divisor; | 
|  | unsigned int valid; | 
|  | }; | 
|  |  | 
|  | struct mmp_clk_mix_config { | 
|  | struct mmp_clk_mix_reg_info reg_info; | 
|  | struct mmp_clk_mix_clk_table *table; | 
|  | unsigned int table_size; | 
|  | u32 *mux_table; | 
|  | struct clk_div_table *div_table; | 
|  | u8 div_flags; | 
|  | u8 mux_flags; | 
|  | }; | 
|  |  | 
|  | struct mmp_clk_mix { | 
|  | struct clk_hw hw; | 
|  | struct mmp_clk_mix_reg_info reg_info; | 
|  | struct mmp_clk_mix_clk_table *table; | 
|  | u32 *mux_table; | 
|  | struct clk_div_table *div_table; | 
|  | unsigned int table_size; | 
|  | u8 div_flags; | 
|  | u8 mux_flags; | 
|  | unsigned int type; | 
|  | spinlock_t *lock; | 
|  | }; | 
|  |  | 
|  | extern const struct clk_ops mmp_clk_mix_ops; | 
|  | extern struct clk *mmp_clk_register_mix(struct device *dev, | 
|  | const char *name, | 
|  | const char **parent_names, | 
|  | u8 num_parents, | 
|  | unsigned long flags, | 
|  | struct mmp_clk_mix_config *config, | 
|  | spinlock_t *lock); | 
|  |  | 
|  |  | 
|  | /* Clock type "gate". MMP private gate */ | 
|  | #define MMP_CLK_GATE_NEED_DELAY		BIT(0) | 
|  |  | 
|  | struct mmp_clk_gate { | 
|  | struct clk_hw hw; | 
|  | void __iomem *reg; | 
|  | u32 mask; | 
|  | u32 val_enable; | 
|  | u32 val_disable; | 
|  | unsigned int flags; | 
|  | spinlock_t *lock; | 
|  | }; | 
|  |  | 
|  | extern const struct clk_ops mmp_clk_gate_ops; | 
|  | extern struct clk *mmp_clk_register_gate(struct device *dev, const char *name, | 
|  | const char *parent_name, unsigned long flags, | 
|  | void __iomem *reg, u32 mask, u32 val_enable, | 
|  | u32 val_disable, unsigned int gate_flags, | 
|  | spinlock_t *lock); | 
|  |  | 
|  |  | 
|  | extern struct clk *mmp_clk_register_pll2(const char *name, | 
|  | const char *parent_name, unsigned long flags); | 
|  | extern struct clk *mmp_clk_register_apbc(const char *name, | 
|  | const char *parent_name, void __iomem *base, | 
|  | unsigned int delay, unsigned int apbc_flags, spinlock_t *lock); | 
|  | extern struct clk *mmp_clk_register_apmu(const char *name, | 
|  | const char *parent_name, void __iomem *base, u32 enable_mask, | 
|  | spinlock_t *lock); | 
|  |  | 
|  | struct mmp_clk_unit { | 
|  | unsigned int nr_clks; | 
|  | struct clk **clk_table; | 
|  | struct clk_onecell_data clk_data; | 
|  | }; | 
|  |  | 
|  | struct mmp_param_fixed_rate_clk { | 
|  | unsigned int id; | 
|  | char *name; | 
|  | const char *parent_name; | 
|  | unsigned long flags; | 
|  | unsigned long fixed_rate; | 
|  | }; | 
|  | void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit, | 
|  | struct mmp_param_fixed_rate_clk *clks, | 
|  | int size); | 
|  |  | 
|  | struct mmp_param_fixed_factor_clk { | 
|  | unsigned int id; | 
|  | char *name; | 
|  | const char *parent_name; | 
|  | unsigned long mult; | 
|  | unsigned long div; | 
|  | unsigned long flags; | 
|  | }; | 
|  | void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit, | 
|  | struct mmp_param_fixed_factor_clk *clks, | 
|  | int size); | 
|  |  | 
|  | struct mmp_param_general_gate_clk { | 
|  | unsigned int id; | 
|  | const char *name; | 
|  | const char *parent_name; | 
|  | unsigned long flags; | 
|  | unsigned long offset; | 
|  | u8 bit_idx; | 
|  | u8 gate_flags; | 
|  | spinlock_t *lock; | 
|  | }; | 
|  | void mmp_register_general_gate_clks(struct mmp_clk_unit *unit, | 
|  | struct mmp_param_general_gate_clk *clks, | 
|  | void __iomem *base, int size); | 
|  |  | 
|  | struct mmp_param_gate_clk { | 
|  | unsigned int id; | 
|  | char *name; | 
|  | const char *parent_name; | 
|  | unsigned long flags; | 
|  | unsigned long offset; | 
|  | u32 mask; | 
|  | u32 val_enable; | 
|  | u32 val_disable; | 
|  | unsigned int gate_flags; | 
|  | spinlock_t *lock; | 
|  | }; | 
|  | void mmp_register_gate_clks(struct mmp_clk_unit *unit, | 
|  | struct mmp_param_gate_clk *clks, | 
|  | void __iomem *base, int size); | 
|  |  | 
|  | struct mmp_param_mux_clk { | 
|  | unsigned int id; | 
|  | char *name; | 
|  | const char **parent_name; | 
|  | u8 num_parents; | 
|  | unsigned long flags; | 
|  | unsigned long offset; | 
|  | u8 shift; | 
|  | u8 width; | 
|  | u8 mux_flags; | 
|  | spinlock_t *lock; | 
|  | }; | 
|  | void mmp_register_mux_clks(struct mmp_clk_unit *unit, | 
|  | struct mmp_param_mux_clk *clks, | 
|  | void __iomem *base, int size); | 
|  |  | 
|  | struct mmp_param_div_clk { | 
|  | unsigned int id; | 
|  | char *name; | 
|  | const char *parent_name; | 
|  | unsigned long flags; | 
|  | unsigned long offset; | 
|  | u8 shift; | 
|  | u8 width; | 
|  | u8 div_flags; | 
|  | spinlock_t *lock; | 
|  | }; | 
|  | void mmp_register_div_clks(struct mmp_clk_unit *unit, | 
|  | struct mmp_param_div_clk *clks, | 
|  | void __iomem *base, int size); | 
|  |  | 
|  | #define DEFINE_MIX_REG_INFO(w_d, s_d, w_m, s_m, fc)	\ | 
|  | {							\ | 
|  | .width_div = (w_d),				\ | 
|  | .shift_div = (s_d),				\ | 
|  | .width_mux = (w_m),				\ | 
|  | .shift_mux = (s_m),				\ | 
|  | .bit_fc = (fc),					\ | 
|  | } | 
|  |  | 
|  | void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, | 
|  | int nr_clks); | 
|  | void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id, | 
|  | struct clk *clk); | 
|  | #endif |