1fdfd3a90SEmmanuel Vadot /*- 2fdfd3a90SEmmanuel Vadot * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3fdfd3a90SEmmanuel Vadot * 4fdfd3a90SEmmanuel Vadot * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG 5fdfd3a90SEmmanuel Vadot * 6fdfd3a90SEmmanuel Vadot * Redistribution and use in source and binary forms, with or without 7fdfd3a90SEmmanuel Vadot * modification, are permitted provided that the following conditions 8fdfd3a90SEmmanuel Vadot * are met: 9fdfd3a90SEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright 10fdfd3a90SEmmanuel Vadot * notice, this list of conditions and the following disclaimer. 11fdfd3a90SEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright 12fdfd3a90SEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the 13fdfd3a90SEmmanuel Vadot * documentation and/or other materials provided with the distribution. 14fdfd3a90SEmmanuel Vadot * 15fdfd3a90SEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16fdfd3a90SEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17fdfd3a90SEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18fdfd3a90SEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19fdfd3a90SEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20fdfd3a90SEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21fdfd3a90SEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22fdfd3a90SEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23fdfd3a90SEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24fdfd3a90SEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25fdfd3a90SEmmanuel Vadot * SUCH DAMAGE. 26fdfd3a90SEmmanuel Vadot */ 27fdfd3a90SEmmanuel Vadot 28fdfd3a90SEmmanuel Vadot #include <sys/cdefs.h> 29fdfd3a90SEmmanuel Vadot 30fdfd3a90SEmmanuel Vadot #include <sys/param.h> 31fdfd3a90SEmmanuel Vadot #include <sys/systm.h> 32fdfd3a90SEmmanuel Vadot #include <sys/kernel.h> 33fdfd3a90SEmmanuel Vadot #include <sys/module.h> 34fdfd3a90SEmmanuel Vadot #include <sys/malloc.h> 35fdfd3a90SEmmanuel Vadot #include <sys/bus.h> 36fdfd3a90SEmmanuel Vadot #include <sys/cpu.h> 37fdfd3a90SEmmanuel Vadot #include <machine/bus.h> 38fdfd3a90SEmmanuel Vadot 39fdfd3a90SEmmanuel Vadot #include <dev/fdt/simplebus.h> 40fdfd3a90SEmmanuel Vadot 41fdfd3a90SEmmanuel Vadot #include <dev/ofw/openfirm.h> 42fdfd3a90SEmmanuel Vadot #include <dev/ofw/ofw_bus.h> 43fdfd3a90SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h> 44fdfd3a90SEmmanuel Vadot 45fdfd3a90SEmmanuel Vadot struct ofw_firmware_softc { 46fdfd3a90SEmmanuel Vadot struct simplebus_softc sc; 47fdfd3a90SEmmanuel Vadot device_t dev; 48fdfd3a90SEmmanuel Vadot }; 49fdfd3a90SEmmanuel Vadot 50fdfd3a90SEmmanuel Vadot static struct simplebus_devinfo * 51fdfd3a90SEmmanuel Vadot ofw_firmware_setup_dinfo(device_t dev, phandle_t node, 52fdfd3a90SEmmanuel Vadot struct simplebus_devinfo *di) 53fdfd3a90SEmmanuel Vadot { 54fdfd3a90SEmmanuel Vadot struct simplebus_softc *sc; 55fdfd3a90SEmmanuel Vadot struct simplebus_devinfo *ndi; 56fdfd3a90SEmmanuel Vadot 57fdfd3a90SEmmanuel Vadot sc = device_get_softc(dev); 58fdfd3a90SEmmanuel Vadot if (di == NULL) 59fdfd3a90SEmmanuel Vadot ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO); 60fdfd3a90SEmmanuel Vadot else 61fdfd3a90SEmmanuel Vadot ndi = di; 62fdfd3a90SEmmanuel Vadot if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) { 63fdfd3a90SEmmanuel Vadot if (di == NULL) 64fdfd3a90SEmmanuel Vadot free(ndi, M_DEVBUF); 65fdfd3a90SEmmanuel Vadot return (NULL); 66fdfd3a90SEmmanuel Vadot } 67fdfd3a90SEmmanuel Vadot 68fdfd3a90SEmmanuel Vadot /* reg resources is from the parent but interrupts is on the node itself */ 69fdfd3a90SEmmanuel Vadot resource_list_init(&ndi->rl); 70fdfd3a90SEmmanuel Vadot ofw_bus_reg_to_rl(dev, OF_parent(node), sc->acells, sc->scells, &ndi->rl); 71fdfd3a90SEmmanuel Vadot ofw_bus_intr_to_rl(dev, node, &ndi->rl, NULL); 72fdfd3a90SEmmanuel Vadot 73fdfd3a90SEmmanuel Vadot return (ndi); 74fdfd3a90SEmmanuel Vadot } 75fdfd3a90SEmmanuel Vadot 76fdfd3a90SEmmanuel Vadot static device_t 77fdfd3a90SEmmanuel Vadot ofw_firmware_add_device(device_t dev, phandle_t node, u_int order, 78fdfd3a90SEmmanuel Vadot const char *name, int unit, struct simplebus_devinfo *di) 79fdfd3a90SEmmanuel Vadot { 80fdfd3a90SEmmanuel Vadot struct simplebus_devinfo *ndi; 81fdfd3a90SEmmanuel Vadot device_t cdev; 82fdfd3a90SEmmanuel Vadot 83fdfd3a90SEmmanuel Vadot if ((ndi = ofw_firmware_setup_dinfo(dev, node, di)) == NULL) 84fdfd3a90SEmmanuel Vadot return (NULL); 85fdfd3a90SEmmanuel Vadot cdev = device_add_child_ordered(dev, order, name, unit); 86fdfd3a90SEmmanuel Vadot if (cdev == NULL) { 87fdfd3a90SEmmanuel Vadot device_printf(dev, "<%s>: device_add_child failed\n", 88fdfd3a90SEmmanuel Vadot ndi->obdinfo.obd_name); 89fdfd3a90SEmmanuel Vadot resource_list_free(&ndi->rl); 90fdfd3a90SEmmanuel Vadot ofw_bus_gen_destroy_devinfo(&ndi->obdinfo); 91fdfd3a90SEmmanuel Vadot if (di == NULL) 92fdfd3a90SEmmanuel Vadot free(ndi, M_DEVBUF); 93fdfd3a90SEmmanuel Vadot return (NULL); 94fdfd3a90SEmmanuel Vadot } 95fdfd3a90SEmmanuel Vadot device_set_ivars(cdev, ndi); 96fdfd3a90SEmmanuel Vadot 97fdfd3a90SEmmanuel Vadot return(cdev); 98fdfd3a90SEmmanuel Vadot } 99fdfd3a90SEmmanuel Vadot 100fdfd3a90SEmmanuel Vadot static int 101fdfd3a90SEmmanuel Vadot ofw_firmware_probe(device_t dev) 102fdfd3a90SEmmanuel Vadot { 103fdfd3a90SEmmanuel Vadot const char *name; 104fdfd3a90SEmmanuel Vadot 105fdfd3a90SEmmanuel Vadot name = ofw_bus_get_name(dev); 106fdfd3a90SEmmanuel Vadot if (name == NULL || strcmp(name, "firmware") != 0) 107fdfd3a90SEmmanuel Vadot return (ENXIO); 108fdfd3a90SEmmanuel Vadot 109fdfd3a90SEmmanuel Vadot device_set_desc(dev, "OFW Firmware Group"); 110fdfd3a90SEmmanuel Vadot return (0); 111fdfd3a90SEmmanuel Vadot } 112fdfd3a90SEmmanuel Vadot 113fdfd3a90SEmmanuel Vadot static int 114fdfd3a90SEmmanuel Vadot ofw_firmware_attach(device_t dev) 115fdfd3a90SEmmanuel Vadot { 116fdfd3a90SEmmanuel Vadot struct ofw_firmware_softc *sc; 117fdfd3a90SEmmanuel Vadot phandle_t node, child; 118fdfd3a90SEmmanuel Vadot device_t cdev; 119fdfd3a90SEmmanuel Vadot 120fdfd3a90SEmmanuel Vadot sc = device_get_softc(dev); 121fdfd3a90SEmmanuel Vadot sc->dev = dev; 122fdfd3a90SEmmanuel Vadot node = ofw_bus_get_node(dev); 123fdfd3a90SEmmanuel Vadot 124fdfd3a90SEmmanuel Vadot if (OF_getencprop(node, "#address-cells", &sc->sc.acells, 125fdfd3a90SEmmanuel Vadot sizeof(sc->sc.acells)) == -1) { 126fdfd3a90SEmmanuel Vadot if (OF_getencprop(OF_parent(node), "#address-cells", &sc->sc.acells, 127fdfd3a90SEmmanuel Vadot sizeof(sc->sc.acells)) == -1) { 128fdfd3a90SEmmanuel Vadot sc->sc.acells = 2; 129fdfd3a90SEmmanuel Vadot } 130fdfd3a90SEmmanuel Vadot } 131fdfd3a90SEmmanuel Vadot if (OF_getencprop(node, "#size-cells", &sc->sc.scells, 132fdfd3a90SEmmanuel Vadot sizeof(sc->sc.scells)) == -1) { 133fdfd3a90SEmmanuel Vadot if (OF_getencprop(OF_parent(node), "#size-cells", &sc->sc.scells, 134fdfd3a90SEmmanuel Vadot sizeof(sc->sc.scells)) == -1) { 135fdfd3a90SEmmanuel Vadot sc->sc.scells = 1; 136fdfd3a90SEmmanuel Vadot } 137fdfd3a90SEmmanuel Vadot } 138fdfd3a90SEmmanuel Vadot 139fdfd3a90SEmmanuel Vadot for (child = OF_child(node); child != 0; child = OF_peer(child)) { 140fdfd3a90SEmmanuel Vadot cdev = ofw_firmware_add_device(dev, child, 0, NULL, -1, NULL); 141fdfd3a90SEmmanuel Vadot if (cdev != NULL) 142fdfd3a90SEmmanuel Vadot device_probe_and_attach(cdev); 143fdfd3a90SEmmanuel Vadot } 144fdfd3a90SEmmanuel Vadot 145fdfd3a90SEmmanuel Vadot return (bus_generic_attach(dev)); 146fdfd3a90SEmmanuel Vadot } 147fdfd3a90SEmmanuel Vadot 148fdfd3a90SEmmanuel Vadot static device_method_t ofw_firmware_methods[] = { 149fdfd3a90SEmmanuel Vadot /* device_if */ 150fdfd3a90SEmmanuel Vadot DEVMETHOD(device_probe, ofw_firmware_probe), 151fdfd3a90SEmmanuel Vadot DEVMETHOD(device_attach, ofw_firmware_attach), 152fdfd3a90SEmmanuel Vadot 153fdfd3a90SEmmanuel Vadot DEVMETHOD_END 154fdfd3a90SEmmanuel Vadot }; 155fdfd3a90SEmmanuel Vadot 156fdfd3a90SEmmanuel Vadot DEFINE_CLASS_1(ofw_firmware, ofw_firmware_driver, ofw_firmware_methods, 157fdfd3a90SEmmanuel Vadot sizeof(struct ofw_firmware_softc), simplebus_driver); 158fdfd3a90SEmmanuel Vadot 159fdfd3a90SEmmanuel Vadot EARLY_DRIVER_MODULE(ofw_firmware, simplebus, ofw_firmware_driver, 0, 0, 160fdfd3a90SEmmanuel Vadot BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); 161fdfd3a90SEmmanuel Vadot MODULE_VERSION(ofw_firmware, 1); 162