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
49struct 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
65static int	wiigpio_probe(device_t);
66static int	wiigpio_attach(device_t);
67static int	wiigpio_detach(device_t);
68static int	wiigpio_pin_max(device_t, int *);
69static int	wiigpio_pin_getname(device_t, uint32_t, char *);
70static int	wiigpio_pin_getflags(device_t, uint32_t, uint32_t *);
71static int	wiigpio_pin_setflags(device_t, uint32_t, uint32_t);
72static int	wiigpio_pin_getcaps(device_t, uint32_t, uint32_t *);
73static int	wiigpio_pin_get(device_t, uint32_t, unsigned int *);
74static int	wiigpio_pin_set(device_t, uint32_t, unsigned int);
75static int	wiigpio_pin_toggle(device_t, uint32_t);
76static void	wiigpio_shutdown(void *, int);
77
78static 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
97static driver_t wiigpio_driver = {
98	"wiigpio",
99	wiigpio_methods,
100	sizeof(struct wiigpio_softc)
101};
102
103static devclass_t wiigpio_devclass;
104
105DRIVER_MODULE(wiigpio, wiibus, wiigpio_driver, wiigpio_devclass, 0, 0);
106
107static __inline uint32_t
108wiigpio_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
114static __inline void
115wiigpio_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
121static __inline uint32_t
122wiigpio_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
128static __inline void
129wiigpio_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
135static int
136wiigpio_probe(device_t dev)
137{
138        device_set_desc(dev, "Nintendo Wii GPIO");
139
140        return (BUS_PROBE_NOWILDCARD);
141}
142
143static int
144wiigpio_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", -1);
186	device_add_child(dev, "gpiobus", -1);
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
196static int
197wiigpio_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
208static int
209wiigpio_pin_max(device_t dev, int *maxpin)
210{
211
212	*maxpin = WIIGPIO_NPINS - 1;
213
214	return (0);
215}
216
217static int
218wiigpio_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
230static int
231wiigpio_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
247static int
248wiigpio_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
268static int
269wiigpio_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
290static int
291wiigpio_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	sc = device_get_softc(dev);
299	pinbank = WIIGPIO_PINBANK(pin);
300	pinmask = WIIGPIO_PINMASK(pin);
301	WIIGPIO_LOCK(sc);
302	reg = wiigpio_dir_read(sc, WIIGPIO_PINBANK(pin));
303	if (flags & GPIO_PIN_OUTPUT)
304		wiigpio_dir_write(sc, pinbank, reg | pinmask);
305	else
306		wiigpio_dir_write(sc, pinbank, reg & ~pinmask);
307	sc->sc_pins[pin].gp_flags = flags;
308	WIIGPIO_UNLOCK(sc);
309
310	return (0);
311}
312
313static int
314wiigpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
315{
316	struct wiigpio_softc *sc;
317
318	if (pin >= WIIGPIO_NPINS)
319		return (EINVAL);
320	sc = device_get_softc(dev);
321	WIIGPIO_LOCK(sc);
322	*flags = sc->sc_pins[pin].gp_flags;
323	WIIGPIO_UNLOCK(sc);
324
325	return (0);
326}
327
328static int
329wiigpio_pin_getname(device_t dev, uint32_t pin, char *name)
330{
331	struct wiigpio_softc *sc;
332
333	if (pin >= WIIGPIO_NPINS)
334		return (EINVAL);
335	sc = device_get_softc(dev);
336	WIIGPIO_LOCK(sc);
337	memcpy(name, sc->sc_pins[pin].gp_name, GPIOMAXNAME);
338	WIIGPIO_UNLOCK(sc);
339
340	return (0);
341}
342
343static void
344wiigpio_shutdown(void *xdev, int howto)
345{
346	device_t dev;
347
348	if (!(howto & RB_POWEROFF))
349		return;
350	dev = (device_t)xdev;
351	wiigpio_pin_setflags(dev, WIIGPIO_POWEROFF_PIN, GPIO_PIN_OUTPUT);
352	wiigpio_pin_set(dev, WIIGPIO_POWEROFF_PIN, 1);
353}
354