1e37e8677SEmmanuel Vadot /*-
2e37e8677SEmmanuel Vadot * SPDX-License-Identifier: BSD-2-Clause
3e37e8677SEmmanuel Vadot *
4e37e8677SEmmanuel Vadot * Copyright (c) 2017,2018 Emmanuel Vadot <manu@freebsd.org>
5e37e8677SEmmanuel Vadot *
6e37e8677SEmmanuel Vadot * Redistribution and use in source and binary forms, with or without
7e37e8677SEmmanuel Vadot * modification, are permitted provided that the following conditions
8e37e8677SEmmanuel Vadot * are met:
9e37e8677SEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright
10e37e8677SEmmanuel Vadot * notice, this list of conditions and the following disclaimer.
11e37e8677SEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright
12e37e8677SEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the
13e37e8677SEmmanuel Vadot * documentation and/or other materials provided with the distribution.
14e37e8677SEmmanuel Vadot *
15e37e8677SEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16e37e8677SEmmanuel Vadot * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17e37e8677SEmmanuel Vadot * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18e37e8677SEmmanuel Vadot * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19e37e8677SEmmanuel Vadot * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20e37e8677SEmmanuel Vadot * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21e37e8677SEmmanuel Vadot * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22e37e8677SEmmanuel Vadot * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23e37e8677SEmmanuel Vadot * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e37e8677SEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e37e8677SEmmanuel Vadot * SUCH DAMAGE.
26e37e8677SEmmanuel Vadot */
27e37e8677SEmmanuel Vadot
28e37e8677SEmmanuel Vadot #include <sys/param.h>
29e37e8677SEmmanuel Vadot #include <sys/systm.h>
30e37e8677SEmmanuel Vadot #include <sys/bus.h>
31e37e8677SEmmanuel Vadot #include <sys/rman.h>
32e37e8677SEmmanuel Vadot #include <sys/kernel.h>
33e37e8677SEmmanuel Vadot #include <sys/module.h>
34e37e8677SEmmanuel Vadot #include <machine/bus.h>
35e37e8677SEmmanuel Vadot
36e37e8677SEmmanuel Vadot #include <dev/fdt/simplebus.h>
37e37e8677SEmmanuel Vadot
38e37e8677SEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
39e37e8677SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
40e37e8677SEmmanuel Vadot
41e37e8677SEmmanuel Vadot #if defined(__aarch64__)
42e37e8677SEmmanuel Vadot #include "opt_soc.h"
43e37e8677SEmmanuel Vadot #endif
44e37e8677SEmmanuel Vadot
45*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_div.h>
46*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_fixed.h>
47*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_mux.h>
48e37e8677SEmmanuel Vadot
49e37e8677SEmmanuel Vadot #include <dev/clk/allwinner/aw_ccung.h>
50e37e8677SEmmanuel Vadot
51e37e8677SEmmanuel Vadot #include <dt-bindings/clock/sun8i-r-ccu.h>
52e37e8677SEmmanuel Vadot #include <dt-bindings/reset/sun8i-r-ccu.h>
53e37e8677SEmmanuel Vadot
54e37e8677SEmmanuel Vadot /* Non-exported clocks */
55e37e8677SEmmanuel Vadot #define CLK_AHB0 1
56e37e8677SEmmanuel Vadot #define CLK_APB0 2
57e37e8677SEmmanuel Vadot
58e37e8677SEmmanuel Vadot static struct aw_ccung_reset ccu_sun8i_r_resets[] = {
59e37e8677SEmmanuel Vadot CCU_RESET(RST_APB0_IR, 0xb0, 1)
60e37e8677SEmmanuel Vadot CCU_RESET(RST_APB0_TIMER, 0xb0, 2)
61e37e8677SEmmanuel Vadot CCU_RESET(RST_APB0_RSB, 0xb0, 3)
62e37e8677SEmmanuel Vadot CCU_RESET(RST_APB0_UART, 0xb0, 4)
63e37e8677SEmmanuel Vadot CCU_RESET(RST_APB0_I2C, 0xb0, 6)
64e37e8677SEmmanuel Vadot };
65e37e8677SEmmanuel Vadot
66e37e8677SEmmanuel Vadot static struct aw_ccung_gate ccu_sun8i_r_gates[] = {
67e37e8677SEmmanuel Vadot CCU_GATE(CLK_APB0_PIO, "apb0-pio", "apb0", 0x28, 0)
68e37e8677SEmmanuel Vadot CCU_GATE(CLK_APB0_IR, "apb0-ir", "apb0", 0x28, 1)
69e37e8677SEmmanuel Vadot CCU_GATE(CLK_APB0_TIMER, "apb0-timer", "apb0", 0x28, 2)
70e37e8677SEmmanuel Vadot CCU_GATE(CLK_APB0_RSB, "apb0-rsb", "apb0", 0x28, 3)
71e37e8677SEmmanuel Vadot CCU_GATE(CLK_APB0_UART, "apb0-uart", "apb0", 0x28, 4)
72e37e8677SEmmanuel Vadot CCU_GATE(CLK_APB0_I2C, "apb0-i2c", "apb0", 0x28, 6)
73e37e8677SEmmanuel Vadot CCU_GATE(CLK_APB0_TWD, "apb0-twd", "apb0", 0x28, 7)
74e37e8677SEmmanuel Vadot };
75e37e8677SEmmanuel Vadot
76e37e8677SEmmanuel Vadot static const char *ar100_parents[] = {"osc32k", "osc24M", "pll_periph0", "iosc"};
77e37e8677SEmmanuel Vadot static const char *a83t_ar100_parents[] = {"osc16M-d512", "osc24M", "pll_periph", "osc16M"};
78e37e8677SEmmanuel Vadot PREDIV_CLK(ar100_clk, CLK_AR100, /* id */
79e37e8677SEmmanuel Vadot "ar100", ar100_parents, /* name, parents */
80e37e8677SEmmanuel Vadot 0x00, /* offset */
81e37e8677SEmmanuel Vadot 16, 2, /* mux */
82e37e8677SEmmanuel Vadot 4, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* div */
83e37e8677SEmmanuel Vadot 8, 5, 0, AW_CLK_FACTOR_HAS_COND, /* prediv */
84e37e8677SEmmanuel Vadot 16, 2, 2); /* prediv condition */
85e37e8677SEmmanuel Vadot PREDIV_CLK(a83t_ar100_clk, CLK_AR100, /* id */
86e37e8677SEmmanuel Vadot "ar100", a83t_ar100_parents, /* name, parents */
87e37e8677SEmmanuel Vadot 0x00, /* offset */
88e37e8677SEmmanuel Vadot 16, 2, /* mux */
89e37e8677SEmmanuel Vadot 4, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* div */
90e37e8677SEmmanuel Vadot 8, 5, 0, AW_CLK_FACTOR_HAS_COND, /* prediv */
91e37e8677SEmmanuel Vadot 16, 2, 2); /* prediv condition */
92e37e8677SEmmanuel Vadot
93e37e8677SEmmanuel Vadot static const char *ahb0_parents[] = {"ar100"};
94e37e8677SEmmanuel Vadot FIXED_CLK(ahb0_clk,
95e37e8677SEmmanuel Vadot CLK_AHB0, /* id */
96e37e8677SEmmanuel Vadot "ahb0", /* name */
97e37e8677SEmmanuel Vadot ahb0_parents, /* parent */
98e37e8677SEmmanuel Vadot 0, /* freq */
99e37e8677SEmmanuel Vadot 1, /* mult */
100e37e8677SEmmanuel Vadot 1, /* div */
101e37e8677SEmmanuel Vadot 0); /* flags */
102e37e8677SEmmanuel Vadot
103e37e8677SEmmanuel Vadot static const char *apb0_parents[] = {"ahb0"};
104e37e8677SEmmanuel Vadot DIV_CLK(apb0_clk,
105e37e8677SEmmanuel Vadot CLK_APB0, /* id */
106e37e8677SEmmanuel Vadot "apb0", apb0_parents, /* name, parents */
107e37e8677SEmmanuel Vadot 0x0c, /* offset */
108e37e8677SEmmanuel Vadot 0, 2, /* shift, width */
109e37e8677SEmmanuel Vadot 0, NULL); /* flags, div table */
110e37e8677SEmmanuel Vadot
111e37e8677SEmmanuel Vadot static const char *r_ccu_ir_parents[] = {"osc32k", "osc24M"};
112e37e8677SEmmanuel Vadot NM_CLK(r_ccu_ir_clk,
113e37e8677SEmmanuel Vadot CLK_IR, /* id */
114e37e8677SEmmanuel Vadot "ir", r_ccu_ir_parents, /* names, parents */
115e37e8677SEmmanuel Vadot 0x54, /* offset */
116e37e8677SEmmanuel Vadot 0, 4, 0, 0, /* N factor */
117e37e8677SEmmanuel Vadot 16, 2, 0, 0, /* M factor */
118e37e8677SEmmanuel Vadot 24, 2, /* mux */
119e37e8677SEmmanuel Vadot 31, /* gate */
120e37e8677SEmmanuel Vadot AW_CLK_HAS_MUX | AW_CLK_REPARENT | AW_CLK_HAS_GATE);/* flags */
121e37e8677SEmmanuel Vadot
122e37e8677SEmmanuel Vadot static const char *a83t_ir_parents[] = {"osc16M", "osc24M"};
123e37e8677SEmmanuel Vadot static struct aw_clk_nm_def a83t_ir_clk = {
124e37e8677SEmmanuel Vadot .clkdef = {
125e37e8677SEmmanuel Vadot .id = CLK_IR,
126e37e8677SEmmanuel Vadot .name = "ir",
127e37e8677SEmmanuel Vadot .parent_names = a83t_ir_parents,
128e37e8677SEmmanuel Vadot .parent_cnt = nitems(a83t_ir_parents),
129e37e8677SEmmanuel Vadot },
130e37e8677SEmmanuel Vadot .offset = 0x54,
131e37e8677SEmmanuel Vadot .n = {.shift = 0, .width = 4, .flags = AW_CLK_FACTOR_POWER_OF_TWO, },
132e37e8677SEmmanuel Vadot .m = {.shift = 16, .width = 2},
133e37e8677SEmmanuel Vadot .prediv = {
134e37e8677SEmmanuel Vadot .cond_shift = 24,
135e37e8677SEmmanuel Vadot .cond_width = 2,
136e37e8677SEmmanuel Vadot .cond_value = 0,
137e37e8677SEmmanuel Vadot .value = 16
138e37e8677SEmmanuel Vadot },
139e37e8677SEmmanuel Vadot .mux_shift = 24,
140e37e8677SEmmanuel Vadot .mux_width = 2,
141e37e8677SEmmanuel Vadot .flags = AW_CLK_HAS_MUX | AW_CLK_HAS_PREDIV,
142e37e8677SEmmanuel Vadot };
143e37e8677SEmmanuel Vadot
144e37e8677SEmmanuel Vadot static struct aw_ccung_clk clks[] = {
145e37e8677SEmmanuel Vadot { .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &ar100_clk},
146e37e8677SEmmanuel Vadot { .type = AW_CLK_DIV, .clk.div = &apb0_clk},
147e37e8677SEmmanuel Vadot { .type = AW_CLK_FIXED, .clk.fixed = &ahb0_clk},
148e37e8677SEmmanuel Vadot { .type = AW_CLK_NM, .clk.nm = &r_ccu_ir_clk},
149e37e8677SEmmanuel Vadot };
150e37e8677SEmmanuel Vadot
151e37e8677SEmmanuel Vadot static struct aw_ccung_clk a83t_clks[] = {
152e37e8677SEmmanuel Vadot { .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &a83t_ar100_clk},
153e37e8677SEmmanuel Vadot { .type = AW_CLK_DIV, .clk.div = &apb0_clk},
154e37e8677SEmmanuel Vadot { .type = AW_CLK_FIXED, .clk.fixed = &ahb0_clk},
155e37e8677SEmmanuel Vadot { .type = AW_CLK_NM, .clk.nm = &a83t_ir_clk},
156e37e8677SEmmanuel Vadot };
157e37e8677SEmmanuel Vadot
158e37e8677SEmmanuel Vadot static struct ofw_compat_data compat_data[] = {
159e37e8677SEmmanuel Vadot #if defined(SOC_ALLWINNER_H3) || defined(SOC_ALLWINNER_H5)
160e37e8677SEmmanuel Vadot { "allwinner,sun8i-h3-r-ccu", 1 },
161e37e8677SEmmanuel Vadot #endif
162e37e8677SEmmanuel Vadot #if defined(SOC_ALLWINNER_A64)
163e37e8677SEmmanuel Vadot { "allwinner,sun50i-a64-r-ccu", 1 },
164e37e8677SEmmanuel Vadot #endif
165e37e8677SEmmanuel Vadot { NULL, 0},
166e37e8677SEmmanuel Vadot };
167e37e8677SEmmanuel Vadot
168e37e8677SEmmanuel Vadot static int
ccu_sun8i_r_probe(device_t dev)169e37e8677SEmmanuel Vadot ccu_sun8i_r_probe(device_t dev)
170e37e8677SEmmanuel Vadot {
171e37e8677SEmmanuel Vadot
172e37e8677SEmmanuel Vadot if (!ofw_bus_status_okay(dev))
173e37e8677SEmmanuel Vadot return (ENXIO);
174e37e8677SEmmanuel Vadot
175e37e8677SEmmanuel Vadot if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
176e37e8677SEmmanuel Vadot return (ENXIO);
177e37e8677SEmmanuel Vadot
178e37e8677SEmmanuel Vadot device_set_desc(dev, "Allwinner SUN8I_R Clock Control Unit NG");
179e37e8677SEmmanuel Vadot return (BUS_PROBE_DEFAULT);
180e37e8677SEmmanuel Vadot }
181e37e8677SEmmanuel Vadot
182e37e8677SEmmanuel Vadot static int
ccu_sun8i_r_attach(device_t dev)183e37e8677SEmmanuel Vadot ccu_sun8i_r_attach(device_t dev)
184e37e8677SEmmanuel Vadot {
185e37e8677SEmmanuel Vadot struct aw_ccung_softc *sc;
186e37e8677SEmmanuel Vadot
187e37e8677SEmmanuel Vadot sc = device_get_softc(dev);
188e37e8677SEmmanuel Vadot
189e37e8677SEmmanuel Vadot sc->resets = ccu_sun8i_r_resets;
190e37e8677SEmmanuel Vadot sc->nresets = nitems(ccu_sun8i_r_resets);
191e37e8677SEmmanuel Vadot sc->gates = ccu_sun8i_r_gates;
192e37e8677SEmmanuel Vadot sc->ngates = nitems(ccu_sun8i_r_gates);
193e37e8677SEmmanuel Vadot sc->clks = clks;
194e37e8677SEmmanuel Vadot sc->nclks = nitems(clks);
195e37e8677SEmmanuel Vadot
196e37e8677SEmmanuel Vadot return (aw_ccung_attach(dev));
197e37e8677SEmmanuel Vadot }
198e37e8677SEmmanuel Vadot
199e37e8677SEmmanuel Vadot static device_method_t ccu_sun8i_r_methods[] = {
200e37e8677SEmmanuel Vadot /* Device interface */
201e37e8677SEmmanuel Vadot DEVMETHOD(device_probe, ccu_sun8i_r_probe),
202e37e8677SEmmanuel Vadot DEVMETHOD(device_attach, ccu_sun8i_r_attach),
203e37e8677SEmmanuel Vadot
204e37e8677SEmmanuel Vadot DEVMETHOD_END
205e37e8677SEmmanuel Vadot };
206e37e8677SEmmanuel Vadot
207e37e8677SEmmanuel Vadot DEFINE_CLASS_1(ccu_sun8i_r, ccu_sun8i_r_driver, ccu_sun8i_r_methods,
208e37e8677SEmmanuel Vadot sizeof(struct aw_ccung_softc), aw_ccung_driver);
209e37e8677SEmmanuel Vadot
210e37e8677SEmmanuel Vadot EARLY_DRIVER_MODULE(ccu_sun8i_r, simplebus, ccu_sun8i_r_driver, 0, 0,
211e37e8677SEmmanuel Vadot BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
212e37e8677SEmmanuel Vadot
213e37e8677SEmmanuel Vadot static int
ccu_a83t_r_probe(device_t dev)214e37e8677SEmmanuel Vadot ccu_a83t_r_probe(device_t dev)
215e37e8677SEmmanuel Vadot {
216e37e8677SEmmanuel Vadot
217e37e8677SEmmanuel Vadot if (!ofw_bus_status_okay(dev))
218e37e8677SEmmanuel Vadot return (ENXIO);
219e37e8677SEmmanuel Vadot
220e37e8677SEmmanuel Vadot if (!ofw_bus_is_compatible(dev, "allwinner,sun8i-a83t-r-ccu"))
221e37e8677SEmmanuel Vadot return (ENXIO);
222e37e8677SEmmanuel Vadot
223e37e8677SEmmanuel Vadot device_set_desc(dev, "Allwinner A83T_R Clock Control Unit NG");
224e37e8677SEmmanuel Vadot return (BUS_PROBE_DEFAULT);
225e37e8677SEmmanuel Vadot }
226e37e8677SEmmanuel Vadot
227e37e8677SEmmanuel Vadot static int
ccu_a83t_r_attach(device_t dev)228e37e8677SEmmanuel Vadot ccu_a83t_r_attach(device_t dev)
229e37e8677SEmmanuel Vadot {
230e37e8677SEmmanuel Vadot struct aw_ccung_softc *sc;
231e37e8677SEmmanuel Vadot
232e37e8677SEmmanuel Vadot sc = device_get_softc(dev);
233e37e8677SEmmanuel Vadot
234e37e8677SEmmanuel Vadot sc->resets = ccu_sun8i_r_resets;
235e37e8677SEmmanuel Vadot sc->nresets = nitems(ccu_sun8i_r_resets);
236e37e8677SEmmanuel Vadot sc->gates = ccu_sun8i_r_gates;
237e37e8677SEmmanuel Vadot sc->ngates = nitems(ccu_sun8i_r_gates);
238e37e8677SEmmanuel Vadot sc->clks = a83t_clks;
239e37e8677SEmmanuel Vadot sc->nclks = nitems(a83t_clks);
240e37e8677SEmmanuel Vadot
241e37e8677SEmmanuel Vadot return (aw_ccung_attach(dev));
242e37e8677SEmmanuel Vadot }
243e37e8677SEmmanuel Vadot
244e37e8677SEmmanuel Vadot static device_method_t ccu_a83t_r_methods[] = {
245e37e8677SEmmanuel Vadot /* Device interface */
246e37e8677SEmmanuel Vadot DEVMETHOD(device_probe, ccu_a83t_r_probe),
247e37e8677SEmmanuel Vadot DEVMETHOD(device_attach, ccu_a83t_r_attach),
248e37e8677SEmmanuel Vadot
249e37e8677SEmmanuel Vadot DEVMETHOD_END
250e37e8677SEmmanuel Vadot };
251e37e8677SEmmanuel Vadot
252e37e8677SEmmanuel Vadot DEFINE_CLASS_1(ccu_a83t_r, ccu_a83t_r_driver, ccu_a83t_r_methods,
253e37e8677SEmmanuel Vadot sizeof(struct aw_ccung_softc), aw_ccung_driver);
254e37e8677SEmmanuel Vadot
255e37e8677SEmmanuel Vadot EARLY_DRIVER_MODULE(ccu_a83t_r, simplebus, ccu_a83t_r_driver, 0, 0,
256e37e8677SEmmanuel Vadot BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
257