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 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 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