sunxi_ccu.h revision 1.3 1 /* $NetBSD: sunxi_ccu.h,v 1.3 2017/06/29 10:53:59 jmcneill Exp $ */
2
3 /*-
4 * Copyright (c) 2017 Jared McNeill <jmcneill (at) invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #ifndef _ARM_SUNXI_CCU_H
30 #define _ARM_SUNXI_CCU_H
31
32 #include <dev/clk/clk_backend.h>
33
34 struct sunxi_ccu_softc;
35 struct sunxi_ccu_clk;
36 struct sunxi_ccu_reset;
37
38 /*
39 * Resets
40 */
41
42 struct sunxi_ccu_reset {
43 bus_size_t reg;
44 uint32_t mask;
45 };
46
47 #define SUNXI_CCU_RESET(_id, _reg, _bit) \
48 [_id] = { \
49 .reg = (_reg), \
50 .mask = __BIT(_bit), \
51 }
52
53 /*
54 * Clocks
55 */
56
57 enum sunxi_ccu_clktype {
58 SUNXI_CCU_UNKNOWN,
59 SUNXI_CCU_GATE,
60 SUNXI_CCU_NM,
61 SUNXI_CCU_NKMP,
62 SUNXI_CCU_PREDIV,
63 };
64
65 struct sunxi_ccu_gate {
66 bus_size_t reg;
67 uint32_t mask;
68 const char *parent;
69 };
70
71 int sunxi_ccu_gate_enable(struct sunxi_ccu_softc *,
72 struct sunxi_ccu_clk *, int);
73 const char *sunxi_ccu_gate_get_parent(struct sunxi_ccu_softc *,
74 struct sunxi_ccu_clk *);
75
76 #define SUNXI_CCU_GATE(_id, _name, _pname, _reg, _bit) \
77 [_id] = { \
78 .type = SUNXI_CCU_GATE, \
79 .base.name = (_name), \
80 .u.gate.parent = (_pname), \
81 .u.gate.reg = (_reg), \
82 .u.gate.mask = __BIT(_bit), \
83 .enable = sunxi_ccu_gate_enable, \
84 .get_parent = sunxi_ccu_gate_get_parent, \
85 }
86
87 struct sunxi_ccu_nkmp {
88 bus_size_t reg;
89 const char *parent;
90 uint32_t n;
91 uint32_t k;
92 uint32_t m;
93 uint32_t p;
94 uint32_t lock;
95 uint32_t enable;
96 uint32_t flags;
97 #define SUNXI_CCU_NKMP_DIVIDE_BY_TWO __BIT(0)
98 };
99
100 int sunxi_ccu_nkmp_enable(struct sunxi_ccu_softc *,
101 struct sunxi_ccu_clk *, int);
102 u_int sunxi_ccu_nkmp_get_rate(struct sunxi_ccu_softc *,
103 struct sunxi_ccu_clk *);
104 int sunxi_ccu_nkmp_set_rate(struct sunxi_ccu_softc *,
105 struct sunxi_ccu_clk *, u_int);
106 const char *sunxi_ccu_nkmp_get_parent(struct sunxi_ccu_softc *,
107 struct sunxi_ccu_clk *);
108
109 #define SUNXI_CCU_NKMP(_id, _name, _parent, _reg, _n, _k, _m, \
110 _p, _enable, _flags) \
111 [_id] = { \
112 .type = SUNXI_CCU_NKMP, \
113 .base.name = (_name), \
114 .u.nkmp.reg = (_reg), \
115 .u.nkmp.parent = (_parent), \
116 .u.nkmp.n = (_n), \
117 .u.nkmp.k = (_k), \
118 .u.nkmp.m = (_m), \
119 .u.nkmp.p = (_p), \
120 .u.nkmp.enable = (_enable), \
121 .u.nkmp.flags = (_flags), \
122 .enable = sunxi_ccu_nkmp_enable, \
123 .get_rate = sunxi_ccu_nkmp_get_rate, \
124 .set_rate = sunxi_ccu_nkmp_set_rate, \
125 .get_parent = sunxi_ccu_nkmp_get_parent, \
126 }
127
128 struct sunxi_ccu_nm {
129 bus_size_t reg;
130 const char **parents;
131 u_int nparents;
132 uint32_t n;
133 uint32_t m;
134 uint32_t sel;
135 uint32_t enable;
136 uint32_t flags;
137 #define SUNXI_CCU_NM_POWER_OF_TWO __BIT(0)
138 #define SUNXI_CCU_NM_ROUND_DOWN __BIT(1)
139 };
140
141 int sunxi_ccu_nm_enable(struct sunxi_ccu_softc *,
142 struct sunxi_ccu_clk *, int);
143 u_int sunxi_ccu_nm_get_rate(struct sunxi_ccu_softc *,
144 struct sunxi_ccu_clk *);
145 int sunxi_ccu_nm_set_rate(struct sunxi_ccu_softc *,
146 struct sunxi_ccu_clk *, u_int);
147 int sunxi_ccu_nm_set_parent(struct sunxi_ccu_softc *,
148 struct sunxi_ccu_clk *,
149 const char *);
150 const char *sunxi_ccu_nm_get_parent(struct sunxi_ccu_softc *,
151 struct sunxi_ccu_clk *);
152
153 #define SUNXI_CCU_NM(_id, _name, _parents, _reg, _n, _m, _sel, \
154 _enable, _flags) \
155 [_id] = { \
156 .type = SUNXI_CCU_NM, \
157 .base.name = (_name), \
158 .u.nm.reg = (_reg), \
159 .u.nm.parents = (_parents), \
160 .u.nm.nparents = __arraycount(_parents), \
161 .u.nm.n = (_n), \
162 .u.nm.m = (_m), \
163 .u.nm.sel = (_sel), \
164 .u.nm.enable = (_enable), \
165 .u.nm.flags = (_flags), \
166 .enable = sunxi_ccu_nm_enable, \
167 .get_rate = sunxi_ccu_nm_get_rate, \
168 .set_rate = sunxi_ccu_nm_set_rate, \
169 .set_parent = sunxi_ccu_nm_set_parent, \
170 .get_parent = sunxi_ccu_nm_get_parent, \
171 }
172
173 struct sunxi_ccu_prediv {
174 bus_size_t reg;
175 const char **parents;
176 u_int nparents;
177 uint32_t prediv;
178 uint32_t prediv_sel;
179 uint32_t div;
180 uint32_t sel;
181 uint32_t flags;
182 #define SUNXI_CCU_PREDIV_POWER_OF_TWO __BIT(0)
183 };
184
185 u_int sunxi_ccu_prediv_get_rate(struct sunxi_ccu_softc *,
186 struct sunxi_ccu_clk *);
187 int sunxi_ccu_prediv_set_rate(struct sunxi_ccu_softc *,
188 struct sunxi_ccu_clk *, u_int);
189 int sunxi_ccu_prediv_set_parent(struct sunxi_ccu_softc *,
190 struct sunxi_ccu_clk *,
191 const char *);
192 const char *sunxi_ccu_prediv_get_parent(struct sunxi_ccu_softc *,
193 struct sunxi_ccu_clk *);
194
195 #define SUNXI_CCU_PREDIV(_id, _name, _parents, _reg, _prediv, \
196 _prediv_sel, _div, _sel, _flags) \
197 [_id] = { \
198 .type = SUNXI_CCU_PREDIV, \
199 .base.name = (_name), \
200 .u.prediv.reg = (_reg), \
201 .u.prediv.parents = (_parents), \
202 .u.prediv.nparents = __arraycount(_parents), \
203 .u.prediv.prediv = (_prediv), \
204 .u.prediv.prediv_sel = (_prediv_sel), \
205 .u.prediv.div = (_div), \
206 .u.prediv.sel = (_sel), \
207 .u.prediv.flags = (_flags), \
208 .get_rate = sunxi_ccu_prediv_get_rate, \
209 .set_rate = sunxi_ccu_prediv_set_rate, \
210 .set_parent = sunxi_ccu_prediv_set_parent, \
211 .get_parent = sunxi_ccu_prediv_get_parent, \
212 }
213
214 struct sunxi_ccu_clk {
215 struct clk base;
216 enum sunxi_ccu_clktype type;
217 union {
218 struct sunxi_ccu_gate gate;
219 struct sunxi_ccu_nm nm;
220 struct sunxi_ccu_nkmp nkmp;
221 struct sunxi_ccu_prediv prediv;
222 } u;
223
224 int (*enable)(struct sunxi_ccu_softc *,
225 struct sunxi_ccu_clk *, int);
226 u_int (*get_rate)(struct sunxi_ccu_softc *,
227 struct sunxi_ccu_clk *);
228 int (*set_rate)(struct sunxi_ccu_softc *,
229 struct sunxi_ccu_clk *, u_int);
230 const char * (*get_parent)(struct sunxi_ccu_softc *,
231 struct sunxi_ccu_clk *);
232 int (*set_parent)(struct sunxi_ccu_softc *,
233 struct sunxi_ccu_clk *,
234 const char *);
235 };
236
237 struct sunxi_ccu_softc {
238 device_t sc_dev;
239 int sc_phandle;
240 bus_space_tag_t sc_bst;
241 bus_space_handle_t sc_bsh;
242
243 struct clk_domain sc_clkdom;
244
245 struct sunxi_ccu_reset *sc_resets;
246 u_int sc_nresets;
247
248 struct sunxi_ccu_clk *sc_clks;
249 u_int sc_nclks;
250 };
251
252 int sunxi_ccu_attach(struct sunxi_ccu_softc *);
253 struct sunxi_ccu_clk *sunxi_ccu_clock_find(struct sunxi_ccu_softc *,
254 const char *);
255 void sunxi_ccu_print(struct sunxi_ccu_softc *);
256
257 #define CCU_READ(sc, reg) \
258 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
259 #define CCU_WRITE(sc, reg, val) \
260 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
261
262 #endif /* _ARM_SUNXI_CCU_H */
263