xref: /freebsd/sys/dev/gpio/dwgpio/dwgpio_bus.c (revision fdafd315)
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/param.h>
34564e8256SRuslan Bukin #include <sys/systm.h>
35564e8256SRuslan Bukin #include <sys/bus.h>
36564e8256SRuslan Bukin #include <sys/kernel.h>
37564e8256SRuslan Bukin #include <sys/module.h>
38564e8256SRuslan Bukin #include <sys/rman.h>
39564e8256SRuslan Bukin 
40564e8256SRuslan Bukin #include <machine/bus.h>
41564e8256SRuslan Bukin 
42564e8256SRuslan Bukin #include <dev/fdt/simplebus.h>
43564e8256SRuslan Bukin #include <dev/fdt/fdt_common.h>
44564e8256SRuslan Bukin #include <dev/ofw/ofw_bus_subr.h>
45564e8256SRuslan Bukin 
46564e8256SRuslan Bukin #include "dwgpio_if.h"
47564e8256SRuslan Bukin 
48564e8256SRuslan Bukin struct dwgpiobus_softc {
49564e8256SRuslan Bukin 	struct simplebus_softc	simplebus_sc;
50564e8256SRuslan Bukin 	device_t		dev;
51564e8256SRuslan Bukin 	struct resource		*res[1];
52564e8256SRuslan Bukin };
53564e8256SRuslan Bukin 
54564e8256SRuslan Bukin static struct resource_spec dwgpio_spec[] = {
55564e8256SRuslan Bukin 	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
56564e8256SRuslan Bukin 	{ -1, 0 }
57564e8256SRuslan Bukin };
58564e8256SRuslan Bukin 
59564e8256SRuslan Bukin static int
dwgpiobus_probe(device_t dev)60564e8256SRuslan Bukin dwgpiobus_probe(device_t dev)
61564e8256SRuslan Bukin {
62564e8256SRuslan Bukin 
63564e8256SRuslan Bukin 	if (!ofw_bus_is_compatible(dev, "snps,dw-apb-gpio"))
64564e8256SRuslan Bukin 		return (ENXIO);
65564e8256SRuslan Bukin 
66564e8256SRuslan Bukin 	if (!ofw_bus_status_okay(dev))
67564e8256SRuslan Bukin 		return (ENXIO);
68564e8256SRuslan Bukin 
69564e8256SRuslan Bukin 	device_set_desc(dev, "Synopsys® DesignWare® APB GPIO BUS");
70564e8256SRuslan Bukin 
71564e8256SRuslan Bukin 	return (BUS_PROBE_DEFAULT);
72564e8256SRuslan Bukin }
73564e8256SRuslan Bukin 
74564e8256SRuslan Bukin static int
dwgpiobus_attach(device_t dev)75564e8256SRuslan Bukin dwgpiobus_attach(device_t dev)
76564e8256SRuslan Bukin {
77564e8256SRuslan Bukin 	struct dwgpiobus_softc *sc;
78564e8256SRuslan Bukin 	phandle_t node;
79564e8256SRuslan Bukin 
80564e8256SRuslan Bukin 	sc = device_get_softc(dev);
81564e8256SRuslan Bukin 	sc->dev = dev;
82564e8256SRuslan Bukin 
83564e8256SRuslan Bukin 	node = ofw_bus_get_node(dev);
84564e8256SRuslan Bukin 	if (node == -1)
85564e8256SRuslan Bukin 		return (ENXIO);
86564e8256SRuslan Bukin 
87564e8256SRuslan Bukin 	if (bus_alloc_resources(dev, dwgpio_spec, sc->res)) {
88564e8256SRuslan Bukin 		device_printf(dev, "Could not allocate resources.\n");
89564e8256SRuslan Bukin 		return (ENXIO);
90564e8256SRuslan Bukin 	}
91564e8256SRuslan Bukin 
92564e8256SRuslan Bukin 	simplebus_init(dev, node);
93564e8256SRuslan Bukin 
94564e8256SRuslan Bukin 	/*
95564e8256SRuslan Bukin 	 * Allow devices to identify.
96564e8256SRuslan Bukin 	 */
97564e8256SRuslan Bukin 	bus_generic_probe(dev);
98564e8256SRuslan Bukin 
99564e8256SRuslan Bukin 	/*
100564e8256SRuslan Bukin 	 * Now walk the OFW tree and attach top-level devices.
101564e8256SRuslan Bukin 	 */
102564e8256SRuslan Bukin 	for (node = OF_child(node); node > 0; node = OF_peer(node))
103564e8256SRuslan Bukin 		simplebus_add_device(dev, node, 0, NULL, -1, NULL);
104564e8256SRuslan Bukin 
105564e8256SRuslan Bukin 	return (bus_generic_attach(dev));
106564e8256SRuslan Bukin }
107564e8256SRuslan Bukin 
108564e8256SRuslan Bukin static int
dwgpiobus_detach(device_t dev)109564e8256SRuslan Bukin dwgpiobus_detach(device_t dev)
110564e8256SRuslan Bukin {
111564e8256SRuslan Bukin 	struct dwgpiobus_softc *sc;
112564e8256SRuslan Bukin 
113564e8256SRuslan Bukin 	sc = device_get_softc(dev);
114564e8256SRuslan Bukin 
115564e8256SRuslan Bukin 	bus_release_resources(dev, dwgpio_spec, sc->res);
116564e8256SRuslan Bukin 
117564e8256SRuslan Bukin 	return (0);
118564e8256SRuslan Bukin }
119564e8256SRuslan Bukin 
120564e8256SRuslan Bukin static int
dwgpiobus_write(device_t dev,bus_size_t offset,int val)121564e8256SRuslan Bukin dwgpiobus_write(device_t dev, bus_size_t offset, int val)
122564e8256SRuslan Bukin {
123564e8256SRuslan Bukin 	struct dwgpiobus_softc *sc;
124564e8256SRuslan Bukin 
125564e8256SRuslan Bukin 	sc = device_get_softc(dev);
126564e8256SRuslan Bukin 
127564e8256SRuslan Bukin 	bus_write_4(sc->res[0], offset, val);
128564e8256SRuslan Bukin 
129564e8256SRuslan Bukin 	return (0);
130564e8256SRuslan Bukin };
131564e8256SRuslan Bukin 
132564e8256SRuslan Bukin static int
dwgpiobus_read(device_t dev,bus_size_t offset)133564e8256SRuslan Bukin dwgpiobus_read(device_t dev, bus_size_t offset)
134564e8256SRuslan Bukin {
135564e8256SRuslan Bukin 	struct dwgpiobus_softc *sc;
136564e8256SRuslan Bukin 	int val;
137564e8256SRuslan Bukin 
138564e8256SRuslan Bukin 	sc = device_get_softc(dev);
139564e8256SRuslan Bukin 
140564e8256SRuslan Bukin 	val = bus_read_4(sc->res[0], offset);
141564e8256SRuslan Bukin 
142564e8256SRuslan Bukin 	return (val);
143564e8256SRuslan Bukin };
144564e8256SRuslan Bukin 
145564e8256SRuslan Bukin static device_method_t dwgpiobus_methods[] = {
146564e8256SRuslan Bukin 	DEVMETHOD(device_probe,		dwgpiobus_probe),
147564e8256SRuslan Bukin 	DEVMETHOD(device_attach,	dwgpiobus_attach),
148564e8256SRuslan Bukin 	DEVMETHOD(device_detach,	dwgpiobus_detach),
149564e8256SRuslan Bukin 
150564e8256SRuslan Bukin 	DEVMETHOD(dwgpio_write,		dwgpiobus_write),
151564e8256SRuslan Bukin 	DEVMETHOD(dwgpio_read,		dwgpiobus_read),
152564e8256SRuslan Bukin 
153564e8256SRuslan Bukin 	DEVMETHOD_END
154564e8256SRuslan Bukin };
155564e8256SRuslan Bukin 
156564e8256SRuslan Bukin DEFINE_CLASS_1(dwgpiobus, dwgpiobus_driver, dwgpiobus_methods,
157564e8256SRuslan Bukin     sizeof(struct dwgpiobus_softc), simplebus_driver);
158564e8256SRuslan Bukin 
15984c5f982SJohn Baldwin EARLY_DRIVER_MODULE(dwgpiobus, simplebus, dwgpiobus_driver, 0, 0,
16084c5f982SJohn Baldwin     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
161564e8256SRuslan Bukin MODULE_VERSION(dwgpiobus, 1);
162