xref: /netbsd-src/sys/arch/arm/sunxi/sunxi_ccu.h (revision f001abf4c1c042ccf378c1e0b9c9ebec18a12c73)
1*f001abf4Smacallan /* $NetBSD: sunxi_ccu.h,v 1.24 2024/09/16 23:37:13 macallan Exp $ */
2a07e90f3Sjmcneill 
3a07e90f3Sjmcneill /*-
4a07e90f3Sjmcneill  * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
5a07e90f3Sjmcneill  * All rights reserved.
6a07e90f3Sjmcneill  *
7a07e90f3Sjmcneill  * Redistribution and use in source and binary forms, with or without
8a07e90f3Sjmcneill  * modification, are permitted provided that the following conditions
9a07e90f3Sjmcneill  * are met:
10a07e90f3Sjmcneill  * 1. Redistributions of source code must retain the above copyright
11a07e90f3Sjmcneill  *    notice, this list of conditions and the following disclaimer.
12a07e90f3Sjmcneill  * 2. Redistributions in binary form must reproduce the above copyright
13a07e90f3Sjmcneill  *    notice, this list of conditions and the following disclaimer in the
14a07e90f3Sjmcneill  *    documentation and/or other materials provided with the distribution.
15a07e90f3Sjmcneill  *
16a07e90f3Sjmcneill  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17a07e90f3Sjmcneill  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18a07e90f3Sjmcneill  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19a07e90f3Sjmcneill  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20a07e90f3Sjmcneill  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21a07e90f3Sjmcneill  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22a07e90f3Sjmcneill  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23a07e90f3Sjmcneill  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24a07e90f3Sjmcneill  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25a07e90f3Sjmcneill  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26a07e90f3Sjmcneill  * SUCH DAMAGE.
27a07e90f3Sjmcneill  */
28a07e90f3Sjmcneill 
29a07e90f3Sjmcneill #ifndef _ARM_SUNXI_CCU_H
30a07e90f3Sjmcneill #define _ARM_SUNXI_CCU_H
31a07e90f3Sjmcneill 
32a07e90f3Sjmcneill #include <dev/clk/clk_backend.h>
33a07e90f3Sjmcneill 
34a07e90f3Sjmcneill struct sunxi_ccu_softc;
35a07e90f3Sjmcneill struct sunxi_ccu_clk;
36a07e90f3Sjmcneill struct sunxi_ccu_reset;
37a07e90f3Sjmcneill 
38a07e90f3Sjmcneill /*
39a07e90f3Sjmcneill  * Resets
40a07e90f3Sjmcneill  */
41a07e90f3Sjmcneill 
42a07e90f3Sjmcneill struct sunxi_ccu_reset {
43a07e90f3Sjmcneill 	bus_size_t	reg;
44a07e90f3Sjmcneill 	uint32_t	mask;
45a07e90f3Sjmcneill };
46a07e90f3Sjmcneill 
47a07e90f3Sjmcneill #define	SUNXI_CCU_RESET(_id, _reg, _bit)	\
48a07e90f3Sjmcneill 	[_id] = {				\
49a07e90f3Sjmcneill 		.reg = (_reg),			\
50a07e90f3Sjmcneill 		.mask = __BIT(_bit),		\
51a07e90f3Sjmcneill 	}
52a07e90f3Sjmcneill 
53a07e90f3Sjmcneill /*
54a07e90f3Sjmcneill  * Clocks
55a07e90f3Sjmcneill  */
56a07e90f3Sjmcneill 
57a07e90f3Sjmcneill enum sunxi_ccu_clktype {
58a07e90f3Sjmcneill 	SUNXI_CCU_UNKNOWN,
59a07e90f3Sjmcneill 	SUNXI_CCU_GATE,
60a07e90f3Sjmcneill 	SUNXI_CCU_NM,
6111d415cdSjmcneill 	SUNXI_CCU_NKMP,
6211d415cdSjmcneill 	SUNXI_CCU_PREDIV,
63ddb9dd9cSjmcneill 	SUNXI_CCU_DIV,
64deeed1ddSjmcneill 	SUNXI_CCU_PHASE,
65a5198ca0Sjmcneill 	SUNXI_CCU_FIXED_FACTOR,
66a1f84860Sbouyer 	SUNXI_CCU_FRACTIONAL,
67c26e3874Sjmcneill 	SUNXI_CCU_MUX,
68a07e90f3Sjmcneill };
69a07e90f3Sjmcneill 
70a07e90f3Sjmcneill struct sunxi_ccu_gate {
71a07e90f3Sjmcneill 	bus_size_t	reg;
72a07e90f3Sjmcneill 	uint32_t	mask;
73a07e90f3Sjmcneill 	const char	*parent;
74a07e90f3Sjmcneill };
75a07e90f3Sjmcneill 
76a07e90f3Sjmcneill int	sunxi_ccu_gate_enable(struct sunxi_ccu_softc *,
77a07e90f3Sjmcneill 			      struct sunxi_ccu_clk *, int);
78a07e90f3Sjmcneill const char *sunxi_ccu_gate_get_parent(struct sunxi_ccu_softc *,
79a07e90f3Sjmcneill 				      struct sunxi_ccu_clk *);
80a07e90f3Sjmcneill 
81a07e90f3Sjmcneill #define	SUNXI_CCU_GATE(_id, _name, _pname, _reg, _bit)		\
82a07e90f3Sjmcneill 	[_id] = {						\
83a07e90f3Sjmcneill 		.type = SUNXI_CCU_GATE,				\
84a07e90f3Sjmcneill 		.base.name = (_name),				\
85ecf61253Sjmcneill 		.base.flags = CLK_SET_RATE_PARENT,		\
86a07e90f3Sjmcneill 		.u.gate.parent = (_pname),			\
87a07e90f3Sjmcneill 		.u.gate.reg = (_reg),				\
88a07e90f3Sjmcneill 		.u.gate.mask = __BIT(_bit),			\
89a07e90f3Sjmcneill 		.enable = sunxi_ccu_gate_enable,		\
90a07e90f3Sjmcneill 		.get_parent = sunxi_ccu_gate_get_parent,	\
91a07e90f3Sjmcneill 	}
92a07e90f3Sjmcneill 
93ecf61253Sjmcneill struct sunxi_ccu_nkmp_tbl {
94ecf61253Sjmcneill 	u_int		rate;
95ecf61253Sjmcneill 	uint32_t	n;
96ecf61253Sjmcneill 	uint32_t	k;
97ecf61253Sjmcneill 	uint32_t	m;
98ecf61253Sjmcneill 	uint32_t	p;
99ecf61253Sjmcneill };
100ecf61253Sjmcneill 
10111d415cdSjmcneill struct sunxi_ccu_nkmp {
10211d415cdSjmcneill 	bus_size_t	reg;
10311d415cdSjmcneill 	const char	*parent;
10411d415cdSjmcneill 	uint32_t	n;
10511d415cdSjmcneill 	uint32_t	k;
10611d415cdSjmcneill 	uint32_t	m;
10711d415cdSjmcneill 	uint32_t	p;
10811d415cdSjmcneill 	uint32_t	lock;
10911d415cdSjmcneill 	uint32_t	enable;
11011d415cdSjmcneill 	uint32_t	flags;
111ecf61253Sjmcneill 	const struct sunxi_ccu_nkmp_tbl *table;
11268166010Sjmcneill #define	SUNXI_CCU_NKMP_DIVIDE_BY_TWO		__BIT(0)
1136685c529Sjmcneill #define	SUNXI_CCU_NKMP_FACTOR_N_EXACT		__BIT(1)
114b3e175fcSjmcneill #define	SUNXI_CCU_NKMP_SCALE_CLOCK		__BIT(2)
115b3e175fcSjmcneill #define	SUNXI_CCU_NKMP_FACTOR_P_POW2		__BIT(3)
1166dec99e3Sjmcneill #define	SUNXI_CCU_NKMP_FACTOR_N_ZERO_IS_ONE	__BIT(4)
1174681bc70Sjmcneill #define	SUNXI_CCU_NKMP_FACTOR_P_X4		__BIT(5)
11811d415cdSjmcneill };
11911d415cdSjmcneill 
12011d415cdSjmcneill int	sunxi_ccu_nkmp_enable(struct sunxi_ccu_softc *,
12111d415cdSjmcneill 			      struct sunxi_ccu_clk *, int);
12211d415cdSjmcneill u_int	sunxi_ccu_nkmp_get_rate(struct sunxi_ccu_softc *,
12311d415cdSjmcneill 				struct sunxi_ccu_clk *);
12411d415cdSjmcneill int	sunxi_ccu_nkmp_set_rate(struct sunxi_ccu_softc *,
12511d415cdSjmcneill 				struct sunxi_ccu_clk *, u_int);
12611d415cdSjmcneill const char *sunxi_ccu_nkmp_get_parent(struct sunxi_ccu_softc *,
12711d415cdSjmcneill 				      struct sunxi_ccu_clk *);
12811d415cdSjmcneill 
129ecf61253Sjmcneill #define	SUNXI_CCU_NKMP_TABLE(_id, _name, _parent, _reg, _n, _k, _m, \
130ecf61253Sjmcneill 		       _p, _enable, _lock, _tbl, _flags)	\
13111d415cdSjmcneill 	[_id] = {						\
13211d415cdSjmcneill 		.type = SUNXI_CCU_NKMP,				\
13311d415cdSjmcneill 		.base.name = (_name),				\
13411d415cdSjmcneill 		.u.nkmp.reg = (_reg),				\
13511d415cdSjmcneill 		.u.nkmp.parent = (_parent),			\
13611d415cdSjmcneill 		.u.nkmp.n = (_n),				\
13711d415cdSjmcneill 		.u.nkmp.k = (_k),				\
13811d415cdSjmcneill 		.u.nkmp.m = (_m),				\
13911d415cdSjmcneill 		.u.nkmp.p = (_p),				\
14011d415cdSjmcneill 		.u.nkmp.enable = (_enable),			\
14111d415cdSjmcneill 		.u.nkmp.flags = (_flags),			\
142ecf61253Sjmcneill 		.u.nkmp.lock = (_lock),				\
143ecf61253Sjmcneill 		.u.nkmp.table = (_tbl),				\
14411d415cdSjmcneill 		.enable = sunxi_ccu_nkmp_enable,		\
14511d415cdSjmcneill 		.get_rate = sunxi_ccu_nkmp_get_rate,		\
14611d415cdSjmcneill 		.set_rate = sunxi_ccu_nkmp_set_rate,		\
14711d415cdSjmcneill 		.get_parent = sunxi_ccu_nkmp_get_parent,	\
14811d415cdSjmcneill 	}
14911d415cdSjmcneill 
150ecf61253Sjmcneill #define	SUNXI_CCU_NKMP(_id, _name, _parent, _reg, _n, _k, _m,	\
151ecf61253Sjmcneill 		       _p, _enable, _flags)			\
152ecf61253Sjmcneill 	SUNXI_CCU_NKMP_TABLE(_id, _name, _parent, _reg, _n, _k, _m, \
153ecf61253Sjmcneill 			     _p, _enable, 0, NULL, _flags)
154ecf61253Sjmcneill 
155ecf61253Sjmcneill 
156a07e90f3Sjmcneill struct sunxi_ccu_nm {
157a07e90f3Sjmcneill 	bus_size_t	reg;
158a07e90f3Sjmcneill 	const char	**parents;
159a07e90f3Sjmcneill 	u_int		nparents;
160a07e90f3Sjmcneill 	uint32_t	n;
161a07e90f3Sjmcneill 	uint32_t	m;
162a07e90f3Sjmcneill 	uint32_t	sel;
16311d415cdSjmcneill 	uint32_t	enable;
164a07e90f3Sjmcneill 	uint32_t	flags;
165a07e90f3Sjmcneill #define	SUNXI_CCU_NM_POWER_OF_TWO	__BIT(0)
16611d415cdSjmcneill #define	SUNXI_CCU_NM_ROUND_DOWN		__BIT(1)
167c68d93beSjmcneill #define	SUNXI_CCU_NM_DIVIDE_BY_TWO	__BIT(2)
168a07e90f3Sjmcneill };
169a07e90f3Sjmcneill 
17011d415cdSjmcneill int	sunxi_ccu_nm_enable(struct sunxi_ccu_softc *,
17111d415cdSjmcneill 			    struct sunxi_ccu_clk *, int);
172a07e90f3Sjmcneill u_int	sunxi_ccu_nm_get_rate(struct sunxi_ccu_softc *,
173a07e90f3Sjmcneill 			      struct sunxi_ccu_clk *);
174a07e90f3Sjmcneill int	sunxi_ccu_nm_set_rate(struct sunxi_ccu_softc *,
175a07e90f3Sjmcneill 			      struct sunxi_ccu_clk *, u_int);
176a07e90f3Sjmcneill int	sunxi_ccu_nm_set_parent(struct sunxi_ccu_softc *,
177a07e90f3Sjmcneill 				struct sunxi_ccu_clk *,
178a07e90f3Sjmcneill 				const char *);
179a07e90f3Sjmcneill const char *sunxi_ccu_nm_get_parent(struct sunxi_ccu_softc *,
180a07e90f3Sjmcneill 				    struct sunxi_ccu_clk *);
181a07e90f3Sjmcneill 
182a07e90f3Sjmcneill #define	SUNXI_CCU_NM(_id, _name, _parents, _reg, _n, _m, _sel,	\
18311d415cdSjmcneill 		     _enable, _flags)				\
184a07e90f3Sjmcneill 	[_id] = {						\
185a07e90f3Sjmcneill 		.type = SUNXI_CCU_NM,				\
186a07e90f3Sjmcneill 		.base.name = (_name),				\
187a07e90f3Sjmcneill 		.u.nm.reg = (_reg),				\
188a07e90f3Sjmcneill 		.u.nm.parents = (_parents),			\
189a07e90f3Sjmcneill 		.u.nm.nparents = __arraycount(_parents),	\
190a07e90f3Sjmcneill 		.u.nm.n = (_n),					\
191a07e90f3Sjmcneill 		.u.nm.m = (_m),					\
192a07e90f3Sjmcneill 		.u.nm.sel = (_sel),				\
19311d415cdSjmcneill 		.u.nm.enable = (_enable),			\
194a07e90f3Sjmcneill 		.u.nm.flags = (_flags),				\
19511d415cdSjmcneill 		.enable = sunxi_ccu_nm_enable,			\
19611d415cdSjmcneill 		.get_rate = sunxi_ccu_nm_get_rate,		\
19711d415cdSjmcneill 		.set_rate = sunxi_ccu_nm_set_rate,		\
198a07e90f3Sjmcneill 		.set_parent = sunxi_ccu_nm_set_parent,		\
199a07e90f3Sjmcneill 		.get_parent = sunxi_ccu_nm_get_parent,		\
200a07e90f3Sjmcneill 	}
201a07e90f3Sjmcneill 
202ddb9dd9cSjmcneill struct sunxi_ccu_div {
203ddb9dd9cSjmcneill 	bus_size_t	reg;
204ddb9dd9cSjmcneill 	const char	**parents;
205ddb9dd9cSjmcneill 	u_int		nparents;
206ddb9dd9cSjmcneill 	uint32_t	div;
207ddb9dd9cSjmcneill 	uint32_t	sel;
208607cd651Sjmcneill 	uint32_t	enable;
209ddb9dd9cSjmcneill 	uint32_t	flags;
210ddb9dd9cSjmcneill #define	SUNXI_CCU_DIV_POWER_OF_TWO	__BIT(0)
211ddb9dd9cSjmcneill #define	SUNXI_CCU_DIV_ZERO_IS_ONE	__BIT(1)
212607cd651Sjmcneill #define	SUNXI_CCU_DIV_TIMES_TWO		__BIT(2)
213df83149aSjmcneill #define	SUNXI_CCU_DIV_SET_RATE_PARENT	__BIT(3)
214ddb9dd9cSjmcneill };
215ddb9dd9cSjmcneill 
216607cd651Sjmcneill int	sunxi_ccu_div_enable(struct sunxi_ccu_softc *,
217607cd651Sjmcneill 			     struct sunxi_ccu_clk *, int);
218ddb9dd9cSjmcneill u_int	sunxi_ccu_div_get_rate(struct sunxi_ccu_softc *,
219ddb9dd9cSjmcneill 			       struct sunxi_ccu_clk *);
220ddb9dd9cSjmcneill int	sunxi_ccu_div_set_rate(struct sunxi_ccu_softc *,
221ddb9dd9cSjmcneill 			       struct sunxi_ccu_clk *, u_int);
222ddb9dd9cSjmcneill int	sunxi_ccu_div_set_parent(struct sunxi_ccu_softc *,
223ddb9dd9cSjmcneill 			         struct sunxi_ccu_clk *,
224ddb9dd9cSjmcneill 			         const char *);
225ddb9dd9cSjmcneill const char *sunxi_ccu_div_get_parent(struct sunxi_ccu_softc *,
226ddb9dd9cSjmcneill 				     struct sunxi_ccu_clk *);
227ddb9dd9cSjmcneill 
228ddb9dd9cSjmcneill #define	SUNXI_CCU_DIV(_id, _name, _parents, _reg, _div,		\
229ddb9dd9cSjmcneill 		      _sel, _flags)				\
230607cd651Sjmcneill 	SUNXI_CCU_DIV_GATE(_id, _name, _parents, _reg, _div,	\
231607cd651Sjmcneill 			   _sel, 0, _flags)
232607cd651Sjmcneill 
233607cd651Sjmcneill #define	SUNXI_CCU_DIV_GATE(_id, _name, _parents, _reg, _div,	\
234607cd651Sjmcneill 		      _sel, _enable, _flags)			\
235ddb9dd9cSjmcneill 	[_id] = {						\
236ddb9dd9cSjmcneill 		.type = SUNXI_CCU_DIV,				\
237ddb9dd9cSjmcneill 		.base.name = (_name),				\
238ddb9dd9cSjmcneill 		.u.div.reg = (_reg),				\
239ddb9dd9cSjmcneill 		.u.div.parents = (_parents),			\
240ddb9dd9cSjmcneill 		.u.div.nparents = __arraycount(_parents),	\
241ddb9dd9cSjmcneill 		.u.div.div = (_div),				\
242ddb9dd9cSjmcneill 		.u.div.sel = (_sel),				\
243607cd651Sjmcneill 		.u.div.enable = (_enable),			\
244ddb9dd9cSjmcneill 		.u.div.flags = (_flags),			\
245607cd651Sjmcneill 		.enable = sunxi_ccu_div_enable,			\
246ddb9dd9cSjmcneill 		.get_rate = sunxi_ccu_div_get_rate,		\
247ddb9dd9cSjmcneill 		.set_rate = sunxi_ccu_div_set_rate,		\
248ddb9dd9cSjmcneill 		.set_parent = sunxi_ccu_div_set_parent,		\
249ddb9dd9cSjmcneill 		.get_parent = sunxi_ccu_div_get_parent,		\
250ddb9dd9cSjmcneill 	}
251ddb9dd9cSjmcneill 
252db6d41fbSbouyer /* special case of the div model for display clocks */
253db6d41fbSbouyer int sunxi_ccu_lcdxch0_set_rate(struct sunxi_ccu_softc *,
254db6d41fbSbouyer     struct sunxi_ccu_clk *, struct sunxi_ccu_clk *,
255db6d41fbSbouyer     struct sunxi_ccu_clk *, u_int);
256db6d41fbSbouyer u_int sunxi_ccu_lcdxch0_round_rate(struct sunxi_ccu_softc *,
257db6d41fbSbouyer     struct sunxi_ccu_clk *, struct sunxi_ccu_clk *,
258db6d41fbSbouyer     struct sunxi_ccu_clk *, u_int);
259db6d41fbSbouyer 
260db6d41fbSbouyer int sunxi_ccu_lcdxch1_set_rate(struct sunxi_ccu_softc *sc,
261db6d41fbSbouyer     struct sunxi_ccu_clk *clk, struct sunxi_ccu_clk *pclk,
262db6d41fbSbouyer     struct sunxi_ccu_clk *pclk_x2, u_int);
263db6d41fbSbouyer 
26411d415cdSjmcneill struct sunxi_ccu_prediv {
26511d415cdSjmcneill 	bus_size_t	reg;
26611d415cdSjmcneill 	const char	**parents;
26711d415cdSjmcneill 	u_int		nparents;
26811d415cdSjmcneill 	uint32_t	prediv;
26911d415cdSjmcneill 	uint32_t	prediv_sel;
27069b44ac7Sjmcneill 	uint32_t	prediv_fixed;
27111d415cdSjmcneill 	uint32_t	div;
27211d415cdSjmcneill 	uint32_t	sel;
27311d415cdSjmcneill 	uint32_t	flags;
27411d415cdSjmcneill #define	SUNXI_CCU_PREDIV_POWER_OF_TWO	__BIT(0)
2751e6185e4Sjmcneill #define	SUNXI_CCU_PREDIV_DIVIDE_BY_TWO	__BIT(1)
27611d415cdSjmcneill };
27711d415cdSjmcneill 
27811d415cdSjmcneill u_int	sunxi_ccu_prediv_get_rate(struct sunxi_ccu_softc *,
27911d415cdSjmcneill 				  struct sunxi_ccu_clk *);
28011d415cdSjmcneill int	sunxi_ccu_prediv_set_rate(struct sunxi_ccu_softc *,
28111d415cdSjmcneill 				  struct sunxi_ccu_clk *, u_int);
28211d415cdSjmcneill int	sunxi_ccu_prediv_set_parent(struct sunxi_ccu_softc *,
28311d415cdSjmcneill 				    struct sunxi_ccu_clk *,
28411d415cdSjmcneill 				    const char *);
28511d415cdSjmcneill const char *sunxi_ccu_prediv_get_parent(struct sunxi_ccu_softc *,
28611d415cdSjmcneill 					struct sunxi_ccu_clk *);
28711d415cdSjmcneill 
28811d415cdSjmcneill #define	SUNXI_CCU_PREDIV(_id, _name, _parents, _reg, _prediv,	\
28911d415cdSjmcneill 		     _prediv_sel, _div, _sel, _flags)		\
29069b44ac7Sjmcneill 	SUNXI_CCU_PREDIV_FIXED(_id, _name, _parents, _reg, _prediv, \
29169b44ac7Sjmcneill 		     _prediv_sel, 0, _div, _sel, _flags)
29269b44ac7Sjmcneill 
29369b44ac7Sjmcneill #define	SUNXI_CCU_PREDIV_FIXED(_id, _name, _parents, _reg, _prediv, \
29469b44ac7Sjmcneill 		     _prediv_sel, _prediv_fixed, _div, _sel, _flags) \
29511d415cdSjmcneill 	[_id] = {						\
29611d415cdSjmcneill 		.type = SUNXI_CCU_PREDIV,			\
29711d415cdSjmcneill 		.base.name = (_name),				\
29811d415cdSjmcneill 		.u.prediv.reg = (_reg),				\
29911d415cdSjmcneill 		.u.prediv.parents = (_parents),			\
30011d415cdSjmcneill 		.u.prediv.nparents = __arraycount(_parents),	\
30111d415cdSjmcneill 		.u.prediv.prediv = (_prediv),			\
30211d415cdSjmcneill 		.u.prediv.prediv_sel = (_prediv_sel),		\
30369b44ac7Sjmcneill 		.u.prediv.prediv_fixed = (_prediv_fixed),	\
30411d415cdSjmcneill 		.u.prediv.div = (_div),				\
30511d415cdSjmcneill 		.u.prediv.sel = (_sel),				\
30611d415cdSjmcneill 		.u.prediv.flags = (_flags),			\
30711d415cdSjmcneill 		.get_rate = sunxi_ccu_prediv_get_rate,		\
30811d415cdSjmcneill 		.set_rate = sunxi_ccu_prediv_set_rate,		\
30911d415cdSjmcneill 		.set_parent = sunxi_ccu_prediv_set_parent,	\
31011d415cdSjmcneill 		.get_parent = sunxi_ccu_prediv_get_parent,	\
31111d415cdSjmcneill 	}
31211d415cdSjmcneill 
313deeed1ddSjmcneill struct sunxi_ccu_phase {
314deeed1ddSjmcneill 	bus_size_t	reg;
315deeed1ddSjmcneill 	const char	*parent;
316deeed1ddSjmcneill 	uint32_t	mask;
317deeed1ddSjmcneill };
318deeed1ddSjmcneill 
319deeed1ddSjmcneill u_int	sunxi_ccu_phase_get_rate(struct sunxi_ccu_softc *,
320deeed1ddSjmcneill 				 struct sunxi_ccu_clk *);
321deeed1ddSjmcneill int	sunxi_ccu_phase_set_rate(struct sunxi_ccu_softc *,
322deeed1ddSjmcneill 				 struct sunxi_ccu_clk *, u_int);
323deeed1ddSjmcneill const char *sunxi_ccu_phase_get_parent(struct sunxi_ccu_softc *,
324deeed1ddSjmcneill 				       struct sunxi_ccu_clk *);
325deeed1ddSjmcneill 
326deeed1ddSjmcneill #define	SUNXI_CCU_PHASE(_id, _name, _parent, _reg, _mask)	\
327deeed1ddSjmcneill 	[_id] = {						\
328deeed1ddSjmcneill 		.type = SUNXI_CCU_PHASE,			\
329deeed1ddSjmcneill 		.base.name = (_name),				\
330deeed1ddSjmcneill 		.u.phase.reg = (_reg),				\
331deeed1ddSjmcneill 		.u.phase.parent = (_parent),			\
332deeed1ddSjmcneill 		.u.phase.mask = (_mask),			\
333deeed1ddSjmcneill 		.get_rate = sunxi_ccu_phase_get_rate,		\
334deeed1ddSjmcneill 		.set_rate = sunxi_ccu_phase_set_rate,		\
335deeed1ddSjmcneill 		.get_parent = sunxi_ccu_phase_get_parent,	\
336deeed1ddSjmcneill 	}
337deeed1ddSjmcneill 
338a5198ca0Sjmcneill struct sunxi_ccu_fixed_factor {
339a5198ca0Sjmcneill 	const char	*parent;
340a5198ca0Sjmcneill 	u_int		div;
341a5198ca0Sjmcneill 	u_int		mult;
342a5198ca0Sjmcneill };
343a5198ca0Sjmcneill 
344a5198ca0Sjmcneill u_int	sunxi_ccu_fixed_factor_get_rate(struct sunxi_ccu_softc *,
345a5198ca0Sjmcneill 					struct sunxi_ccu_clk *);
346aac64003Sjmcneill int	sunxi_ccu_fixed_factor_set_rate(struct sunxi_ccu_softc *,
347aac64003Sjmcneill 					struct sunxi_ccu_clk *, u_int);
348a5198ca0Sjmcneill const char *sunxi_ccu_fixed_factor_get_parent(struct sunxi_ccu_softc *,
349a5198ca0Sjmcneill 					      struct sunxi_ccu_clk *);
350a5198ca0Sjmcneill 
351a5198ca0Sjmcneill #define	SUNXI_CCU_FIXED_FACTOR(_id, _name, _parent, _div, _mult)	\
352a5198ca0Sjmcneill 	[_id] = {							\
353a5198ca0Sjmcneill 		.type = SUNXI_CCU_FIXED_FACTOR,				\
354a5198ca0Sjmcneill 		.base.name = (_name),					\
355a5198ca0Sjmcneill 		.u.fixed_factor.parent = (_parent),			\
356a5198ca0Sjmcneill 		.u.fixed_factor.div = (_div),				\
357a5198ca0Sjmcneill 		.u.fixed_factor.mult = (_mult),				\
358a5198ca0Sjmcneill 		.get_rate = sunxi_ccu_fixed_factor_get_rate,		\
359a5198ca0Sjmcneill 		.get_parent = sunxi_ccu_fixed_factor_get_parent,	\
360aac64003Sjmcneill 		.set_rate = sunxi_ccu_fixed_factor_set_rate,		\
361a5198ca0Sjmcneill 	}
362a5198ca0Sjmcneill 
363a1f84860Sbouyer struct sunxi_ccu_fractional {
364a1f84860Sbouyer 	bus_size_t	reg;
365a1f84860Sbouyer 	const char	*parent;
366a1f84860Sbouyer 	uint32_t	m;
367a1f84860Sbouyer 	uint32_t	m_min;
368a1f84860Sbouyer 	uint32_t	m_max;
369db6d41fbSbouyer 	uint32_t	div_en;
370a1f84860Sbouyer 	uint32_t	frac_sel;
371a1f84860Sbouyer 	uint32_t	frac[2];
372a1f84860Sbouyer 	uint32_t	prediv;
373cf80abdeSjmcneill 	uint32_t	prediv_val;
374a1f84860Sbouyer 	uint32_t	enable;
375cf80abdeSjmcneill 	uint32_t	flags;
376cf80abdeSjmcneill #define	SUNXI_CCU_FRACTIONAL_PLUSONE	__BIT(0)
377a9d03646Sjmcneill #define	SUNXI_CCU_FRACTIONAL_SET_ENABLE	__BIT(1)
378a1f84860Sbouyer };
379a1f84860Sbouyer 
380a1f84860Sbouyer int	sunxi_ccu_fractional_enable(struct sunxi_ccu_softc *,
381a1f84860Sbouyer 			    struct sunxi_ccu_clk *, int);
382a1f84860Sbouyer u_int	sunxi_ccu_fractional_get_rate(struct sunxi_ccu_softc *,
383a1f84860Sbouyer 			      struct sunxi_ccu_clk *);
384a1f84860Sbouyer int	sunxi_ccu_fractional_set_rate(struct sunxi_ccu_softc *,
385a1f84860Sbouyer 			      struct sunxi_ccu_clk *, u_int);
386db6d41fbSbouyer u_int	sunxi_ccu_fractional_round_rate(struct sunxi_ccu_softc *,
387db6d41fbSbouyer 			      struct sunxi_ccu_clk *, u_int);
388a1f84860Sbouyer const char *sunxi_ccu_fractional_get_parent(struct sunxi_ccu_softc *,
389a1f84860Sbouyer 				    struct sunxi_ccu_clk *);
390a1f84860Sbouyer 
391a1f84860Sbouyer #define	SUNXI_CCU_FRACTIONAL(_id, _name, _parent, _reg, _m, _m_min, _m_max, \
392cf80abdeSjmcneill 		     _div_en, _frac_sel, _frac0, _frac1, _prediv, _prediv_val, \
393cf80abdeSjmcneill 		     _enable, _flags)					\
394a1f84860Sbouyer 	[_id] = {							\
395a1f84860Sbouyer 		.type = SUNXI_CCU_FRACTIONAL,				\
396a1f84860Sbouyer 		.base.name = (_name),					\
397a1f84860Sbouyer 		.u.fractional.reg = (_reg),				\
398a1f84860Sbouyer 		.u.fractional.parent = (_parent),			\
399a1f84860Sbouyer 		.u.fractional.m = (_m),					\
400a1f84860Sbouyer 		.u.fractional.m_min = (_m_min),				\
401a1f84860Sbouyer 		.u.fractional.m_max = (_m_max),				\
402a1f84860Sbouyer 		.u.fractional.prediv = (_prediv),			\
403cf80abdeSjmcneill 		.u.fractional.prediv_val = (_prediv_val),		\
404db6d41fbSbouyer 		.u.fractional.div_en = (_div_en),			\
405a1f84860Sbouyer 		.u.fractional.frac_sel = (_frac_sel),			\
406a1f84860Sbouyer 		.u.fractional.frac[0] = (_frac0),			\
407a1f84860Sbouyer 		.u.fractional.frac[1] = (_frac1),			\
408a1f84860Sbouyer 		.u.fractional.enable = (_enable),			\
409b770b2aaSjakllsch 		.u.fractional.flags = (_flags),				\
410a1f84860Sbouyer 		.enable = sunxi_ccu_fractional_enable,			\
411a1f84860Sbouyer 		.get_rate = sunxi_ccu_fractional_get_rate,		\
412a1f84860Sbouyer 		.set_rate = sunxi_ccu_fractional_set_rate,		\
413db6d41fbSbouyer 		.round_rate = sunxi_ccu_fractional_round_rate,		\
414a1f84860Sbouyer 		.get_parent = sunxi_ccu_fractional_get_parent,		\
415a1f84860Sbouyer 	}
416a1f84860Sbouyer 
417c26e3874Sjmcneill struct sunxi_ccu_mux {
418c26e3874Sjmcneill 	bus_size_t	reg;
419c26e3874Sjmcneill 	const char	**parents;
420c26e3874Sjmcneill 	u_int		nparents;
421c26e3874Sjmcneill 	uint32_t	sel;
422c26e3874Sjmcneill 	uint32_t	flags;
423c26e3874Sjmcneill };
424c26e3874Sjmcneill 
425c26e3874Sjmcneill int	sunxi_ccu_mux_set_parent(struct sunxi_ccu_softc *,
426c26e3874Sjmcneill 				 struct sunxi_ccu_clk *,
427c26e3874Sjmcneill 				 const char *);
428c26e3874Sjmcneill const char *sunxi_ccu_mux_get_parent(struct sunxi_ccu_softc *,
429c26e3874Sjmcneill 				     struct sunxi_ccu_clk *);
430c26e3874Sjmcneill 
431c26e3874Sjmcneill #define	SUNXI_CCU_MUX(_id, _name, _parents, _reg, _sel, _flags)	\
432c26e3874Sjmcneill 	[_id] = {						\
433c26e3874Sjmcneill 		.type = SUNXI_CCU_MUX,				\
434c26e3874Sjmcneill 		.base.name = (_name),				\
435*f001abf4Smacallan 		.base.flags = CLK_SET_RATE_PARENT,		\
436c26e3874Sjmcneill 		.u.mux.reg = (_reg),				\
437c26e3874Sjmcneill 		.u.mux.parents = (_parents),			\
438c26e3874Sjmcneill 		.u.mux.nparents = __arraycount(_parents),	\
439c26e3874Sjmcneill 		.u.mux.sel = (_sel),				\
440c26e3874Sjmcneill 		.u.mux.flags = (_flags),			\
441c26e3874Sjmcneill 		.set_parent = sunxi_ccu_mux_set_parent,		\
442c26e3874Sjmcneill 		.get_parent = sunxi_ccu_mux_get_parent,		\
443c26e3874Sjmcneill 	}
444c26e3874Sjmcneill 
445c26e3874Sjmcneill 
446a07e90f3Sjmcneill struct sunxi_ccu_clk {
447a07e90f3Sjmcneill 	struct clk	base;
448a07e90f3Sjmcneill 	enum sunxi_ccu_clktype type;
449a07e90f3Sjmcneill 	union {
450a07e90f3Sjmcneill 		struct sunxi_ccu_gate gate;
451a07e90f3Sjmcneill 		struct sunxi_ccu_nm nm;
45211d415cdSjmcneill 		struct sunxi_ccu_nkmp nkmp;
45311d415cdSjmcneill 		struct sunxi_ccu_prediv prediv;
454ddb9dd9cSjmcneill 		struct sunxi_ccu_div div;
455deeed1ddSjmcneill 		struct sunxi_ccu_phase phase;
456a5198ca0Sjmcneill 		struct sunxi_ccu_fixed_factor fixed_factor;
457a1f84860Sbouyer 		struct sunxi_ccu_fractional fractional;
458c26e3874Sjmcneill 		struct sunxi_ccu_mux mux;
459a07e90f3Sjmcneill 	} u;
460a07e90f3Sjmcneill 
461a07e90f3Sjmcneill 	int		(*enable)(struct sunxi_ccu_softc *,
462a07e90f3Sjmcneill 				  struct sunxi_ccu_clk *, int);
463a07e90f3Sjmcneill 	u_int		(*get_rate)(struct sunxi_ccu_softc *,
464a07e90f3Sjmcneill 				    struct sunxi_ccu_clk *);
465a07e90f3Sjmcneill 	int		(*set_rate)(struct sunxi_ccu_softc *,
466a07e90f3Sjmcneill 				    struct sunxi_ccu_clk *, u_int);
467db6d41fbSbouyer 	u_int		(*round_rate)(struct sunxi_ccu_softc *,
468db6d41fbSbouyer 				    struct sunxi_ccu_clk *, u_int);
469a07e90f3Sjmcneill 	const char *	(*get_parent)(struct sunxi_ccu_softc *,
470a07e90f3Sjmcneill 				      struct sunxi_ccu_clk *);
471a07e90f3Sjmcneill 	int		(*set_parent)(struct sunxi_ccu_softc *,
472a07e90f3Sjmcneill 				      struct sunxi_ccu_clk *,
473a07e90f3Sjmcneill 				      const char *);
474a07e90f3Sjmcneill };
475a07e90f3Sjmcneill 
476a07e90f3Sjmcneill struct sunxi_ccu_softc {
477a07e90f3Sjmcneill 	device_t		sc_dev;
478a07e90f3Sjmcneill 	int			sc_phandle;
479a07e90f3Sjmcneill 	bus_space_tag_t		sc_bst;
480a07e90f3Sjmcneill 	bus_space_handle_t	sc_bsh;
481a07e90f3Sjmcneill 
482a07e90f3Sjmcneill 	struct clk_domain	sc_clkdom;
483a07e90f3Sjmcneill 
484a07e90f3Sjmcneill 	struct sunxi_ccu_reset *sc_resets;
485a07e90f3Sjmcneill 	u_int			sc_nresets;
486a07e90f3Sjmcneill 
487a07e90f3Sjmcneill 	struct sunxi_ccu_clk	*sc_clks;
488a07e90f3Sjmcneill 	u_int			sc_nclks;
489a07e90f3Sjmcneill };
490a07e90f3Sjmcneill 
491a07e90f3Sjmcneill int	sunxi_ccu_attach(struct sunxi_ccu_softc *);
492a07e90f3Sjmcneill struct sunxi_ccu_clk *sunxi_ccu_clock_find(struct sunxi_ccu_softc *,
493a07e90f3Sjmcneill 					   const char *);
494a07e90f3Sjmcneill void	sunxi_ccu_print(struct sunxi_ccu_softc *);
495a07e90f3Sjmcneill 
496a07e90f3Sjmcneill #define CCU_READ(sc, reg)	\
497a07e90f3Sjmcneill 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
498a07e90f3Sjmcneill #define CCU_WRITE(sc, reg, val)	\
499a07e90f3Sjmcneill 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
500a07e90f3Sjmcneill 
501a07e90f3Sjmcneill #endif /* _ARM_SUNXI_CCU_H */
502