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