16844eecfSMichal Meloun /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
36844eecfSMichal Meloun *
46844eecfSMichal Meloun * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
56844eecfSMichal Meloun *
66844eecfSMichal Meloun * Redistribution and use in source and binary forms, with or without
76844eecfSMichal Meloun * modification, are permitted provided that the following conditions
86844eecfSMichal Meloun * are met:
96844eecfSMichal Meloun * 1. Redistributions of source code must retain the above copyright
106844eecfSMichal Meloun * notice, this list of conditions and the following disclaimer.
116844eecfSMichal Meloun * 2. Redistributions in binary form must reproduce the above copyright
126844eecfSMichal Meloun * notice, this list of conditions and the following disclaimer in the
136844eecfSMichal Meloun * documentation and/or other materials provided with the distribution.
146844eecfSMichal Meloun *
156844eecfSMichal Meloun * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
166844eecfSMichal Meloun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
176844eecfSMichal Meloun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
186844eecfSMichal Meloun * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
196844eecfSMichal Meloun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
206844eecfSMichal Meloun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
216844eecfSMichal Meloun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
226844eecfSMichal Meloun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
236844eecfSMichal Meloun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
246844eecfSMichal Meloun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
256844eecfSMichal Meloun * SUCH DAMAGE.
266844eecfSMichal Meloun */
276844eecfSMichal Meloun
286844eecfSMichal Meloun #include <sys/cdefs.h>
296844eecfSMichal Meloun /*
306844eecfSMichal Meloun * Clock driver for LX2160A SoC.
316844eecfSMichal Meloun */
326844eecfSMichal Meloun #include <sys/param.h>
336844eecfSMichal Meloun #include <sys/bus.h>
346844eecfSMichal Meloun #include <sys/kernel.h>
356844eecfSMichal Meloun #include <sys/module.h>
366844eecfSMichal Meloun #include <sys/mutex.h>
376844eecfSMichal Meloun #include <sys/rman.h>
386844eecfSMichal Meloun #include <machine/bus.h>
396844eecfSMichal Meloun
406844eecfSMichal Meloun #include <dev/fdt/simplebus.h>
416844eecfSMichal Meloun
426844eecfSMichal Meloun #include <dev/ofw/ofw_bus.h>
436844eecfSMichal Meloun #include <dev/ofw/ofw_bus_subr.h>
446844eecfSMichal Meloun
45*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_fixed.h>
466844eecfSMichal Meloun
476844eecfSMichal Meloun #include <arm64/qoriq/clk/qoriq_clkgen.h>
486844eecfSMichal Meloun
496844eecfSMichal Meloun #define PLL(_id1, _id2, cname, o, d) \
506844eecfSMichal Meloun { \
516844eecfSMichal Meloun .clkdef.id = QORIQ_CLK_ID(_id1, _id2), \
526844eecfSMichal Meloun .clkdef.name = cname, \
536844eecfSMichal Meloun .clkdef.flags = 0, \
546844eecfSMichal Meloun .offset = o, \
556844eecfSMichal Meloun .shift = 1, \
566844eecfSMichal Meloun .mask = 0xFE, \
576844eecfSMichal Meloun .dividers = d, \
586844eecfSMichal Meloun .flags = QORIQ_CLK_PLL_HAS_KILL_BIT, \
596844eecfSMichal Meloun }
606844eecfSMichal Meloun
616844eecfSMichal Meloun static const uint8_t plt_divs[] =
626844eecfSMichal Meloun {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0};
636844eecfSMichal Meloun static const uint8_t cga_divs[] = {2, 4, 0};
646844eecfSMichal Meloun static const uint8_t cgb_divs[] = {2, 3, 4, 0};
656844eecfSMichal Meloun
666844eecfSMichal Meloun static struct qoriq_clk_pll_def pltfrm_pll =
676844eecfSMichal Meloun PLL(QORIQ_TYPE_PLATFORM_PLL, 0, "platform_pll", 0x60080, plt_divs);
686844eecfSMichal Meloun static struct qoriq_clk_pll_def cga_pll1 =
696844eecfSMichal Meloun PLL(QORIQ_TYPE_INTERNAL, 0, "cga_pll1", 0x80, cga_divs);
706844eecfSMichal Meloun static struct qoriq_clk_pll_def cga_pll2 =
716844eecfSMichal Meloun PLL(QORIQ_TYPE_INTERNAL, 0, "cga_pll2", 0xA0, cga_divs);
726844eecfSMichal Meloun static struct qoriq_clk_pll_def cgb_pll1 =
736844eecfSMichal Meloun PLL(QORIQ_TYPE_INTERNAL, 0, "cgb_pll1", 0x10080, cgb_divs);
746844eecfSMichal Meloun static struct qoriq_clk_pll_def cgb_pll2 =
756844eecfSMichal Meloun PLL(QORIQ_TYPE_INTERNAL, 0, "cgb_pll2", 0x100A0, cgb_divs);
766844eecfSMichal Meloun
776844eecfSMichal Meloun static struct qoriq_clk_pll_def *cg_plls[] = {
786844eecfSMichal Meloun &cga_pll1,
796844eecfSMichal Meloun &cga_pll2,
806844eecfSMichal Meloun &cgb_pll1,
816844eecfSMichal Meloun &cgb_pll2,
826844eecfSMichal Meloun };
836844eecfSMichal Meloun
846844eecfSMichal Meloun #if 0
856844eecfSMichal Meloun static struct qoriq_clk_pll_def *cg_plls[] = {
866844eecfSMichal Meloun &(struct qoriq_clk_pll_def)
876844eecfSMichal Meloun {PLL(QORIQ_TYPE_INTERNAL, 0, "cga_pll1", 0x80, cg_divs)},
886844eecfSMichal Meloun &(struct qoriq_clk_pll_def)
896844eecfSMichal Meloun {PLL(QORIQ_TYPE_INTERNAL, 0, "cga_pll2", 0xA0, cg_divs)},
906844eecfSMichal Meloun &(struct qoriq_clk_pll_def)
916844eecfSMichal Meloun {PLL(QORIQ_TYPE_INTERNAL, 0, "cgb_pll1", 0x10080, cg_divs)},
926844eecfSMichal Meloun &(struct qoriq_clk_pll_def)
936844eecfSMichal Meloun {PLL(QORIQ_TYPE_INTERNAL, 0, "cgb_pll2", 0x100A0, cg_divs)},
946844eecfSMichal Meloun };
956844eecfSMichal Meloun #endif
966844eecfSMichal Meloun
976844eecfSMichal Meloun static const char *cmuxa_plist[] = {
986844eecfSMichal Meloun "cga_pll1",
996844eecfSMichal Meloun "cga_pll1_div2",
1006844eecfSMichal Meloun "cga_pll1_div4",
1016844eecfSMichal Meloun NULL,
1026844eecfSMichal Meloun "cga_pll2",
1036844eecfSMichal Meloun "cga_pll2_div2",
1046844eecfSMichal Meloun "cga_pll2_div4",
1056844eecfSMichal Meloun };
1066844eecfSMichal Meloun
1076844eecfSMichal Meloun static const char *cmuxb_plist[] = {
1086844eecfSMichal Meloun "cgb_pll1",
1096844eecfSMichal Meloun "cgb_pll1_div2",
1106844eecfSMichal Meloun "cgb_pll1_div4",
1116844eecfSMichal Meloun NULL,
1126844eecfSMichal Meloun "cgb_pll2",
1136844eecfSMichal Meloun "cgb_pll2_div2",
1146844eecfSMichal Meloun "cgb_pll2_div4",
1156844eecfSMichal Meloun };
1166844eecfSMichal Meloun
1176844eecfSMichal Meloun #define MUX(_id1, _id2, cname, plist, o) \
1186844eecfSMichal Meloun { \
1196844eecfSMichal Meloun .clkdef.id = QORIQ_CLK_ID(_id1, _id2), \
1206844eecfSMichal Meloun .clkdef.name = cname, \
1216844eecfSMichal Meloun .clkdef.parent_names = plist, \
1226844eecfSMichal Meloun .clkdef.parent_cnt = nitems(plist), \
1236844eecfSMichal Meloun .clkdef.flags = 0, \
1246844eecfSMichal Meloun .offset = o, \
1256844eecfSMichal Meloun .width = 4, \
1266844eecfSMichal Meloun .shift = 27, \
1276844eecfSMichal Meloun .mux_flags = 0, \
1286844eecfSMichal Meloun }
1296844eecfSMichal Meloun static struct clk_mux_def cmux0 =
1306844eecfSMichal Meloun MUX(QORIQ_TYPE_CMUX, 0, "cg-cmux0", cmuxa_plist, 0x70000);
1316844eecfSMichal Meloun static struct clk_mux_def cmux1 =
1326844eecfSMichal Meloun MUX(QORIQ_TYPE_CMUX, 1, "cg-cmux1", cmuxa_plist, 0x70020);
1336844eecfSMichal Meloun static struct clk_mux_def cmux2 =
1346844eecfSMichal Meloun MUX(QORIQ_TYPE_CMUX, 2, "cg-cmux2", cmuxa_plist, 0x70040);
1356844eecfSMichal Meloun static struct clk_mux_def cmux3 =
1366844eecfSMichal Meloun MUX(QORIQ_TYPE_CMUX, 3, "cg-cmux3", cmuxa_plist, 0x70060);
1376844eecfSMichal Meloun static struct clk_mux_def cmux4 =
1386844eecfSMichal Meloun MUX(QORIQ_TYPE_CMUX, 4, "cg-cmux4", cmuxb_plist, 0x70080);
1396844eecfSMichal Meloun static struct clk_mux_def cmux5 =
1406844eecfSMichal Meloun MUX(QORIQ_TYPE_CMUX, 5, "cg-cmux5", cmuxb_plist, 0x700A0);
1416844eecfSMichal Meloun static struct clk_mux_def cmux6 =
1426844eecfSMichal Meloun MUX(QORIQ_TYPE_CMUX, 6, "cg-cmux6", cmuxb_plist, 0x700C0);
1436844eecfSMichal Meloun static struct clk_mux_def cmux7 =
1446844eecfSMichal Meloun MUX(QORIQ_TYPE_CMUX, 7, "cg-cmux7", cmuxb_plist, 0x700E0);
1456844eecfSMichal Meloun
1466844eecfSMichal Meloun static struct clk_mux_def *mux_nodes[] = {
1476844eecfSMichal Meloun &cmux0,
1486844eecfSMichal Meloun &cmux1,
1496844eecfSMichal Meloun &cmux2,
1506844eecfSMichal Meloun &cmux3,
1516844eecfSMichal Meloun &cmux4,
1526844eecfSMichal Meloun &cmux5,
1536844eecfSMichal Meloun &cmux6,
1546844eecfSMichal Meloun &cmux7,
1556844eecfSMichal Meloun };
1566844eecfSMichal Meloun
1576844eecfSMichal Meloun static int
lx2160a_clkgen_probe(device_t dev)1586844eecfSMichal Meloun lx2160a_clkgen_probe(device_t dev)
1596844eecfSMichal Meloun {
1606844eecfSMichal Meloun
1616844eecfSMichal Meloun if (!ofw_bus_status_okay(dev))
1626844eecfSMichal Meloun return (ENXIO);
1636844eecfSMichal Meloun
1646844eecfSMichal Meloun if(!ofw_bus_is_compatible(dev, "fsl,lx2160a-clockgen"))
1656844eecfSMichal Meloun return (ENXIO);
1666844eecfSMichal Meloun
1676844eecfSMichal Meloun device_set_desc(dev, "LX2160A clockgen");
1686844eecfSMichal Meloun return (BUS_PROBE_DEFAULT);
1696844eecfSMichal Meloun }
1706844eecfSMichal Meloun
1716844eecfSMichal Meloun static int
lx2160a_clkgen_attach(device_t dev)1726844eecfSMichal Meloun lx2160a_clkgen_attach(device_t dev)
1736844eecfSMichal Meloun {
1746844eecfSMichal Meloun struct qoriq_clkgen_softc *sc;
1756844eecfSMichal Meloun int rv;
1766844eecfSMichal Meloun
1776844eecfSMichal Meloun sc = device_get_softc(dev);
1786844eecfSMichal Meloun
1796844eecfSMichal Meloun sc->pltfrm_pll_def = &pltfrm_pll;
1806844eecfSMichal Meloun sc->cga_pll = cg_plls;
1816844eecfSMichal Meloun sc->cga_pll_num = nitems(cg_plls);
1826844eecfSMichal Meloun sc->mux = mux_nodes;
1836844eecfSMichal Meloun sc->mux_num = nitems(mux_nodes);
1846844eecfSMichal Meloun sc->flags = QORIQ_LITTLE_ENDIAN;
1856844eecfSMichal Meloun
1866844eecfSMichal Meloun rv = qoriq_clkgen_attach(dev);
1876844eecfSMichal Meloun
1886844eecfSMichal Meloun printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x00080, bus_read_4(sc->res, 0x00080));
1896844eecfSMichal Meloun printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x000A0, bus_read_4(sc->res, 0x000A0));
1906844eecfSMichal Meloun printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x10080, bus_read_4(sc->res, 0x10080));
1916844eecfSMichal Meloun printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x100A0, bus_read_4(sc->res, 0x100A0));
1926844eecfSMichal Meloun printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x60080, bus_read_4(sc->res, 0x60080));
1936844eecfSMichal Meloun printf(" %s: offset: 0x%08X, val: 0x%08X\n", __func__, 0x600A0, bus_read_4(sc->res, 0x600A0));
1946844eecfSMichal Meloun return (rv);
1956844eecfSMichal Meloun }
1966844eecfSMichal Meloun
1976844eecfSMichal Meloun static device_method_t lx2160a_clkgen_methods[] = {
1986844eecfSMichal Meloun DEVMETHOD(device_probe, lx2160a_clkgen_probe),
1996844eecfSMichal Meloun DEVMETHOD(device_attach, lx2160a_clkgen_attach),
2006844eecfSMichal Meloun
2016844eecfSMichal Meloun DEVMETHOD_END
2026844eecfSMichal Meloun };
2036844eecfSMichal Meloun
2046844eecfSMichal Meloun DEFINE_CLASS_1(lx2160a_clkgen, lx2160a_clkgen_driver, lx2160a_clkgen_methods,
2056844eecfSMichal Meloun sizeof(struct qoriq_clkgen_softc), qoriq_clkgen_driver);
206d7827042SJohn Baldwin EARLY_DRIVER_MODULE(lx2160a_clkgen, simplebus, lx2160a_clkgen_driver, 0, 0,
207d7827042SJohn Baldwin BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
208