1*c26e3874Sjmcneill /* $NetBSD: sunxi_ccu.c,v 1.14 2021/11/07 17:13:12 jmcneill 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 #include "opt_soc.h"
30a07e90f3Sjmcneill #include "opt_multiprocessor.h"
315a821b2cSskrll #include "opt_console.h"
32a07e90f3Sjmcneill
33a07e90f3Sjmcneill #include <sys/cdefs.h>
34*c26e3874Sjmcneill __KERNEL_RCSID(0, "$NetBSD: sunxi_ccu.c,v 1.14 2021/11/07 17:13:12 jmcneill Exp $");
35a07e90f3Sjmcneill
36a07e90f3Sjmcneill #include <sys/param.h>
37a07e90f3Sjmcneill #include <sys/bus.h>
38a07e90f3Sjmcneill #include <sys/cpu.h>
39a07e90f3Sjmcneill #include <sys/device.h>
40a07e90f3Sjmcneill
41a07e90f3Sjmcneill #include <dev/fdt/fdtvar.h>
42a07e90f3Sjmcneill
43a07e90f3Sjmcneill #include <dev/clk/clk_backend.h>
44a07e90f3Sjmcneill
45a07e90f3Sjmcneill #include <arm/sunxi/sunxi_ccu.h>
46a07e90f3Sjmcneill
47a07e90f3Sjmcneill static void *
sunxi_ccu_reset_acquire(device_t dev,const void * data,size_t len)48a07e90f3Sjmcneill sunxi_ccu_reset_acquire(device_t dev, const void *data, size_t len)
49a07e90f3Sjmcneill {
50a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = device_private(dev);
51a07e90f3Sjmcneill struct sunxi_ccu_reset *reset;
52a07e90f3Sjmcneill
53a07e90f3Sjmcneill if (len != 4)
54a07e90f3Sjmcneill return NULL;
55a07e90f3Sjmcneill
56a07e90f3Sjmcneill const u_int reset_id = be32dec(data);
57a07e90f3Sjmcneill
58a07e90f3Sjmcneill if (reset_id >= sc->sc_nresets)
59a07e90f3Sjmcneill return NULL;
60a07e90f3Sjmcneill
61a07e90f3Sjmcneill reset = &sc->sc_resets[reset_id];
62a07e90f3Sjmcneill if (reset->mask == 0)
63a07e90f3Sjmcneill return NULL;
64a07e90f3Sjmcneill
65a07e90f3Sjmcneill return reset;
66a07e90f3Sjmcneill }
67a07e90f3Sjmcneill
68a07e90f3Sjmcneill static void
sunxi_ccu_reset_release(device_t dev,void * priv)69a07e90f3Sjmcneill sunxi_ccu_reset_release(device_t dev, void *priv)
70a07e90f3Sjmcneill {
71a07e90f3Sjmcneill }
72a07e90f3Sjmcneill
73a07e90f3Sjmcneill static int
sunxi_ccu_reset_assert(device_t dev,void * priv)74a07e90f3Sjmcneill sunxi_ccu_reset_assert(device_t dev, void *priv)
75a07e90f3Sjmcneill {
76a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = device_private(dev);
77a07e90f3Sjmcneill struct sunxi_ccu_reset * const reset = priv;
78a07e90f3Sjmcneill
79a07e90f3Sjmcneill const uint32_t val = CCU_READ(sc, reset->reg);
80a07e90f3Sjmcneill CCU_WRITE(sc, reset->reg, val & ~reset->mask);
81a07e90f3Sjmcneill
82a07e90f3Sjmcneill return 0;
83a07e90f3Sjmcneill }
84a07e90f3Sjmcneill
85a07e90f3Sjmcneill static int
sunxi_ccu_reset_deassert(device_t dev,void * priv)86a07e90f3Sjmcneill sunxi_ccu_reset_deassert(device_t dev, void *priv)
87a07e90f3Sjmcneill {
88a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = device_private(dev);
89a07e90f3Sjmcneill struct sunxi_ccu_reset * const reset = priv;
90a07e90f3Sjmcneill
91a07e90f3Sjmcneill const uint32_t val = CCU_READ(sc, reset->reg);
92a07e90f3Sjmcneill CCU_WRITE(sc, reset->reg, val | reset->mask);
93a07e90f3Sjmcneill
94a07e90f3Sjmcneill return 0;
95a07e90f3Sjmcneill }
96a07e90f3Sjmcneill
97a07e90f3Sjmcneill static const struct fdtbus_reset_controller_func sunxi_ccu_fdtreset_funcs = {
98a07e90f3Sjmcneill .acquire = sunxi_ccu_reset_acquire,
99a07e90f3Sjmcneill .release = sunxi_ccu_reset_release,
100a07e90f3Sjmcneill .reset_assert = sunxi_ccu_reset_assert,
101a07e90f3Sjmcneill .reset_deassert = sunxi_ccu_reset_deassert,
102a07e90f3Sjmcneill };
103a07e90f3Sjmcneill
104a07e90f3Sjmcneill static struct clk *
sunxi_ccu_clock_decode(device_t dev,int cc_phandle,const void * data,size_t len)10551b425efSaymeric sunxi_ccu_clock_decode(device_t dev, int cc_phandle, const void *data,
10651b425efSaymeric size_t len)
107a07e90f3Sjmcneill {
108a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = device_private(dev);
109a07e90f3Sjmcneill struct sunxi_ccu_clk *clk;
110a07e90f3Sjmcneill
111a07e90f3Sjmcneill if (len != 4)
112a07e90f3Sjmcneill return NULL;
113a07e90f3Sjmcneill
114a07e90f3Sjmcneill const u_int clock_id = be32dec(data);
115a07e90f3Sjmcneill if (clock_id >= sc->sc_nclks)
116a07e90f3Sjmcneill return NULL;
117a07e90f3Sjmcneill
118a07e90f3Sjmcneill clk = &sc->sc_clks[clock_id];
119a07e90f3Sjmcneill if (clk->type == SUNXI_CCU_UNKNOWN)
120a07e90f3Sjmcneill return NULL;
121a07e90f3Sjmcneill
122a07e90f3Sjmcneill return &clk->base;
123a07e90f3Sjmcneill }
124a07e90f3Sjmcneill
125a07e90f3Sjmcneill static const struct fdtbus_clock_controller_func sunxi_ccu_fdtclock_funcs = {
126a07e90f3Sjmcneill .decode = sunxi_ccu_clock_decode,
127a07e90f3Sjmcneill };
128a07e90f3Sjmcneill
129a07e90f3Sjmcneill static struct clk *
sunxi_ccu_clock_get(void * priv,const char * name)130a07e90f3Sjmcneill sunxi_ccu_clock_get(void *priv, const char *name)
131a07e90f3Sjmcneill {
132a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = priv;
133a07e90f3Sjmcneill struct sunxi_ccu_clk *clk;
134a07e90f3Sjmcneill
135a07e90f3Sjmcneill clk = sunxi_ccu_clock_find(sc, name);
136a07e90f3Sjmcneill if (clk == NULL)
137a07e90f3Sjmcneill return NULL;
138a07e90f3Sjmcneill
139a07e90f3Sjmcneill return &clk->base;
140a07e90f3Sjmcneill }
141a07e90f3Sjmcneill
142a07e90f3Sjmcneill static void
sunxi_ccu_clock_put(void * priv,struct clk * clk)143a07e90f3Sjmcneill sunxi_ccu_clock_put(void *priv, struct clk *clk)
144a07e90f3Sjmcneill {
145a07e90f3Sjmcneill }
146a07e90f3Sjmcneill
147a07e90f3Sjmcneill static u_int
sunxi_ccu_clock_get_rate(void * priv,struct clk * clkp)148a07e90f3Sjmcneill sunxi_ccu_clock_get_rate(void *priv, struct clk *clkp)
149a07e90f3Sjmcneill {
150a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = priv;
151a07e90f3Sjmcneill struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
152a07e90f3Sjmcneill struct clk *clkp_parent;
153a07e90f3Sjmcneill
154a07e90f3Sjmcneill if (clk->get_rate)
155a07e90f3Sjmcneill return clk->get_rate(sc, clk);
156a07e90f3Sjmcneill
157a07e90f3Sjmcneill clkp_parent = clk_get_parent(clkp);
158a07e90f3Sjmcneill if (clkp_parent == NULL) {
159a07e90f3Sjmcneill aprint_error("%s: no parent for %s\n", __func__, clk->base.name);
160a07e90f3Sjmcneill return 0;
161a07e90f3Sjmcneill }
162a07e90f3Sjmcneill
163a07e90f3Sjmcneill return clk_get_rate(clkp_parent);
164a07e90f3Sjmcneill }
165a07e90f3Sjmcneill
166a07e90f3Sjmcneill static int
sunxi_ccu_clock_set_rate(void * priv,struct clk * clkp,u_int rate)167a07e90f3Sjmcneill sunxi_ccu_clock_set_rate(void *priv, struct clk *clkp, u_int rate)
168a07e90f3Sjmcneill {
169a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = priv;
170a07e90f3Sjmcneill struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
171a07e90f3Sjmcneill struct clk *clkp_parent;
172a07e90f3Sjmcneill
173a07e90f3Sjmcneill if (clkp->flags & CLK_SET_RATE_PARENT) {
174a07e90f3Sjmcneill clkp_parent = clk_get_parent(clkp);
175a07e90f3Sjmcneill if (clkp_parent == NULL) {
176a07e90f3Sjmcneill aprint_error("%s: no parent for %s\n", __func__, clk->base.name);
177a07e90f3Sjmcneill return ENXIO;
178a07e90f3Sjmcneill }
179a07e90f3Sjmcneill return clk_set_rate(clkp_parent, rate);
180a07e90f3Sjmcneill }
181a07e90f3Sjmcneill
182a07e90f3Sjmcneill if (clk->set_rate)
183a07e90f3Sjmcneill return clk->set_rate(sc, clk, rate);
184a07e90f3Sjmcneill
185a07e90f3Sjmcneill return ENXIO;
186a07e90f3Sjmcneill }
187a07e90f3Sjmcneill
188db6d41fbSbouyer static u_int
sunxi_ccu_clock_round_rate(void * priv,struct clk * clkp,u_int rate)189db6d41fbSbouyer sunxi_ccu_clock_round_rate(void *priv, struct clk *clkp, u_int rate)
190db6d41fbSbouyer {
191db6d41fbSbouyer struct sunxi_ccu_softc * const sc = priv;
192db6d41fbSbouyer struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
193db6d41fbSbouyer struct clk *clkp_parent;
194db6d41fbSbouyer
195db6d41fbSbouyer if (clkp->flags & CLK_SET_RATE_PARENT) {
196db6d41fbSbouyer clkp_parent = clk_get_parent(clkp);
197db6d41fbSbouyer if (clkp_parent == NULL) {
198db6d41fbSbouyer aprint_error("%s: no parent for %s\n", __func__, clk->base.name);
199db6d41fbSbouyer return 0;
200db6d41fbSbouyer }
201db6d41fbSbouyer return clk_round_rate(clkp_parent, rate);
202db6d41fbSbouyer }
203db6d41fbSbouyer
204db6d41fbSbouyer if (clk->round_rate)
205db6d41fbSbouyer return clk->round_rate(sc, clk, rate);
206db6d41fbSbouyer
207db6d41fbSbouyer return 0;
208db6d41fbSbouyer }
209db6d41fbSbouyer
210a07e90f3Sjmcneill static int
sunxi_ccu_clock_enable(void * priv,struct clk * clkp)211a07e90f3Sjmcneill sunxi_ccu_clock_enable(void *priv, struct clk *clkp)
212a07e90f3Sjmcneill {
213a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = priv;
214a07e90f3Sjmcneill struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
215a07e90f3Sjmcneill struct clk *clkp_parent;
216a07e90f3Sjmcneill int error = 0;
217a07e90f3Sjmcneill
218a07e90f3Sjmcneill clkp_parent = clk_get_parent(clkp);
219a07e90f3Sjmcneill if (clkp_parent != NULL) {
220a07e90f3Sjmcneill error = clk_enable(clkp_parent);
221a07e90f3Sjmcneill if (error != 0)
222a07e90f3Sjmcneill return error;
223a07e90f3Sjmcneill }
224a07e90f3Sjmcneill
225a07e90f3Sjmcneill if (clk->enable)
226a07e90f3Sjmcneill error = clk->enable(sc, clk, 1);
227a07e90f3Sjmcneill
228a07e90f3Sjmcneill return error;
229a07e90f3Sjmcneill }
230a07e90f3Sjmcneill
231a07e90f3Sjmcneill static int
sunxi_ccu_clock_disable(void * priv,struct clk * clkp)232a07e90f3Sjmcneill sunxi_ccu_clock_disable(void *priv, struct clk *clkp)
233a07e90f3Sjmcneill {
234a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = priv;
235a07e90f3Sjmcneill struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
236a07e90f3Sjmcneill int error = EINVAL;
237a07e90f3Sjmcneill
238a07e90f3Sjmcneill if (clk->enable)
239a07e90f3Sjmcneill error = clk->enable(sc, clk, 0);
240a07e90f3Sjmcneill
241a07e90f3Sjmcneill return error;
242a07e90f3Sjmcneill }
243a07e90f3Sjmcneill
244a07e90f3Sjmcneill static int
sunxi_ccu_clock_set_parent(void * priv,struct clk * clkp,struct clk * clkp_parent)245a07e90f3Sjmcneill sunxi_ccu_clock_set_parent(void *priv, struct clk *clkp,
246a07e90f3Sjmcneill struct clk *clkp_parent)
247a07e90f3Sjmcneill {
248a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = priv;
249a07e90f3Sjmcneill struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
250a07e90f3Sjmcneill
251a07e90f3Sjmcneill if (clk->set_parent == NULL)
252a07e90f3Sjmcneill return EINVAL;
253a07e90f3Sjmcneill
254a07e90f3Sjmcneill return clk->set_parent(sc, clk, clkp_parent->name);
255a07e90f3Sjmcneill }
256a07e90f3Sjmcneill
257a07e90f3Sjmcneill static struct clk *
sunxi_ccu_clock_get_parent(void * priv,struct clk * clkp)258a07e90f3Sjmcneill sunxi_ccu_clock_get_parent(void *priv, struct clk *clkp)
259a07e90f3Sjmcneill {
260a07e90f3Sjmcneill struct sunxi_ccu_softc * const sc = priv;
261a07e90f3Sjmcneill struct sunxi_ccu_clk *clk = (struct sunxi_ccu_clk *)clkp;
262a07e90f3Sjmcneill struct sunxi_ccu_clk *clk_parent;
263a07e90f3Sjmcneill const char *parent;
264a07e90f3Sjmcneill
265a07e90f3Sjmcneill if (clk->get_parent == NULL)
266a07e90f3Sjmcneill return NULL;
267a07e90f3Sjmcneill
268a07e90f3Sjmcneill parent = clk->get_parent(sc, clk);
269a07e90f3Sjmcneill if (parent == NULL)
270a07e90f3Sjmcneill return NULL;
271a07e90f3Sjmcneill
272a07e90f3Sjmcneill clk_parent = sunxi_ccu_clock_find(sc, parent);
273a07e90f3Sjmcneill if (clk_parent != NULL)
274a07e90f3Sjmcneill return &clk_parent->base;
275a07e90f3Sjmcneill
276a07e90f3Sjmcneill /* No parent in this domain, try FDT */
277a07e90f3Sjmcneill return fdtbus_clock_get(sc->sc_phandle, parent);
278a07e90f3Sjmcneill }
279a07e90f3Sjmcneill
280a07e90f3Sjmcneill static const struct clk_funcs sunxi_ccu_clock_funcs = {
281a07e90f3Sjmcneill .get = sunxi_ccu_clock_get,
282a07e90f3Sjmcneill .put = sunxi_ccu_clock_put,
283a07e90f3Sjmcneill .get_rate = sunxi_ccu_clock_get_rate,
284a07e90f3Sjmcneill .set_rate = sunxi_ccu_clock_set_rate,
285db6d41fbSbouyer .round_rate = sunxi_ccu_clock_round_rate,
286a07e90f3Sjmcneill .enable = sunxi_ccu_clock_enable,
287a07e90f3Sjmcneill .disable = sunxi_ccu_clock_disable,
288a07e90f3Sjmcneill .set_parent = sunxi_ccu_clock_set_parent,
289a07e90f3Sjmcneill .get_parent = sunxi_ccu_clock_get_parent,
290a07e90f3Sjmcneill };
291a07e90f3Sjmcneill
292a07e90f3Sjmcneill struct sunxi_ccu_clk *
sunxi_ccu_clock_find(struct sunxi_ccu_softc * sc,const char * name)293a07e90f3Sjmcneill sunxi_ccu_clock_find(struct sunxi_ccu_softc *sc, const char *name)
294a07e90f3Sjmcneill {
295a07e90f3Sjmcneill for (int i = 0; i < sc->sc_nclks; i++) {
296a07e90f3Sjmcneill if (sc->sc_clks[i].base.name == NULL)
297a07e90f3Sjmcneill continue;
298a07e90f3Sjmcneill if (strcmp(sc->sc_clks[i].base.name, name) == 0)
299a07e90f3Sjmcneill return &sc->sc_clks[i];
300a07e90f3Sjmcneill }
301a07e90f3Sjmcneill
302a07e90f3Sjmcneill return NULL;
303a07e90f3Sjmcneill }
304a07e90f3Sjmcneill
305a07e90f3Sjmcneill int
sunxi_ccu_attach(struct sunxi_ccu_softc * sc)306a07e90f3Sjmcneill sunxi_ccu_attach(struct sunxi_ccu_softc *sc)
307a07e90f3Sjmcneill {
308a07e90f3Sjmcneill bus_addr_t addr;
309a07e90f3Sjmcneill bus_size_t size;
310a07e90f3Sjmcneill int i;
311a07e90f3Sjmcneill
312a07e90f3Sjmcneill if (fdtbus_get_reg(sc->sc_phandle, 0, &addr, &size) != 0) {
313a07e90f3Sjmcneill aprint_error(": couldn't get registers\n");
314a07e90f3Sjmcneill return ENXIO;
315a07e90f3Sjmcneill }
316a07e90f3Sjmcneill if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
317a07e90f3Sjmcneill aprint_error(": couldn't map registers\n");
318a07e90f3Sjmcneill return ENXIO;
319a07e90f3Sjmcneill }
320a07e90f3Sjmcneill
321a756758dSjmcneill sc->sc_clkdom.name = device_xname(sc->sc_dev);
322a07e90f3Sjmcneill sc->sc_clkdom.funcs = &sunxi_ccu_clock_funcs;
323a07e90f3Sjmcneill sc->sc_clkdom.priv = sc;
324a756758dSjmcneill for (i = 0; i < sc->sc_nclks; i++) {
325a07e90f3Sjmcneill sc->sc_clks[i].base.domain = &sc->sc_clkdom;
326a756758dSjmcneill clk_attach(&sc->sc_clks[i].base);
327a756758dSjmcneill }
328a07e90f3Sjmcneill
329a07e90f3Sjmcneill fdtbus_register_clock_controller(sc->sc_dev, sc->sc_phandle,
330a07e90f3Sjmcneill &sunxi_ccu_fdtclock_funcs);
331a07e90f3Sjmcneill
332a07e90f3Sjmcneill fdtbus_register_reset_controller(sc->sc_dev, sc->sc_phandle,
333a07e90f3Sjmcneill &sunxi_ccu_fdtreset_funcs);
334a07e90f3Sjmcneill
335a07e90f3Sjmcneill return 0;
336a07e90f3Sjmcneill }
337a07e90f3Sjmcneill
338a07e90f3Sjmcneill void
sunxi_ccu_print(struct sunxi_ccu_softc * sc)339a07e90f3Sjmcneill sunxi_ccu_print(struct sunxi_ccu_softc *sc)
340a07e90f3Sjmcneill {
341a07e90f3Sjmcneill struct sunxi_ccu_clk *clk;
342a07e90f3Sjmcneill struct clk *clkp_parent;
343a07e90f3Sjmcneill const char *type;
344a07e90f3Sjmcneill int i;
345a07e90f3Sjmcneill
346a07e90f3Sjmcneill for (i = 0; i < sc->sc_nclks; i++) {
347a07e90f3Sjmcneill clk = &sc->sc_clks[i];
348a07e90f3Sjmcneill if (clk->type == SUNXI_CCU_UNKNOWN)
349a07e90f3Sjmcneill continue;
350a07e90f3Sjmcneill
351a07e90f3Sjmcneill clkp_parent = clk_get_parent(&clk->base);
352a07e90f3Sjmcneill
353a07e90f3Sjmcneill switch (clk->type) {
354a07e90f3Sjmcneill case SUNXI_CCU_GATE: type = "gate"; break;
355a07e90f3Sjmcneill case SUNXI_CCU_NM: type = "nm"; break;
35611d415cdSjmcneill case SUNXI_CCU_NKMP: type = "nkmp"; break;
35768166010Sjmcneill case SUNXI_CCU_PREDIV: type = "prediv"; break;
358ddb9dd9cSjmcneill case SUNXI_CCU_DIV: type = "div"; break;
359deeed1ddSjmcneill case SUNXI_CCU_PHASE: type = "phase"; break;
360a5198ca0Sjmcneill case SUNXI_CCU_FIXED_FACTOR: type = "fixed-factor"; break;
361a1f84860Sbouyer case SUNXI_CCU_FRACTIONAL: type = "fractional"; break;
362*c26e3874Sjmcneill case SUNXI_CCU_MUX: type = "mux"; break;
363a07e90f3Sjmcneill default: type = "???"; break;
364a07e90f3Sjmcneill }
365a07e90f3Sjmcneill
3660629510eSjmcneill aprint_debug_dev(sc->sc_dev,
367ddb9dd9cSjmcneill "%3d %-12s %2s %-12s %-7s ",
3680629510eSjmcneill i,
369a07e90f3Sjmcneill clk->base.name,
370a07e90f3Sjmcneill clkp_parent ? "<-" : "",
371a07e90f3Sjmcneill clkp_parent ? clkp_parent->name : "",
372ddb9dd9cSjmcneill type);
373e964f5aaSjakllsch aprint_debug("%10u Hz\n", clk_get_rate(&clk->base));
374a07e90f3Sjmcneill }
375a07e90f3Sjmcneill }
376