xref: /linux/drivers/clk/mediatek/clk-mtk.h (revision e9862118)
19741b1a6SJames Liao /*
29741b1a6SJames Liao  * Copyright (c) 2014 MediaTek Inc.
39741b1a6SJames Liao  * Author: James Liao <jamesjj.liao@mediatek.com>
49741b1a6SJames Liao  *
59741b1a6SJames Liao  * This program is free software; you can redistribute it and/or modify
69741b1a6SJames Liao  * it under the terms of the GNU General Public License version 2 as
79741b1a6SJames Liao  * published by the Free Software Foundation.
89741b1a6SJames Liao  *
99741b1a6SJames Liao  * This program is distributed in the hope that it will be useful,
109741b1a6SJames Liao  * but WITHOUT ANY WARRANTY; without even the implied warranty of
119741b1a6SJames Liao  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
129741b1a6SJames Liao  * GNU General Public License for more details.
139741b1a6SJames Liao  */
149741b1a6SJames Liao 
159741b1a6SJames Liao #ifndef __DRV_CLK_MTK_H
169741b1a6SJames Liao #define __DRV_CLK_MTK_H
179741b1a6SJames Liao 
189741b1a6SJames Liao #include <linux/regmap.h>
199741b1a6SJames Liao #include <linux/bitops.h>
209741b1a6SJames Liao #include <linux/clk-provider.h>
219741b1a6SJames Liao 
22c726639bSStephen Boyd struct clk;
23c726639bSStephen Boyd 
249741b1a6SJames Liao #define MAX_MUX_GATE_BIT	31
259741b1a6SJames Liao #define INVALID_MUX_GATE_BIT	(MAX_MUX_GATE_BIT + 1)
269741b1a6SJames Liao 
279741b1a6SJames Liao #define MHZ (1000 * 1000)
289741b1a6SJames Liao 
294fa04380SJames Liao struct mtk_fixed_clk {
304fa04380SJames Liao 	int id;
314fa04380SJames Liao 	const char *name;
324fa04380SJames Liao 	const char *parent;
334fa04380SJames Liao 	unsigned long rate;
344fa04380SJames Liao };
354fa04380SJames Liao 
364fa04380SJames Liao #define FIXED_CLK(_id, _name, _parent, _rate) {		\
374fa04380SJames Liao 		.id = _id,				\
384fa04380SJames Liao 		.name = _name,				\
394fa04380SJames Liao 		.parent = _parent,			\
404fa04380SJames Liao 		.rate = _rate,				\
414fa04380SJames Liao 	}
424fa04380SJames Liao 
434fa04380SJames Liao void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
444fa04380SJames Liao 		int num, struct clk_onecell_data *clk_data);
454fa04380SJames Liao 
469741b1a6SJames Liao struct mtk_fixed_factor {
479741b1a6SJames Liao 	int id;
489741b1a6SJames Liao 	const char *name;
499741b1a6SJames Liao 	const char *parent_name;
509741b1a6SJames Liao 	int mult;
519741b1a6SJames Liao 	int div;
529741b1a6SJames Liao };
539741b1a6SJames Liao 
549741b1a6SJames Liao #define FACTOR(_id, _name, _parent, _mult, _div) {	\
559741b1a6SJames Liao 		.id = _id,				\
569741b1a6SJames Liao 		.name = _name,				\
579741b1a6SJames Liao 		.parent_name = _parent,			\
589741b1a6SJames Liao 		.mult = _mult,				\
599741b1a6SJames Liao 		.div = _div,				\
609741b1a6SJames Liao 	}
619741b1a6SJames Liao 
6207d13069SJames Liao void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
639741b1a6SJames Liao 		int num, struct clk_onecell_data *clk_data);
649741b1a6SJames Liao 
659741b1a6SJames Liao struct mtk_composite {
669741b1a6SJames Liao 	int id;
679741b1a6SJames Liao 	const char *name;
689741b1a6SJames Liao 	const char * const *parent_names;
699741b1a6SJames Liao 	const char *parent;
709741b1a6SJames Liao 	unsigned flags;
719741b1a6SJames Liao 
729741b1a6SJames Liao 	uint32_t mux_reg;
739741b1a6SJames Liao 	uint32_t divider_reg;
749741b1a6SJames Liao 	uint32_t gate_reg;
759741b1a6SJames Liao 
769741b1a6SJames Liao 	signed char mux_shift;
779741b1a6SJames Liao 	signed char mux_width;
789741b1a6SJames Liao 	signed char gate_shift;
799741b1a6SJames Liao 
809741b1a6SJames Liao 	signed char divider_shift;
819741b1a6SJames Liao 	signed char divider_width;
829741b1a6SJames Liao 
839741b1a6SJames Liao 	signed char num_parents;
849741b1a6SJames Liao };
859741b1a6SJames Liao 
8606445994SPhilipp Zabel /*
8706445994SPhilipp Zabel  * In case the rate change propagation to parent clocks is undesirable,
8806445994SPhilipp Zabel  * this macro allows to specify the clock flags manually.
8906445994SPhilipp Zabel  */
90*e9862118SShunli Wang #define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,	\
91*e9862118SShunli Wang 			_gate, _flags) {				\
929741b1a6SJames Liao 		.id = _id,						\
939741b1a6SJames Liao 		.name = _name,						\
949741b1a6SJames Liao 		.mux_reg = _reg,					\
959741b1a6SJames Liao 		.mux_shift = _shift,					\
969741b1a6SJames Liao 		.mux_width = _width,					\
979741b1a6SJames Liao 		.gate_reg = _reg,					\
989741b1a6SJames Liao 		.gate_shift = _gate,					\
999741b1a6SJames Liao 		.divider_shift = -1,					\
1009741b1a6SJames Liao 		.parent_names = _parents,				\
1019741b1a6SJames Liao 		.num_parents = ARRAY_SIZE(_parents),			\
10206445994SPhilipp Zabel 		.flags = _flags,					\
1039741b1a6SJames Liao 	}
1049741b1a6SJames Liao 
10506445994SPhilipp Zabel /*
10606445994SPhilipp Zabel  * Unless necessary, all MUX_GATE clocks propagate rate changes to their
10706445994SPhilipp Zabel  * parent clock by default.
10806445994SPhilipp Zabel  */
10906445994SPhilipp Zabel #define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate)	\
110*e9862118SShunli Wang 	MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,	\
111*e9862118SShunli Wang 		_gate, CLK_SET_RATE_PARENT)
11206445994SPhilipp Zabel 
1139741b1a6SJames Liao #define MUX(_id, _name, _parents, _reg, _shift, _width) {		\
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_shift = -1,					\
1209741b1a6SJames Liao 		.divider_shift = -1,					\
1219741b1a6SJames Liao 		.parent_names = _parents,				\
1229741b1a6SJames Liao 		.num_parents = ARRAY_SIZE(_parents),			\
1239741b1a6SJames Liao 		.flags = CLK_SET_RATE_PARENT,				\
1249741b1a6SJames Liao 	}
1259741b1a6SJames Liao 
126*e9862118SShunli Wang #define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg,	\
127*e9862118SShunli Wang 					_div_width, _div_shift) {	\
1289741b1a6SJames Liao 		.id = _id,						\
1299741b1a6SJames Liao 		.parent = _parent,					\
1309741b1a6SJames Liao 		.name = _name,						\
1319741b1a6SJames Liao 		.divider_reg = _div_reg,				\
1329741b1a6SJames Liao 		.divider_shift = _div_shift,				\
1339741b1a6SJames Liao 		.divider_width = _div_width,				\
1349741b1a6SJames Liao 		.gate_reg = _gate_reg,					\
1359741b1a6SJames Liao 		.gate_shift = _gate_shift,				\
1369741b1a6SJames Liao 		.mux_shift = -1,					\
1379741b1a6SJames Liao 		.flags = 0,						\
1389741b1a6SJames Liao 	}
1399741b1a6SJames Liao 
1409741b1a6SJames Liao struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
1419741b1a6SJames Liao 		void __iomem *base, spinlock_t *lock);
1429741b1a6SJames Liao 
1439741b1a6SJames Liao void mtk_clk_register_composites(const struct mtk_composite *mcs,
1449741b1a6SJames Liao 		int num, void __iomem *base, spinlock_t *lock,
1459741b1a6SJames Liao 		struct clk_onecell_data *clk_data);
1469741b1a6SJames Liao 
1479741b1a6SJames Liao struct mtk_gate_regs {
1489741b1a6SJames Liao 	u32 sta_ofs;
1499741b1a6SJames Liao 	u32 clr_ofs;
1509741b1a6SJames Liao 	u32 set_ofs;
1519741b1a6SJames Liao };
1529741b1a6SJames Liao 
1539741b1a6SJames Liao struct mtk_gate {
1549741b1a6SJames Liao 	int id;
1559741b1a6SJames Liao 	const char *name;
1569741b1a6SJames Liao 	const char *parent_name;
1579741b1a6SJames Liao 	const struct mtk_gate_regs *regs;
1589741b1a6SJames Liao 	int shift;
1599741b1a6SJames Liao 	const struct clk_ops *ops;
1609741b1a6SJames Liao };
1619741b1a6SJames Liao 
162*e9862118SShunli Wang int mtk_clk_register_gates(struct device_node *node,
163*e9862118SShunli Wang 			const struct mtk_gate *clks, int num,
164*e9862118SShunli Wang 			struct clk_onecell_data *clk_data);
165*e9862118SShunli Wang 
166*e9862118SShunli Wang struct mtk_clk_divider {
167*e9862118SShunli Wang 	int id;
168*e9862118SShunli Wang 	const char *name;
169*e9862118SShunli Wang 	const char *parent_name;
170*e9862118SShunli Wang 	unsigned long flags;
171*e9862118SShunli Wang 
172*e9862118SShunli Wang 	u32 div_reg;
173*e9862118SShunli Wang 	unsigned char div_shift;
174*e9862118SShunli Wang 	unsigned char div_width;
175*e9862118SShunli Wang 	unsigned char clk_divider_flags;
176*e9862118SShunli Wang 	const struct clk_div_table *clk_div_table;
177*e9862118SShunli Wang };
178*e9862118SShunli Wang 
179*e9862118SShunli Wang #define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) {	\
180*e9862118SShunli Wang 		.id = _id,					\
181*e9862118SShunli Wang 		.name = _name,					\
182*e9862118SShunli Wang 		.parent_name = _parent,				\
183*e9862118SShunli Wang 		.div_reg = _reg,				\
184*e9862118SShunli Wang 		.div_shift = _shift,				\
185*e9862118SShunli Wang 		.div_width = _width,				\
186*e9862118SShunli Wang }
187*e9862118SShunli Wang 
188*e9862118SShunli Wang void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
189*e9862118SShunli Wang 			int num, void __iomem *base, spinlock_t *lock,
190*e9862118SShunli Wang 				struct clk_onecell_data *clk_data);
1919741b1a6SJames Liao 
1929741b1a6SJames Liao struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
1939741b1a6SJames Liao 
1949741b1a6SJames Liao #define HAVE_RST_BAR	BIT(0)
195*e9862118SShunli Wang #define PLL_AO		BIT(1)
1969741b1a6SJames Liao 
19775ce0cdbSJames Liao struct mtk_pll_div_table {
19875ce0cdbSJames Liao 	u32 div;
19975ce0cdbSJames Liao 	unsigned long freq;
20075ce0cdbSJames Liao };
20175ce0cdbSJames Liao 
2029741b1a6SJames Liao struct mtk_pll_data {
2039741b1a6SJames Liao 	int id;
2049741b1a6SJames Liao 	const char *name;
2059741b1a6SJames Liao 	uint32_t reg;
2069741b1a6SJames Liao 	uint32_t pwr_reg;
2079741b1a6SJames Liao 	uint32_t en_mask;
2089741b1a6SJames Liao 	uint32_t pd_reg;
2099741b1a6SJames Liao 	uint32_t tuner_reg;
2109741b1a6SJames Liao 	int pd_shift;
2119741b1a6SJames Liao 	unsigned int flags;
2129741b1a6SJames Liao 	const struct clk_ops *ops;
2139741b1a6SJames Liao 	u32 rst_bar_mask;
2149741b1a6SJames Liao 	unsigned long fmax;
2159741b1a6SJames Liao 	int pcwbits;
2169741b1a6SJames Liao 	uint32_t pcw_reg;
2179741b1a6SJames Liao 	int pcw_shift;
21875ce0cdbSJames Liao 	const struct mtk_pll_div_table *div_table;
2199741b1a6SJames Liao };
2209741b1a6SJames Liao 
22107d13069SJames Liao void mtk_clk_register_plls(struct device_node *node,
2229741b1a6SJames Liao 		const struct mtk_pll_data *plls, int num_plls,
2239741b1a6SJames Liao 		struct clk_onecell_data *clk_data);
2249741b1a6SJames Liao 
225cdb2bab7SJames Liao struct clk *mtk_clk_register_ref2usb_tx(const char *name,
226cdb2bab7SJames Liao 			const char *parent_name, void __iomem *reg);
227cdb2bab7SJames Liao 
228d633fb7aSSascha Hauer #ifdef CONFIG_RESET_CONTROLLER
229d633fb7aSSascha Hauer void mtk_register_reset_controller(struct device_node *np,
230d633fb7aSSascha Hauer 			unsigned int num_regs, int regofs);
231d633fb7aSSascha Hauer #else
232d633fb7aSSascha Hauer static inline void mtk_register_reset_controller(struct device_node *np,
233d633fb7aSSascha Hauer 			unsigned int num_regs, int regofs)
234d633fb7aSSascha Hauer {
235d633fb7aSSascha Hauer }
236d633fb7aSSascha Hauer #endif
237d633fb7aSSascha Hauer 
2389741b1a6SJames Liao #endif /* __DRV_CLK_MTK_H */
239