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