1*0612538eSJari Sihvola /*-
2*0612538eSJari Sihvola * SPDX-License-Identifier: BSD-2-Clause
3*0612538eSJari Sihvola *
4*0612538eSJari Sihvola * Copyright (c) 2024 Jari Sihvola <jsihv@gmx.com>
5*0612538eSJari Sihvola * Copyright (c) 2024 The FreeBSD Foundation
6*0612538eSJari Sihvola *
7*0612538eSJari Sihvola * Portions of this software were developed by Mitchell Horne
8*0612538eSJari Sihvola * <mhorne@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
9*0612538eSJari Sihvola */
10*0612538eSJari Sihvola
11*0612538eSJari Sihvola #include <sys/param.h>
12*0612538eSJari Sihvola #include <sys/systm.h>
13*0612538eSJari Sihvola #include <sys/bus.h>
14*0612538eSJari Sihvola #include <sys/kernel.h>
15*0612538eSJari Sihvola #include <sys/module.h>
16*0612538eSJari Sihvola #include <sys/mutex.h>
17*0612538eSJari Sihvola
18*0612538eSJari Sihvola #include <machine/bus.h>
19*0612538eSJari Sihvola
20*0612538eSJari Sihvola #include <dev/fdt/simplebus.h>
21*0612538eSJari Sihvola #include <dev/ofw/ofw_bus.h>
22*0612538eSJari Sihvola #include <dev/ofw/ofw_bus_subr.h>
23*0612538eSJari Sihvola
24*0612538eSJari Sihvola #include <dev/clk/clk.h>
25*0612538eSJari Sihvola #include <dev/clk/starfive/jh7110_clk.h>
26*0612538eSJari Sihvola #include <dev/clk/starfive/jh7110_clk_pll.h>
27*0612538eSJari Sihvola #include <dev/syscon/syscon.h>
28*0612538eSJari Sihvola
29*0612538eSJari Sihvola #include <dt-bindings/clock/starfive,jh7110-crg.h>
30*0612538eSJari Sihvola
31*0612538eSJari Sihvola #include "clkdev_if.h"
32*0612538eSJari Sihvola #include "syscon_if.h"
33*0612538eSJari Sihvola
34*0612538eSJari Sihvola #define JH7110_SYS_SYSCON_SYSCFG24 0x18
35*0612538eSJari Sihvola #define JH7110_SYS_SYSCON_SYSCFG28 0x1c
36*0612538eSJari Sihvola #define JH7110_SYS_SYSCON_SYSCFG32 0x20
37*0612538eSJari Sihvola #define JH7110_SYS_SYSCON_SYSCFG36 0x24
38*0612538eSJari Sihvola #define JH7110_SYS_SYSCON_SYSCFG40 0x28
39*0612538eSJari Sihvola #define JH7110_SYS_SYSCON_SYSCFG44 0x2c
40*0612538eSJari Sihvola #define JH7110_SYS_SYSCON_SYSCFG48 0x30
41*0612538eSJari Sihvola #define JH7110_SYS_SYSCON_SYSCFG52 0x34
42*0612538eSJari Sihvola
43*0612538eSJari Sihvola #define DEVICE_LOCK(_clk) \
44*0612538eSJari Sihvola CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
45*0612538eSJari Sihvola #define DEVICE_UNLOCK(_clk) \
46*0612538eSJari Sihvola CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
47*0612538eSJari Sihvola
48*0612538eSJari Sihvola #define PLL_MASK_FILL(sc, id) \
49*0612538eSJari Sihvola do { \
50*0612538eSJari Sihvola sc->dacpd_mask = PLL## id ##_DACPD_MASK; \
51*0612538eSJari Sihvola sc->dsmpd_mask = PLL## id ##_DSMPD_MASK; \
52*0612538eSJari Sihvola sc->fbdiv_mask = PLL## id ##_FBDIV_MASK; \
53*0612538eSJari Sihvola sc->frac_mask = PLL## id ##_FRAC_MASK; \
54*0612538eSJari Sihvola sc->prediv_mask = PLL## id ##_PREDIV_MASK; \
55*0612538eSJari Sihvola sc->postdiv1_mask = PLL## id ##_POSTDIV1_MASK; \
56*0612538eSJari Sihvola } while (0)
57*0612538eSJari Sihvola
58*0612538eSJari Sihvola #define PLL_SHIFT_FILL(sc, id) \
59*0612538eSJari Sihvola do { \
60*0612538eSJari Sihvola sc->dacpd_shift = PLL## id ##_DACPD_SHIFT; \
61*0612538eSJari Sihvola sc->dsmpd_shift = PLL## id ##_DSMPD_SHIFT; \
62*0612538eSJari Sihvola sc->fbdiv_shift = PLL## id ##_FBDIV_SHIFT; \
63*0612538eSJari Sihvola sc->frac_shift = PLL## id ##_FRAC_SHIFT; \
64*0612538eSJari Sihvola sc->prediv_shift = PLL## id ##_PREDIV_SHIFT; \
65*0612538eSJari Sihvola sc->postdiv1_shift = PLL## id ##_POSTDIV1_SHIFT; \
66*0612538eSJari Sihvola } while (0)
67*0612538eSJari Sihvola
68*0612538eSJari Sihvola struct jh7110_clk_pll_softc {
69*0612538eSJari Sihvola struct mtx mtx;
70*0612538eSJari Sihvola struct clkdom *clkdom;
71*0612538eSJari Sihvola struct syscon *syscon;
72*0612538eSJari Sihvola };
73*0612538eSJari Sihvola
74*0612538eSJari Sihvola struct jh7110_pll_clknode_softc {
75*0612538eSJari Sihvola uint32_t dacpd_offset;
76*0612538eSJari Sihvola uint32_t dsmpd_offset;
77*0612538eSJari Sihvola uint32_t fbdiv_offset;
78*0612538eSJari Sihvola uint32_t frac_offset;
79*0612538eSJari Sihvola uint32_t prediv_offset;
80*0612538eSJari Sihvola uint32_t postdiv1_offset;
81*0612538eSJari Sihvola
82*0612538eSJari Sihvola uint32_t dacpd_mask;
83*0612538eSJari Sihvola uint32_t dsmpd_mask;
84*0612538eSJari Sihvola uint32_t fbdiv_mask;
85*0612538eSJari Sihvola uint32_t frac_mask;
86*0612538eSJari Sihvola uint32_t prediv_mask;
87*0612538eSJari Sihvola uint32_t postdiv1_mask;
88*0612538eSJari Sihvola
89*0612538eSJari Sihvola uint32_t dacpd_shift;
90*0612538eSJari Sihvola uint32_t dsmpd_shift;
91*0612538eSJari Sihvola uint32_t fbdiv_shift;
92*0612538eSJari Sihvola uint32_t frac_shift;
93*0612538eSJari Sihvola uint32_t prediv_shift;
94*0612538eSJari Sihvola uint32_t postdiv1_shift;
95*0612538eSJari Sihvola
96*0612538eSJari Sihvola const struct jh7110_pll_syscon_value *syscon_arr;
97*0612538eSJari Sihvola int syscon_nitems;
98*0612538eSJari Sihvola };
99*0612538eSJari Sihvola
100*0612538eSJari Sihvola static const char *pll_parents[] = { "osc" };
101*0612538eSJari Sihvola
102*0612538eSJari Sihvola static struct jh7110_clk_def pll_out_clks[] = {
103*0612538eSJari Sihvola {
104*0612538eSJari Sihvola .clkdef.id = JH7110_PLLCLK_PLL0_OUT,
105*0612538eSJari Sihvola .clkdef.name = "pll0_out",
106*0612538eSJari Sihvola .clkdef.parent_names = pll_parents,
107*0612538eSJari Sihvola .clkdef.parent_cnt = nitems(pll_parents),
108*0612538eSJari Sihvola .clkdef.flags = CLK_NODE_STATIC_STRINGS,
109*0612538eSJari Sihvola },
110*0612538eSJari Sihvola {
111*0612538eSJari Sihvola .clkdef.id = JH7110_PLLCLK_PLL1_OUT,
112*0612538eSJari Sihvola .clkdef.name = "pll1_out",
113*0612538eSJari Sihvola .clkdef.parent_names = pll_parents,
114*0612538eSJari Sihvola .clkdef.parent_cnt = nitems(pll_parents),
115*0612538eSJari Sihvola .clkdef.flags = CLK_NODE_STATIC_STRINGS,
116*0612538eSJari Sihvola },
117*0612538eSJari Sihvola {
118*0612538eSJari Sihvola .clkdef.id = JH7110_PLLCLK_PLL2_OUT,
119*0612538eSJari Sihvola .clkdef.name = "pll2_out",
120*0612538eSJari Sihvola .clkdef.parent_names = pll_parents,
121*0612538eSJari Sihvola .clkdef.parent_cnt = nitems(pll_parents),
122*0612538eSJari Sihvola .clkdef.flags = CLK_NODE_STATIC_STRINGS,
123*0612538eSJari Sihvola },
124*0612538eSJari Sihvola };
125*0612538eSJari Sihvola
126*0612538eSJari Sihvola static int jh7110_clk_pll_register(struct clkdom *clkdom,
127*0612538eSJari Sihvola struct jh7110_clk_def *clkdef);
128*0612538eSJari Sihvola
129*0612538eSJari Sihvola static int
jh7110_clk_pll_recalc_freq(struct clknode * clk,uint64_t * freq)130*0612538eSJari Sihvola jh7110_clk_pll_recalc_freq(struct clknode *clk, uint64_t *freq)
131*0612538eSJari Sihvola {
132*0612538eSJari Sihvola struct jh7110_clk_pll_softc *sc;
133*0612538eSJari Sihvola struct jh7110_pll_clknode_softc *clk_sc;
134*0612538eSJari Sihvola uint32_t dacpd, dsmpd, fbdiv, prediv, postdiv1;
135*0612538eSJari Sihvola uint64_t frac, fcal = 0;
136*0612538eSJari Sihvola
137*0612538eSJari Sihvola sc = device_get_softc(clknode_get_device(clk));
138*0612538eSJari Sihvola clk_sc = clknode_get_softc(clk);
139*0612538eSJari Sihvola
140*0612538eSJari Sihvola DEVICE_LOCK(clk);
141*0612538eSJari Sihvola
142*0612538eSJari Sihvola dacpd = (SYSCON_READ_4(sc->syscon, clk_sc->dacpd_offset) & clk_sc->dacpd_mask) >>
143*0612538eSJari Sihvola clk_sc->dacpd_shift;
144*0612538eSJari Sihvola dsmpd = (SYSCON_READ_4(sc->syscon, clk_sc->dsmpd_offset) & clk_sc->dsmpd_mask) >>
145*0612538eSJari Sihvola clk_sc->dsmpd_shift;
146*0612538eSJari Sihvola fbdiv = (SYSCON_READ_4(sc->syscon, clk_sc->fbdiv_offset) & clk_sc->fbdiv_mask) >>
147*0612538eSJari Sihvola clk_sc->fbdiv_shift;
148*0612538eSJari Sihvola prediv = (SYSCON_READ_4(sc->syscon, clk_sc->prediv_offset) & clk_sc->prediv_mask) >>
149*0612538eSJari Sihvola clk_sc->prediv_shift;
150*0612538eSJari Sihvola postdiv1 = (SYSCON_READ_4(sc->syscon, clk_sc->postdiv1_offset) &
151*0612538eSJari Sihvola clk_sc->postdiv1_mask) >> clk_sc->postdiv1_shift;
152*0612538eSJari Sihvola frac = (SYSCON_READ_4(sc->syscon, clk_sc->frac_offset) & clk_sc->frac_mask) >>
153*0612538eSJari Sihvola clk_sc->frac_shift;
154*0612538eSJari Sihvola
155*0612538eSJari Sihvola DEVICE_UNLOCK(clk);
156*0612538eSJari Sihvola
157*0612538eSJari Sihvola /* dacpd and dsmpd both being 0 entails Fraction Multiple Mode */
158*0612538eSJari Sihvola if (dacpd == 0 && dsmpd == 0)
159*0612538eSJari Sihvola fcal = frac * FRAC_PATR_SIZE / (1 << 24);
160*0612538eSJari Sihvola
161*0612538eSJari Sihvola *freq = *freq / FRAC_PATR_SIZE * (fbdiv * FRAC_PATR_SIZE + fcal) /
162*0612538eSJari Sihvola prediv / (1 << postdiv1);
163*0612538eSJari Sihvola
164*0612538eSJari Sihvola return (0);
165*0612538eSJari Sihvola }
166*0612538eSJari Sihvola
167*0612538eSJari Sihvola static int
jh7110_clk_pll_set_freq(struct clknode * clk,uint64_t fin,uint64_t * fout,int flags,int * done)168*0612538eSJari Sihvola jh7110_clk_pll_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
169*0612538eSJari Sihvola int flags, int *done)
170*0612538eSJari Sihvola {
171*0612538eSJari Sihvola struct jh7110_clk_pll_softc *sc;
172*0612538eSJari Sihvola struct jh7110_pll_clknode_softc *clk_sc;
173*0612538eSJari Sihvola const struct jh7110_pll_syscon_value *syscon_val = NULL;
174*0612538eSJari Sihvola
175*0612538eSJari Sihvola sc = device_get_softc(clknode_get_device(clk));
176*0612538eSJari Sihvola clk_sc = clknode_get_softc(clk);
177*0612538eSJari Sihvola
178*0612538eSJari Sihvola for (int i = 0; i != clk_sc->syscon_nitems; i++) {
179*0612538eSJari Sihvola if (*fout == clk_sc->syscon_arr[i].freq) {
180*0612538eSJari Sihvola syscon_val = &clk_sc->syscon_arr[i];
181*0612538eSJari Sihvola }
182*0612538eSJari Sihvola }
183*0612538eSJari Sihvola
184*0612538eSJari Sihvola if (syscon_val == NULL) {
185*0612538eSJari Sihvola printf("%s: tried to set an unknown frequency %ju for %s\n",
186*0612538eSJari Sihvola __func__, *fout, clknode_get_name(clk));
187*0612538eSJari Sihvola return (EINVAL);
188*0612538eSJari Sihvola }
189*0612538eSJari Sihvola
190*0612538eSJari Sihvola if ((flags & CLK_SET_DRYRUN) != 0) {
191*0612538eSJari Sihvola *done = 1;
192*0612538eSJari Sihvola return (0);
193*0612538eSJari Sihvola }
194*0612538eSJari Sihvola
195*0612538eSJari Sihvola DEVICE_LOCK(clk);
196*0612538eSJari Sihvola
197*0612538eSJari Sihvola SYSCON_MODIFY_4(sc->syscon, clk_sc->dacpd_offset, clk_sc->dacpd_mask,
198*0612538eSJari Sihvola syscon_val->dacpd << clk_sc->dacpd_shift & clk_sc->dacpd_mask);
199*0612538eSJari Sihvola SYSCON_MODIFY_4(sc->syscon, clk_sc->dsmpd_offset, clk_sc->dsmpd_mask,
200*0612538eSJari Sihvola syscon_val->dsmpd << clk_sc->dsmpd_shift & clk_sc->dsmpd_mask);
201*0612538eSJari Sihvola SYSCON_MODIFY_4(sc->syscon, clk_sc->prediv_offset, clk_sc->prediv_mask,
202*0612538eSJari Sihvola syscon_val->prediv << clk_sc->prediv_shift & clk_sc->prediv_mask);
203*0612538eSJari Sihvola SYSCON_MODIFY_4(sc->syscon, clk_sc->fbdiv_offset, clk_sc->fbdiv_mask,
204*0612538eSJari Sihvola syscon_val->fbdiv << clk_sc->fbdiv_shift & clk_sc->fbdiv_mask);
205*0612538eSJari Sihvola SYSCON_MODIFY_4(sc->syscon, clk_sc->postdiv1_offset,
206*0612538eSJari Sihvola clk_sc->postdiv1_mask, (syscon_val->postdiv1 >> 1) <<
207*0612538eSJari Sihvola clk_sc->postdiv1_shift & clk_sc->postdiv1_mask);
208*0612538eSJari Sihvola
209*0612538eSJari Sihvola if (!syscon_val->dacpd && !syscon_val->dsmpd) {
210*0612538eSJari Sihvola SYSCON_MODIFY_4(sc->syscon, clk_sc->frac_offset, clk_sc->frac_mask,
211*0612538eSJari Sihvola syscon_val->frac << clk_sc->frac_shift & clk_sc->frac_mask);
212*0612538eSJari Sihvola }
213*0612538eSJari Sihvola
214*0612538eSJari Sihvola DEVICE_UNLOCK(clk);
215*0612538eSJari Sihvola
216*0612538eSJari Sihvola *done = 1;
217*0612538eSJari Sihvola return (0);
218*0612538eSJari Sihvola }
219*0612538eSJari Sihvola
220*0612538eSJari Sihvola static int
jh7110_clk_pll_init(struct clknode * clk,device_t dev)221*0612538eSJari Sihvola jh7110_clk_pll_init(struct clknode *clk, device_t dev)
222*0612538eSJari Sihvola {
223*0612538eSJari Sihvola clknode_init_parent_idx(clk, 0);
224*0612538eSJari Sihvola
225*0612538eSJari Sihvola return (0);
226*0612538eSJari Sihvola }
227*0612538eSJari Sihvola
228*0612538eSJari Sihvola static int
jh7110_clk_pll_probe(device_t dev)229*0612538eSJari Sihvola jh7110_clk_pll_probe(device_t dev)
230*0612538eSJari Sihvola {
231*0612538eSJari Sihvola if (!ofw_bus_status_okay(dev))
232*0612538eSJari Sihvola return (ENXIO);
233*0612538eSJari Sihvola
234*0612538eSJari Sihvola if (!ofw_bus_is_compatible(dev, "starfive,jh7110-pll"))
235*0612538eSJari Sihvola return (ENXIO);
236*0612538eSJari Sihvola
237*0612538eSJari Sihvola device_set_desc(dev, "StarFive JH7110 PLL clock generator");
238*0612538eSJari Sihvola
239*0612538eSJari Sihvola return (BUS_PROBE_DEFAULT);
240*0612538eSJari Sihvola }
241*0612538eSJari Sihvola
242*0612538eSJari Sihvola static int
jh7110_clk_pll_attach(device_t dev)243*0612538eSJari Sihvola jh7110_clk_pll_attach(device_t dev)
244*0612538eSJari Sihvola {
245*0612538eSJari Sihvola struct jh7110_clk_pll_softc *sc;
246*0612538eSJari Sihvola int error;
247*0612538eSJari Sihvola
248*0612538eSJari Sihvola sc = device_get_softc(dev);
249*0612538eSJari Sihvola
250*0612538eSJari Sihvola mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
251*0612538eSJari Sihvola
252*0612538eSJari Sihvola sc->clkdom = clkdom_create(dev);
253*0612538eSJari Sihvola if (sc->clkdom == NULL) {
254*0612538eSJari Sihvola device_printf(dev, "Couldn't create clkdom\n");
255*0612538eSJari Sihvola return (ENXIO);
256*0612538eSJari Sihvola }
257*0612538eSJari Sihvola
258*0612538eSJari Sihvola error = syscon_get_by_ofw_node(dev, OF_parent(ofw_bus_get_node(dev)),
259*0612538eSJari Sihvola &sc->syscon);
260*0612538eSJari Sihvola if (error != 0) {
261*0612538eSJari Sihvola device_printf(dev, "Couldn't get syscon handle of parent\n");
262*0612538eSJari Sihvola return (error);
263*0612538eSJari Sihvola }
264*0612538eSJari Sihvola
265*0612538eSJari Sihvola for (int i = 0; i < nitems(pll_out_clks); i++) {
266*0612538eSJari Sihvola error = jh7110_clk_pll_register(sc->clkdom, &pll_out_clks[i]);
267*0612538eSJari Sihvola if (error != 0)
268*0612538eSJari Sihvola device_printf(dev, "Couldn't register clock %s: %d\n",
269*0612538eSJari Sihvola pll_out_clks[i].clkdef.name, error);
270*0612538eSJari Sihvola }
271*0612538eSJari Sihvola
272*0612538eSJari Sihvola error = clkdom_finit(sc->clkdom);
273*0612538eSJari Sihvola if (error != 0) {
274*0612538eSJari Sihvola device_printf(dev, "clkdom_finit() returned %d\n", error);
275*0612538eSJari Sihvola }
276*0612538eSJari Sihvola
277*0612538eSJari Sihvola if (bootverbose)
278*0612538eSJari Sihvola clkdom_dump(sc->clkdom);
279*0612538eSJari Sihvola
280*0612538eSJari Sihvola return (0);
281*0612538eSJari Sihvola }
282*0612538eSJari Sihvola
283*0612538eSJari Sihvola static void
jh7110_clk_pll_device_lock(device_t dev)284*0612538eSJari Sihvola jh7110_clk_pll_device_lock(device_t dev)
285*0612538eSJari Sihvola {
286*0612538eSJari Sihvola struct jh7110_clk_pll_softc *sc;
287*0612538eSJari Sihvola
288*0612538eSJari Sihvola sc = device_get_softc(dev);
289*0612538eSJari Sihvola mtx_lock(&sc->mtx);
290*0612538eSJari Sihvola }
291*0612538eSJari Sihvola
292*0612538eSJari Sihvola static void
jh7110_clk_pll_device_unlock(device_t dev)293*0612538eSJari Sihvola jh7110_clk_pll_device_unlock(device_t dev)
294*0612538eSJari Sihvola {
295*0612538eSJari Sihvola struct jh7110_clk_pll_softc *sc;
296*0612538eSJari Sihvola
297*0612538eSJari Sihvola sc = device_get_softc(dev);
298*0612538eSJari Sihvola mtx_unlock(&sc->mtx);
299*0612538eSJari Sihvola }
300*0612538eSJari Sihvola
301*0612538eSJari Sihvola static clknode_method_t jh7110_pllnode_methods[] = {
302*0612538eSJari Sihvola /* Device interface */
303*0612538eSJari Sihvola CLKNODEMETHOD(clknode_init, jh7110_clk_pll_init),
304*0612538eSJari Sihvola CLKNODEMETHOD(clknode_recalc_freq, jh7110_clk_pll_recalc_freq),
305*0612538eSJari Sihvola CLKNODEMETHOD(clknode_set_freq, jh7110_clk_pll_set_freq),
306*0612538eSJari Sihvola
307*0612538eSJari Sihvola CLKNODEMETHOD_END
308*0612538eSJari Sihvola };
309*0612538eSJari Sihvola
310*0612538eSJari Sihvola static device_method_t jh7110_clk_pll_methods[] = {
311*0612538eSJari Sihvola /* Device interface */
312*0612538eSJari Sihvola DEVMETHOD(device_probe, jh7110_clk_pll_probe),
313*0612538eSJari Sihvola DEVMETHOD(device_attach, jh7110_clk_pll_attach),
314*0612538eSJari Sihvola
315*0612538eSJari Sihvola /* clkdev interface */
316*0612538eSJari Sihvola DEVMETHOD(clkdev_device_lock, jh7110_clk_pll_device_lock),
317*0612538eSJari Sihvola DEVMETHOD(clkdev_device_unlock, jh7110_clk_pll_device_unlock),
318*0612538eSJari Sihvola
319*0612538eSJari Sihvola DEVMETHOD_END
320*0612538eSJari Sihvola };
321*0612538eSJari Sihvola
322*0612538eSJari Sihvola DEFINE_CLASS_1(jh7110_pllnode, jh7110_pllnode_class, jh7110_pllnode_methods,
323*0612538eSJari Sihvola sizeof(struct jh7110_pll_clknode_softc), clknode_class);
324*0612538eSJari Sihvola DEFINE_CLASS_0(jh7110_clk_pll, jh7110_clk_pll_driver, jh7110_clk_pll_methods,
325*0612538eSJari Sihvola sizeof(struct jh7110_clk_pll_softc));
326*0612538eSJari Sihvola EARLY_DRIVER_MODULE(jh7110_clk_pll, simplebus, jh7110_clk_pll_driver, 0, 0,
327*0612538eSJari Sihvola BUS_PASS_BUS + BUS_PASS_ORDER_EARLY);
328*0612538eSJari Sihvola MODULE_VERSION(jh7110_clk_pll, 1);
329*0612538eSJari Sihvola
330*0612538eSJari Sihvola int
jh7110_clk_pll_register(struct clkdom * clkdom,struct jh7110_clk_def * clkdef)331*0612538eSJari Sihvola jh7110_clk_pll_register(struct clkdom *clkdom, struct jh7110_clk_def *clkdef)
332*0612538eSJari Sihvola {
333*0612538eSJari Sihvola struct clknode *clk = NULL;
334*0612538eSJari Sihvola struct jh7110_pll_clknode_softc *sc;
335*0612538eSJari Sihvola
336*0612538eSJari Sihvola clk = clknode_create(clkdom, &jh7110_pllnode_class, &clkdef->clkdef);
337*0612538eSJari Sihvola if (clk == NULL)
338*0612538eSJari Sihvola return (1);
339*0612538eSJari Sihvola
340*0612538eSJari Sihvola sc = clknode_get_softc(clk);
341*0612538eSJari Sihvola
342*0612538eSJari Sihvola switch (clkdef->clkdef.id) {
343*0612538eSJari Sihvola case JH7110_PLLCLK_PLL0_OUT:
344*0612538eSJari Sihvola sc->syscon_arr = jh7110_pll0_syscon_freq;
345*0612538eSJari Sihvola sc->syscon_nitems = nitems(jh7110_pll0_syscon_freq);
346*0612538eSJari Sihvola PLL_MASK_FILL(sc, 0);
347*0612538eSJari Sihvola PLL_SHIFT_FILL(sc, 0);
348*0612538eSJari Sihvola sc->dacpd_offset = JH7110_SYS_SYSCON_SYSCFG24;
349*0612538eSJari Sihvola sc->dsmpd_offset = JH7110_SYS_SYSCON_SYSCFG24;
350*0612538eSJari Sihvola sc->fbdiv_offset = JH7110_SYS_SYSCON_SYSCFG28;
351*0612538eSJari Sihvola sc->frac_offset = JH7110_SYS_SYSCON_SYSCFG32;
352*0612538eSJari Sihvola sc->prediv_offset = JH7110_SYS_SYSCON_SYSCFG36;
353*0612538eSJari Sihvola sc->postdiv1_offset = JH7110_SYS_SYSCON_SYSCFG32;
354*0612538eSJari Sihvola break;
355*0612538eSJari Sihvola case JH7110_PLLCLK_PLL1_OUT:
356*0612538eSJari Sihvola sc->syscon_arr = jh7110_pll1_syscon_freq;
357*0612538eSJari Sihvola sc->syscon_nitems = nitems(jh7110_pll1_syscon_freq);
358*0612538eSJari Sihvola PLL_MASK_FILL(sc, 1);
359*0612538eSJari Sihvola PLL_SHIFT_FILL(sc, 1);
360*0612538eSJari Sihvola sc->dacpd_offset = JH7110_SYS_SYSCON_SYSCFG36;
361*0612538eSJari Sihvola sc->dsmpd_offset = JH7110_SYS_SYSCON_SYSCFG36;
362*0612538eSJari Sihvola sc->fbdiv_offset = JH7110_SYS_SYSCON_SYSCFG36;
363*0612538eSJari Sihvola sc->frac_offset = JH7110_SYS_SYSCON_SYSCFG40;
364*0612538eSJari Sihvola sc->prediv_offset = JH7110_SYS_SYSCON_SYSCFG44;
365*0612538eSJari Sihvola sc->postdiv1_offset = JH7110_SYS_SYSCON_SYSCFG40;
366*0612538eSJari Sihvola break;
367*0612538eSJari Sihvola case JH7110_PLLCLK_PLL2_OUT:
368*0612538eSJari Sihvola sc->syscon_arr = jh7110_pll2_syscon_freq;
369*0612538eSJari Sihvola sc->syscon_nitems = nitems(jh7110_pll2_syscon_freq);
370*0612538eSJari Sihvola PLL_MASK_FILL(sc, 2);
371*0612538eSJari Sihvola PLL_SHIFT_FILL(sc, 2);
372*0612538eSJari Sihvola sc->dacpd_offset = JH7110_SYS_SYSCON_SYSCFG44;
373*0612538eSJari Sihvola sc->dsmpd_offset = JH7110_SYS_SYSCON_SYSCFG44;
374*0612538eSJari Sihvola sc->fbdiv_offset = JH7110_SYS_SYSCON_SYSCFG44;
375*0612538eSJari Sihvola sc->frac_offset = JH7110_SYS_SYSCON_SYSCFG48;
376*0612538eSJari Sihvola sc->prediv_offset = JH7110_SYS_SYSCON_SYSCFG52;
377*0612538eSJari Sihvola sc->postdiv1_offset = JH7110_SYS_SYSCON_SYSCFG48;
378*0612538eSJari Sihvola break;
379*0612538eSJari Sihvola default:
380*0612538eSJari Sihvola return (EINVAL);
381*0612538eSJari Sihvola }
382*0612538eSJari Sihvola
383*0612538eSJari Sihvola clknode_register(clkdom, clk);
384*0612538eSJari Sihvola
385*0612538eSJari Sihvola return (0);
386*0612538eSJari Sihvola }
387