18154df37SBjoern A. Zeeb /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
38154df37SBjoern A. Zeeb *
48154df37SBjoern A. Zeeb * Copyright (c) 2021 Alstom Group.
58154df37SBjoern A. Zeeb * Copyright (c) 2021 Semihalf.
68154df37SBjoern A. Zeeb * Copyright (c) 2022 Bjoern A. Zeeb
78154df37SBjoern A. Zeeb *
88154df37SBjoern A. Zeeb * Redistribution and use in source and binary forms, with or without
98154df37SBjoern A. Zeeb * modification, are permitted provided that the following conditions
108154df37SBjoern A. Zeeb * are met:
118154df37SBjoern A. Zeeb * 1. Redistributions of source code must retain the above copyright
128154df37SBjoern A. Zeeb * notice, this list of conditions and the following disclaimer.
138154df37SBjoern A. Zeeb * 2. Redistributions in binary form must reproduce the above copyright
148154df37SBjoern A. Zeeb * notice, this list of conditions and the following disclaimer in the
158154df37SBjoern A. Zeeb * documentation and/or other materials provided with the distribution.
168154df37SBjoern A. Zeeb *
178154df37SBjoern A. Zeeb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
188154df37SBjoern A. Zeeb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
198154df37SBjoern A. Zeeb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
208154df37SBjoern A. Zeeb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
218154df37SBjoern A. Zeeb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
228154df37SBjoern A. Zeeb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
238154df37SBjoern A. Zeeb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
248154df37SBjoern A. Zeeb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
258154df37SBjoern A. Zeeb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
268154df37SBjoern A. Zeeb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
278154df37SBjoern A. Zeeb * SUCH DAMAGE.
288154df37SBjoern A. Zeeb */
298154df37SBjoern A. Zeeb /*
308154df37SBjoern A. Zeeb * Based on QorIQ LS1088A Reference Manual, Rev. 1, 11/2020.
318154df37SBjoern A. Zeeb * [LS1088ARM.pdf]
328154df37SBjoern A. Zeeb */
338154df37SBjoern A. Zeeb
348154df37SBjoern A. Zeeb #include <sys/param.h>
358154df37SBjoern A. Zeeb #include <sys/bus.h>
368154df37SBjoern A. Zeeb #include <sys/kernel.h>
378154df37SBjoern A. Zeeb #include <sys/module.h>
388154df37SBjoern A. Zeeb #include <sys/mutex.h>
398154df37SBjoern A. Zeeb #include <sys/rman.h>
408154df37SBjoern A. Zeeb #include <machine/bus.h>
418154df37SBjoern A. Zeeb
428154df37SBjoern A. Zeeb #include <dev/fdt/simplebus.h>
438154df37SBjoern A. Zeeb
448154df37SBjoern A. Zeeb #include <dev/ofw/ofw_bus.h>
458154df37SBjoern A. Zeeb #include <dev/ofw/ofw_bus_subr.h>
468154df37SBjoern A. Zeeb
47*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_fixed.h>
488154df37SBjoern A. Zeeb
498154df37SBjoern A. Zeeb #include <arm64/qoriq/clk/qoriq_clkgen.h>
508154df37SBjoern A. Zeeb
518154df37SBjoern A. Zeeb static uint8_t ls1088a_pltfrm_pll_divs[] = {
528154df37SBjoern A. Zeeb 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0
538154df37SBjoern A. Zeeb };
548154df37SBjoern A. Zeeb
558154df37SBjoern A. Zeeb static struct qoriq_clk_pll_def ls1088a_pltfrm_pll = {
568154df37SBjoern A. Zeeb .clkdef = {
578154df37SBjoern A. Zeeb .name = "ls1088a_platform_pll",
588154df37SBjoern A. Zeeb .id = QORIQ_CLK_ID(QORIQ_TYPE_PLATFORM_PLL, 0),
598154df37SBjoern A. Zeeb .flags = 0
608154df37SBjoern A. Zeeb },
618154df37SBjoern A. Zeeb .offset = 0x60080,
628154df37SBjoern A. Zeeb .shift = 1,
638154df37SBjoern A. Zeeb .mask = 0xFE,
648154df37SBjoern A. Zeeb .dividers = ls1088a_pltfrm_pll_divs,
658154df37SBjoern A. Zeeb .flags = QORIQ_CLK_PLL_HAS_KILL_BIT
668154df37SBjoern A. Zeeb };
678154df37SBjoern A. Zeeb
688154df37SBjoern A. Zeeb static const uint8_t ls1088a_cga_pll_divs[] = {
698154df37SBjoern A. Zeeb 2, 3, 4, 0
708154df37SBjoern A. Zeeb };
718154df37SBjoern A. Zeeb
728154df37SBjoern A. Zeeb static struct qoriq_clk_pll_def ls1088a_cga_pll1 = {
738154df37SBjoern A. Zeeb .clkdef = {
748154df37SBjoern A. Zeeb .name = "ls1088a_cga_pll1",
758154df37SBjoern A. Zeeb .id = QORIQ_CLK_ID(QORIQ_TYPE_INTERNAL, 0),
768154df37SBjoern A. Zeeb .flags = 0
778154df37SBjoern A. Zeeb },
788154df37SBjoern A. Zeeb .offset = 0x80,
798154df37SBjoern A. Zeeb .shift = 1,
808154df37SBjoern A. Zeeb .mask = 0xFE,
818154df37SBjoern A. Zeeb .dividers = ls1088a_cga_pll_divs,
828154df37SBjoern A. Zeeb .flags = QORIQ_CLK_PLL_HAS_KILL_BIT
838154df37SBjoern A. Zeeb };
848154df37SBjoern A. Zeeb
858154df37SBjoern A. Zeeb static struct qoriq_clk_pll_def ls1088a_cga_pll2 = {
868154df37SBjoern A. Zeeb .clkdef = {
878154df37SBjoern A. Zeeb .name = "ls1088a_cga_pll2",
888154df37SBjoern A. Zeeb .id = QORIQ_CLK_ID(QORIQ_TYPE_INTERNAL, 20),
898154df37SBjoern A. Zeeb .flags = 0
908154df37SBjoern A. Zeeb },
918154df37SBjoern A. Zeeb .offset = 0xA0,
928154df37SBjoern A. Zeeb .shift = 1,
938154df37SBjoern A. Zeeb .mask = 0xFE,
948154df37SBjoern A. Zeeb .dividers = ls1088a_cga_pll_divs,
958154df37SBjoern A. Zeeb .flags = QORIQ_CLK_PLL_HAS_KILL_BIT
968154df37SBjoern A. Zeeb };
978154df37SBjoern A. Zeeb
988154df37SBjoern A. Zeeb static struct qoriq_clk_pll_def *ls1088a_cga_plls[] = {
998154df37SBjoern A. Zeeb &ls1088a_cga_pll1,
1008154df37SBjoern A. Zeeb &ls1088a_cga_pll2
1018154df37SBjoern A. Zeeb };
1028154df37SBjoern A. Zeeb
1038154df37SBjoern A. Zeeb
1048154df37SBjoern A. Zeeb /* 4.7.2 Core Cluster a Clock Control/Status Register (CLKC1CSR - CLKC2CSR) */
1058154df37SBjoern A. Zeeb static const char *ls1088a_cmux0_parent_names[] = {
1068154df37SBjoern A. Zeeb "ls1088a_cga_pll1",
1078154df37SBjoern A. Zeeb "ls1088a_cga_pll1_div2",
1088154df37SBjoern A. Zeeb "ls1088a_cga_pll1_div4",
1098154df37SBjoern A. Zeeb NULL,
1108154df37SBjoern A. Zeeb "ls1088a_cga_pll2",
1118154df37SBjoern A. Zeeb "ls1088a_cga_pll2_div2",
1128154df37SBjoern A. Zeeb "ls1088a_cga_pll2_div4"
1138154df37SBjoern A. Zeeb };
1148154df37SBjoern A. Zeeb
1158154df37SBjoern A. Zeeb static struct clk_mux_def ls1088a_cmux0 = {
1168154df37SBjoern A. Zeeb .clkdef = {
1178154df37SBjoern A. Zeeb .name = "ls1088a_cmux0",
1188154df37SBjoern A. Zeeb .id = QORIQ_CLK_ID(QORIQ_TYPE_CMUX, 0),
1198154df37SBjoern A. Zeeb .parent_names = ls1088a_cmux0_parent_names,
1208154df37SBjoern A. Zeeb .parent_cnt = nitems(ls1088a_cmux0_parent_names),
1218154df37SBjoern A. Zeeb .flags = 0
1228154df37SBjoern A. Zeeb },
1238154df37SBjoern A. Zeeb .offset = 0x70000,
1248154df37SBjoern A. Zeeb .shift = 27,
1258154df37SBjoern A. Zeeb .width = 4,
1268154df37SBjoern A. Zeeb .mux_flags = 0
1278154df37SBjoern A. Zeeb };
1288154df37SBjoern A. Zeeb
1298154df37SBjoern A. Zeeb static struct clk_mux_def ls1088a_cmux1 = {
1308154df37SBjoern A. Zeeb .clkdef = {
1318154df37SBjoern A. Zeeb .name = "ls1088a_cmux1",
1328154df37SBjoern A. Zeeb .id = QORIQ_CLK_ID(QORIQ_TYPE_CMUX, 1),
1338154df37SBjoern A. Zeeb .parent_names = ls1088a_cmux0_parent_names,
1348154df37SBjoern A. Zeeb .parent_cnt = nitems(ls1088a_cmux0_parent_names),
1358154df37SBjoern A. Zeeb .flags = 0
1368154df37SBjoern A. Zeeb },
1378154df37SBjoern A. Zeeb .offset = 0x70020,
1388154df37SBjoern A. Zeeb .shift = 27,
1398154df37SBjoern A. Zeeb .width = 4,
1408154df37SBjoern A. Zeeb .mux_flags = 0
1418154df37SBjoern A. Zeeb };
1428154df37SBjoern A. Zeeb
1438154df37SBjoern A. Zeeb /* 4.4.2 HWAaCSR (HWA1CSR - HWA3CSR) */
1448154df37SBjoern A. Zeeb static const char *ls1088a_hwaccel1_parent_names[] = {
1458154df37SBjoern A. Zeeb "ls1088a_platform_pll",
1468154df37SBjoern A. Zeeb "ls1088a_cga_pll1",
1478154df37SBjoern A. Zeeb "ls1088a_cga_pll1_div2",
1488154df37SBjoern A. Zeeb "ls1088a_cga_pll1_div3",
1498154df37SBjoern A. Zeeb "ls1088a_cga_pll1_div4",
1508154df37SBjoern A. Zeeb NULL, /* HWAMUX1 External Clock Source */
1518154df37SBjoern A. Zeeb "ls1088a_cga_pll2_div2",
1528154df37SBjoern A. Zeeb "ls1088a_cga_pll2_div3"
1538154df37SBjoern A. Zeeb };
1548154df37SBjoern A. Zeeb
1558154df37SBjoern A. Zeeb static const char *ls1088a_hwaccel2_parent_names[] = {
1568154df37SBjoern A. Zeeb "ls1088a_platform_pll",
1578154df37SBjoern A. Zeeb "ls1088a_cga_pll2",
1588154df37SBjoern A. Zeeb "ls1088a_cga_pll2_div2",
1598154df37SBjoern A. Zeeb "ls1088a_cga_pll2_div3",
1608154df37SBjoern A. Zeeb "ls1088a_cga_pll2_div4",
1618154df37SBjoern A. Zeeb NULL, /* HWAMUX2 External Clock Source */
1628154df37SBjoern A. Zeeb "ls1088a_cga_pll1_div2",
1638154df37SBjoern A. Zeeb "ls1088a_cga_pll1_div3"
1648154df37SBjoern A. Zeeb };
1658154df37SBjoern A. Zeeb
1668154df37SBjoern A. Zeeb static const char *ls1088a_hwaccel3_parent_names[] = {
1678154df37SBjoern A. Zeeb "ls1088a_platform_pll",
1688154df37SBjoern A. Zeeb NULL,
1698154df37SBjoern A. Zeeb NULL,
1708154df37SBjoern A. Zeeb NULL,
1718154df37SBjoern A. Zeeb NULL,
1728154df37SBjoern A. Zeeb NULL, /* HWAMUX3 External Clock Source */
1738154df37SBjoern A. Zeeb "ls1088a_cga_pll2_div2",
1748154df37SBjoern A. Zeeb "ls1088a_cga_pll2_div3"
1758154df37SBjoern A. Zeeb };
1768154df37SBjoern A. Zeeb
1778154df37SBjoern A. Zeeb static struct clk_mux_def ls1088a_hwaccel1 = {
1788154df37SBjoern A. Zeeb .clkdef = {
1798154df37SBjoern A. Zeeb .name = "ls1088a_hwaccel1",
1808154df37SBjoern A. Zeeb .id = QORIQ_CLK_ID(QORIQ_TYPE_HWACCEL, 0),
1818154df37SBjoern A. Zeeb .parent_names = ls1088a_hwaccel1_parent_names,
1828154df37SBjoern A. Zeeb .parent_cnt = nitems(ls1088a_hwaccel1_parent_names),
1838154df37SBjoern A. Zeeb .flags = 0
1848154df37SBjoern A. Zeeb },
1858154df37SBjoern A. Zeeb .offset = 0x10,
1868154df37SBjoern A. Zeeb .shift = 27,
1878154df37SBjoern A. Zeeb .width = 4,
1888154df37SBjoern A. Zeeb .mux_flags = 0
1898154df37SBjoern A. Zeeb };
1908154df37SBjoern A. Zeeb
1918154df37SBjoern A. Zeeb static struct clk_mux_def ls1088a_hwaccel2 = {
1928154df37SBjoern A. Zeeb .clkdef = {
1938154df37SBjoern A. Zeeb .name = "ls1088a_hwaccel2",
1948154df37SBjoern A. Zeeb .id = QORIQ_CLK_ID(QORIQ_TYPE_HWACCEL, 1),
1958154df37SBjoern A. Zeeb .parent_names = ls1088a_hwaccel2_parent_names,
1968154df37SBjoern A. Zeeb .parent_cnt = nitems(ls1088a_hwaccel2_parent_names),
1978154df37SBjoern A. Zeeb .flags = 0
1988154df37SBjoern A. Zeeb },
1998154df37SBjoern A. Zeeb .offset = 0x30,
2008154df37SBjoern A. Zeeb .shift = 27,
2018154df37SBjoern A. Zeeb .width = 4,
2028154df37SBjoern A. Zeeb .mux_flags = 0
2038154df37SBjoern A. Zeeb };
2048154df37SBjoern A. Zeeb
2058154df37SBjoern A. Zeeb static struct clk_mux_def ls1088a_hwaccel3 = {
2068154df37SBjoern A. Zeeb .clkdef = {
2078154df37SBjoern A. Zeeb .name = "ls1088a_hwaccel3",
2088154df37SBjoern A. Zeeb .id = QORIQ_CLK_ID(QORIQ_TYPE_HWACCEL, 2),
2098154df37SBjoern A. Zeeb .parent_names = ls1088a_hwaccel3_parent_names,
2108154df37SBjoern A. Zeeb .parent_cnt = nitems(ls1088a_hwaccel3_parent_names),
2118154df37SBjoern A. Zeeb .flags = 0
2128154df37SBjoern A. Zeeb },
2138154df37SBjoern A. Zeeb .offset = 0x50,
2148154df37SBjoern A. Zeeb .shift = 27,
2158154df37SBjoern A. Zeeb .width = 4,
2168154df37SBjoern A. Zeeb .mux_flags = 0
2178154df37SBjoern A. Zeeb };
2188154df37SBjoern A. Zeeb
2198154df37SBjoern A. Zeeb
2208154df37SBjoern A. Zeeb static struct clk_mux_def *ls1088a_mux_nodes[] = {
2218154df37SBjoern A. Zeeb &ls1088a_cmux0,
2228154df37SBjoern A. Zeeb &ls1088a_cmux1,
2238154df37SBjoern A. Zeeb &ls1088a_hwaccel1,
2248154df37SBjoern A. Zeeb &ls1088a_hwaccel2,
2258154df37SBjoern A. Zeeb &ls1088a_hwaccel3
2268154df37SBjoern A. Zeeb };
2278154df37SBjoern A. Zeeb
2288154df37SBjoern A. Zeeb static int
ls1088a_clkgen_probe(device_t dev)2298154df37SBjoern A. Zeeb ls1088a_clkgen_probe(device_t dev)
2308154df37SBjoern A. Zeeb {
2318154df37SBjoern A. Zeeb
2328154df37SBjoern A. Zeeb if (!ofw_bus_status_okay(dev))
2338154df37SBjoern A. Zeeb return (ENXIO);
2348154df37SBjoern A. Zeeb
2358154df37SBjoern A. Zeeb if(!ofw_bus_is_compatible(dev, "fsl,ls1088a-clockgen"))
2368154df37SBjoern A. Zeeb return (ENXIO);
2378154df37SBjoern A. Zeeb
2388154df37SBjoern A. Zeeb device_set_desc(dev, "LS1088A clockgen");
2398154df37SBjoern A. Zeeb return (BUS_PROBE_DEFAULT);
2408154df37SBjoern A. Zeeb }
2418154df37SBjoern A. Zeeb
2428154df37SBjoern A. Zeeb static int
ls1088a_clkgen_attach(device_t dev)2438154df37SBjoern A. Zeeb ls1088a_clkgen_attach(device_t dev)
2448154df37SBjoern A. Zeeb {
2458154df37SBjoern A. Zeeb struct qoriq_clkgen_softc *sc;
2468154df37SBjoern A. Zeeb
2478154df37SBjoern A. Zeeb sc = device_get_softc(dev);
2488154df37SBjoern A. Zeeb
2498154df37SBjoern A. Zeeb sc->pltfrm_pll_def = &ls1088a_pltfrm_pll;
2508154df37SBjoern A. Zeeb sc->cga_pll = ls1088a_cga_plls;
2518154df37SBjoern A. Zeeb sc->cga_pll_num = nitems(ls1088a_cga_plls);
2528154df37SBjoern A. Zeeb sc->mux = ls1088a_mux_nodes;
2538154df37SBjoern A. Zeeb sc->mux_num = nitems(ls1088a_mux_nodes);
2548154df37SBjoern A. Zeeb sc->flags = QORIQ_LITTLE_ENDIAN;
2558154df37SBjoern A. Zeeb
2568154df37SBjoern A. Zeeb return (qoriq_clkgen_attach(dev));
2578154df37SBjoern A. Zeeb }
2588154df37SBjoern A. Zeeb
2598154df37SBjoern A. Zeeb static device_method_t ls1088a_clkgen_methods[] = {
2608154df37SBjoern A. Zeeb DEVMETHOD(device_probe, ls1088a_clkgen_probe),
2618154df37SBjoern A. Zeeb DEVMETHOD(device_attach, ls1088a_clkgen_attach),
2628154df37SBjoern A. Zeeb
2638154df37SBjoern A. Zeeb DEVMETHOD_END
2648154df37SBjoern A. Zeeb };
2658154df37SBjoern A. Zeeb
2668154df37SBjoern A. Zeeb DEFINE_CLASS_1(ls1088a_clkgen, ls1088a_clkgen_driver, ls1088a_clkgen_methods,
2678154df37SBjoern A. Zeeb sizeof(struct qoriq_clkgen_softc), qoriq_clkgen_driver);
2688154df37SBjoern A. Zeeb
2698154df37SBjoern A. Zeeb EARLY_DRIVER_MODULE(ls1088a_clkgen, simplebus, ls1088a_clkgen_driver, 0, 0,
2708154df37SBjoern A. Zeeb BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
271