xref: /freebsd/sys/dev/clk/starfive/jh7110_clk_pll.c (revision 0612538e)
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