]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/xscale/pxa/pxa_gpio.c
Revert r336773: it removed too much.
[FreeBSD/FreeBSD.git] / sys / arm / xscale / pxa / pxa_gpio.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2006 Benno Rice.  All rights reserved.
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 ``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.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/kernel.h>
34 #include <sys/lock.h>
35 #include <sys/interrupt.h>
36 #include <sys/module.h>
37 #include <sys/malloc.h>
38 #include <sys/mutex.h>
39 #include <sys/rman.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>
45
46 #include <arm/xscale/pxa/pxavar.h>
47 #include <arm/xscale/pxa/pxareg.h>
48
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;
53         struct mtx              pg_mtx;
54
55         uint32_t                pg_intr[3];
56 };
57
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 },
63         { -1, 0 }
64 };
65
66 static struct pxa_gpio_softc *pxa_gpio_softc = NULL;
67
68 static int      pxa_gpio_probe(device_t);
69 static int      pxa_gpio_attach(device_t);
70
71 static driver_filter_t  pxa_gpio_intr0;
72 static driver_filter_t  pxa_gpio_intr1;
73 static driver_filter_t  pxa_gpio_intrN;
74
75 static int
76 pxa_gpio_probe(device_t dev)
77 {
78         
79         device_set_desc(dev, "GPIO Controller");
80         return (0);
81 }
82
83 static int
84 pxa_gpio_attach(device_t dev)
85 {
86         int     error;
87         void    *ihl;
88         struct  pxa_gpio_softc *sc;
89         
90         sc = (struct pxa_gpio_softc *)device_get_softc(dev);
91         
92         if (pxa_gpio_softc != NULL)
93                 return (ENXIO);
94         pxa_gpio_softc = sc;
95         
96         error = bus_alloc_resources(dev, pxa_gpio_spec, sc->pg_res);
97         if (error) {
98                 device_printf(dev, "could not allocate resources\n");
99                 return (ENXIO);
100         }
101         
102         sc->pg_bst = rman_get_bustag(sc->pg_res[0]);
103         sc->pg_bsh = rman_get_bushandle(sc->pg_res[0]);
104         
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);
115         
116         mtx_init(&sc->pg_mtx, "GPIO mutex", NULL, MTX_SPIN);
117         
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");
122                 return (ENXIO);
123         }
124         
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");
129                 return (ENXIO);
130         }
131         
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");
136                 return (ENXIO);
137         }
138         
139         return (0);
140 }
141
142 static int
143 pxa_gpio_intr0(void *arg)
144 {
145         struct  pxa_gpio_softc *sc;
146         
147         sc = (struct pxa_gpio_softc *)arg;
148         
149         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x1);
150         sc->pg_intr[0] |= 1;
151         
152         return (FILTER_HANDLED);
153 }
154
155 static int
156 pxa_gpio_intr1(void *arg)
157 {
158         struct  pxa_gpio_softc *sc;
159         
160         sc = (struct pxa_gpio_softc *)arg;
161         
162         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x2);
163         sc->pg_intr[1] |= 2;
164         
165         return (FILTER_HANDLED);
166 }
167
168 static int
169 pxa_gpio_intrN(void *arg)
170 {
171         uint32_t        gedr0, gedr1, gedr2;
172         struct          pxa_gpio_softc *sc;
173         
174         sc = (struct pxa_gpio_softc *)arg;
175         
176         gedr0 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0);
177         gedr0 &= 0xfffffffc;
178         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, gedr0);
179         
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);
182         
183         gedr2 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2);
184         gedr2 &= 0x001fffff;
185         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, gedr2);
186         
187         sc->pg_intr[0] |= gedr0;
188         sc->pg_intr[1] |= gedr1;
189         sc->pg_intr[2] |= gedr2;
190         
191         return (FILTER_HANDLED);
192 }
193
194 static device_method_t pxa_gpio_methods[] = {
195         DEVMETHOD(device_probe, pxa_gpio_probe),
196         DEVMETHOD(device_attach, pxa_gpio_attach),
197         
198         {0, 0}
199 };
200
201 static driver_t pxa_gpio_driver = {
202         "gpio",
203         pxa_gpio_methods,
204         sizeof(struct pxa_gpio_softc),
205 };
206
207 static devclass_t pxa_gpio_devclass;
208
209 DRIVER_MODULE(pxagpio, pxa, pxa_gpio_driver, pxa_gpio_devclass, 0, 0);
210
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)
215
216 uint32_t
217 pxa_gpio_get_function(int gpio)
218 {
219         struct          pxa_gpio_softc *sc;
220         uint32_t        rv, io;
221         
222         sc = pxa_gpio_softc;
223         
224         rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) >> GPIO_FN_SHIFT(gpio);
225         rv = GPIO_FN(rv);
226         
227         io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio));
228         if (io & GPIO_BIT(gpio))
229                 rv |= GPIO_OUT;
230         
231         io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPLR0, gpio));
232         if (io & GPIO_BIT(gpio))
233                 rv |= GPIO_SET;
234         
235         return (rv);
236 }
237
238 uint32_t
239 pxa_gpio_set_function(int gpio, uint32_t fn)
240 {
241         struct          pxa_gpio_softc *sc;
242         uint32_t        rv, bit, oldfn;
243         
244         sc = pxa_gpio_softc;
245         
246         oldfn = pxa_gpio_get_function(gpio);
247         
248         if (GPIO_FN(fn) == GPIO_FN(oldfn) &&
249             GPIO_FN_IS_OUT(fn) == GPIO_FN_IS_OUT(oldfn)) {
250                 /*
251                  * The pin's function is not changing.
252                  * For Alternate Functions and GPIO input, we can just
253                  * return now.
254                  * For GPIO output pins, check the initial state is
255                  * the same.
256                  *
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-
260                  * GPIO output pins).
261                  */
262                 if (!GPIO_IS_GPIO_OUT(fn) ||
263                     GPIO_FN_IS_SET(fn) == GPIO_FN_IS_SET(oldfn))
264                         return (fn);
265         }
266         
267         /*
268          * See section 4.1.3.7 of the PXA2x0 Developer's Manual for
269          * the correct procedure for changing GPIO pin functions.
270          */
271         
272         bit = GPIO_BIT(gpio);
273         
274         /*
275          * 1. Configure the correct set/clear state of the pin
276          */
277         if (GPIO_FN_IS_SET(fn))
278                 pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPSR0, gpio), bit);
279         else
280                 pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPCR0, gpio), bit);
281         
282         /*
283          * 2. Configure the pin as an input or output as appropriate
284          */
285         rv = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio)) & ~bit;
286         if (GPIO_FN_IS_OUT(fn))
287                 rv |= bit;
288         pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio), rv);
289         
290         /*
291          * 3. Configure the pin's function
292          */
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);
297         
298         return (oldfn);
299 }
300
301 /*
302  * GPIO "interrupt" handling.
303  */
304
305 void
306 pxa_gpio_mask_irq(int irq)
307 {
308         uint32_t        val;
309         struct          pxa_gpio_softc *sc;
310         int             gpio;
311         
312         sc = pxa_gpio_softc;
313         gpio = IRQ_TO_GPIO(irq);
314         
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);
318 }
319
320 void
321 pxa_gpio_unmask_irq(int irq)
322 {
323         uint32_t        val;
324         struct          pxa_gpio_softc *sc;
325         int             gpio;
326         
327         sc = pxa_gpio_softc;
328         gpio = IRQ_TO_GPIO(irq);
329         
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);
333 }
334
335 int
336 pxa_gpio_get_next_irq(void)
337 {
338         struct  pxa_gpio_softc *sc;
339         int     gpio;
340         
341         sc = pxa_gpio_softc;
342         
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));
347         }
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));
352         }
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));
357         }
358
359         return (-1);
360 }