]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/arm/xscale/pxa/pxa_gpio.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / arm / xscale / pxa / pxa_gpio.c
1 /*-
2  * Copyright (c) 2006 Benno Rice.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/bus.h>
31 #include <sys/kernel.h>
32 #include <sys/lock.h>
33 #include <sys/interrupt.h>
34 #include <sys/module.h>
35 #include <sys/malloc.h>
36 #include <sys/mutex.h>
37 #include <sys/rman.h>
38 #include <sys/queue.h>
39 #include <sys/taskqueue.h>
40 #include <sys/timetc.h>
41 #include <machine/bus.h>
42 #include <machine/intr.h>
43
44 #include <arm/xscale/pxa/pxavar.h>
45 #include <arm/xscale/pxa/pxareg.h>
46
47 struct pxa_gpio_softc {
48         struct resource *       pg_res[4];
49         bus_space_tag_t         pg_bst;
50         bus_space_handle_t      pg_bsh;
51         struct mtx              pg_mtx;
52
53         uint32_t                pg_intr[3];
54 };
55
56 static struct resource_spec pxa_gpio_spec[] = {
57         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
58         { SYS_RES_IRQ,          0,      RF_ACTIVE },
59         { SYS_RES_IRQ,          1,      RF_ACTIVE },
60         { SYS_RES_IRQ,          2,      RF_ACTIVE },
61         { -1, 0 }
62 };
63
64 static struct pxa_gpio_softc *pxa_gpio_softc = NULL;
65
66 static int      pxa_gpio_probe(device_t);
67 static int      pxa_gpio_attach(device_t);
68
69 static driver_filter_t  pxa_gpio_intr0;
70 static driver_filter_t  pxa_gpio_intr1;
71 static driver_filter_t  pxa_gpio_intrN;
72
73 static int
74 pxa_gpio_probe(device_t dev)
75 {
76         
77         device_set_desc(dev, "GPIO Controller");
78         return (0);
79 }
80
81 static int
82 pxa_gpio_attach(device_t dev)
83 {
84         int     error;
85         void    *ihl;
86         struct  pxa_gpio_softc *sc;
87         
88         sc = (struct pxa_gpio_softc *)device_get_softc(dev);
89         
90         if (pxa_gpio_softc != NULL)
91                 return (ENXIO);
92         pxa_gpio_softc = sc;
93         
94         error = bus_alloc_resources(dev, pxa_gpio_spec, sc->pg_res);
95         if (error) {
96                 device_printf(dev, "could not allocate resources\n");
97                 return (ENXIO);
98         }
99         
100         sc->pg_bst = rman_get_bustag(sc->pg_res[0]);
101         sc->pg_bsh = rman_get_bushandle(sc->pg_res[0]);
102         
103         /* Disable and clear all interrupts. */
104         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER0, 0);
105         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER1, 0);
106         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GRER2, 0);
107         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER0, 0);
108         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER1, 0);
109         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GFER2, 0);
110         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, ~0);
111         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1, ~0);
112         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, ~0);
113         
114         mtx_init(&sc->pg_mtx, "GPIO mutex", NULL, MTX_SPIN);
115         
116         if (bus_setup_intr(dev, sc->pg_res[1], INTR_TYPE_MISC|INTR_MPSAFE,
117             pxa_gpio_intr0, NULL, sc, &ihl) != 0) {
118                 bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
119                 device_printf(dev, "could not set up intr0\n");
120                 return (ENXIO);
121         }
122         
123         if (bus_setup_intr(dev, sc->pg_res[2], INTR_TYPE_MISC|INTR_MPSAFE,
124             pxa_gpio_intr1, NULL, sc, &ihl) != 0) {
125                 bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
126                 device_printf(dev, "could not set up intr1\n");
127                 return (ENXIO);
128         }
129         
130         if (bus_setup_intr(dev, sc->pg_res[3], INTR_TYPE_MISC|INTR_MPSAFE,
131             pxa_gpio_intrN, NULL, sc, &ihl) != 0) {
132                 bus_release_resources(dev, pxa_gpio_spec, sc->pg_res);
133                 device_printf(dev, "could not set up intrN\n");
134                 return (ENXIO);
135         }
136         
137         return (0);
138 }
139
140 static int
141 pxa_gpio_intr0(void *arg)
142 {
143         struct  pxa_gpio_softc *sc;
144         
145         sc = (struct pxa_gpio_softc *)arg;
146         
147         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x1);
148         sc->pg_intr[0] |= 1;
149         
150         return (FILTER_HANDLED);
151 }
152
153 static int
154 pxa_gpio_intr1(void *arg)
155 {
156         struct  pxa_gpio_softc *sc;
157         
158         sc = (struct pxa_gpio_softc *)arg;
159         
160         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, 0x2);
161         sc->pg_intr[1] |= 2;
162         
163         return (FILTER_HANDLED);
164 }
165
166 static int
167 pxa_gpio_intrN(void *arg)
168 {
169         uint32_t        gedr0, gedr1, gedr2;
170         struct          pxa_gpio_softc *sc;
171         
172         sc = (struct pxa_gpio_softc *)arg;
173         
174         gedr0 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0);
175         gedr0 &= 0xfffffffc;
176         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR0, gedr0);
177         
178         gedr1 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1);
179         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR1, gedr1);
180         
181         gedr2 = bus_space_read_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2);
182         gedr2 &= 0x001fffff;
183         bus_space_write_4(sc->pg_bst, sc->pg_bsh, GPIO_GEDR2, gedr2);
184         
185         sc->pg_intr[0] |= gedr0;
186         sc->pg_intr[1] |= gedr1;
187         sc->pg_intr[2] |= gedr2;
188         
189         return (FILTER_HANDLED);
190 }
191
192 static device_method_t pxa_gpio_methods[] = {
193         DEVMETHOD(device_probe, pxa_gpio_probe),
194         DEVMETHOD(device_attach, pxa_gpio_attach),
195         
196         {0, 0}
197 };
198
199 static driver_t pxa_gpio_driver = {
200         "gpio",
201         pxa_gpio_methods,
202         sizeof(struct pxa_gpio_softc),
203 };
204
205 static devclass_t pxa_gpio_devclass;
206
207 DRIVER_MODULE(pxagpio, pxa, pxa_gpio_driver, pxa_gpio_devclass, 0, 0);
208
209 #define pxagpio_reg_read(softc, reg)            \
210         bus_space_read_4(sc->pg_bst, sc->pg_bsh, reg)
211 #define pxagpio_reg_write(softc, reg, val)      \
212         bus_space_write_4(sc->pg_bst, sc->pg_bsh, reg, val)
213
214 uint32_t
215 pxa_gpio_get_function(int gpio)
216 {
217         struct          pxa_gpio_softc *sc;
218         uint32_t        rv, io;
219         
220         sc = pxa_gpio_softc;
221         
222         rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) >> GPIO_FN_SHIFT(gpio);
223         rv = GPIO_FN(rv);
224         
225         io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio));
226         if (io & GPIO_BIT(gpio))
227                 rv |= GPIO_OUT;
228         
229         io = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPLR0, gpio));
230         if (io & GPIO_BIT(gpio))
231                 rv |= GPIO_SET;
232         
233         return (rv);
234 }
235
236 uint32_t
237 pxa_gpio_set_function(int gpio, uint32_t fn)
238 {
239         struct          pxa_gpio_softc *sc;
240         uint32_t        rv, bit, oldfn;
241         
242         sc = pxa_gpio_softc;
243         
244         oldfn = pxa_gpio_get_function(gpio);
245         
246         if (GPIO_FN(fn) == GPIO_FN(oldfn) &&
247             GPIO_FN_IS_OUT(fn) == GPIO_FN_IS_OUT(oldfn)) {
248                 /*
249                  * The pin's function is not changing.
250                  * For Alternate Functions and GPIO input, we can just
251                  * return now.
252                  * For GPIO output pins, check the initial state is
253                  * the same.
254                  *
255                  * Return 'fn' instead of 'oldfn' so the caller can
256                  * reliably detect that we didn't change anything.
257                  * (The initial state might be different for non-
258                  * GPIO output pins).
259                  */
260                 if (!GPIO_IS_GPIO_OUT(fn) ||
261                     GPIO_FN_IS_SET(fn) == GPIO_FN_IS_SET(oldfn))
262                         return (fn);
263         }
264         
265         /*
266          * See section 4.1.3.7 of the PXA2x0 Developer's Manual for
267          * the correct procedure for changing GPIO pin functions.
268          */
269         
270         bit = GPIO_BIT(gpio);
271         
272         /*
273          * 1. Configure the correct set/clear state of the pin
274          */
275         if (GPIO_FN_IS_SET(fn))
276                 pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPSR0, gpio), bit);
277         else
278                 pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPCR0, gpio), bit);
279         
280         /*
281          * 2. Configure the pin as an input or output as appropriate
282          */
283         rv = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio)) & ~bit;
284         if (GPIO_FN_IS_OUT(fn))
285                 rv |= bit;
286         pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GPDR0, gpio), rv);
287         
288         /*
289          * 3. Configure the pin's function
290          */
291         bit = GPIO_FN_MASK << GPIO_FN_SHIFT(gpio);
292         fn = GPIO_FN(fn) << GPIO_FN_SHIFT(gpio);
293         rv = pxagpio_reg_read(sc, GPIO_FN_REG(gpio)) & ~bit;
294         pxagpio_reg_write(sc, GPIO_FN_REG(gpio), rv | fn);
295         
296         return (oldfn);
297 }
298
299 /*
300  * GPIO "interrupt" handling.
301  */
302
303 void
304 pxa_gpio_mask_irq(int irq)
305 {
306         uint32_t        val;
307         struct          pxa_gpio_softc *sc;
308         int             gpio;
309         
310         sc = pxa_gpio_softc;
311         gpio = IRQ_TO_GPIO(irq);
312         
313         val = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio));
314         val &= ~GPIO_BIT(gpio);
315         pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio), val);
316 }
317
318 void
319 pxa_gpio_unmask_irq(int irq)
320 {
321         uint32_t        val;
322         struct          pxa_gpio_softc *sc;
323         int             gpio;
324         
325         sc = pxa_gpio_softc;
326         gpio = IRQ_TO_GPIO(irq);
327         
328         val = pxagpio_reg_read(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio));
329         val |= GPIO_BIT(gpio);
330         pxagpio_reg_write(sc, PXA250_GPIO_REG(GPIO_GRER0, gpio), val);
331 }
332
333 int
334 pxa_gpio_get_next_irq()
335 {
336         struct  pxa_gpio_softc *sc;
337         int     gpio;
338         
339         sc = pxa_gpio_softc;
340         
341         if (sc->pg_intr[0] != 0) {
342                 gpio = ffs(sc->pg_intr[0]) - 1;
343                 sc->pg_intr[0] &= ~(1 << gpio);
344                 return (GPIO_TO_IRQ(gpio));
345         }
346         if (sc->pg_intr[1] != 0) {
347                 gpio = ffs(sc->pg_intr[1]) - 1;
348                 sc->pg_intr[1] &= ~(1 << gpio);
349                 return (GPIO_TO_IRQ(gpio + 32));
350         }
351         if (sc->pg_intr[2] != 0) {
352                 gpio = ffs(sc->pg_intr[2]) - 1;
353                 sc->pg_intr[2] &= ~(1 << gpio);
354                 return (GPIO_TO_IRQ(gpio + 64));
355         }
356
357         return (-1);
358 }