Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 May 2013 19:30:42 +0000 (UTC)
From:      Rui Paulo <rpaulo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r250788 - head/sys/powerpc/wii
Message-ID:  <201305181930.r4IJUg4I092269@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rpaulo
Date: Sat May 18 19:30:42 2013
New Revision: 250788
URL: http://svnweb.freebsd.org/changeset/base/250788

Log:
  Add support for the second GPIO pin bank on the Wii and add support for
  shutting down the system.

Modified:
  head/sys/powerpc/wii/wii_gpio.c
  head/sys/powerpc/wii/wii_gpioreg.h

Modified: head/sys/powerpc/wii/wii_gpio.c
==============================================================================
--- head/sys/powerpc/wii/wii_gpio.c	Sat May 18 19:21:33 2013	(r250787)
+++ head/sys/powerpc/wii/wii_gpio.c	Sat May 18 19:30:42 2013	(r250788)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/malloc.h>
 #include <sys/rman.h>
 #include <sys/gpio.h>
+#include <sys/reboot.h>
 
 #include <machine/bus.h>
 #include <machine/platform.h>
@@ -55,6 +56,9 @@ struct wiigpio_softc {
 	struct gpio_pin		 sc_pins[WIIGPIO_NPINS];
 };
 
+
+#define	WIIGPIO_PINBANK(_p)	((_p) / (WIIGPIO_NPINS / 2))
+#define	WIIGPIO_PINMASK(_p)	(1 << ((_p) % (WIIGPIO_NPINS / 2)))
 #define WIIGPIO_LOCK(sc)	mtx_lock(&(sc)->sc_mtx)
 #define WIIGPIO_UNLOCK(sc)	mtx_unlock(&(sc)->sc_mtx)
 
@@ -69,6 +73,7 @@ static int	wiigpio_pin_getcaps(device_t,
 static int	wiigpio_pin_get(device_t, uint32_t, unsigned int *);
 static int	wiigpio_pin_set(device_t, uint32_t, unsigned int);
 static int	wiigpio_pin_toggle(device_t, uint32_t);
+static void	wiigpio_shutdown(void *, int);
 
 static device_method_t wiigpio_methods[] = {
 	/* Device interface */
@@ -100,17 +105,31 @@ static devclass_t wiigpio_devclass;
 DRIVER_MODULE(wiigpio, wiibus, wiigpio_driver, wiigpio_devclass, 0, 0);
 
 static __inline uint32_t
-wiigpio_read(struct wiigpio_softc *sc)
+wiigpio_read(struct wiigpio_softc *sc, int n)
+{
+
+	return (bus_space_read_4(sc->sc_bt, sc->sc_bh, n * 0x20));
+}
+
+static __inline void
+wiigpio_write(struct wiigpio_softc *sc, int n, uint32_t reg)
+{
+
+	bus_space_write_4(sc->sc_bt, sc->sc_bh, n * 0x20, reg);
+}
+
+static __inline uint32_t
+wiigpio_dir_read(struct wiigpio_softc *sc, int n)
 {
 
-	return (bus_space_read_4(sc->sc_bt, sc->sc_bh, 0));
+	return (bus_space_read_4(sc->sc_bt, sc->sc_bh, n * 0x20 + 4));
 }
 
 static __inline void
-wiigpio_write(struct wiigpio_softc *sc, uint32_t reg)
+wiigpio_dir_write(struct wiigpio_softc *sc, int n, uint32_t reg)
 {
 
-	bus_space_write_4(sc->sc_bt, sc->sc_bh, 0, reg);
+	bus_space_write_4(sc->sc_bt, sc->sc_bh, n * 0x20 + 4, reg);
 }
 
 static int
@@ -126,10 +145,10 @@ wiigpio_attach(device_t dev)
 {
 	struct wiigpio_softc *sc;
 	int i;
+	uint32_t d;
 
 	sc = device_get_softc(dev);
 	sc->sc_dev = dev;
-
 	sc->sc_rrid = 0;
 	sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
 	    &sc->sc_rrid, RF_ACTIVE);
@@ -139,18 +158,37 @@ wiigpio_attach(device_t dev)
 	}
 	sc->sc_bt = rman_get_bustag(sc->sc_rres);
 	sc->sc_bh = rman_get_bushandle(sc->sc_rres);
-
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
-
+#ifdef WIIGPIO_DEBUG
+	device_printf(dev, "dir bank0=0x%08x bank1=0x%08x\n",
+	    wiigpio_dir_read(sc, 0), wiigpio_dir_read(sc, 1));
+	device_printf(dev, "val bank0=0x%08x bank1=0x%08x\n",
+	    wiigpio_read(sc, 0), wiigpio_read(sc, 1));
+#endif
 	for (i = 0; i < WIIGPIO_NPINS; i++) {
 		sc->sc_pins[i].gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
 		sc->sc_pins[i].gp_pin = i;
-		sc->sc_pins[i].gp_flags = 0;
+		d = wiigpio_dir_read(sc, WIIGPIO_PINBANK(i));
+		if (d & WIIGPIO_PINMASK(i))
+			sc->sc_pins[i].gp_flags = GPIO_PIN_OUTPUT;
+		else
+			sc->sc_pins[i].gp_flags = GPIO_PIN_INPUT;
 		snprintf(sc->sc_pins[i].gp_name, GPIOMAXNAME, "PIN %d", i);
+#ifdef WIIGPIO_DEBUG
+		device_printf(dev, "PIN %d state %d flag %s\n", i,
+		    wiigpio_read(sc, WIIGPIO_PINBANK(i)) >> 
+			(i % (WIIGPIO_NPINS / 2)) & 1,
+		    sc->sc_pins[i].gp_flags == GPIO_PIN_INPUT ?
+		    "GPIO_PIN_INPUT" : "GPIO_PIN_OUTPUT");
+#endif
 	}
-
 	device_add_child(dev, "gpioc", device_get_unit(dev));
 	device_add_child(dev, "gpiobus", device_get_unit(dev));
+	/*
+	 * We will be responsible for powering off the system.
+	 */
+	EVENTHANDLER_REGISTER(shutdown_final, wiigpio_shutdown, dev,
+	    SHUTDOWN_PRI_LAST);
 
 	return (bus_generic_attach(dev));
 }
@@ -199,8 +237,8 @@ wiigpio_pin_get(device_t dev, uint32_t p
 		return (EINVAL);
 	sc = device_get_softc(dev);
 	WIIGPIO_LOCK(sc);
-	reg = wiigpio_read(sc);
-	*val = !!(reg & (1 << pin));
+	reg = wiigpio_read(sc, WIIGPIO_PINBANK(pin));
+	*val = !!(reg & WIIGPIO_PINMASK(pin));
 	WIIGPIO_UNLOCK(sc);
 
 	return (0);
@@ -210,16 +248,18 @@ static int
 wiigpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
 {
 	struct wiigpio_softc *sc;
-	uint32_t reg, pinmask = 1 << pin;
+	uint32_t reg, pinbank, pinmask;
 
 	if (pin >= WIIGPIO_NPINS)
 		return (EINVAL);
 	sc = device_get_softc(dev);
+	pinbank = WIIGPIO_PINBANK(pin);
+	pinmask = WIIGPIO_PINMASK(pin);
 	WIIGPIO_LOCK(sc);
-	reg = wiigpio_read(sc) & ~pinmask;
+	reg = wiigpio_read(sc, pinbank) & ~pinmask;
 	if (value)
 		reg |= pinmask;
-	wiigpio_write(sc, reg);
+	wiigpio_write(sc, pinbank, reg);
 	WIIGPIO_UNLOCK(sc);
 
 	return (0);
@@ -229,15 +269,19 @@ static int
 wiigpio_pin_toggle(device_t dev, uint32_t pin)
 {
 	struct wiigpio_softc *sc;
-	uint32_t val, pinmask = 1 << pin;
+	uint32_t val, pinbank, pinmask;
 
+	if (pin >= WIIGPIO_NPINS)
+		return (EINVAL);
 	sc = device_get_softc(dev);
+	pinbank = WIIGPIO_PINBANK(pin);
+	pinmask = WIIGPIO_PINMASK(pin);
 	WIIGPIO_LOCK(sc);
-	val = wiigpio_read(sc) & pinmask;
-	if (val)
-		wiigpio_write(sc, wiigpio_read(sc) & ~pinmask);
+	val = wiigpio_read(sc, pinbank);
+	if (val & pinmask)
+		wiigpio_write(sc, pinbank, val & ~pinmask);
 	else
-		wiigpio_write(sc, wiigpio_read(sc) | pinmask);
+		wiigpio_write(sc, pinbank, val | pinmask);
 	WIIGPIO_UNLOCK(sc);
 
 	return (0);
@@ -247,11 +291,24 @@ static int
 wiigpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
 {
 	struct wiigpio_softc *sc;
+	uint32_t reg, pinbank, pinmask;
 
 	if (pin >= WIIGPIO_NPINS)
 		return (EINVAL);
+	if ((flags & ~(GPIO_PIN_OUTPUT|GPIO_PIN_INPUT)) != 0)
+		return (EINVAL);
+	if ((flags & (GPIO_PIN_OUTPUT|GPIO_PIN_INPUT)) == 
+	    (GPIO_PIN_OUTPUT|GPIO_PIN_INPUT))
+		return (EINVAL);
 	sc = device_get_softc(dev);
+	pinbank = WIIGPIO_PINBANK(pin);
+	pinmask = WIIGPIO_PINMASK(pin);
 	WIIGPIO_LOCK(sc);
+	reg = wiigpio_dir_read(sc, WIIGPIO_PINBANK(pin));
+	if (flags & GPIO_PIN_OUTPUT)
+		wiigpio_dir_write(sc, pinbank, reg | pinmask);
+	else
+		wiigpio_dir_write(sc, pinbank, reg & ~pinmask);
 	sc->sc_pins[pin].gp_flags = flags;
 	WIIGPIO_UNLOCK(sc);
 
@@ -287,3 +344,15 @@ wiigpio_pin_getname(device_t dev, uint32
 
 	return (0);
 }
+
+static void
+wiigpio_shutdown(void *xdev, int howto)
+{
+	device_t dev;
+
+	if (!(howto & RB_POWEROFF))
+		return;
+	dev = (device_t)xdev;
+	wiigpio_pin_setflags(dev, WIIGPIO_POWEROFF_PIN, GPIO_PIN_OUTPUT);
+	wiigpio_pin_set(dev, WIIGPIO_POWEROFF_PIN, 1);
+}

Modified: head/sys/powerpc/wii/wii_gpioreg.h
==============================================================================
--- head/sys/powerpc/wii/wii_gpioreg.h	Sat May 18 19:21:33 2013	(r250787)
+++ head/sys/powerpc/wii/wii_gpioreg.h	Sat May 18 19:30:42 2013	(r250788)
@@ -29,9 +29,10 @@
 #ifndef	_POWERPC_WII_WII_GPIOREG_H
 #define	_POWERPC_WII_WII_GPIOREG_H
 
-#define	WIIGPIO_NPINS		32
+#define	WIIGPIO_NPINS		64
+#define	WIIGPIO_POWEROFF_PIN	33
 
 #define	WIIGPIO_REG_ADDR	0x0d8000c0
-#define	WIIGPIO_REG_LEN		0x4
+#define	WIIGPIO_REG_LEN		0x40
 
 #endif	/* _POWERPC_WII_WII_GPIOREG_H */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201305181930.r4IJUg4I092269>