14a4c6dc9SAlbert Jakieła /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
34a4c6dc9SAlbert Jakieła *
44a4c6dc9SAlbert Jakieła * Copyright (c) 2022 Semihalf.
54a4c6dc9SAlbert Jakieła *
64a4c6dc9SAlbert Jakieła * Redistribution and use in source and binary forms, with or without
74a4c6dc9SAlbert Jakieła * modification, are permitted provided that the following conditions
84a4c6dc9SAlbert Jakieła * are met:
94a4c6dc9SAlbert Jakieła * 1. Redistributions of source code must retain the above copyright
104a4c6dc9SAlbert Jakieła * notice, this list of conditions and the following disclaimer.
114a4c6dc9SAlbert Jakieła * 2. Redistributions in binary form must reproduce the above copyright
124a4c6dc9SAlbert Jakieła * notice, this list of conditions and the following disclaimer in the
134a4c6dc9SAlbert Jakieła * documentation and/or other materials provided with the distribution.
144a4c6dc9SAlbert Jakieła *
154a4c6dc9SAlbert Jakieła * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
164a4c6dc9SAlbert Jakieła * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
174a4c6dc9SAlbert Jakieła * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
184a4c6dc9SAlbert Jakieła * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
194a4c6dc9SAlbert Jakieła * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
204a4c6dc9SAlbert Jakieła * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
214a4c6dc9SAlbert Jakieła * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
224a4c6dc9SAlbert Jakieła * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
234a4c6dc9SAlbert Jakieła * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
244a4c6dc9SAlbert Jakieła * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
254a4c6dc9SAlbert Jakieła */
264a4c6dc9SAlbert Jakieła
274a4c6dc9SAlbert Jakieła #include <sys/param.h>
284a4c6dc9SAlbert Jakieła #include <sys/systm.h>
294a4c6dc9SAlbert Jakieła #include <sys/bus.h>
304a4c6dc9SAlbert Jakieła #include <sys/rman.h>
314a4c6dc9SAlbert Jakieła #include <sys/kernel.h>
324a4c6dc9SAlbert Jakieła #include <sys/lock.h>
334a4c6dc9SAlbert Jakieła #include <sys/module.h>
344a4c6dc9SAlbert Jakieła #include <sys/mutex.h>
354a4c6dc9SAlbert Jakieła
364a4c6dc9SAlbert Jakieła #include <machine/bus.h>
374a4c6dc9SAlbert Jakieła
384a4c6dc9SAlbert Jakieła #include <dev/fdt/simplebus.h>
394a4c6dc9SAlbert Jakieła #include <dev/ofw/ofw_bus.h>
404a4c6dc9SAlbert Jakieła #include <dev/ofw/ofw_bus_subr.h>
41*be82b3a0SEmmanuel Vadot #include <dev/clk/clk.h>
42*be82b3a0SEmmanuel Vadot #include <dev/clk/clk_gate.h>
434a4c6dc9SAlbert Jakieła
444a4c6dc9SAlbert Jakieła #include "clkdev_if.h"
454a4c6dc9SAlbert Jakieła
464a4c6dc9SAlbert Jakieła struct armada38x_gateclk_softc
474a4c6dc9SAlbert Jakieła {
484a4c6dc9SAlbert Jakieła struct clkdom *clkdom;
494a4c6dc9SAlbert Jakieła struct mtx mtx;
504a4c6dc9SAlbert Jakieła const char* parent;
514a4c6dc9SAlbert Jakieła };
524a4c6dc9SAlbert Jakieła
534a4c6dc9SAlbert Jakieła static struct clk_gate_def gateclk_nodes[] =
544a4c6dc9SAlbert Jakieła {
554a4c6dc9SAlbert Jakieła {
564a4c6dc9SAlbert Jakieła .clkdef = {
574a4c6dc9SAlbert Jakieła .name = "gateclk-audio",
584a4c6dc9SAlbert Jakieła .id = 0,
594a4c6dc9SAlbert Jakieła .parent_cnt = 1,
604a4c6dc9SAlbert Jakieła .flags = 0,
614a4c6dc9SAlbert Jakieła },
624a4c6dc9SAlbert Jakieła .shift = 0,
634a4c6dc9SAlbert Jakieła },
644a4c6dc9SAlbert Jakieła {
654a4c6dc9SAlbert Jakieła .clkdef = {
664a4c6dc9SAlbert Jakieła .name = "gateclk-eth2",
674a4c6dc9SAlbert Jakieła .id = 2,
684a4c6dc9SAlbert Jakieła .parent_cnt = 1,
694a4c6dc9SAlbert Jakieła .flags = 0,
704a4c6dc9SAlbert Jakieła },
714a4c6dc9SAlbert Jakieła .shift = 2,
724a4c6dc9SAlbert Jakieła },
734a4c6dc9SAlbert Jakieła {
744a4c6dc9SAlbert Jakieła .clkdef = {
754a4c6dc9SAlbert Jakieła .name = "gateclk-eth1",
764a4c6dc9SAlbert Jakieła .id = 3,
774a4c6dc9SAlbert Jakieła .parent_cnt = 1,
784a4c6dc9SAlbert Jakieła .flags = 0,
794a4c6dc9SAlbert Jakieła },
804a4c6dc9SAlbert Jakieła .shift = 3,
814a4c6dc9SAlbert Jakieła },
824a4c6dc9SAlbert Jakieła {
834a4c6dc9SAlbert Jakieła .clkdef = {
844a4c6dc9SAlbert Jakieła .name = "gateclk-eth0",
854a4c6dc9SAlbert Jakieła .id = 4,
864a4c6dc9SAlbert Jakieła .parent_cnt = 1,
874a4c6dc9SAlbert Jakieła .flags = 0,
884a4c6dc9SAlbert Jakieła },
894a4c6dc9SAlbert Jakieła .shift = 4,
904a4c6dc9SAlbert Jakieła },
914a4c6dc9SAlbert Jakieła {
924a4c6dc9SAlbert Jakieła .clkdef = {
934a4c6dc9SAlbert Jakieła .name = "gateclk-mdio",
944a4c6dc9SAlbert Jakieła .id = 4,
954a4c6dc9SAlbert Jakieła .parent_cnt = 1,
964a4c6dc9SAlbert Jakieła .flags = 0,
974a4c6dc9SAlbert Jakieła },
984a4c6dc9SAlbert Jakieła .shift = 4,
994a4c6dc9SAlbert Jakieła },
1004a4c6dc9SAlbert Jakieła {
1014a4c6dc9SAlbert Jakieła .clkdef = {
1024a4c6dc9SAlbert Jakieła .name = "gateclk-usb3h0",
1034a4c6dc9SAlbert Jakieła .id = 9,
1044a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1054a4c6dc9SAlbert Jakieła .flags = 0,
1064a4c6dc9SAlbert Jakieła },
1074a4c6dc9SAlbert Jakieła .shift = 9,
1084a4c6dc9SAlbert Jakieła },
1094a4c6dc9SAlbert Jakieła {
1104a4c6dc9SAlbert Jakieła .clkdef = {
1114a4c6dc9SAlbert Jakieła .name = "gateclk-usb3h1",
1124a4c6dc9SAlbert Jakieła .id = 10,
1134a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1144a4c6dc9SAlbert Jakieła .flags = 0,
1154a4c6dc9SAlbert Jakieła },
1164a4c6dc9SAlbert Jakieła .shift = 10,
1174a4c6dc9SAlbert Jakieła },
1184a4c6dc9SAlbert Jakieła {
1194a4c6dc9SAlbert Jakieła .clkdef = {
1204a4c6dc9SAlbert Jakieła .name = "gateclk-bm",
1214a4c6dc9SAlbert Jakieła .id = 13,
1224a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1234a4c6dc9SAlbert Jakieła .flags = 0,
1244a4c6dc9SAlbert Jakieła },
1254a4c6dc9SAlbert Jakieła .shift = 13,
1264a4c6dc9SAlbert Jakieła },
1274a4c6dc9SAlbert Jakieła {
1284a4c6dc9SAlbert Jakieła .clkdef = {
1294a4c6dc9SAlbert Jakieła .name = "gateclk-crypto0z",
1304a4c6dc9SAlbert Jakieła .id = 14,
1314a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1324a4c6dc9SAlbert Jakieła .flags = 0,
1334a4c6dc9SAlbert Jakieła },
1344a4c6dc9SAlbert Jakieła .shift = 14,
1354a4c6dc9SAlbert Jakieła },
1364a4c6dc9SAlbert Jakieła {
1374a4c6dc9SAlbert Jakieła .clkdef = {
1384a4c6dc9SAlbert Jakieła .name = "gateclk-sata0",
1394a4c6dc9SAlbert Jakieła .id = 15,
1404a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1414a4c6dc9SAlbert Jakieła .flags = 0,
1424a4c6dc9SAlbert Jakieła },
1434a4c6dc9SAlbert Jakieła .shift = 15,
1444a4c6dc9SAlbert Jakieła },
1454a4c6dc9SAlbert Jakieła {
1464a4c6dc9SAlbert Jakieła .clkdef = {
1474a4c6dc9SAlbert Jakieła .name = "gateclk-crypto1z",
1484a4c6dc9SAlbert Jakieła .id = 16,
1494a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1504a4c6dc9SAlbert Jakieła .flags = 0,
1514a4c6dc9SAlbert Jakieła },
1524a4c6dc9SAlbert Jakieła .shift = 16,
1534a4c6dc9SAlbert Jakieła },
1544a4c6dc9SAlbert Jakieła {
1554a4c6dc9SAlbert Jakieła .clkdef = {
1564a4c6dc9SAlbert Jakieła .name = "gateclk-sdio",
1574a4c6dc9SAlbert Jakieła .id = 17,
1584a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1594a4c6dc9SAlbert Jakieła .flags = 0,
1604a4c6dc9SAlbert Jakieła },
1614a4c6dc9SAlbert Jakieła .shift = 17,
1624a4c6dc9SAlbert Jakieła },
1634a4c6dc9SAlbert Jakieła {
1644a4c6dc9SAlbert Jakieła .clkdef = {
1654a4c6dc9SAlbert Jakieła .name = "gateclk-usb2",
1664a4c6dc9SAlbert Jakieła .id = 18,
1674a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1684a4c6dc9SAlbert Jakieła .flags = 0,
1694a4c6dc9SAlbert Jakieła },
1704a4c6dc9SAlbert Jakieła .shift = 18,
1714a4c6dc9SAlbert Jakieła },
1724a4c6dc9SAlbert Jakieła {
1734a4c6dc9SAlbert Jakieła .clkdef = {
1744a4c6dc9SAlbert Jakieła .name = "gateclk-crypto1",
1754a4c6dc9SAlbert Jakieła .id = 21,
1764a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1774a4c6dc9SAlbert Jakieła .flags = 0,
1784a4c6dc9SAlbert Jakieła },
1794a4c6dc9SAlbert Jakieła .shift = 21,
1804a4c6dc9SAlbert Jakieła },
1814a4c6dc9SAlbert Jakieła {
1824a4c6dc9SAlbert Jakieła .clkdef = {
1834a4c6dc9SAlbert Jakieła .name = "gateclk-xor0",
1844a4c6dc9SAlbert Jakieła .id = 22,
1854a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1864a4c6dc9SAlbert Jakieła .flags = 0,
1874a4c6dc9SAlbert Jakieła },
1884a4c6dc9SAlbert Jakieła .shift = 22,
1894a4c6dc9SAlbert Jakieła },
1904a4c6dc9SAlbert Jakieła {
1914a4c6dc9SAlbert Jakieła .clkdef = {
1924a4c6dc9SAlbert Jakieła .name = "gateclk-crypto0",
1934a4c6dc9SAlbert Jakieła .id = 23,
1944a4c6dc9SAlbert Jakieła .parent_cnt = 1,
1954a4c6dc9SAlbert Jakieła .flags = 0,
1964a4c6dc9SAlbert Jakieła },
1974a4c6dc9SAlbert Jakieła .shift = 23,
1984a4c6dc9SAlbert Jakieła },
1994a4c6dc9SAlbert Jakieła {
2004a4c6dc9SAlbert Jakieła .clkdef = {
2014a4c6dc9SAlbert Jakieła .name = "gateclk-xor1",
2024a4c6dc9SAlbert Jakieła .id = 28,
2034a4c6dc9SAlbert Jakieła .parent_cnt = 1,
2044a4c6dc9SAlbert Jakieła .flags = 0,
2054a4c6dc9SAlbert Jakieła },
2064a4c6dc9SAlbert Jakieła .shift = 28,
2074a4c6dc9SAlbert Jakieła },
2084a4c6dc9SAlbert Jakieła {
2094a4c6dc9SAlbert Jakieła .clkdef = {
2104a4c6dc9SAlbert Jakieła .name = "gateclk-sata1",
2114a4c6dc9SAlbert Jakieła .id = 30,
2124a4c6dc9SAlbert Jakieła .parent_cnt = 1,
2134a4c6dc9SAlbert Jakieła .flags = 0,
2144a4c6dc9SAlbert Jakieła },
2154a4c6dc9SAlbert Jakieła .shift = 30,
2164a4c6dc9SAlbert Jakieła }
2174a4c6dc9SAlbert Jakieła };
2184a4c6dc9SAlbert Jakieła
2194a4c6dc9SAlbert Jakieła static int armada38x_gateclk_probe(device_t dev);
2204a4c6dc9SAlbert Jakieła static int armada38x_gateclk_attach(device_t dev);
2214a4c6dc9SAlbert Jakieła
2224a4c6dc9SAlbert Jakieła static device_method_t armada38x_gateclk_methods[] = {
2234a4c6dc9SAlbert Jakieła DEVMETHOD(device_probe, armada38x_gateclk_probe),
2244a4c6dc9SAlbert Jakieła DEVMETHOD(device_attach, armada38x_gateclk_attach),
2254a4c6dc9SAlbert Jakieła
2264a4c6dc9SAlbert Jakieła DEVMETHOD_END
2274a4c6dc9SAlbert Jakieła };
2284a4c6dc9SAlbert Jakieła
2294a4c6dc9SAlbert Jakieła static driver_t armada38x_gateclk_driver = {
2304a4c6dc9SAlbert Jakieła "armada38x_gateclk",
2314a4c6dc9SAlbert Jakieła armada38x_gateclk_methods,
2324a4c6dc9SAlbert Jakieła sizeof(struct armada38x_gateclk_softc),
2334a4c6dc9SAlbert Jakieła };
2344a4c6dc9SAlbert Jakieła
2354a4c6dc9SAlbert Jakieła EARLY_DRIVER_MODULE(armada38x_gateclk, simplebus, armada38x_gateclk_driver, 0, 0,
2364a4c6dc9SAlbert Jakieła BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 1);
2374a4c6dc9SAlbert Jakieła
2384a4c6dc9SAlbert Jakieła static int
armada38x_gateclk_probe(device_t dev)2394a4c6dc9SAlbert Jakieła armada38x_gateclk_probe(device_t dev)
2404a4c6dc9SAlbert Jakieła {
2414a4c6dc9SAlbert Jakieła
2424a4c6dc9SAlbert Jakieła if (!ofw_bus_status_okay(dev))
2434a4c6dc9SAlbert Jakieła return (ENXIO);
2444a4c6dc9SAlbert Jakieła
2454a4c6dc9SAlbert Jakieła if(!ofw_bus_is_compatible(dev, "marvell,armada-380-gating-clock"))
2464a4c6dc9SAlbert Jakieła return (ENXIO);
2474a4c6dc9SAlbert Jakieła
2484a4c6dc9SAlbert Jakieła device_set_desc(dev, "ARMADA38X gateclk");
2494a4c6dc9SAlbert Jakieła
2504a4c6dc9SAlbert Jakieła return (BUS_PROBE_DEFAULT);
2514a4c6dc9SAlbert Jakieła }
2524a4c6dc9SAlbert Jakieła
2534a4c6dc9SAlbert Jakieła static int
armada38x_gateclk_attach(device_t dev)2544a4c6dc9SAlbert Jakieła armada38x_gateclk_attach(device_t dev)
2554a4c6dc9SAlbert Jakieła {
2564a4c6dc9SAlbert Jakieła struct armada38x_gateclk_softc *sc;
2574a4c6dc9SAlbert Jakieła phandle_t node;
2584a4c6dc9SAlbert Jakieła int i, error;
2594a4c6dc9SAlbert Jakieła clk_t clock;
2604a4c6dc9SAlbert Jakieła
2614a4c6dc9SAlbert Jakieła sc = device_get_softc(dev);
2624a4c6dc9SAlbert Jakieła node = ofw_bus_get_node(dev);
2634a4c6dc9SAlbert Jakieła
2644a4c6dc9SAlbert Jakieła mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
2654a4c6dc9SAlbert Jakieła
2664a4c6dc9SAlbert Jakieła sc->clkdom = clkdom_create(dev);
2674a4c6dc9SAlbert Jakieła if (sc->clkdom == NULL) {
2684a4c6dc9SAlbert Jakieła device_printf(dev, "Cannot create clock domain.\n");
2694a4c6dc9SAlbert Jakieła return (ENXIO);
2704a4c6dc9SAlbert Jakieła }
2714a4c6dc9SAlbert Jakieła
2724a4c6dc9SAlbert Jakieła error = clk_get_by_ofw_index(dev, node, 0, &clock);
2734a4c6dc9SAlbert Jakieła if (error > 0)
2744a4c6dc9SAlbert Jakieła return (error);
2754a4c6dc9SAlbert Jakieła
2764a4c6dc9SAlbert Jakieła sc->parent = clk_get_name(clock);
2774a4c6dc9SAlbert Jakieła
2784a4c6dc9SAlbert Jakieła for (i = 0; i < nitems(gateclk_nodes); ++i) {
2794a4c6dc9SAlbert Jakieła gateclk_nodes[i].clkdef.parent_names = &sc->parent;
2804a4c6dc9SAlbert Jakieła error = clknode_gate_register(sc->clkdom, &gateclk_nodes[i]);
2814a4c6dc9SAlbert Jakieła if (error != 0) {
2824a4c6dc9SAlbert Jakieła device_printf(dev, "Cannot create gate nodes\n");
2834a4c6dc9SAlbert Jakieła return (error);
2844a4c6dc9SAlbert Jakieła }
2854a4c6dc9SAlbert Jakieła }
2864a4c6dc9SAlbert Jakieła
2874a4c6dc9SAlbert Jakieła if (clkdom_finit(sc->clkdom) != 0)
2884a4c6dc9SAlbert Jakieła panic("Cannot finalize clock domain initialization.\n");
2894a4c6dc9SAlbert Jakieła
2904a4c6dc9SAlbert Jakieła return (0);
2914a4c6dc9SAlbert Jakieła }
292