1*4a4c6dc9SAlbert Jakieła /*- 2*4a4c6dc9SAlbert Jakieła * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*4a4c6dc9SAlbert Jakieła * 4*4a4c6dc9SAlbert Jakieła * Copyright (c) 2022 Semihalf. 5*4a4c6dc9SAlbert Jakieła * 6*4a4c6dc9SAlbert Jakieła * Redistribution and use in source and binary forms, with or without 7*4a4c6dc9SAlbert Jakieła * modification, are permitted provided that the following conditions 8*4a4c6dc9SAlbert Jakieła * are met: 9*4a4c6dc9SAlbert Jakieła * 1. Redistributions of source code must retain the above copyright 10*4a4c6dc9SAlbert Jakieła * notice, this list of conditions and the following disclaimer. 11*4a4c6dc9SAlbert Jakieła * 2. Redistributions in binary form must reproduce the above copyright 12*4a4c6dc9SAlbert Jakieła * notice, this list of conditions and the following disclaimer in the 13*4a4c6dc9SAlbert Jakieła * documentation and/or other materials provided with the distribution. 14*4a4c6dc9SAlbert Jakieła * 15*4a4c6dc9SAlbert Jakieła * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*4a4c6dc9SAlbert Jakieła * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*4a4c6dc9SAlbert Jakieła * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*4a4c6dc9SAlbert Jakieła * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*4a4c6dc9SAlbert Jakieła * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*4a4c6dc9SAlbert Jakieła * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*4a4c6dc9SAlbert Jakieła * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*4a4c6dc9SAlbert Jakieła * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*4a4c6dc9SAlbert Jakieła * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*4a4c6dc9SAlbert Jakieła * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*4a4c6dc9SAlbert Jakieła */ 26*4a4c6dc9SAlbert Jakieła 27*4a4c6dc9SAlbert Jakieła #include <sys/cdefs.h> 28*4a4c6dc9SAlbert Jakieła __FBSDID("$FreeBSD$"); 29*4a4c6dc9SAlbert Jakieła 30*4a4c6dc9SAlbert Jakieła #include <sys/param.h> 31*4a4c6dc9SAlbert Jakieła #include <sys/systm.h> 32*4a4c6dc9SAlbert Jakieła #include <sys/bus.h> 33*4a4c6dc9SAlbert Jakieła #include <sys/rman.h> 34*4a4c6dc9SAlbert Jakieła #include <sys/kernel.h> 35*4a4c6dc9SAlbert Jakieła #include <sys/lock.h> 36*4a4c6dc9SAlbert Jakieła #include <sys/module.h> 37*4a4c6dc9SAlbert Jakieła #include <sys/mutex.h> 38*4a4c6dc9SAlbert Jakieła 39*4a4c6dc9SAlbert Jakieła #include <machine/bus.h> 40*4a4c6dc9SAlbert Jakieła 41*4a4c6dc9SAlbert Jakieła #include <dev/fdt/simplebus.h> 42*4a4c6dc9SAlbert Jakieła #include <dev/ofw/ofw_bus.h> 43*4a4c6dc9SAlbert Jakieła #include <dev/ofw/ofw_bus_subr.h> 44*4a4c6dc9SAlbert Jakieła #include <dev/extres/clk/clk.h> 45*4a4c6dc9SAlbert Jakieła #include <dev/extres/clk/clk_gate.h> 46*4a4c6dc9SAlbert Jakieła 47*4a4c6dc9SAlbert Jakieła #include "clkdev_if.h" 48*4a4c6dc9SAlbert Jakieła 49*4a4c6dc9SAlbert Jakieła struct armada38x_gateclk_softc 50*4a4c6dc9SAlbert Jakieła { 51*4a4c6dc9SAlbert Jakieła struct clkdom *clkdom; 52*4a4c6dc9SAlbert Jakieła struct mtx mtx; 53*4a4c6dc9SAlbert Jakieła const char* parent; 54*4a4c6dc9SAlbert Jakieła }; 55*4a4c6dc9SAlbert Jakieła 56*4a4c6dc9SAlbert Jakieła static struct clk_gate_def gateclk_nodes[] = 57*4a4c6dc9SAlbert Jakieła { 58*4a4c6dc9SAlbert Jakieła { 59*4a4c6dc9SAlbert Jakieła .clkdef = { 60*4a4c6dc9SAlbert Jakieła .name = "gateclk-audio", 61*4a4c6dc9SAlbert Jakieła .id = 0, 62*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 63*4a4c6dc9SAlbert Jakieła .flags = 0, 64*4a4c6dc9SAlbert Jakieła }, 65*4a4c6dc9SAlbert Jakieła .shift = 0, 66*4a4c6dc9SAlbert Jakieła }, 67*4a4c6dc9SAlbert Jakieła { 68*4a4c6dc9SAlbert Jakieła .clkdef = { 69*4a4c6dc9SAlbert Jakieła .name = "gateclk-eth2", 70*4a4c6dc9SAlbert Jakieła .id = 2, 71*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 72*4a4c6dc9SAlbert Jakieła .flags = 0, 73*4a4c6dc9SAlbert Jakieła }, 74*4a4c6dc9SAlbert Jakieła .shift = 2, 75*4a4c6dc9SAlbert Jakieła }, 76*4a4c6dc9SAlbert Jakieła { 77*4a4c6dc9SAlbert Jakieła .clkdef = { 78*4a4c6dc9SAlbert Jakieła .name = "gateclk-eth1", 79*4a4c6dc9SAlbert Jakieła .id = 3, 80*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 81*4a4c6dc9SAlbert Jakieła .flags = 0, 82*4a4c6dc9SAlbert Jakieła }, 83*4a4c6dc9SAlbert Jakieła .shift = 3, 84*4a4c6dc9SAlbert Jakieła }, 85*4a4c6dc9SAlbert Jakieła { 86*4a4c6dc9SAlbert Jakieła .clkdef = { 87*4a4c6dc9SAlbert Jakieła .name = "gateclk-eth0", 88*4a4c6dc9SAlbert Jakieła .id = 4, 89*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 90*4a4c6dc9SAlbert Jakieła .flags = 0, 91*4a4c6dc9SAlbert Jakieła }, 92*4a4c6dc9SAlbert Jakieła .shift = 4, 93*4a4c6dc9SAlbert Jakieła }, 94*4a4c6dc9SAlbert Jakieła { 95*4a4c6dc9SAlbert Jakieła .clkdef = { 96*4a4c6dc9SAlbert Jakieła .name = "gateclk-mdio", 97*4a4c6dc9SAlbert Jakieła .id = 4, 98*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 99*4a4c6dc9SAlbert Jakieła .flags = 0, 100*4a4c6dc9SAlbert Jakieła }, 101*4a4c6dc9SAlbert Jakieła .shift = 4, 102*4a4c6dc9SAlbert Jakieła }, 103*4a4c6dc9SAlbert Jakieła { 104*4a4c6dc9SAlbert Jakieła .clkdef = { 105*4a4c6dc9SAlbert Jakieła .name = "gateclk-usb3h0", 106*4a4c6dc9SAlbert Jakieła .id = 9, 107*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 108*4a4c6dc9SAlbert Jakieła .flags = 0, 109*4a4c6dc9SAlbert Jakieła }, 110*4a4c6dc9SAlbert Jakieła .shift = 9, 111*4a4c6dc9SAlbert Jakieła }, 112*4a4c6dc9SAlbert Jakieła { 113*4a4c6dc9SAlbert Jakieła .clkdef = { 114*4a4c6dc9SAlbert Jakieła .name = "gateclk-usb3h1", 115*4a4c6dc9SAlbert Jakieła .id = 10, 116*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 117*4a4c6dc9SAlbert Jakieła .flags = 0, 118*4a4c6dc9SAlbert Jakieła }, 119*4a4c6dc9SAlbert Jakieła .shift = 10, 120*4a4c6dc9SAlbert Jakieła }, 121*4a4c6dc9SAlbert Jakieła { 122*4a4c6dc9SAlbert Jakieła .clkdef = { 123*4a4c6dc9SAlbert Jakieła .name = "gateclk-bm", 124*4a4c6dc9SAlbert Jakieła .id = 13, 125*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 126*4a4c6dc9SAlbert Jakieła .flags = 0, 127*4a4c6dc9SAlbert Jakieła }, 128*4a4c6dc9SAlbert Jakieła .shift = 13, 129*4a4c6dc9SAlbert Jakieła }, 130*4a4c6dc9SAlbert Jakieła { 131*4a4c6dc9SAlbert Jakieła .clkdef = { 132*4a4c6dc9SAlbert Jakieła .name = "gateclk-crypto0z", 133*4a4c6dc9SAlbert Jakieła .id = 14, 134*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 135*4a4c6dc9SAlbert Jakieła .flags = 0, 136*4a4c6dc9SAlbert Jakieła }, 137*4a4c6dc9SAlbert Jakieła .shift = 14, 138*4a4c6dc9SAlbert Jakieła }, 139*4a4c6dc9SAlbert Jakieła { 140*4a4c6dc9SAlbert Jakieła .clkdef = { 141*4a4c6dc9SAlbert Jakieła .name = "gateclk-sata0", 142*4a4c6dc9SAlbert Jakieła .id = 15, 143*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 144*4a4c6dc9SAlbert Jakieła .flags = 0, 145*4a4c6dc9SAlbert Jakieła }, 146*4a4c6dc9SAlbert Jakieła .shift = 15, 147*4a4c6dc9SAlbert Jakieła }, 148*4a4c6dc9SAlbert Jakieła { 149*4a4c6dc9SAlbert Jakieła .clkdef = { 150*4a4c6dc9SAlbert Jakieła .name = "gateclk-crypto1z", 151*4a4c6dc9SAlbert Jakieła .id = 16, 152*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 153*4a4c6dc9SAlbert Jakieła .flags = 0, 154*4a4c6dc9SAlbert Jakieła }, 155*4a4c6dc9SAlbert Jakieła .shift = 16, 156*4a4c6dc9SAlbert Jakieła }, 157*4a4c6dc9SAlbert Jakieła { 158*4a4c6dc9SAlbert Jakieła .clkdef = { 159*4a4c6dc9SAlbert Jakieła .name = "gateclk-sdio", 160*4a4c6dc9SAlbert Jakieła .id = 17, 161*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 162*4a4c6dc9SAlbert Jakieła .flags = 0, 163*4a4c6dc9SAlbert Jakieła }, 164*4a4c6dc9SAlbert Jakieła .shift = 17, 165*4a4c6dc9SAlbert Jakieła }, 166*4a4c6dc9SAlbert Jakieła { 167*4a4c6dc9SAlbert Jakieła .clkdef = { 168*4a4c6dc9SAlbert Jakieła .name = "gateclk-usb2", 169*4a4c6dc9SAlbert Jakieła .id = 18, 170*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 171*4a4c6dc9SAlbert Jakieła .flags = 0, 172*4a4c6dc9SAlbert Jakieła }, 173*4a4c6dc9SAlbert Jakieła .shift = 18, 174*4a4c6dc9SAlbert Jakieła }, 175*4a4c6dc9SAlbert Jakieła { 176*4a4c6dc9SAlbert Jakieła .clkdef = { 177*4a4c6dc9SAlbert Jakieła .name = "gateclk-crypto1", 178*4a4c6dc9SAlbert Jakieła .id = 21, 179*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 180*4a4c6dc9SAlbert Jakieła .flags = 0, 181*4a4c6dc9SAlbert Jakieła }, 182*4a4c6dc9SAlbert Jakieła .shift = 21, 183*4a4c6dc9SAlbert Jakieła }, 184*4a4c6dc9SAlbert Jakieła { 185*4a4c6dc9SAlbert Jakieła .clkdef = { 186*4a4c6dc9SAlbert Jakieła .name = "gateclk-xor0", 187*4a4c6dc9SAlbert Jakieła .id = 22, 188*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 189*4a4c6dc9SAlbert Jakieła .flags = 0, 190*4a4c6dc9SAlbert Jakieła }, 191*4a4c6dc9SAlbert Jakieła .shift = 22, 192*4a4c6dc9SAlbert Jakieła }, 193*4a4c6dc9SAlbert Jakieła { 194*4a4c6dc9SAlbert Jakieła .clkdef = { 195*4a4c6dc9SAlbert Jakieła .name = "gateclk-crypto0", 196*4a4c6dc9SAlbert Jakieła .id = 23, 197*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 198*4a4c6dc9SAlbert Jakieła .flags = 0, 199*4a4c6dc9SAlbert Jakieła }, 200*4a4c6dc9SAlbert Jakieła .shift = 23, 201*4a4c6dc9SAlbert Jakieła }, 202*4a4c6dc9SAlbert Jakieła { 203*4a4c6dc9SAlbert Jakieła .clkdef = { 204*4a4c6dc9SAlbert Jakieła .name = "gateclk-xor1", 205*4a4c6dc9SAlbert Jakieła .id = 28, 206*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 207*4a4c6dc9SAlbert Jakieła .flags = 0, 208*4a4c6dc9SAlbert Jakieła }, 209*4a4c6dc9SAlbert Jakieła .shift = 28, 210*4a4c6dc9SAlbert Jakieła }, 211*4a4c6dc9SAlbert Jakieła { 212*4a4c6dc9SAlbert Jakieła .clkdef = { 213*4a4c6dc9SAlbert Jakieła .name = "gateclk-sata1", 214*4a4c6dc9SAlbert Jakieła .id = 30, 215*4a4c6dc9SAlbert Jakieła .parent_cnt = 1, 216*4a4c6dc9SAlbert Jakieła .flags = 0, 217*4a4c6dc9SAlbert Jakieła }, 218*4a4c6dc9SAlbert Jakieła .shift = 30, 219*4a4c6dc9SAlbert Jakieła } 220*4a4c6dc9SAlbert Jakieła }; 221*4a4c6dc9SAlbert Jakieła 222*4a4c6dc9SAlbert Jakieła static int armada38x_gateclk_probe(device_t dev); 223*4a4c6dc9SAlbert Jakieła static int armada38x_gateclk_attach(device_t dev); 224*4a4c6dc9SAlbert Jakieła 225*4a4c6dc9SAlbert Jakieła static device_method_t armada38x_gateclk_methods[] = { 226*4a4c6dc9SAlbert Jakieła DEVMETHOD(device_probe, armada38x_gateclk_probe), 227*4a4c6dc9SAlbert Jakieła DEVMETHOD(device_attach, armada38x_gateclk_attach), 228*4a4c6dc9SAlbert Jakieła 229*4a4c6dc9SAlbert Jakieła DEVMETHOD_END 230*4a4c6dc9SAlbert Jakieła }; 231*4a4c6dc9SAlbert Jakieła 232*4a4c6dc9SAlbert Jakieła static driver_t armada38x_gateclk_driver = { 233*4a4c6dc9SAlbert Jakieła "armada38x_gateclk", 234*4a4c6dc9SAlbert Jakieła armada38x_gateclk_methods, 235*4a4c6dc9SAlbert Jakieła sizeof(struct armada38x_gateclk_softc), 236*4a4c6dc9SAlbert Jakieła }; 237*4a4c6dc9SAlbert Jakieła 238*4a4c6dc9SAlbert Jakieła EARLY_DRIVER_MODULE(armada38x_gateclk, simplebus, armada38x_gateclk_driver, 0, 0, 239*4a4c6dc9SAlbert Jakieła BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE + 1); 240*4a4c6dc9SAlbert Jakieła 241*4a4c6dc9SAlbert Jakieła static int 242*4a4c6dc9SAlbert Jakieła armada38x_gateclk_probe(device_t dev) 243*4a4c6dc9SAlbert Jakieła { 244*4a4c6dc9SAlbert Jakieła 245*4a4c6dc9SAlbert Jakieła if (!ofw_bus_status_okay(dev)) 246*4a4c6dc9SAlbert Jakieła return (ENXIO); 247*4a4c6dc9SAlbert Jakieła 248*4a4c6dc9SAlbert Jakieła if(!ofw_bus_is_compatible(dev, "marvell,armada-380-gating-clock")) 249*4a4c6dc9SAlbert Jakieła return (ENXIO); 250*4a4c6dc9SAlbert Jakieła 251*4a4c6dc9SAlbert Jakieła device_set_desc(dev, "ARMADA38X gateclk"); 252*4a4c6dc9SAlbert Jakieła 253*4a4c6dc9SAlbert Jakieła return (BUS_PROBE_DEFAULT); 254*4a4c6dc9SAlbert Jakieła } 255*4a4c6dc9SAlbert Jakieła 256*4a4c6dc9SAlbert Jakieła static int 257*4a4c6dc9SAlbert Jakieła armada38x_gateclk_attach(device_t dev) 258*4a4c6dc9SAlbert Jakieła { 259*4a4c6dc9SAlbert Jakieła struct armada38x_gateclk_softc *sc; 260*4a4c6dc9SAlbert Jakieła phandle_t node; 261*4a4c6dc9SAlbert Jakieła int i, error; 262*4a4c6dc9SAlbert Jakieła clk_t clock; 263*4a4c6dc9SAlbert Jakieła 264*4a4c6dc9SAlbert Jakieła sc = device_get_softc(dev); 265*4a4c6dc9SAlbert Jakieła node = ofw_bus_get_node(dev); 266*4a4c6dc9SAlbert Jakieła 267*4a4c6dc9SAlbert Jakieła mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); 268*4a4c6dc9SAlbert Jakieła 269*4a4c6dc9SAlbert Jakieła sc->clkdom = clkdom_create(dev); 270*4a4c6dc9SAlbert Jakieła if (sc->clkdom == NULL) { 271*4a4c6dc9SAlbert Jakieła device_printf(dev, "Cannot create clock domain.\n"); 272*4a4c6dc9SAlbert Jakieła return (ENXIO); 273*4a4c6dc9SAlbert Jakieła } 274*4a4c6dc9SAlbert Jakieła 275*4a4c6dc9SAlbert Jakieła error = clk_get_by_ofw_index(dev, node, 0, &clock); 276*4a4c6dc9SAlbert Jakieła if (error > 0) 277*4a4c6dc9SAlbert Jakieła return (error); 278*4a4c6dc9SAlbert Jakieła 279*4a4c6dc9SAlbert Jakieła sc->parent = clk_get_name(clock); 280*4a4c6dc9SAlbert Jakieła 281*4a4c6dc9SAlbert Jakieła for (i = 0; i < nitems(gateclk_nodes); ++i) { 282*4a4c6dc9SAlbert Jakieła gateclk_nodes[i].clkdef.parent_names = &sc->parent; 283*4a4c6dc9SAlbert Jakieła error = clknode_gate_register(sc->clkdom, &gateclk_nodes[i]); 284*4a4c6dc9SAlbert Jakieła if (error != 0) { 285*4a4c6dc9SAlbert Jakieła device_printf(dev, "Cannot create gate nodes\n"); 286*4a4c6dc9SAlbert Jakieła return (error); 287*4a4c6dc9SAlbert Jakieła } 288*4a4c6dc9SAlbert Jakieła } 289*4a4c6dc9SAlbert Jakieła 290*4a4c6dc9SAlbert Jakieła if (clkdom_finit(sc->clkdom) != 0) 291*4a4c6dc9SAlbert Jakieła panic("Cannot finalize clock domain initialization.\n"); 292*4a4c6dc9SAlbert Jakieła 293*4a4c6dc9SAlbert Jakieła return (0); 294*4a4c6dc9SAlbert Jakieła } 295