xref: /freebsd/sys/arm/mv/clk/armada38x_gateclk.c (revision be82b3a0bf72ed3b5f01ac9fcd8dcd3802e3c742)
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