162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef __MACH_MMP_CLK_H 362306a36Sopenharmony_ci#define __MACH_MMP_CLK_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/clk-provider.h> 662306a36Sopenharmony_ci#include <linux/pm_domain.h> 762306a36Sopenharmony_ci#include <linux/clkdev.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#define APBC_NO_BUS_CTRL BIT(0) 1062306a36Sopenharmony_ci#define APBC_POWER_CTRL BIT(1) 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* Clock type "factor" */ 1462306a36Sopenharmony_cistruct mmp_clk_factor_masks { 1562306a36Sopenharmony_ci unsigned int factor; 1662306a36Sopenharmony_ci unsigned int num_mask; 1762306a36Sopenharmony_ci unsigned int den_mask; 1862306a36Sopenharmony_ci unsigned int num_shift; 1962306a36Sopenharmony_ci unsigned int den_shift; 2062306a36Sopenharmony_ci unsigned int enable_mask; 2162306a36Sopenharmony_ci}; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct mmp_clk_factor_tbl { 2462306a36Sopenharmony_ci unsigned int num; 2562306a36Sopenharmony_ci unsigned int den; 2662306a36Sopenharmony_ci}; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistruct mmp_clk_factor { 2962306a36Sopenharmony_ci struct clk_hw hw; 3062306a36Sopenharmony_ci void __iomem *base; 3162306a36Sopenharmony_ci struct mmp_clk_factor_masks *masks; 3262306a36Sopenharmony_ci struct mmp_clk_factor_tbl *ftbl; 3362306a36Sopenharmony_ci unsigned int ftbl_cnt; 3462306a36Sopenharmony_ci spinlock_t *lock; 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciextern struct clk *mmp_clk_register_factor(const char *name, 3862306a36Sopenharmony_ci const char *parent_name, unsigned long flags, 3962306a36Sopenharmony_ci void __iomem *base, struct mmp_clk_factor_masks *masks, 4062306a36Sopenharmony_ci struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt, 4162306a36Sopenharmony_ci spinlock_t *lock); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* Clock type "mix" */ 4462306a36Sopenharmony_ci#define MMP_CLK_BITS_MASK(width, shift) \ 4562306a36Sopenharmony_ci (((1 << (width)) - 1) << (shift)) 4662306a36Sopenharmony_ci#define MMP_CLK_BITS_GET_VAL(data, width, shift) \ 4762306a36Sopenharmony_ci ((data & MMP_CLK_BITS_MASK(width, shift)) >> (shift)) 4862306a36Sopenharmony_ci#define MMP_CLK_BITS_SET_VAL(val, width, shift) \ 4962306a36Sopenharmony_ci (((val) << (shift)) & MMP_CLK_BITS_MASK(width, shift)) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cienum { 5262306a36Sopenharmony_ci MMP_CLK_MIX_TYPE_V1, 5362306a36Sopenharmony_ci MMP_CLK_MIX_TYPE_V2, 5462306a36Sopenharmony_ci MMP_CLK_MIX_TYPE_V3, 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* The register layout */ 5862306a36Sopenharmony_cistruct mmp_clk_mix_reg_info { 5962306a36Sopenharmony_ci void __iomem *reg_clk_ctrl; 6062306a36Sopenharmony_ci void __iomem *reg_clk_sel; 6162306a36Sopenharmony_ci u8 width_div; 6262306a36Sopenharmony_ci u8 shift_div; 6362306a36Sopenharmony_ci u8 width_mux; 6462306a36Sopenharmony_ci u8 shift_mux; 6562306a36Sopenharmony_ci u8 bit_fc; 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* The suggested clock table from user. */ 6962306a36Sopenharmony_cistruct mmp_clk_mix_clk_table { 7062306a36Sopenharmony_ci unsigned long rate; 7162306a36Sopenharmony_ci u8 parent_index; 7262306a36Sopenharmony_ci unsigned int divisor; 7362306a36Sopenharmony_ci unsigned int valid; 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistruct mmp_clk_mix_config { 7762306a36Sopenharmony_ci struct mmp_clk_mix_reg_info reg_info; 7862306a36Sopenharmony_ci struct mmp_clk_mix_clk_table *table; 7962306a36Sopenharmony_ci unsigned int table_size; 8062306a36Sopenharmony_ci u32 *mux_table; 8162306a36Sopenharmony_ci struct clk_div_table *div_table; 8262306a36Sopenharmony_ci u8 div_flags; 8362306a36Sopenharmony_ci u8 mux_flags; 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistruct mmp_clk_mix { 8762306a36Sopenharmony_ci struct clk_hw hw; 8862306a36Sopenharmony_ci struct mmp_clk_mix_reg_info reg_info; 8962306a36Sopenharmony_ci struct mmp_clk_mix_clk_table *table; 9062306a36Sopenharmony_ci u32 *mux_table; 9162306a36Sopenharmony_ci struct clk_div_table *div_table; 9262306a36Sopenharmony_ci unsigned int table_size; 9362306a36Sopenharmony_ci u8 div_flags; 9462306a36Sopenharmony_ci u8 mux_flags; 9562306a36Sopenharmony_ci unsigned int type; 9662306a36Sopenharmony_ci spinlock_t *lock; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciextern const struct clk_ops mmp_clk_mix_ops; 10062306a36Sopenharmony_ciextern struct clk *mmp_clk_register_mix(struct device *dev, 10162306a36Sopenharmony_ci const char *name, 10262306a36Sopenharmony_ci const char * const *parent_names, 10362306a36Sopenharmony_ci u8 num_parents, 10462306a36Sopenharmony_ci unsigned long flags, 10562306a36Sopenharmony_ci struct mmp_clk_mix_config *config, 10662306a36Sopenharmony_ci spinlock_t *lock); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci/* Clock type "gate". MMP private gate */ 11062306a36Sopenharmony_ci#define MMP_CLK_GATE_NEED_DELAY BIT(0) 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistruct mmp_clk_gate { 11362306a36Sopenharmony_ci struct clk_hw hw; 11462306a36Sopenharmony_ci void __iomem *reg; 11562306a36Sopenharmony_ci u32 mask; 11662306a36Sopenharmony_ci u32 val_enable; 11762306a36Sopenharmony_ci u32 val_disable; 11862306a36Sopenharmony_ci unsigned int flags; 11962306a36Sopenharmony_ci spinlock_t *lock; 12062306a36Sopenharmony_ci}; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ciextern const struct clk_ops mmp_clk_gate_ops; 12362306a36Sopenharmony_ciextern struct clk *mmp_clk_register_gate(struct device *dev, const char *name, 12462306a36Sopenharmony_ci const char *parent_name, unsigned long flags, 12562306a36Sopenharmony_ci void __iomem *reg, u32 mask, u32 val_enable, 12662306a36Sopenharmony_ci u32 val_disable, unsigned int gate_flags, 12762306a36Sopenharmony_ci spinlock_t *lock); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ciextern struct clk *mmp_clk_register_apbc(const char *name, 13062306a36Sopenharmony_ci const char *parent_name, void __iomem *base, 13162306a36Sopenharmony_ci unsigned int delay, unsigned int apbc_flags, spinlock_t *lock); 13262306a36Sopenharmony_ciextern struct clk *mmp_clk_register_apmu(const char *name, 13362306a36Sopenharmony_ci const char *parent_name, void __iomem *base, u32 enable_mask, 13462306a36Sopenharmony_ci spinlock_t *lock); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistruct mmp_clk_unit { 13762306a36Sopenharmony_ci unsigned int nr_clks; 13862306a36Sopenharmony_ci struct clk **clk_table; 13962306a36Sopenharmony_ci struct clk_onecell_data clk_data; 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistruct mmp_param_fixed_rate_clk { 14362306a36Sopenharmony_ci unsigned int id; 14462306a36Sopenharmony_ci char *name; 14562306a36Sopenharmony_ci const char *parent_name; 14662306a36Sopenharmony_ci unsigned long flags; 14762306a36Sopenharmony_ci unsigned long fixed_rate; 14862306a36Sopenharmony_ci}; 14962306a36Sopenharmony_civoid mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit, 15062306a36Sopenharmony_ci struct mmp_param_fixed_rate_clk *clks, 15162306a36Sopenharmony_ci int size); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistruct mmp_param_fixed_factor_clk { 15462306a36Sopenharmony_ci unsigned int id; 15562306a36Sopenharmony_ci char *name; 15662306a36Sopenharmony_ci const char *parent_name; 15762306a36Sopenharmony_ci unsigned long mult; 15862306a36Sopenharmony_ci unsigned long div; 15962306a36Sopenharmony_ci unsigned long flags; 16062306a36Sopenharmony_ci}; 16162306a36Sopenharmony_civoid mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit, 16262306a36Sopenharmony_ci struct mmp_param_fixed_factor_clk *clks, 16362306a36Sopenharmony_ci int size); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistruct mmp_param_general_gate_clk { 16662306a36Sopenharmony_ci unsigned int id; 16762306a36Sopenharmony_ci const char *name; 16862306a36Sopenharmony_ci const char *parent_name; 16962306a36Sopenharmony_ci unsigned long flags; 17062306a36Sopenharmony_ci unsigned long offset; 17162306a36Sopenharmony_ci u8 bit_idx; 17262306a36Sopenharmony_ci u8 gate_flags; 17362306a36Sopenharmony_ci spinlock_t *lock; 17462306a36Sopenharmony_ci}; 17562306a36Sopenharmony_civoid mmp_register_general_gate_clks(struct mmp_clk_unit *unit, 17662306a36Sopenharmony_ci struct mmp_param_general_gate_clk *clks, 17762306a36Sopenharmony_ci void __iomem *base, int size); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistruct mmp_param_gate_clk { 18062306a36Sopenharmony_ci unsigned int id; 18162306a36Sopenharmony_ci char *name; 18262306a36Sopenharmony_ci const char *parent_name; 18362306a36Sopenharmony_ci unsigned long flags; 18462306a36Sopenharmony_ci unsigned long offset; 18562306a36Sopenharmony_ci u32 mask; 18662306a36Sopenharmony_ci u32 val_enable; 18762306a36Sopenharmony_ci u32 val_disable; 18862306a36Sopenharmony_ci unsigned int gate_flags; 18962306a36Sopenharmony_ci spinlock_t *lock; 19062306a36Sopenharmony_ci}; 19162306a36Sopenharmony_civoid mmp_register_gate_clks(struct mmp_clk_unit *unit, 19262306a36Sopenharmony_ci struct mmp_param_gate_clk *clks, 19362306a36Sopenharmony_ci void __iomem *base, int size); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistruct mmp_param_mux_clk { 19662306a36Sopenharmony_ci unsigned int id; 19762306a36Sopenharmony_ci char *name; 19862306a36Sopenharmony_ci const char * const *parent_name; 19962306a36Sopenharmony_ci u8 num_parents; 20062306a36Sopenharmony_ci unsigned long flags; 20162306a36Sopenharmony_ci unsigned long offset; 20262306a36Sopenharmony_ci u8 shift; 20362306a36Sopenharmony_ci u8 width; 20462306a36Sopenharmony_ci u8 mux_flags; 20562306a36Sopenharmony_ci spinlock_t *lock; 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_civoid mmp_register_mux_clks(struct mmp_clk_unit *unit, 20862306a36Sopenharmony_ci struct mmp_param_mux_clk *clks, 20962306a36Sopenharmony_ci void __iomem *base, int size); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistruct mmp_param_div_clk { 21262306a36Sopenharmony_ci unsigned int id; 21362306a36Sopenharmony_ci char *name; 21462306a36Sopenharmony_ci const char *parent_name; 21562306a36Sopenharmony_ci unsigned long flags; 21662306a36Sopenharmony_ci unsigned long offset; 21762306a36Sopenharmony_ci u8 shift; 21862306a36Sopenharmony_ci u8 width; 21962306a36Sopenharmony_ci u8 div_flags; 22062306a36Sopenharmony_ci spinlock_t *lock; 22162306a36Sopenharmony_ci}; 22262306a36Sopenharmony_civoid mmp_register_div_clks(struct mmp_clk_unit *unit, 22362306a36Sopenharmony_ci struct mmp_param_div_clk *clks, 22462306a36Sopenharmony_ci void __iomem *base, int size); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistruct mmp_param_pll_clk { 22762306a36Sopenharmony_ci unsigned int id; 22862306a36Sopenharmony_ci char *name; 22962306a36Sopenharmony_ci unsigned long default_rate; 23062306a36Sopenharmony_ci unsigned long enable_offset; 23162306a36Sopenharmony_ci u32 enable; 23262306a36Sopenharmony_ci unsigned long offset; 23362306a36Sopenharmony_ci u8 shift; 23462306a36Sopenharmony_ci /* MMP3 specific: */ 23562306a36Sopenharmony_ci unsigned long input_rate; 23662306a36Sopenharmony_ci unsigned long postdiv_offset; 23762306a36Sopenharmony_ci unsigned long postdiv_shift; 23862306a36Sopenharmony_ci}; 23962306a36Sopenharmony_civoid mmp_register_pll_clks(struct mmp_clk_unit *unit, 24062306a36Sopenharmony_ci struct mmp_param_pll_clk *clks, 24162306a36Sopenharmony_ci void __iomem *base, int size); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci#define DEFINE_MIX_REG_INFO(w_d, s_d, w_m, s_m, fc) \ 24462306a36Sopenharmony_ci{ \ 24562306a36Sopenharmony_ci .width_div = (w_d), \ 24662306a36Sopenharmony_ci .shift_div = (s_d), \ 24762306a36Sopenharmony_ci .width_mux = (w_m), \ 24862306a36Sopenharmony_ci .shift_mux = (s_m), \ 24962306a36Sopenharmony_ci .bit_fc = (fc), \ 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_civoid mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, 25362306a36Sopenharmony_ci int nr_clks); 25462306a36Sopenharmony_civoid mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id, 25562306a36Sopenharmony_ci struct clk *clk); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci/* Power islands */ 25862306a36Sopenharmony_ci#define MMP_PM_DOMAIN_NO_DISABLE BIT(0) 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cistruct generic_pm_domain *mmp_pm_domain_register(const char *name, 26162306a36Sopenharmony_ci void __iomem *reg, 26262306a36Sopenharmony_ci u32 power_on, u32 reset, u32 clock_enable, 26362306a36Sopenharmony_ci unsigned int flags, spinlock_t *lock); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci#endif 266