1 /*
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2025 Tetsuya Uemura <t_uemura@macome.co.jp>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 /*
29 * This is a driver for bcm2835-virtgpio GPIO controller device found on some
30 * Raspberry Pi models (listed below but not limited to). On which, the green
31 * LED (ACT) is connected to this controller. With the help of this driver, a
32 * node corresponding to the green LED will be created under /dev/led, allowing
33 * us to control it.
34 *
35 * Applicable models (according to the FDTs of those models):
36 * Compute Module 2 (CM2)
37 * 3 Model B (not 3B+)
38 * Compute Module 3 (CM3) and possibly 3+ (CM3+)
39 * Compute Module 4 SODIMM (CM4S)
40 */
41
42 #include "opt_platform.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/gpio.h>
47 #include <sys/kernel.h>
48 #include <sys/malloc.h>
49 #include <sys/module.h>
50 #include <sys/mutex.h>
51
52 #include <vm/vm.h>
53 #include <vm/pmap.h>
54
55 #include <dev/gpio/gpiobusvar.h>
56 #include <dev/ofw/ofw_bus.h>
57
58 #include <arm/broadcom/bcm2835/bcm2835_firmware.h>
59 #include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
60
61 #include "gpio_if.h"
62
63 #define RPI_VIRT_GPIO_PINS 2
64
65 struct rpi_virt_gpio_softc {
66 device_t busdev;
67 device_t firmware;
68 struct mtx sc_mtx;
69
70 void *vaddr; /* Virtual address. */
71 vm_paddr_t paddr; /* Physical address. */
72
73 struct gpio_pin gpio_pins[RPI_VIRT_GPIO_PINS];
74 uint32_t state[RPI_VIRT_GPIO_PINS];
75 };
76
77 #define RPI_VIRT_GPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx)
78 #define RPI_VIRT_GPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx)
79
80 static struct ofw_compat_data compat_data[] = {
81 {"brcm,bcm2835-virtgpio", 1},
82 {NULL, 0}
83 };
84
85 static device_t
rpi_virt_gpio_get_bus(device_t dev)86 rpi_virt_gpio_get_bus(device_t dev)
87 {
88 struct rpi_virt_gpio_softc *sc;
89
90 sc = device_get_softc(dev);
91
92 return (sc->busdev);
93 }
94
95 static int
rpi_virt_gpio_pin_max(device_t dev,int * maxpin)96 rpi_virt_gpio_pin_max(device_t dev, int *maxpin)
97 {
98 *maxpin = RPI_VIRT_GPIO_PINS - 1;
99
100 return (0);
101 }
102
103 static int
rpi_virt_gpio_pin_getcaps(device_t dev,uint32_t pin,uint32_t * caps)104 rpi_virt_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
105 {
106 if (pin >= RPI_VIRT_GPIO_PINS)
107 return (EINVAL);
108
109 *caps = GPIO_PIN_OUTPUT;
110
111 return (0);
112 }
113
114 static int
rpi_virt_gpio_pin_getflags(device_t dev,uint32_t pin,uint32_t * flags)115 rpi_virt_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
116 {
117 if (pin >= RPI_VIRT_GPIO_PINS)
118 return (EINVAL);
119
120 *flags = GPIO_PIN_OUTPUT;
121
122 return (0);
123 }
124
125 static int
rpi_virt_gpio_pin_set(device_t dev,uint32_t pin,uint32_t value)126 rpi_virt_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value)
127 {
128 struct rpi_virt_gpio_softc *sc;
129 uint32_t *ptr;
130 uint16_t on, off;
131
132 if (pin >= RPI_VIRT_GPIO_PINS)
133 return (EINVAL);
134
135 sc = device_get_softc(dev);
136
137 RPI_VIRT_GPIO_LOCK(sc);
138 on = (uint16_t)(sc->state[pin] >> 16);
139 off = (uint16_t)sc->state[pin];
140
141 if (bootverbose)
142 device_printf(dev, "on: %hu, off: %hu, now: %d -> %u\n",
143 on, off, on - off, value);
144
145 if ((value > 0 && on - off != 0) || (value == 0 && on - off == 0)) {
146 RPI_VIRT_GPIO_UNLOCK(sc);
147 return (0);
148 }
149
150 if (value > 0)
151 ++on;
152 else
153 ++off;
154
155 sc->state[pin] = (on << 16 | off);
156 ptr = (uint32_t *)sc->vaddr;
157 ptr[pin] = sc->state[pin];
158 RPI_VIRT_GPIO_UNLOCK(sc);
159
160 return (0);
161 }
162
163 static int
rpi_virt_gpio_pin_get(device_t dev,uint32_t pin,uint32_t * val)164 rpi_virt_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *val)
165 {
166 struct rpi_virt_gpio_softc *sc;
167 uint32_t *ptr, v;
168
169 if (pin >= RPI_VIRT_GPIO_PINS)
170 return (EINVAL);
171
172 sc = device_get_softc(dev);
173
174 ptr = (uint32_t *)sc->vaddr;
175 RPI_VIRT_GPIO_LOCK(sc);
176 v = ptr[pin];
177 RPI_VIRT_GPIO_UNLOCK(sc);
178 *val = ((uint16_t)(v >> 16) - (uint16_t)v) == 0 ? 0 : 1;
179
180 return (0);
181 }
182
183 static int
rpi_virt_gpio_pin_toggle(device_t dev,uint32_t pin)184 rpi_virt_gpio_pin_toggle(device_t dev, uint32_t pin)
185 {
186 int rv;
187 unsigned int val;
188
189 if (pin >= RPI_VIRT_GPIO_PINS)
190 return (EINVAL);
191
192 rv = rpi_virt_gpio_pin_get(dev, pin, &val);
193 if (rv != 0)
194 return (rv);
195
196 rv = rpi_virt_gpio_pin_set(dev, pin, val == 0 ? 1 : 0);
197
198 return (rv);
199 }
200
201 static int
rpi_virt_gpio_probe(device_t dev)202 rpi_virt_gpio_probe(device_t dev)
203 {
204 device_t firmware;
205 phandle_t gpio;
206 union msg_gpiovirtbuf cfg;
207 int rv;
208
209 if (ofw_bus_status_okay(dev) == 0)
210 return (ENXIO);
211
212 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
213 return (ENXIO);
214
215 gpio = ofw_bus_get_node(dev);
216 if (OF_hasprop(gpio, "gpio-controller") == 0)
217 return (ENXIO);
218
219 /* Check whether the firmware is ready. */
220 firmware = device_get_parent(dev);
221 rv = bcm2835_firmware_property(firmware,
222 BCM2835_FIRMWARE_TAG_GET_GPIOVIRTBUF, &cfg, sizeof(cfg));
223 if (rv != 0)
224 return (ENXIO);
225
226 device_set_desc(dev, "Raspberry Pi Virtual GPIO controller");
227
228 return (BUS_PROBE_DEFAULT);
229 }
230
231 static int
rpi_virt_gpio_attach(device_t dev)232 rpi_virt_gpio_attach(device_t dev)
233 {
234 struct rpi_virt_gpio_softc *sc;
235 union msg_gpiovirtbuf cfg;
236 int i, rv;
237
238 sc = device_get_softc(dev);
239 sc->firmware = device_get_parent(dev);
240 mtx_init(&sc->sc_mtx, "Raspberry Pi virtgpio", NULL, MTX_SPIN);
241
242 /*
243 * According to the Linux source at:
244 * https://github.com/raspberrypi/linux/blob/rpi-6.12.y/drivers/gpio/gpio-bcm-virt.c
245 * it first attempts to set the pre-allocated physical memory address
246 * in the firmware. If it is successfully acquired, access virtgpio via
247 * the virtual memory address mapped to that physical address.
248 *
249 * If the above fails, then as a fallback, attempts to obtain a
250 * physical memory address for accessing virtgpio from the firmware.
251 * And if obtained, link it to a virtual memory address and access
252 * virtgpio via it.
253 *
254 * An OpenWRT virtgpio driver I happened to see at first only
255 * implemented the fallback method. Then I implemented this method on
256 * FreeBSD and tested it with the 20240429 firmware, but it didn't
257 * work.
258 *
259 * At this point, I realised the first method in the source above. So I
260 * implemented this method on FreeBSD and tested it, and it worked. In
261 * my opinion, the second method was used until some time prior to
262 * 20240429, and then the firmware was modified and the first method
263 * was introduced. In my driver, only the first method exists.
264 */
265
266 /* Allocate a physical memory range for accessing virtgpio. */
267 sc->vaddr = contigmalloc(
268 PAGE_SIZE, /* size */
269 M_DEVBUF, M_ZERO, /* type, flags */
270 0, BCM2838_PERIPH_MAXADDR, /* low, high */
271 PAGE_SIZE, 0); /* alignment, boundary */
272 if (sc->vaddr == NULL) {
273 device_printf(dev, "Failed to allocate memory.\n");
274 return ENOMEM;
275 }
276 sc->paddr = vtophys(sc->vaddr);
277 /* Mark it uncacheable. */
278 pmap_change_attr((vm_offset_t)sc->vaddr, PAGE_SIZE,
279 VM_MEMATTR_UNCACHEABLE);
280
281 if (bootverbose)
282 device_printf(dev,
283 "KVA alloc'd: virtual: %p, phys: %#jx\n",
284 sc->vaddr, (uintmax_t)sc->paddr);
285
286 /* Set this address in firmware. */
287 cfg.req.addr = (uint32_t)sc->paddr;
288 rv = bcm2835_firmware_property(sc->firmware,
289 BCM2835_FIRMWARE_TAG_SET_GPIOVIRTBUF, &cfg, sizeof(cfg));
290 if (bootverbose)
291 device_printf(dev, "rv: %d, addr: 0x%x\n", rv, cfg.resp.addr);
292 if (rv != 0 || cfg.resp.addr != 0)
293 goto fail;
294
295 /* Pins only support output. */
296 for (i = 0; i < RPI_VIRT_GPIO_PINS; i++) {
297 sc->gpio_pins[i].gp_pin = i;
298 sc->gpio_pins[i].gp_caps = sc->gpio_pins[i].gp_flags
299 = GPIO_PIN_OUTPUT;
300 }
301 sc->busdev = gpiobus_add_bus(dev);
302 if (sc->busdev == NULL)
303 goto fail;
304
305 bus_attach_children(dev);
306 return (0);
307
308 fail:
309 /* Release resource if necessary. */
310 free(sc->vaddr, M_DEVBUF);
311 mtx_destroy(&sc->sc_mtx);
312
313 return (ENXIO);
314 }
315
316 static int
rpi_virt_gpio_detach(device_t dev)317 rpi_virt_gpio_detach(device_t dev)
318 {
319 return (EBUSY);
320 }
321
322 static device_method_t rpi_virt_gpio_methods[] = {
323 /* Device interface */
324 DEVMETHOD(device_probe, rpi_virt_gpio_probe),
325 DEVMETHOD(device_attach, rpi_virt_gpio_attach),
326 DEVMETHOD(device_detach, rpi_virt_gpio_detach),
327
328 /* GPIO protocol */
329 DEVMETHOD(gpio_get_bus, rpi_virt_gpio_get_bus),
330 DEVMETHOD(gpio_pin_max, rpi_virt_gpio_pin_max),
331 DEVMETHOD(gpio_pin_getcaps, rpi_virt_gpio_pin_getcaps),
332 DEVMETHOD(gpio_pin_getflags, rpi_virt_gpio_pin_getflags),
333 DEVMETHOD(gpio_pin_set, rpi_virt_gpio_pin_set),
334 DEVMETHOD(gpio_pin_get, rpi_virt_gpio_pin_get),
335 DEVMETHOD(gpio_pin_toggle, rpi_virt_gpio_pin_toggle),
336
337 DEVMETHOD_END
338 };
339
340 static driver_t rpi_virt_gpio_driver = {
341 "gpio",
342 rpi_virt_gpio_methods,
343 sizeof(struct rpi_virt_gpio_softc),
344 };
345
346 EARLY_DRIVER_MODULE(rpi_virt_gpio, bcm2835_firmware, rpi_virt_gpio_driver,
347 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
348