xref: /linux/drivers/clk/mediatek/clk-mtk.h (revision 878e845d)
11802d0beSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
29741b1a6SJames Liao /*
39741b1a6SJames Liao  * Copyright (c) 2014 MediaTek Inc.
49741b1a6SJames Liao  * Author: James Liao <jamesjj.liao@mediatek.com>
59741b1a6SJames Liao  */
69741b1a6SJames Liao 
79741b1a6SJames Liao #ifndef __DRV_CLK_MTK_H
89741b1a6SJames Liao #define __DRV_CLK_MTK_H
99741b1a6SJames Liao 
109741b1a6SJames Liao #include <linux/clk-provider.h>
11c42a2888SChen-Yu Tsai #include <linux/io.h>
12c42a2888SChen-Yu Tsai #include <linux/kernel.h>
13c42a2888SChen-Yu Tsai #include <linux/spinlock.h>
14c42a2888SChen-Yu Tsai #include <linux/types.h>
15c726639bSStephen Boyd 
16b348c26cSRex-BC Chen #include "reset.h"
17b348c26cSRex-BC Chen 
189741b1a6SJames Liao #define MAX_MUX_GATE_BIT	31
199741b1a6SJames Liao #define INVALID_MUX_GATE_BIT	(MAX_MUX_GATE_BIT + 1)
209741b1a6SJames Liao 
219741b1a6SJames Liao #define MHZ (1000 * 1000)
229741b1a6SJames Liao 
23c42a2888SChen-Yu Tsai struct platform_device;
24c42a2888SChen-Yu Tsai 
25b8eb1081SAngeloGioacchino Del Regno /*
26b8eb1081SAngeloGioacchino Del Regno  * We need the clock IDs to start from zero but to maintain devicetree
27b8eb1081SAngeloGioacchino Del Regno  * backwards compatibility we can't change bindings to start from zero.
28b8eb1081SAngeloGioacchino Del Regno  * Only a few platforms are affected, so we solve issues given by the
29b8eb1081SAngeloGioacchino Del Regno  * commonized MTK clocks probe function(s) by adding a dummy clock at
30b8eb1081SAngeloGioacchino Del Regno  * the beginning where needed.
31b8eb1081SAngeloGioacchino Del Regno  */
32b8eb1081SAngeloGioacchino Del Regno #define CLK_DUMMY		0
33b8eb1081SAngeloGioacchino Del Regno 
34b8eb1081SAngeloGioacchino Del Regno extern const struct clk_ops mtk_clk_dummy_ops;
35b8eb1081SAngeloGioacchino Del Regno extern const struct mtk_gate_regs cg_regs_dummy;
36b8eb1081SAngeloGioacchino Del Regno 
37b8eb1081SAngeloGioacchino Del Regno #define GATE_DUMMY(_id, _name) {				\
38b8eb1081SAngeloGioacchino Del Regno 		.id = _id,					\
39b8eb1081SAngeloGioacchino Del Regno 		.name = _name,					\
40b8eb1081SAngeloGioacchino Del Regno 		.regs = &cg_regs_dummy,				\
41b8eb1081SAngeloGioacchino Del Regno 		.ops = &mtk_clk_dummy_ops,			\
42b8eb1081SAngeloGioacchino Del Regno 	}
43b8eb1081SAngeloGioacchino Del Regno 
444fa04380SJames Liao struct mtk_fixed_clk {
454fa04380SJames Liao 	int id;
464fa04380SJames Liao 	const char *name;
474fa04380SJames Liao 	const char *parent;
484fa04380SJames Liao 	unsigned long rate;
494fa04380SJames Liao };
504fa04380SJames Liao 
514fa04380SJames Liao #define FIXED_CLK(_id, _name, _parent, _rate) {		\
524fa04380SJames Liao 		.id = _id,				\
534fa04380SJames Liao 		.name = _name,				\
544fa04380SJames Liao 		.parent = _parent,			\
554fa04380SJames Liao 		.rate = _rate,				\
564fa04380SJames Liao 	}
574fa04380SJames Liao 
583c3ba2abSChen-Yu Tsai int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num,
59609cc5e1SChen-Yu Tsai 				struct clk_hw_onecell_data *clk_data);
6034c9d454SChen-Yu Tsai void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num,
61609cc5e1SChen-Yu Tsai 				   struct clk_hw_onecell_data *clk_data);
624fa04380SJames Liao 
639741b1a6SJames Liao struct mtk_fixed_factor {
649741b1a6SJames Liao 	int id;
659741b1a6SJames Liao 	const char *name;
669741b1a6SJames Liao 	const char *parent_name;
679741b1a6SJames Liao 	int mult;
689741b1a6SJames Liao 	int div;
69672c779eSAngeloGioacchino Del Regno 	unsigned long flags;
709741b1a6SJames Liao };
719741b1a6SJames Liao 
72672c779eSAngeloGioacchino Del Regno #define FACTOR_FLAGS(_id, _name, _parent, _mult, _div, _fl) {	\
739741b1a6SJames Liao 		.id = _id,				\
749741b1a6SJames Liao 		.name = _name,				\
759741b1a6SJames Liao 		.parent_name = _parent,			\
769741b1a6SJames Liao 		.mult = _mult,				\
779741b1a6SJames Liao 		.div = _div,				\
78672c779eSAngeloGioacchino Del Regno 		.flags = _fl,				\
799741b1a6SJames Liao 	}
809741b1a6SJames Liao 
81672c779eSAngeloGioacchino Del Regno #define FACTOR(_id, _name, _parent, _mult, _div)	\
82672c779eSAngeloGioacchino Del Regno 	FACTOR_FLAGS(_id, _name, _parent, _mult, _div, CLK_SET_RATE_PARENT)
83672c779eSAngeloGioacchino Del Regno 
843c3ba2abSChen-Yu Tsai int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
85609cc5e1SChen-Yu Tsai 			     struct clk_hw_onecell_data *clk_data);
861c6d6b69SChen-Yu Tsai void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num,
87609cc5e1SChen-Yu Tsai 				struct clk_hw_onecell_data *clk_data);
889741b1a6SJames Liao 
899741b1a6SJames Liao struct mtk_composite {
909741b1a6SJames Liao 	int id;
919741b1a6SJames Liao 	const char *name;
929741b1a6SJames Liao 	const char * const *parent_names;
939741b1a6SJames Liao 	const char *parent;
949741b1a6SJames Liao 	unsigned flags;
959741b1a6SJames Liao 
969741b1a6SJames Liao 	uint32_t mux_reg;
979741b1a6SJames Liao 	uint32_t divider_reg;
989741b1a6SJames Liao 	uint32_t gate_reg;
999741b1a6SJames Liao 
1009741b1a6SJames Liao 	signed char mux_shift;
1019741b1a6SJames Liao 	signed char mux_width;
1029741b1a6SJames Liao 	signed char gate_shift;
1039741b1a6SJames Liao 
1049741b1a6SJames Liao 	signed char divider_shift;
1059741b1a6SJames Liao 	signed char divider_width;
1069741b1a6SJames Liao 
107b026a7ecSchunhui dai 	u8 mux_flags;
108b026a7ecSchunhui dai 
1099741b1a6SJames Liao 	signed char num_parents;
1109741b1a6SJames Liao };
1119741b1a6SJames Liao 
112b026a7ecSchunhui dai #define MUX_GATE_FLAGS_2(_id, _name, _parents, _reg, _shift,		\
113b026a7ecSchunhui dai 				_width, _gate, _flags, _muxflags) {	\
1149741b1a6SJames Liao 		.id = _id,						\
1159741b1a6SJames Liao 		.name = _name,						\
1169741b1a6SJames Liao 		.mux_reg = _reg,					\
1179741b1a6SJames Liao 		.mux_shift = _shift,					\
1189741b1a6SJames Liao 		.mux_width = _width,					\
1199741b1a6SJames Liao 		.gate_reg = _reg,					\
1209741b1a6SJames Liao 		.gate_shift = _gate,					\
1219741b1a6SJames Liao 		.divider_shift = -1,					\
1229741b1a6SJames Liao 		.parent_names = _parents,				\
1239741b1a6SJames Liao 		.num_parents = ARRAY_SIZE(_parents),			\
12406445994SPhilipp Zabel 		.flags = _flags,					\
125b026a7ecSchunhui dai 		.mux_flags = _muxflags,					\
1269741b1a6SJames Liao 	}
1279741b1a6SJames Liao 
12806445994SPhilipp Zabel /*
129b026a7ecSchunhui dai  * In case the rate change propagation to parent clocks is undesirable,
130b026a7ecSchunhui dai  * this macro allows to specify the clock flags manually.
131b026a7ecSchunhui dai  */
132b026a7ecSchunhui dai #define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,	\
133b026a7ecSchunhui dai 			_gate, _flags)					\
134b026a7ecSchunhui dai 		MUX_GATE_FLAGS_2(_id, _name, _parents, _reg,		\
135b026a7ecSchunhui dai 					_shift, _width, _gate, _flags, 0)
136b026a7ecSchunhui dai 
137b026a7ecSchunhui dai /*
13806445994SPhilipp Zabel  * Unless necessary, all MUX_GATE clocks propagate rate changes to their
13906445994SPhilipp Zabel  * parent clock by default.
14006445994SPhilipp Zabel  */
14106445994SPhilipp Zabel #define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate)	\
142e9862118SShunli Wang 	MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,	\
143e9862118SShunli Wang 		_gate, CLK_SET_RATE_PARENT)
14406445994SPhilipp Zabel 
14503c4fda6SJasper Mattsson #define MUX(_id, _name, _parents, _reg, _shift, _width)			\
14603c4fda6SJasper Mattsson 	MUX_FLAGS(_id, _name, _parents, _reg,				\
14703c4fda6SJasper Mattsson 		  _shift, _width, CLK_SET_RATE_PARENT)
14803c4fda6SJasper Mattsson 
14903c4fda6SJasper Mattsson #define MUX_FLAGS(_id, _name, _parents, _reg, _shift, _width, _flags) {	\
1509741b1a6SJames Liao 		.id = _id,						\
1519741b1a6SJames Liao 		.name = _name,						\
1529741b1a6SJames Liao 		.mux_reg = _reg,					\
1539741b1a6SJames Liao 		.mux_shift = _shift,					\
1549741b1a6SJames Liao 		.mux_width = _width,					\
1559741b1a6SJames Liao 		.gate_shift = -1,					\
1569741b1a6SJames Liao 		.divider_shift = -1,					\
1579741b1a6SJames Liao 		.parent_names = _parents,				\
1589741b1a6SJames Liao 		.num_parents = ARRAY_SIZE(_parents),			\
15903c4fda6SJasper Mattsson 		.flags = _flags,				\
1609741b1a6SJames Liao 	}
1619741b1a6SJames Liao 
162e9862118SShunli Wang #define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg,	\
163e9862118SShunli Wang 					_div_width, _div_shift) {	\
1649741b1a6SJames Liao 		.id = _id,						\
1659741b1a6SJames Liao 		.parent = _parent,					\
1669741b1a6SJames Liao 		.name = _name,						\
1679741b1a6SJames Liao 		.divider_reg = _div_reg,				\
1689741b1a6SJames Liao 		.divider_shift = _div_shift,				\
1699741b1a6SJames Liao 		.divider_width = _div_width,				\
1709741b1a6SJames Liao 		.gate_reg = _gate_reg,					\
1719741b1a6SJames Liao 		.gate_shift = _gate_shift,				\
1729741b1a6SJames Liao 		.mux_shift = -1,					\
1739741b1a6SJames Liao 		.flags = 0,						\
1749741b1a6SJames Liao 	}
1759741b1a6SJames Liao 
17601a6c1abSAngeloGioacchino Del Regno int mtk_clk_register_composites(struct device *dev,
17701a6c1abSAngeloGioacchino Del Regno 				const struct mtk_composite *mcs, int num,
1783c3ba2abSChen-Yu Tsai 				void __iomem *base, spinlock_t *lock,
179609cc5e1SChen-Yu Tsai 				struct clk_hw_onecell_data *clk_data);
180cb50864fSChen-Yu Tsai void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num,
181609cc5e1SChen-Yu Tsai 				   struct clk_hw_onecell_data *clk_data);
1829741b1a6SJames Liao 
183e9862118SShunli Wang struct mtk_clk_divider {
184e9862118SShunli Wang 	int id;
185e9862118SShunli Wang 	const char *name;
186e9862118SShunli Wang 	const char *parent_name;
187e9862118SShunli Wang 	unsigned long flags;
188e9862118SShunli Wang 
189e9862118SShunli Wang 	u32 div_reg;
190e9862118SShunli Wang 	unsigned char div_shift;
191e9862118SShunli Wang 	unsigned char div_width;
192e9862118SShunli Wang 	unsigned char clk_divider_flags;
193e9862118SShunli Wang 	const struct clk_div_table *clk_div_table;
194e9862118SShunli Wang };
195e9862118SShunli Wang 
196e9862118SShunli Wang #define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) {	\
197e9862118SShunli Wang 		.id = _id,					\
198e9862118SShunli Wang 		.name = _name,					\
199e9862118SShunli Wang 		.parent_name = _parent,				\
200e9862118SShunli Wang 		.div_reg = _reg,				\
201e9862118SShunli Wang 		.div_shift = _shift,				\
202e9862118SShunli Wang 		.div_width = _width,				\
203e9862118SShunli Wang }
204e9862118SShunli Wang 
2056b7daeaaSAngeloGioacchino Del Regno int mtk_clk_register_dividers(struct device *dev,
2066b7daeaaSAngeloGioacchino Del Regno 			      const struct mtk_clk_divider *mcds, int num,
207b87385ebSChen-Yu Tsai 			      void __iomem *base, spinlock_t *lock,
208609cc5e1SChen-Yu Tsai 			      struct clk_hw_onecell_data *clk_data);
209b87385ebSChen-Yu Tsai void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num,
210609cc5e1SChen-Yu Tsai 				 struct clk_hw_onecell_data *clk_data);
2119741b1a6SJames Liao 
212609cc5e1SChen-Yu Tsai struct clk_hw_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
21350e68b99SMarkus Schneider-Pargmann struct clk_hw_onecell_data *mtk_devm_alloc_clk_data(struct device *dev,
21450e68b99SMarkus Schneider-Pargmann 						    unsigned int clk_num);
215609cc5e1SChen-Yu Tsai void mtk_free_clk_data(struct clk_hw_onecell_data *clk_data);
2169741b1a6SJames Liao 
2176f691a58SChen-Yu Tsai struct clk_hw *mtk_clk_register_ref2usb_tx(const char *name,
218cdb2bab7SJames Liao 			const char *parent_name, void __iomem *reg);
219b7520e2dSAngeloGioacchino Del Regno void mtk_clk_unregister_ref2usb_tx(struct clk_hw *hw);
220cdb2bab7SJames Liao 
221c58cd0e4SChun-Jie Chen struct mtk_clk_desc {
222c58cd0e4SChun-Jie Chen 	const struct mtk_gate *clks;
223c58cd0e4SChun-Jie Chen 	size_t num_clks;
2247b618310SAngeloGioacchino Del Regno 	const struct mtk_composite *composite_clks;
2257b618310SAngeloGioacchino Del Regno 	size_t num_composite_clks;
2261fe074b1SAngeloGioacchino Del Regno 	const struct mtk_clk_divider *divider_clks;
2271fe074b1SAngeloGioacchino Del Regno 	size_t num_divider_clks;
2287b618310SAngeloGioacchino Del Regno 	const struct mtk_fixed_clk *fixed_clks;
2297b618310SAngeloGioacchino Del Regno 	size_t num_fixed_clks;
2307b618310SAngeloGioacchino Del Regno 	const struct mtk_fixed_factor *factor_clks;
2317b618310SAngeloGioacchino Del Regno 	size_t num_factor_clks;
2327b618310SAngeloGioacchino Del Regno 	const struct mtk_mux *mux_clks;
2337b618310SAngeloGioacchino Del Regno 	size_t num_mux_clks;
234b27a604aSRex-BC Chen 	const struct mtk_clk_rst_desc *rst_desc;
2357b618310SAngeloGioacchino Del Regno 	spinlock_t *clk_lock;
2367b618310SAngeloGioacchino Del Regno 	bool shared_io;
237fd9fe654SAngeloGioacchino Del Regno 
238fd9fe654SAngeloGioacchino Del Regno 	int (*clk_notifier_func)(struct device *dev, struct clk *clk);
239fd9fe654SAngeloGioacchino Del Regno 	unsigned int mfg_clk_idx;
240*878e845dSPin-yen Lin 
241*878e845dSPin-yen Lin 	bool need_runtime_pm;
242c58cd0e4SChun-Jie Chen };
243c58cd0e4SChun-Jie Chen 
24425209124SAngeloGioacchino Del Regno int mtk_clk_pdev_probe(struct platform_device *pdev);
245b3bc7275SUwe Kleine-König void mtk_clk_pdev_remove(struct platform_device *pdev);
246c58cd0e4SChun-Jie Chen int mtk_clk_simple_probe(struct platform_device *pdev);
24761ca6ee7SUwe Kleine-König void mtk_clk_simple_remove(struct platform_device *pdev);
248c58cd0e4SChun-Jie Chen 
2499741b1a6SJames Liao #endif /* __DRV_CLK_MTK_H */
250