]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/powerpc/wii/wii_gpio.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / powerpc / wii / wii_gpio.c
1 /*-
2  * Copyright (C) 2012 Margarida Gouveia
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
21  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/module.h>
32 #include <sys/bus.h>
33 #include <sys/conf.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/rman.h>
37 #include <sys/gpio.h>
38 #include <sys/reboot.h>
39
40 #include <machine/bus.h>
41 #include <machine/platform.h>
42 #include <machine/intr_machdep.h>
43 #include <machine/resource.h>
44
45 #include <powerpc/wii/wii_gpioreg.h>
46
47 #include "gpio_if.h"
48
49 struct wiigpio_softc {
50         device_t                 sc_dev;
51         struct resource         *sc_rres;
52         bus_space_tag_t          sc_bt;
53         bus_space_handle_t       sc_bh;
54         int                      sc_rrid;
55         struct mtx               sc_mtx;
56         struct gpio_pin          sc_pins[WIIGPIO_NPINS];
57 };
58
59
60 #define WIIGPIO_PINBANK(_p)     ((_p) / (WIIGPIO_NPINS / 2))
61 #define WIIGPIO_PINMASK(_p)     (1 << ((_p) % (WIIGPIO_NPINS / 2)))
62 #define WIIGPIO_LOCK(sc)        mtx_lock(&(sc)->sc_mtx)
63 #define WIIGPIO_UNLOCK(sc)      mtx_unlock(&(sc)->sc_mtx)
64
65 static int      wiigpio_probe(device_t);
66 static int      wiigpio_attach(device_t);
67 static int      wiigpio_detach(device_t);
68 static int      wiigpio_pin_max(device_t, int *);
69 static int      wiigpio_pin_getname(device_t, uint32_t, char *);
70 static int      wiigpio_pin_getflags(device_t, uint32_t, uint32_t *);
71 static int      wiigpio_pin_setflags(device_t, uint32_t, uint32_t);
72 static int      wiigpio_pin_getcaps(device_t, uint32_t, uint32_t *);
73 static int      wiigpio_pin_get(device_t, uint32_t, unsigned int *);
74 static int      wiigpio_pin_set(device_t, uint32_t, unsigned int);
75 static int      wiigpio_pin_toggle(device_t, uint32_t);
76 static void     wiigpio_shutdown(void *, int);
77
78 static device_method_t wiigpio_methods[] = {
79         /* Device interface */
80         DEVMETHOD(device_probe,         wiigpio_probe),
81         DEVMETHOD(device_attach,        wiigpio_attach),
82         DEVMETHOD(device_detach,        wiigpio_detach),
83
84         /* GPIO protocol */
85         DEVMETHOD(gpio_pin_max,         wiigpio_pin_max),
86         DEVMETHOD(gpio_pin_getname,     wiigpio_pin_getname),
87         DEVMETHOD(gpio_pin_getflags,    wiigpio_pin_getflags),
88         DEVMETHOD(gpio_pin_setflags,    wiigpio_pin_setflags),
89         DEVMETHOD(gpio_pin_getcaps,     wiigpio_pin_getcaps),
90         DEVMETHOD(gpio_pin_get,         wiigpio_pin_get),
91         DEVMETHOD(gpio_pin_set,         wiigpio_pin_set),
92         DEVMETHOD(gpio_pin_toggle,      wiigpio_pin_toggle),
93
94         DEVMETHOD_END
95 };
96
97 static driver_t wiigpio_driver = {
98         "wiigpio",
99         wiigpio_methods,
100         sizeof(struct wiigpio_softc)
101 };
102
103 static devclass_t wiigpio_devclass;
104
105 DRIVER_MODULE(wiigpio, wiibus, wiigpio_driver, wiigpio_devclass, 0, 0);
106
107 static __inline uint32_t
108 wiigpio_read(struct wiigpio_softc *sc, int n)
109 {
110
111         return (bus_space_read_4(sc->sc_bt, sc->sc_bh, n * 0x20));
112 }
113
114 static __inline void
115 wiigpio_write(struct wiigpio_softc *sc, int n, uint32_t reg)
116 {
117
118         bus_space_write_4(sc->sc_bt, sc->sc_bh, n * 0x20, reg);
119 }
120
121 static __inline uint32_t
122 wiigpio_dir_read(struct wiigpio_softc *sc, int n)
123 {
124
125         return (bus_space_read_4(sc->sc_bt, sc->sc_bh, n * 0x20 + 4));
126 }
127
128 static __inline void
129 wiigpio_dir_write(struct wiigpio_softc *sc, int n, uint32_t reg)
130 {
131
132         bus_space_write_4(sc->sc_bt, sc->sc_bh, n * 0x20 + 4, reg);
133 }
134
135 static int
136 wiigpio_probe(device_t dev)
137 {
138         device_set_desc(dev, "Nintendo Wii GPIO");
139
140         return (BUS_PROBE_NOWILDCARD);
141 }
142
143 static int
144 wiigpio_attach(device_t dev)
145 {
146         struct wiigpio_softc *sc;
147         int i;
148         uint32_t d;
149
150         sc = device_get_softc(dev);
151         sc->sc_dev = dev;
152         sc->sc_rrid = 0;
153         sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
154             &sc->sc_rrid, RF_ACTIVE);
155         if (sc->sc_rres == NULL) {
156                 device_printf(dev, "could not alloc mem resource\n");
157                 return (ENXIO);
158         }
159         sc->sc_bt = rman_get_bustag(sc->sc_rres);
160         sc->sc_bh = rman_get_bushandle(sc->sc_rres);
161         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
162 #ifdef WIIGPIO_DEBUG
163         device_printf(dev, "dir bank0=0x%08x bank1=0x%08x\n",
164             wiigpio_dir_read(sc, 0), wiigpio_dir_read(sc, 1));
165         device_printf(dev, "val bank0=0x%08x bank1=0x%08x\n",
166             wiigpio_read(sc, 0), wiigpio_read(sc, 1));
167 #endif
168         for (i = 0; i < WIIGPIO_NPINS; i++) {
169                 sc->sc_pins[i].gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
170                 sc->sc_pins[i].gp_pin = i;
171                 d = wiigpio_dir_read(sc, WIIGPIO_PINBANK(i));
172                 if (d & WIIGPIO_PINMASK(i))
173                         sc->sc_pins[i].gp_flags = GPIO_PIN_OUTPUT;
174                 else
175                         sc->sc_pins[i].gp_flags = GPIO_PIN_INPUT;
176                 snprintf(sc->sc_pins[i].gp_name, GPIOMAXNAME, "PIN %d", i);
177 #ifdef WIIGPIO_DEBUG
178                 device_printf(dev, "PIN %d state %d flag %s\n", i,
179                     wiigpio_read(sc, WIIGPIO_PINBANK(i)) >> 
180                         (i % (WIIGPIO_NPINS / 2)) & 1,
181                     sc->sc_pins[i].gp_flags == GPIO_PIN_INPUT ?
182                     "GPIO_PIN_INPUT" : "GPIO_PIN_OUTPUT");
183 #endif
184         }
185         device_add_child(dev, "gpioc", device_get_unit(dev));
186         device_add_child(dev, "gpiobus", device_get_unit(dev));
187         /*
188          * We will be responsible for powering off the system.
189          */
190         EVENTHANDLER_REGISTER(shutdown_final, wiigpio_shutdown, dev,
191             SHUTDOWN_PRI_LAST);
192
193         return (bus_generic_attach(dev));
194 }
195
196 static int
197 wiigpio_detach(device_t dev)
198 {
199         struct wiigpio_softc *sc;
200
201         sc = device_get_softc(dev);
202         bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres);
203         mtx_destroy(&sc->sc_mtx);
204
205         return (0);
206 }
207
208 static int
209 wiigpio_pin_max(device_t dev, int *maxpin)
210 {
211         
212         *maxpin = WIIGPIO_NPINS - 1;
213
214         return (0);
215 }
216
217 static int
218 wiigpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
219 {
220         struct wiigpio_softc *sc;
221
222         if (pin >= WIIGPIO_NPINS)
223                 return (EINVAL);
224         sc = device_get_softc(dev);
225         *caps = sc->sc_pins[pin].gp_caps;
226
227         return (0);
228 }
229
230 static int
231 wiigpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
232 {
233         struct wiigpio_softc *sc;
234         uint32_t reg;
235
236         if (pin >= WIIGPIO_NPINS)
237                 return (EINVAL);
238         sc = device_get_softc(dev);
239         WIIGPIO_LOCK(sc);
240         reg = wiigpio_read(sc, WIIGPIO_PINBANK(pin));
241         *val = !!(reg & WIIGPIO_PINMASK(pin));
242         WIIGPIO_UNLOCK(sc);
243
244         return (0);
245 }
246
247 static int
248 wiigpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
249 {
250         struct wiigpio_softc *sc;
251         uint32_t reg, pinbank, pinmask;
252
253         if (pin >= WIIGPIO_NPINS)
254                 return (EINVAL);
255         sc = device_get_softc(dev);
256         pinbank = WIIGPIO_PINBANK(pin);
257         pinmask = WIIGPIO_PINMASK(pin);
258         WIIGPIO_LOCK(sc);
259         reg = wiigpio_read(sc, pinbank) & ~pinmask;
260         if (value)
261                 reg |= pinmask;
262         wiigpio_write(sc, pinbank, reg);
263         WIIGPIO_UNLOCK(sc);
264
265         return (0);
266 }
267
268 static int
269 wiigpio_pin_toggle(device_t dev, uint32_t pin)
270 {
271         struct wiigpio_softc *sc;
272         uint32_t val, pinbank, pinmask;
273
274         if (pin >= WIIGPIO_NPINS)
275                 return (EINVAL);
276         sc = device_get_softc(dev);
277         pinbank = WIIGPIO_PINBANK(pin);
278         pinmask = WIIGPIO_PINMASK(pin);
279         WIIGPIO_LOCK(sc);
280         val = wiigpio_read(sc, pinbank);
281         if (val & pinmask)
282                 wiigpio_write(sc, pinbank, val & ~pinmask);
283         else
284                 wiigpio_write(sc, pinbank, val | pinmask);
285         WIIGPIO_UNLOCK(sc);
286
287         return (0);
288 }
289
290 static int
291 wiigpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
292 {
293         struct wiigpio_softc *sc;
294         uint32_t reg, pinbank, pinmask;
295
296         if (pin >= WIIGPIO_NPINS)
297                 return (EINVAL);
298         if ((flags & ~(GPIO_PIN_OUTPUT|GPIO_PIN_INPUT)) != 0)
299                 return (EINVAL);
300         if ((flags & (GPIO_PIN_OUTPUT|GPIO_PIN_INPUT)) == 
301             (GPIO_PIN_OUTPUT|GPIO_PIN_INPUT))
302                 return (EINVAL);
303         sc = device_get_softc(dev);
304         pinbank = WIIGPIO_PINBANK(pin);
305         pinmask = WIIGPIO_PINMASK(pin);
306         WIIGPIO_LOCK(sc);
307         reg = wiigpio_dir_read(sc, WIIGPIO_PINBANK(pin));
308         if (flags & GPIO_PIN_OUTPUT)
309                 wiigpio_dir_write(sc, pinbank, reg | pinmask);
310         else
311                 wiigpio_dir_write(sc, pinbank, reg & ~pinmask);
312         sc->sc_pins[pin].gp_flags = flags;
313         WIIGPIO_UNLOCK(sc);
314
315         return (0);
316 }
317
318 static int
319 wiigpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
320 {
321         struct wiigpio_softc *sc;
322
323         if (pin >= WIIGPIO_NPINS)
324                 return (EINVAL);
325         sc = device_get_softc(dev);
326         WIIGPIO_LOCK(sc);
327         *flags = sc->sc_pins[pin].gp_flags;
328         WIIGPIO_UNLOCK(sc);
329
330         return (0);
331 }
332
333 static int
334 wiigpio_pin_getname(device_t dev, uint32_t pin, char *name)
335 {
336         struct wiigpio_softc *sc;
337
338         if (pin >= WIIGPIO_NPINS)
339                 return (EINVAL);
340         sc = device_get_softc(dev);
341         WIIGPIO_LOCK(sc);
342         memcpy(name, sc->sc_pins[pin].gp_name, GPIOMAXNAME);
343         WIIGPIO_UNLOCK(sc);
344
345         return (0);
346 }
347
348 static void
349 wiigpio_shutdown(void *xdev, int howto)
350 {
351         device_t dev;
352
353         if (!(howto & RB_POWEROFF))
354                 return;
355         dev = (device_t)xdev;
356         wiigpio_pin_setflags(dev, WIIGPIO_POWEROFF_PIN, GPIO_PIN_OUTPUT);
357         wiigpio_pin_set(dev, WIIGPIO_POWEROFF_PIN, 1);
358 }