2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2006 Benno Rice. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
31 #include <sys/systm.h>
33 #include <sys/kernel.h>
35 #include <sys/interrupt.h>
36 #include <sys/module.h>
37 #include <sys/malloc.h>
38 #include <sys/mutex.h>
40 #include <sys/queue.h>
41 #include <sys/taskqueue.h>
42 #include <sys/timetc.h>
43 #include <machine/bus.h>
44 #include <machine/intr.h>
46 #include <arm/xscale/pxa/pxavar.h>
47 #include <arm/xscale/pxa/pxareg.h>
49 struct pxa_gpio_softc {
50 struct resource * pg_res[4];
51 bus_space_tag_t pg_bst;
52 bus_space_handle_t pg_bsh;
58 static struct resource_spec pxa_gpio_spec[] = {
59 { SYS_RES_MEMORY, 0, RF_ACTIVE },
60 { SYS_RES_IRQ, 0, RF_ACTIVE },
61 { SYS_RES_IRQ, 1, RF_ACTIVE },
62 { SYS_RES_IRQ, 2, RF_ACTIVE },
66 static struct pxa_gpio_softc *pxa_gpio_softc = NULL;
68 static int pxa_gpio_probe(device_t);
69 static int pxa_gpio_attach(device_t);
71 static driver_filter_t pxa_gpio_intr0;
72 static driver_filter_t pxa_gpio_intr1;
73 static driver_filter_t pxa_gpio_intrN;
76 pxa_gpio_probe(device_t dev)
79 device_set_desc(dev, "GPIO Controller");
84 pxa_gpio_attach(device_t dev)
88 struct pxa_gpio_softc *sc;
90 sc = (struct pxa_gpio_softc *)device_get_softc(dev);
92 if (pxa_gpio_softc != NULL)
96 error = bus_alloc_resources(dev, pxa_gpio_spec, sc->pg_res);
98 device_printf(dev, "could not allocate resources\n");
102 sc->pg_bst = rman_get_bustag(sc->pg_res[0]);
103 sc->pg_bsh = rman_get_bushandle(sc->pg_res[0]);
105 /* Disable and clear all interrupts. */
106 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER0, 0);
107 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER1, 0);
108 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER2, 0);
109 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER0, 0);
110 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER1, 0);
111 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER2, 0);
112 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, ~0);
113 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1, ~0);
114 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, ~0);
116 mtx_init(&sc->pg_mtx, "GPIO mutex", NULL, MTX_SPIN);
118 if (bus_setup_intr(dev, sc->pg_res[1], INTR_TYPE_MISC|INTR_MPSAFE,
119 pxa_gpio_intr0, NULL, sc, &ihl) != 0) {
120 bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
121 device_printf(dev, "could not set up intr0\n");
125 if (bus_setup_intr(dev, sc->pg_res[2], INTR_TYPE_MISC|INTR_MPSAFE,
126 pxa_gpio_intr1, NULL, sc, &ihl) != 0) {
127 bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
128 device_printf(dev, "could not set up intr1\n");
132 if (bus_setup_intr(dev, sc->pg_res[3], INTR_TYPE_MISC|INTR_MPSAFE,
133 pxa_gpio_intrN, NULL, sc, &ihl) != 0) {
134 bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
135 device_printf(dev, "could not set up intrN\n");
143 pxa_gpio_intr0(void *arg)
145 struct pxa_gpio_softc *sc;
147 sc = (struct pxa_gpio_softc *)arg;
149 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x1);
152 return (FILTER_HANDLED);
156 pxa_gpio_intr1(void *arg)
158 struct pxa_gpio_softc *sc;
160 sc = (struct pxa_gpio_softc *)arg;
162 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x2);
165 return (FILTER_HANDLED);
169 pxa_gpio_intrN(void *arg)
171 uint32_t gedr0, gedr1, gedr2;
172 struct pxa_gpio_softc *sc;
174 sc = (struct pxa_gpio_softc *)arg;
176 gedr0 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0);
178 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, gedr0);
180 gedr1 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1);
181 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1, gedr1);
183 gedr2 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2);
185 bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, gedr2);
187 sc->pg_intr[0] |= gedr0;
188 sc->pg_intr[1] |= gedr1;
189 sc->pg_intr[2] |= gedr2;
191 return (FILTER_HANDLED);
194 static device_method_t pxa_gpio_methods[] = {
195 DEVMETHOD(device_probe, pxa_gpio_probe),
196 DEVMETHOD(device_attach, pxa_gpio_attach),
201 static driver_t pxa_gpio_driver = {
204 sizeof(struct pxa_gpio_softc),
207 static devclass_t pxa_gpio_devclass;
209 DRIVER_MODULE(pxagpio, pxa, pxa_gpio_driver, pxa_gpio_devclass, 0, 0);
211 #define pxagpio_reg_read(softc, reg) \
212 bus_space_read_4(sc->pg_bst, sc->pg_bsh, reg)
213 #define pxagpio_reg_write(softc, reg, val) \
214 bus_space_write_4(sc->pg_bst, sc->pg_bsh, reg, val)
217 pxa_gpio_get_function(int gpio)
219 struct pxa_gpio_softc *sc;
224 rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) >> GPIO_FN_SHIFT(gpio);
227 io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio));
228 if (io & GPIO_BIT(gpio))
231 io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPLR0, gpio));
232 if (io & GPIO_BIT(gpio))
239 pxa_gpio_set_function(int gpio, uint32_t fn)
241 struct pxa_gpio_softc *sc;
242 uint32_t rv, bit, oldfn;
246 oldfn = pxa_gpio_get_function(gpio);
248 if (GPIO_FN(fn) == GPIO_FN(oldfn) &&
249 GPIO_FN_IS_OUT(fn) == GPIO_FN_IS_OUT(oldfn)) {
251 * The pin's function is not changing.
252 * For Alternate Functions and GPIO input, we can just
254 * For GPIO output pins, check the initial state is
257 * Return 'fn' instead of 'oldfn' so the caller can
258 * reliably detect that we didn't change anything.
259 * (The initial state might be different for non-
262 if (!GPIO_IS_GPIO_OUT(fn) ||
263 GPIO_FN_IS_SET(fn) == GPIO_FN_IS_SET(oldfn))
268 * See section 4.1.3.7 of the PXA2x0 Developer's Manual for
269 * the correct procedure for changing GPIO pin functions.
272 bit = GPIO_BIT(gpio);
275 * 1. Configure the correct set/clear state of the pin
277 if (GPIO_FN_IS_SET(fn))
278 pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPSR0, gpio), bit);
280 pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPCR0, gpio), bit);
283 * 2. Configure the pin as an input or output as appropriate
285 rv = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio)) & ~bit;
286 if (GPIO_FN_IS_OUT(fn))
288 pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio), rv);
291 * 3. Configure the pin's function
293 bit = GPIO_FN_MASK << GPIO_FN_SHIFT(gpio);
294 fn = GPIO_FN(fn) << GPIO_FN_SHIFT(gpio);
295 rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) & ~bit;
296 pxagpio_reg_write(sc, GPIO_FN_REG(gpio), rv | fn);
302 * GPIO "interrupt" handling.
306 pxa_gpio_mask_irq(int irq)
309 struct pxa_gpio_softc *sc;
313 gpio = IRQ_TO_GPIO(irq);
315 val = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio));
316 val &= ~GPIO_BIT(gpio);
317 pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio), val);
321 pxa_gpio_unmask_irq(int irq)
324 struct pxa_gpio_softc *sc;
328 gpio = IRQ_TO_GPIO(irq);
330 val = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio));
331 val |= GPIO_BIT(gpio);
332 pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio), val);
336 pxa_gpio_get_next_irq(void)
338 struct pxa_gpio_softc *sc;
343 if (sc->pg_intr[0] != 0) {
344 gpio = ffs(sc->pg_intr[0]) - 1;
345 sc->pg_intr[0] &= ~(1 << gpio);
346 return (GPIO_TO_IRQ(gpio));
348 if (sc->pg_intr[1] != 0) {
349 gpio = ffs(sc->pg_intr[1]) - 1;
350 sc->pg_intr[1] &= ~(1 << gpio);
351 return (GPIO_TO_IRQ(gpio + 32));
353 if (sc->pg_intr[2] != 0) {
354 gpio = ffs(sc->pg_intr[2]) - 1;
355 sc->pg_intr[2] &= ~(1 << gpio);
356 return (GPIO_TO_IRQ(gpio + 64));