xref: /freebsd/sys/dev/clk/starfive/jh7110_clk_stg.c (revision 35a2229b67914ff1a4bae6334ad5015aa603967a)
1*35a2229bSJari Sihvola /*-
2*35a2229bSJari Sihvola  * SPDX-License-Identifier: BSD-2-Clause
3*35a2229bSJari Sihvola  *
4*35a2229bSJari Sihvola  * Copyright (c) 2024 Jari Sihvola <jsihv@gmx.com>
5*35a2229bSJari Sihvola  */
6*35a2229bSJari Sihvola 
7*35a2229bSJari Sihvola /* Clocks for STG group. PLL_OUT & SYS clocks must be registered first. */
8*35a2229bSJari Sihvola 
9*35a2229bSJari Sihvola #include <sys/param.h>
10*35a2229bSJari Sihvola #include <sys/systm.h>
11*35a2229bSJari Sihvola #include <sys/bus.h>
12*35a2229bSJari Sihvola #include <sys/mutex.h>
13*35a2229bSJari Sihvola #include <sys/kernel.h>
14*35a2229bSJari Sihvola #include <sys/module.h>
15*35a2229bSJari Sihvola #include <sys/resource.h>
16*35a2229bSJari Sihvola #include <sys/rman.h>
17*35a2229bSJari Sihvola #include <machine/bus.h>
18*35a2229bSJari Sihvola 
19*35a2229bSJari Sihvola #include <dev/fdt/simplebus.h>
20*35a2229bSJari Sihvola #include <dev/hwreset/hwreset.h>
21*35a2229bSJari Sihvola #include <dev/ofw/ofw_bus.h>
22*35a2229bSJari Sihvola #include <dev/ofw/ofw_bus_subr.h>
23*35a2229bSJari Sihvola 
24*35a2229bSJari Sihvola #include <dev/clk/clk.h>
25*35a2229bSJari Sihvola #include <dev/clk/starfive/jh7110_clk.h>
26*35a2229bSJari Sihvola 
27*35a2229bSJari Sihvola #include <dt-bindings/clock/starfive,jh7110-crg.h>
28*35a2229bSJari Sihvola 
29*35a2229bSJari Sihvola #include "clkdev_if.h"
30*35a2229bSJari Sihvola #include "hwreset_if.h"
31*35a2229bSJari Sihvola 
32*35a2229bSJari Sihvola static struct ofw_compat_data compat_data[] = {
33*35a2229bSJari Sihvola 	{ "starfive,jh7110-stgcrg",	1 },
34*35a2229bSJari Sihvola 	{ NULL,				0 }
35*35a2229bSJari Sihvola };
36*35a2229bSJari Sihvola 
37*35a2229bSJari Sihvola static struct resource_spec res_spec[] = {
38*35a2229bSJari Sihvola 	{ SYS_RES_MEMORY, 0, RF_ACTIVE },
39*35a2229bSJari Sihvola 	RESOURCE_SPEC_END
40*35a2229bSJari Sihvola };
41*35a2229bSJari Sihvola 
42*35a2229bSJari Sihvola /* parents */
43*35a2229bSJari Sihvola static const char *e2_rtc_p[] = { "osc" };
44*35a2229bSJari Sihvola static const char *e2_core_p[] = { "stg_axiahb" };
45*35a2229bSJari Sihvola static const char *e2_dbg_p[] = { "stg_axiahb" };
46*35a2229bSJari Sihvola 
47*35a2229bSJari Sihvola static const char *pcie_slv_main_p[] = { "stg_axiahb" };
48*35a2229bSJari Sihvola static const char *pcie0_tl_p[] = { "stg_axiahb" };
49*35a2229bSJari Sihvola static const char *pcie1_tl_p[] = { "stg_axiahb" };
50*35a2229bSJari Sihvola static const char *pcie0_axi_mst0_p[] = { "stg_axiahb" };
51*35a2229bSJari Sihvola static const char *pcie1_axi_mst0_p[] = { "stg_axiahb" };
52*35a2229bSJari Sihvola static const char *pcie0_apb_p[] = { "apb_bus" };
53*35a2229bSJari Sihvola static const char *pcie1_apb_p[] = { "apb_bus" };
54*35a2229bSJari Sihvola 
55*35a2229bSJari Sihvola static const char *usb0_lpm_p[] = { "osc" };
56*35a2229bSJari Sihvola static const char *usb0_stb_p[] = { "osc" };
57*35a2229bSJari Sihvola static const char *usb0_apb_p[] = { "apb_bus" };
58*35a2229bSJari Sihvola static const char *usb0_utmi_apb_p[] = { "apb_bus" };
59*35a2229bSJari Sihvola static const char *usb0_axi_p[] = { "stg_axiahb" };
60*35a2229bSJari Sihvola static const char *usb0_app_125_p[] = { "usb_125m" };
61*35a2229bSJari Sihvola static const char *usb0_refclk_p[] = { "osc" };
62*35a2229bSJari Sihvola 
63*35a2229bSJari Sihvola static const char *dma1p_axi_p[] = { "stg_axiahb" };
64*35a2229bSJari Sihvola static const char *dma1p_ahb_p[] = { "stg_axiahb" };
65*35a2229bSJari Sihvola 
66*35a2229bSJari Sihvola /* STG clocks */
67*35a2229bSJari Sihvola static const struct jh7110_clk_def stg_clks[] = {
68*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_USB0_APB, "usb0_apb", usb0_apb_p),
69*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_USB0_UTMI_APB, "usb0_utmi_apb",
70*35a2229bSJari Sihvola 	    usb0_utmi_apb_p),
71*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_USB0_AXI, "usb0_axi", usb0_axi_p),
72*35a2229bSJari Sihvola 	JH7110_GATEDIV(JH7110_STGCLK_USB0_LPM, "usb0_lpm", usb0_lpm_p, 2),
73*35a2229bSJari Sihvola 	JH7110_GATEDIV(JH7110_STGCLK_USB0_STB, "usb0_stb", usb0_stb_p, 4),
74*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_USB0_APP_125, "usb0_app_125", usb0_app_125_p),
75*35a2229bSJari Sihvola 	JH7110_DIV(JH7110_STGCLK_USB0_REFCLK, "usb0_refclk", usb0_refclk_p, 2),
76*35a2229bSJari Sihvola 
77*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_PCIE0_AXI_MST0, "pcie0_axi_mst0",
78*35a2229bSJari Sihvola 	    pcie0_axi_mst0_p),
79*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_PCIE0_APB, "pcie0_apb", pcie0_apb_p),
80*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_PCIE0_TL, "pcie0_tl", pcie0_tl_p),
81*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_PCIE1_AXI_MST0, "pcie1_axi_mst0",
82*35a2229bSJari Sihvola 	    pcie1_axi_mst0_p),
83*35a2229bSJari Sihvola 
84*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_PCIE1_APB, "pcie1_apb", pcie1_apb_p),
85*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_PCIE1_TL, "pcie1_tl", pcie1_tl_p),
86*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_PCIE_SLV_MAIN, "pcie_slv_main",
87*35a2229bSJari Sihvola 	    pcie_slv_main_p),
88*35a2229bSJari Sihvola 
89*35a2229bSJari Sihvola 	JH7110_GATEDIV(JH7110_STGCLK_E2_RTC, "e2_rtc", e2_rtc_p, 24),
90*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_E2_CORE, "e2_core", e2_core_p),
91*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_E2_DBG, "e2_dbg", e2_dbg_p),
92*35a2229bSJari Sihvola 
93*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_DMA1P_AXI, "dma1p_axi", dma1p_axi_p),
94*35a2229bSJari Sihvola 	JH7110_GATE(JH7110_STGCLK_DMA1P_AHB, "dma1p_ahb", dma1p_ahb_p),
95*35a2229bSJari Sihvola };
96*35a2229bSJari Sihvola 
97*35a2229bSJari Sihvola static int
jh7110_clk_stg_probe(device_t dev)98*35a2229bSJari Sihvola jh7110_clk_stg_probe(device_t dev)
99*35a2229bSJari Sihvola {
100*35a2229bSJari Sihvola 	if (!ofw_bus_status_okay(dev))
101*35a2229bSJari Sihvola 		return (ENXIO);
102*35a2229bSJari Sihvola 
103*35a2229bSJari Sihvola 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
104*35a2229bSJari Sihvola 		return (ENXIO);
105*35a2229bSJari Sihvola 
106*35a2229bSJari Sihvola 	device_set_desc(dev, "StarFive JH7110 STG clock generator");
107*35a2229bSJari Sihvola 
108*35a2229bSJari Sihvola 	return (BUS_PROBE_DEFAULT);
109*35a2229bSJari Sihvola }
110*35a2229bSJari Sihvola 
111*35a2229bSJari Sihvola static int
jh7110_clk_stg_attach(device_t dev)112*35a2229bSJari Sihvola jh7110_clk_stg_attach(device_t dev)
113*35a2229bSJari Sihvola {
114*35a2229bSJari Sihvola 	struct jh7110_clkgen_softc *sc;
115*35a2229bSJari Sihvola 	int err;
116*35a2229bSJari Sihvola 
117*35a2229bSJari Sihvola 	sc = device_get_softc(dev);
118*35a2229bSJari Sihvola 
119*35a2229bSJari Sihvola 	sc->reset_status_offset = STGCRG_RESET_STATUS;
120*35a2229bSJari Sihvola 	sc->reset_selector_offset = STGCRG_RESET_SELECTOR;
121*35a2229bSJari Sihvola 
122*35a2229bSJari Sihvola 	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
123*35a2229bSJari Sihvola 
124*35a2229bSJari Sihvola 	err = bus_alloc_resources(dev, res_spec, &sc->mem_res);
125*35a2229bSJari Sihvola 	if (err != 0) {
126*35a2229bSJari Sihvola 		device_printf(dev, "Couldn't allocate resources, error %d\n",
127*35a2229bSJari Sihvola 		    err);
128*35a2229bSJari Sihvola 		return (ENXIO);
129*35a2229bSJari Sihvola 	}
130*35a2229bSJari Sihvola 
131*35a2229bSJari Sihvola 	sc->clkdom = clkdom_create(dev);
132*35a2229bSJari Sihvola 	if (sc->clkdom == NULL) {
133*35a2229bSJari Sihvola 		device_printf(dev, "Couldn't create clkdom, error %d\n", err);
134*35a2229bSJari Sihvola 		return (ENXIO);
135*35a2229bSJari Sihvola 	}
136*35a2229bSJari Sihvola 
137*35a2229bSJari Sihvola 	for (int i = 0; i < nitems(stg_clks); i++) {
138*35a2229bSJari Sihvola 		err = jh7110_clk_register(sc->clkdom, &stg_clks[i]);
139*35a2229bSJari Sihvola 		if (err != 0) {
140*35a2229bSJari Sihvola 			device_printf(dev,
141*35a2229bSJari Sihvola 			    "Couldn't register clk %s, error %d\n",
142*35a2229bSJari Sihvola 				stg_clks[i].clkdef.name, err);
143*35a2229bSJari Sihvola 			return (ENXIO);
144*35a2229bSJari Sihvola 		}
145*35a2229bSJari Sihvola 	}
146*35a2229bSJari Sihvola 
147*35a2229bSJari Sihvola 	if (clkdom_finit(sc->clkdom) != 0)
148*35a2229bSJari Sihvola 		panic("Cannot finalize clkdom initialization\n");
149*35a2229bSJari Sihvola 
150*35a2229bSJari Sihvola 	if (bootverbose)
151*35a2229bSJari Sihvola 		clkdom_dump(sc->clkdom);
152*35a2229bSJari Sihvola 
153*35a2229bSJari Sihvola 	hwreset_register_ofw_provider(dev);
154*35a2229bSJari Sihvola 
155*35a2229bSJari Sihvola 	return (0);
156*35a2229bSJari Sihvola }
157*35a2229bSJari Sihvola 
158*35a2229bSJari Sihvola static void
jh7110_clk_stg_device_lock(device_t dev)159*35a2229bSJari Sihvola jh7110_clk_stg_device_lock(device_t dev)
160*35a2229bSJari Sihvola {
161*35a2229bSJari Sihvola 	struct jh7110_clkgen_softc *sc;
162*35a2229bSJari Sihvola 
163*35a2229bSJari Sihvola 	sc = device_get_softc(dev);
164*35a2229bSJari Sihvola 	mtx_lock(&sc->mtx);
165*35a2229bSJari Sihvola }
166*35a2229bSJari Sihvola 
167*35a2229bSJari Sihvola static void
jh7110_clk_stg_device_unlock(device_t dev)168*35a2229bSJari Sihvola jh7110_clk_stg_device_unlock(device_t dev)
169*35a2229bSJari Sihvola {
170*35a2229bSJari Sihvola 	struct jh7110_clkgen_softc *sc;
171*35a2229bSJari Sihvola 
172*35a2229bSJari Sihvola 	sc = device_get_softc(dev);
173*35a2229bSJari Sihvola 	mtx_unlock(&sc->mtx);
174*35a2229bSJari Sihvola }
175*35a2229bSJari Sihvola 
176*35a2229bSJari Sihvola static int
jh7110_clk_stg_detach(device_t dev)177*35a2229bSJari Sihvola jh7110_clk_stg_detach(device_t dev)
178*35a2229bSJari Sihvola {
179*35a2229bSJari Sihvola 	/* Detach not supported */
180*35a2229bSJari Sihvola 	return (EBUSY);
181*35a2229bSJari Sihvola }
182*35a2229bSJari Sihvola 
183*35a2229bSJari Sihvola static device_method_t jh7110_clk_stg_methods[] = {
184*35a2229bSJari Sihvola 	/* Device interface */
185*35a2229bSJari Sihvola 	DEVMETHOD(device_probe,         jh7110_clk_stg_probe),
186*35a2229bSJari Sihvola 	DEVMETHOD(device_attach,	jh7110_clk_stg_attach),
187*35a2229bSJari Sihvola 	DEVMETHOD(device_detach,	jh7110_clk_stg_detach),
188*35a2229bSJari Sihvola 
189*35a2229bSJari Sihvola 	/* clkdev interface */
190*35a2229bSJari Sihvola 	DEVMETHOD(clkdev_device_lock,	jh7110_clk_stg_device_lock),
191*35a2229bSJari Sihvola 	DEVMETHOD(clkdev_device_unlock, jh7110_clk_stg_device_unlock),
192*35a2229bSJari Sihvola 
193*35a2229bSJari Sihvola 	/* Reset interface */
194*35a2229bSJari Sihvola 	DEVMETHOD(hwreset_assert,       jh7110_reset_assert),
195*35a2229bSJari Sihvola 	DEVMETHOD(hwreset_is_asserted,  jh7110_reset_is_asserted),
196*35a2229bSJari Sihvola 
197*35a2229bSJari Sihvola 	DEVMETHOD_END
198*35a2229bSJari Sihvola };
199*35a2229bSJari Sihvola 
200*35a2229bSJari Sihvola DEFINE_CLASS_0(jh7110_stg, jh7110_stg_driver, jh7110_clk_stg_methods,
201*35a2229bSJari Sihvola     sizeof(struct jh7110_clkgen_softc));
202*35a2229bSJari Sihvola EARLY_DRIVER_MODULE(jh7110_stg, simplebus, jh7110_stg_driver, 0, 0,
203*35a2229bSJari Sihvola     BUS_PASS_BUS + BUS_PASS_ORDER_LATE + 1);
204*35a2229bSJari Sihvola MODULE_VERSION(jh7110_stg, 1);
205