1564e8256SRuslan Bukin /*- 2564e8256SRuslan Bukin * SPDX-License-Identifier: BSD-2-Clause 3564e8256SRuslan Bukin * 4564e8256SRuslan Bukin * Copyright (c) 2019 Ruslan Bukin <br@bsdpad.com> 5564e8256SRuslan Bukin * 6564e8256SRuslan Bukin * This software was developed by SRI International and the University of 7564e8256SRuslan Bukin * Cambridge Computer Laboratory (Department of Computer Science and 8564e8256SRuslan Bukin * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the 9564e8256SRuslan Bukin * DARPA SSITH research programme. 10564e8256SRuslan Bukin * 11564e8256SRuslan Bukin * Redistribution and use in source and binary forms, with or without 12564e8256SRuslan Bukin * modification, are permitted provided that the following conditions 13564e8256SRuslan Bukin * are met: 14564e8256SRuslan Bukin * 1. Redistributions of source code must retain the above copyright 15564e8256SRuslan Bukin * notice, this list of conditions and the following disclaimer. 16564e8256SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright 17564e8256SRuslan Bukin * notice, this list of conditions and the following disclaimer in the 18564e8256SRuslan Bukin * documentation and/or other materials provided with the distribution. 19564e8256SRuslan Bukin * 20564e8256SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21564e8256SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22564e8256SRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23564e8256SRuslan Bukin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24564e8256SRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25564e8256SRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26564e8256SRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27564e8256SRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28564e8256SRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29564e8256SRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30564e8256SRuslan Bukin * SUCH DAMAGE. 31564e8256SRuslan Bukin */ 32564e8256SRuslan Bukin 33564e8256SRuslan Bukin #include <sys/cdefs.h> 34564e8256SRuslan Bukin __FBSDID("$FreeBSD$"); 35564e8256SRuslan Bukin 36564e8256SRuslan Bukin #include <sys/param.h> 37564e8256SRuslan Bukin #include <sys/systm.h> 38564e8256SRuslan Bukin #include <sys/bus.h> 39564e8256SRuslan Bukin #include <sys/kernel.h> 40564e8256SRuslan Bukin #include <sys/module.h> 41564e8256SRuslan Bukin #include <sys/rman.h> 42564e8256SRuslan Bukin 43564e8256SRuslan Bukin #include <machine/bus.h> 44564e8256SRuslan Bukin 45564e8256SRuslan Bukin #include <dev/fdt/simplebus.h> 46564e8256SRuslan Bukin #include <dev/fdt/fdt_common.h> 47564e8256SRuslan Bukin #include <dev/ofw/ofw_bus_subr.h> 48564e8256SRuslan Bukin 49564e8256SRuslan Bukin #include "dwgpio_if.h" 50564e8256SRuslan Bukin 51564e8256SRuslan Bukin struct dwgpiobus_softc { 52564e8256SRuslan Bukin struct simplebus_softc simplebus_sc; 53564e8256SRuslan Bukin device_t dev; 54564e8256SRuslan Bukin struct resource *res[1]; 55564e8256SRuslan Bukin }; 56564e8256SRuslan Bukin 57564e8256SRuslan Bukin static struct resource_spec dwgpio_spec[] = { 58564e8256SRuslan Bukin { SYS_RES_MEMORY, 0, RF_ACTIVE }, 59564e8256SRuslan Bukin { -1, 0 } 60564e8256SRuslan Bukin }; 61564e8256SRuslan Bukin 62564e8256SRuslan Bukin static int 63564e8256SRuslan Bukin dwgpiobus_probe(device_t dev) 64564e8256SRuslan Bukin { 65564e8256SRuslan Bukin 66564e8256SRuslan Bukin if (!ofw_bus_is_compatible(dev, "snps,dw-apb-gpio")) 67564e8256SRuslan Bukin return (ENXIO); 68564e8256SRuslan Bukin 69564e8256SRuslan Bukin if (!ofw_bus_status_okay(dev)) 70564e8256SRuslan Bukin return (ENXIO); 71564e8256SRuslan Bukin 72564e8256SRuslan Bukin device_set_desc(dev, "Synopsys® DesignWare® APB GPIO BUS"); 73564e8256SRuslan Bukin 74564e8256SRuslan Bukin return (BUS_PROBE_DEFAULT); 75564e8256SRuslan Bukin } 76564e8256SRuslan Bukin 77564e8256SRuslan Bukin static int 78564e8256SRuslan Bukin dwgpiobus_attach(device_t dev) 79564e8256SRuslan Bukin { 80564e8256SRuslan Bukin struct dwgpiobus_softc *sc; 81564e8256SRuslan Bukin phandle_t node; 82564e8256SRuslan Bukin 83564e8256SRuslan Bukin sc = device_get_softc(dev); 84564e8256SRuslan Bukin sc->dev = dev; 85564e8256SRuslan Bukin 86564e8256SRuslan Bukin node = ofw_bus_get_node(dev); 87564e8256SRuslan Bukin if (node == -1) 88564e8256SRuslan Bukin return (ENXIO); 89564e8256SRuslan Bukin 90564e8256SRuslan Bukin if (bus_alloc_resources(dev, dwgpio_spec, sc->res)) { 91564e8256SRuslan Bukin device_printf(dev, "Could not allocate resources.\n"); 92564e8256SRuslan Bukin return (ENXIO); 93564e8256SRuslan Bukin } 94564e8256SRuslan Bukin 95564e8256SRuslan Bukin simplebus_init(dev, node); 96564e8256SRuslan Bukin 97564e8256SRuslan Bukin /* 98564e8256SRuslan Bukin * Allow devices to identify. 99564e8256SRuslan Bukin */ 100564e8256SRuslan Bukin bus_generic_probe(dev); 101564e8256SRuslan Bukin 102564e8256SRuslan Bukin /* 103564e8256SRuslan Bukin * Now walk the OFW tree and attach top-level devices. 104564e8256SRuslan Bukin */ 105564e8256SRuslan Bukin for (node = OF_child(node); node > 0; node = OF_peer(node)) 106564e8256SRuslan Bukin simplebus_add_device(dev, node, 0, NULL, -1, NULL); 107564e8256SRuslan Bukin 108564e8256SRuslan Bukin return (bus_generic_attach(dev)); 109564e8256SRuslan Bukin } 110564e8256SRuslan Bukin 111564e8256SRuslan Bukin static int 112564e8256SRuslan Bukin dwgpiobus_detach(device_t dev) 113564e8256SRuslan Bukin { 114564e8256SRuslan Bukin struct dwgpiobus_softc *sc; 115564e8256SRuslan Bukin 116564e8256SRuslan Bukin sc = device_get_softc(dev); 117564e8256SRuslan Bukin 118564e8256SRuslan Bukin bus_release_resources(dev, dwgpio_spec, sc->res); 119564e8256SRuslan Bukin 120564e8256SRuslan Bukin return (0); 121564e8256SRuslan Bukin } 122564e8256SRuslan Bukin 123564e8256SRuslan Bukin static int 124564e8256SRuslan Bukin dwgpiobus_write(device_t dev, bus_size_t offset, int val) 125564e8256SRuslan Bukin { 126564e8256SRuslan Bukin struct dwgpiobus_softc *sc; 127564e8256SRuslan Bukin 128564e8256SRuslan Bukin sc = device_get_softc(dev); 129564e8256SRuslan Bukin 130564e8256SRuslan Bukin bus_write_4(sc->res[0], offset, val); 131564e8256SRuslan Bukin 132564e8256SRuslan Bukin return (0); 133564e8256SRuslan Bukin }; 134564e8256SRuslan Bukin 135564e8256SRuslan Bukin static int 136564e8256SRuslan Bukin dwgpiobus_read(device_t dev, bus_size_t offset) 137564e8256SRuslan Bukin { 138564e8256SRuslan Bukin struct dwgpiobus_softc *sc; 139564e8256SRuslan Bukin int val; 140564e8256SRuslan Bukin 141564e8256SRuslan Bukin sc = device_get_softc(dev); 142564e8256SRuslan Bukin 143564e8256SRuslan Bukin val = bus_read_4(sc->res[0], offset); 144564e8256SRuslan Bukin 145564e8256SRuslan Bukin return (val); 146564e8256SRuslan Bukin }; 147564e8256SRuslan Bukin 148564e8256SRuslan Bukin static device_method_t dwgpiobus_methods[] = { 149564e8256SRuslan Bukin DEVMETHOD(device_probe, dwgpiobus_probe), 150564e8256SRuslan Bukin DEVMETHOD(device_attach, dwgpiobus_attach), 151564e8256SRuslan Bukin DEVMETHOD(device_detach, dwgpiobus_detach), 152564e8256SRuslan Bukin 153564e8256SRuslan Bukin DEVMETHOD(dwgpio_write, dwgpiobus_write), 154564e8256SRuslan Bukin DEVMETHOD(dwgpio_read, dwgpiobus_read), 155564e8256SRuslan Bukin 156564e8256SRuslan Bukin DEVMETHOD_END 157564e8256SRuslan Bukin }; 158564e8256SRuslan Bukin 159564e8256SRuslan Bukin DEFINE_CLASS_1(dwgpiobus, dwgpiobus_driver, dwgpiobus_methods, 160564e8256SRuslan Bukin sizeof(struct dwgpiobus_softc), simplebus_driver); 161564e8256SRuslan Bukin 162564e8256SRuslan Bukin static devclass_t dwgpiobus_devclass; 163564e8256SRuslan Bukin 164564e8256SRuslan Bukin EARLY_DRIVER_MODULE(dwgpiobus, simplebus, dwgpiobus_driver, dwgpiobus_devclass, 165564e8256SRuslan Bukin 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE); 166564e8256SRuslan Bukin MODULE_VERSION(dwgpiobus, 1); 167