Subject: IBM405GP/GPr OPB bus_space endian (powerpc/ibm4xx/dev/opb.c)
To: None <port-powerpc@netbsd.org>
From: Shigeyuki Fukushima <shige@netbsd.org>
List: port-powerpc
Date: 10/04/2005 20:47:56
This is a multi-part message in MIME format.
--------------060303010804030506010404
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Hello,

Last week, a GPIO framework was imported from OpenBSD.
This is conflicted with IBM405GP/GPr OPB GPIO device name, "gpio".
I have fixed the above breakage.
I send a patch for this modification (with using GPIO fremework).

The bellow is the subject.
In the current source (sys/arch/powerpc/ibm4xx/dev/opb),
byte-ordering for opb(On-chip Peripheral Bus) bus_space is defined by
Little-Endian (as the following).

 static struct powerpc_bus_space opb_tag = {
	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE,
 	0x0, IBM405GP_UART0_BASE, 0x1000
 };

Why it is Little-Endian in spite of CPU byte-order (Big-Endian) ?
Is there any special reason?


In the gpio (on opb) driver,
I want to handle some 32-bit registers easily.
If there is no reason, I want to change bus_space byte-order
from Little to Big.
Is it ok?

-- 
Kind Regards,
--- shige
Shigeyuki Fukushima <shige@{FreeBSD,jp.FreeBSD,NetBSD}.org>


--------------060303010804030506010404
Content-Type: text/plain;
 name="gpio.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="gpio.diff"

Index: sys/arch/evbppc/conf/OPENBLOCKS200
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/conf/OPENBLOCKS200,v
retrieving revision 1.7
diff -u -u -r1.7 OPENBLOCKS200
--- sys/arch/evbppc/conf/OPENBLOCKS200	9 Sep 2005 16:35:29 -0000	1.7
+++ sys/arch/evbppc/conf/OPENBLOCKS200	1 Oct 2005 16:12:51 -0000
@@ -151,7 +151,8 @@
 gpiic0	at opb? addr ? irq ?		# On-chip IIC controller
 iic0	at gpiic?			# I2C bus
 
-gpio0	at opb? addr ? irq ?		# On-chip GPIO controller
+gpio_opb0 at opb? addr ? irq ?		# On-chip GPIO controller
+gpio*	at gpio_opb?
 
 pchb0	at plb?				# PCI-Host bridges
 
Index: sys/arch/evbppc/conf/OPENBLOCKS266
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/conf/OPENBLOCKS266,v
retrieving revision 1.25
diff -u -u -r1.25 OPENBLOCKS266
--- sys/arch/evbppc/conf/OPENBLOCKS266	24 Aug 2005 19:54:50 -0000	1.25
+++ sys/arch/evbppc/conf/OPENBLOCKS266	1 Oct 2005 16:12:52 -0000
@@ -166,10 +166,8 @@
 gpiic0	at opb? addr ? irq ?		# On-chip IIC controller
 iic0	at gpiic?			# I2C bus
 xrtc0	at iic? addr 0x6f		# RTC
-gpio0	at opb? addr ? irq ?		# On-chip GPIO controller
-obsled0	at gpio? addr 0x0c		# OBS LED connected GPIO
-obsled1	at gpio? addr 0x0d		# OBS LED connected GPIO
-obsled2	at gpio? addr 0x0e		# OBS LED connected GPIO
+gpio_opb0 at opb? addr ? irq ?		# On-chip GPIO controller
+gpio*	at gpio_opb?
 
 # PCI bus support
 pci*	at pchb?
Index: sys/arch/evbppc/conf/files.obs405
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/conf/files.obs405,v
retrieving revision 1.12
diff -u -u -r1.12 files.obs405
--- sys/arch/evbppc/conf/files.obs405	10 Sep 2005 04:34:39 -0000	1.12
+++ sys/arch/evbppc/conf/files.obs405	1 Oct 2005 16:12:52 -0000
@@ -14,9 +14,9 @@
 file	arch/evbppc/obs405/obs405_autoconf.c
 file	arch/evbppc/obs405/obs405_machdep.c
 
-device obsled
-attach  obsled at gpio
-file	arch/evbppc/obs405/dev/obsled.c		obsled
+#device obsled
+#attach  obsled at ibmgpio
+#file	arch/evbppc/obs405/dev/obsled.c		obsled
 
 # Memory Disk for install kernel
 file	dev/md_root.c				memory_disk_hooks
Index: sys/arch/evbppc/obs405/obs266_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbppc/obs405/obs266_machdep.c,v
retrieving revision 1.1
diff -u -u -r1.1 obs266_machdep.c
--- sys/arch/evbppc/obs405/obs266_machdep.c	18 Mar 2005 14:12:34 -0000	1.1
+++ sys/arch/evbppc/obs405/obs266_machdep.c	1 Oct 2005 16:12:52 -0000
@@ -214,7 +214,7 @@
 	static char str[256];
 	char *ap = str, *ap1 = ap;
 
-	obs266_led_set(OBS266_LED_ON);
+	/* obs266_led_set(OBS266_LED_ON); */
 
 	boothowto = howto;
 	if (!cold && !(howto & RB_NOSYNC) && !syncing) {
Index: sys/arch/powerpc/conf/files.ibm4xx
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/conf/files.ibm4xx,v
retrieving revision 1.7
diff -u -u -r1.7 files.ibm4xx
--- sys/arch/powerpc/conf/files.ibm4xx	23 Jan 2005 19:24:31 -0000	1.7
+++ sys/arch/powerpc/conf/files.ibm4xx	1 Oct 2005 16:12:52 -0000
@@ -30,9 +30,9 @@
 file	arch/powerpc/ibm4xx/dev/com_opb.c	com_opb
 
 # On-chip GPIO controller
-device	gpio { addr, [size = -1] }
-attach	gpio at opb
-file	arch/powerpc/ibm4xx/dev/gpio_opb.c	gpio
+device	gpio_opb: gpiobus
+attach	gpio_opb at opb
+file	arch/powerpc/ibm4xx/dev/gpio_opb.c	gpio_opb
 
 # On-chip ethernet device(s)
 device	emac: ether, ifnet, arp, mii
Index: sys/arch/powerpc/ibm4xx/dev/gpio_opb.c
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/ibm4xx/dev/gpio_opb.c,v
retrieving revision 1.2
diff -u -u -r1.2 gpio_opb.c
--- sys/arch/powerpc/ibm4xx/dev/gpio_opb.c	26 Aug 2005 13:19:37 -0000	1.2
+++ sys/arch/powerpc/ibm4xx/dev/gpio_opb.c	1 Oct 2005 16:12:52 -0000
@@ -35,72 +35,40 @@
 #include <sys/param.h>
 #include <sys/device.h>
 #include <sys/systm.h>
+#include <sys/gpio.h>
 
-#include <machine/pio.h>
+#include <machine/bus.h>
+
+#include <dev/gpio/gpiovar.h>
 
 #include <powerpc/ibm4xx/dcr405gp.h>
 #include <powerpc/ibm4xx/dev/opbvar.h>
 #include <powerpc/ibm4xx/dev/gpioreg.h>
-#include <powerpc/ibm4xx/dev/gpiovar.h>
 
-struct gpio_softc {
+struct gpio_opb_softc {
 	struct device		sc_dev;		/* device generic */
-	struct gpio_controller	sc_gpio;	/* GPIO controller */
-        u_long			sc_addr;	/* GPIO controller address */
-};
-
-static int	gpio_print(void *, const char *);
-static int	gpio_search(struct device *, struct cfdata *,
-			const int *ldesc, void *aux);
-static int	gpio_match(struct device *, struct cfdata *, void *);
-static void	gpio_attach(struct device *, struct device *, void *);
-
-static int	gpio_or_read(void *, int);
-static int	gpio_tcr_read(void *, int);
-static int	gpio_odr_read(void *, int);
-static int	gpio_ir_read(void *, int);
-static void	gpio_or_write(void *arg, int addr, int bit);
-static void	gpio_tcr_write(void *arg, int addr, int bit);
-static void	gpio_odr_write(void *arg, int addr, int bit);
-
-static int	gpio_read_bit(void *, int, int);
-static void	gpio_write_bit(void *, int, int, int);
-static uint32_t	gpio_read(void *, int);
-static void	gpio_write(void *, int, uint32_t);
-
-CFATTACH_DECL(gpio, sizeof(struct gpio_softc),
-    gpio_match, gpio_attach, NULL, NULL);
-
-static int
-gpio_print(void *aux, const char *pnp)
-{
-	struct gpio_attach_args *gaa = aux;
 
-	aprint_normal(" addr GPIO#%d", gaa->ga_addr);
-
-	return (UNCONF);
-}
-
-static int
-gpio_search(struct device *parent, struct cfdata *cf,
-	const int *ldesc, void *aux)
-{
-	struct gpio_softc *sc = (void *)parent;
-	struct gpio_attach_args gaa;
+	/* GPIO interface */
+	bus_space_tag_t		sc_gpio_iot;
+	bus_space_handle_t	sc_gpio_ioh;
+	struct gpio_chipset_tag	sc_gpio_gc;
+	gpio_pin_t		sc_gpio_pins[GPIO_NPINS];
+};
 
-	gaa.ga_tag = &sc->sc_gpio;
-	gaa.ga_addr = cf->cf_loc[GPIOCF_ADDR];
+int	gpio_opb_match(struct device *, struct cfdata *, void *);
+void	gpio_opb_attach(struct device *, struct device *, void *);
 
-	if (config_match(parent, cf, &gaa) > 0)
-		config_attach(parent, cf, &gaa, gpio_print);
+CFATTACH_DECL(gpio_opb, sizeof(struct gpio_opb_softc),
+	gpio_opb_match, gpio_opb_attach, NULL, NULL);
 
-	return (0);
-}
+int	gpio_opb_pin_read(void *, int);
+void	gpio_opb_pin_write(void *, int, int);
+void	gpio_opb_pin_ctl(void *, int, int);
 
-static int
-gpio_match(struct device *parent, struct cfdata *cf, void *args)
+int
+gpio_opb_match(struct device *parent, struct cfdata *cf, void *aux)
 {
-	struct opb_attach_args *oaa = args;
+	struct opb_attach_args *oaa = aux;
 
 	if (strcmp(oaa->opb_name, cf->cf_name) != 0)
 		return (0);
@@ -108,109 +76,142 @@
 	return (1);
 }
 
-static void
-gpio_attach(struct device *parent, struct device *self, void *aux)
+void
+gpio_opb_attach(struct device *parent, struct device *self, void *aux)
 {
-	struct gpio_softc *sc = (struct gpio_softc *)self;
+	struct gpio_opb_softc *sc = (struct gpio_opb_softc *)self;
 	struct opb_attach_args *oaa = aux;
+	struct gpiobus_attach_args gba;
+	int i;
+	u_int32_t reg1, reg2, reg3;
 
 	aprint_naive(": GPIO controller\n");
 	aprint_normal(": On-Chip GPIO controller\n");
 
-	sc->sc_addr = oaa->opb_addr;
-	sc->sc_gpio.cookie = sc;
-	sc->sc_gpio.io_or_read = gpio_or_read;
-	sc->sc_gpio.io_tcr_read = gpio_tcr_read;
-	sc->sc_gpio.io_odr_read = gpio_odr_read;
-	sc->sc_gpio.io_ir_read = gpio_ir_read;
-	sc->sc_gpio.io_or_write = gpio_or_write;
-	sc->sc_gpio.io_tcr_write = gpio_tcr_write;
-	sc->sc_gpio.io_odr_write = gpio_odr_write;
-
-	(void) config_search_ia(gpio_search, self, "gpio", NULL);
-}
-
-static int
-gpio_or_read(void *arg, int addr)
-{
-	return (gpio_read_bit(arg, GPIO_OR, addr));
-}
-
-static int
-gpio_tcr_read(void *arg, int addr)
-{
-	return (gpio_read_bit(arg, GPIO_TCR, addr));
-}
-
-static int
-gpio_odr_read(void *arg, int addr)
-{
-	return (gpio_read_bit(arg, GPIO_ODR, addr));
-}
-
-static int
-gpio_ir_read(void *arg, int addr)
-{
-	gpio_write_bit(arg, GPIO_ODR, addr, 0);
-	gpio_write_bit(arg, GPIO_TCR, addr, 0);
-	return (gpio_read_bit(arg, GPIO_ODR, addr));
-}
-
-static void
-gpio_or_write(void *arg, int addr, int bit)
-{
-	gpio_write_bit(arg, GPIO_ODR, addr, 0);
-	gpio_write_bit(arg, GPIO_TCR, addr, 1);
-	gpio_write_bit(arg, GPIO_OR, addr, bit);
-}
-
-static void
-gpio_tcr_write(void *arg, int addr, int bit)
-{
-	gpio_write_bit(arg, GPIO_TCR, addr, bit);
-}
+	/* Map GPIO I/O space */
+	sc->sc_gpio_iot = oaa->opb_bt;
+	bus_space_map(sc->sc_gpio_iot, oaa->opb_addr,
+				GPIO_NREG, 0, &sc->sc_gpio_ioh);
+	/* Read current register status */
+	reg1 = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, GPIO_IR);
+	reg2 = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, GPIO_TCR);
+	reg3 = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, GPIO_ODR);
+
+	/* Initialize pins array */
+	for (i = 0 ; i < GPIO_NPINS ; i++) {
+		int p = i + 1;
+		sc->sc_gpio_pins[i].pin_num = i;
+		sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INOUT
+						| GPIO_PIN_OPENDRAIN
+						| GPIO_PIN_TRISTATE;
+
+		/* current defaults */
+		sc->sc_gpio_pins[i].pin_flags =
+			((reg3 >> GPIO_PIN_SHIFT(p)) & 0x01)
+			? GPIO_PIN_OPENDRAIN
+			: (((reg2 >> GPIO_PIN_SHIFT(p)) & 0x01)
+				? GPIO_PIN_INOUT
+				: GPIO_PIN_TRISTATE);
+		sc->sc_gpio_pins[i].pin_state =
+			((reg1 >> GPIO_PIN_SHIFT(p)) & 0x01);
+	}
+
+	/* Create controller tag */
+	sc->sc_gpio_gc.gp_cookie = sc;
+	sc->sc_gpio_gc.gp_pin_read = gpio_opb_pin_read;
+	sc->sc_gpio_gc.gp_pin_write = gpio_opb_pin_write;
+	sc->sc_gpio_gc.gp_pin_ctl = gpio_opb_pin_ctl;
+
+	gba.gba_name = "gpio";
+	gba.gba_gc = &sc->sc_gpio_gc;
+	gba.gba_pins = sc->sc_gpio_pins;
+	gba.gba_npins = GPIO_NPINS;
+
+	/* Attach GPIO framework */
+	(void) config_found(&sc->sc_dev, &gba, gpiobus_print);
+}
+
+int
+gpio_opb_pin_read(void *arg, int pin)
+{
+	struct gpio_opb_softc *sc = arg;
+	u_int32_t data;
+	int p;
 
-static void
-gpio_odr_write(void *arg, int addr, int bit)
-{
-	gpio_write_bit(arg, GPIO_ODR, addr, bit);
-}
+	p = pin % GPIO_NPINS;
+	p = p + 1;
 
-static int
-gpio_read_bit(void *arg, int offset, int addr)
-{
-	uint32_t rv = gpio_read(arg, offset);
-	uint32_t mask = GPIO_SBIT(addr);
+	data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, GPIO_IR);
 
-	return ((rv & mask) >> GPIO_SHIFT(addr));
+	return ((data >> GPIO_PIN_SHIFT(p)) & 0x1);
 }
 
 void
-gpio_write_bit(void *arg, int offset, int addr, int bit)
+gpio_opb_pin_write(void *arg, int pin, int value)
 {
-	uint32_t rv = gpio_read(arg, offset);
-	uint32_t mask = GPIO_SBIT(addr);
+	struct gpio_opb_softc *sc = arg;
+	u_int32_t data;
+	int p;
+
+	p = pin % GPIO_NPINS;
+	p = p + 1;
+
+	data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, GPIO_OR);
+	if (value == 0) {
+		data &= ~(1 << GPIO_PIN_SHIFT(p));
+	} else if (value == 1) {
+		data |= (1 << GPIO_PIN_SHIFT(p));
+	}
 
-	rv = rv & ~mask;
-	rv = rv | ((bit << GPIO_SHIFT(addr)) & mask);
-	gpio_write(arg, offset, rv);
+	bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, GPIO_OR, data);
 }
 
-static uint32_t
-gpio_read(void *arg, int offset)
-{
-	struct gpio_softc *sc = arg;
-	uint32_t rv;
-
-        rv = inl(sc->sc_addr + offset);
-
-	return rv;
-}
-
-static void
-gpio_write(void *arg, int offset, uint32_t out)
+void
+gpio_opb_pin_ctl(void *arg, int pin, int flags)
 {
-	struct gpio_softc *sc = arg;
-
-        outl((sc->sc_addr + offset), out);
+	struct gpio_opb_softc *sc = arg;
+	u_int32_t data;
+	int p;
+
+	p = pin % GPIO_NPINS;
+	p = p + 1;
+
+	if (flags & GPIO_PIN_INOUT) {
+		/* GPIOn_ODR register bit is 0 */
+		data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
+					GPIO_ODR);
+		data &= ~(1 << GPIO_PIN_SHIFT(p));
+		bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
+					GPIO_ODR, data);
+		/* GPIOn_TCR register bit is 1 */
+		data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
+					GPIO_TCR);
+		data |= (1 << GPIO_PIN_SHIFT(p));
+		bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
+					GPIO_TCR, data);
+	}
+
+	if (flags & GPIO_PIN_TRISTATE) {
+		/* GPIOn_ODR register bit is 0 */
+		data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
+					GPIO_ODR);
+		data &= ~(1 << GPIO_PIN_SHIFT(p));
+		bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
+					GPIO_ODR, data);
+		/* GPIOn_TCR register bit is 0 */
+		data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
+					GPIO_TCR);
+		data &= ~(1 << GPIO_PIN_SHIFT(p));
+		bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
+					GPIO_TCR, data);
+	}
+
+	if (flags & GPIO_PIN_OPENDRAIN) {
+		/* GPIOn_ODR register bit is 1 */
+		data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
+					GPIO_ODR);
+		data |= (1 << GPIO_PIN_SHIFT(p));
+		bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh,
+					GPIO_ODR, data);
+	}
 }
Index: sys/arch/powerpc/ibm4xx/dev/gpioreg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/ibm4xx/dev/gpioreg.h,v
retrieving revision 1.2
diff -u -u -r1.2 gpioreg.h
--- sys/arch/powerpc/ibm4xx/dev/gpioreg.h	23 Jan 2005 19:22:22 -0000	1.2
+++ sys/arch/powerpc/ibm4xx/dev/gpioreg.h	1 Oct 2005 16:12:52 -0000
@@ -52,11 +52,13 @@
  *	1	1	0	X	0	Forced to high impedance state
  */
 
+/* GPIO pins */
+#define GPIO_NPINS		(24)
+
 /* GPIO Registers 0x00-0x7f */
 #define GPIO_NREG		(0x80)
 
-#define GPIO_SHIFT(n)		(31 - n)
-#define GPIO_SBIT(n)		(1 << GPIO_SHIFT(n))
+#define GPIO_PIN_SHIFT(n)	(31 - n)
 
 /* Offset */
 #define	GPIO_OR			(0x00)	/* Output */
Index: sys/arch/powerpc/ibm4xx/dev/opb.c
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/ibm4xx/dev/opb.c,v
retrieving revision 1.20
diff -u -u -r1.20 opb.c
--- sys/arch/powerpc/ibm4xx/dev/opb.c	26 Aug 2005 13:19:37 -0000	1.20
+++ sys/arch/powerpc/ibm4xx/dev/opb.c	1 Oct 2005 16:12:52 -0000
@@ -93,7 +93,7 @@
 	{ IBM405GP,	"com",	IBM405GP_UART0_BASE,	 0 },
 	{ IBM405GP,	"com",	IBM405GP_UART1_BASE,	 1 },
 	{ IBM405GP,	"emac",	IBM405GP_EMAC0_BASE,	 9 }, /* XXX: really irq 9..15 */
-	{ IBM405GP,	"gpio",	IBM405GP_GPIO0_BASE,	-1 },
+	{ IBM405GP,	"gpio_opb",IBM405GP_GPIO0_BASE,	-1 },
 	{ IBM405GP,	"gpiic",IBM405GP_IIC0_BASE,	 2 },
 	{ IBM405GP,	"wdog",	-1,	        	-1 },
 
@@ -101,7 +101,7 @@
 	{ IBM405GPR,	"com",	IBM405GP_UART0_BASE,	 0 },
 	{ IBM405GPR,	"com",	IBM405GP_UART1_BASE,	 1 },
 	{ IBM405GPR,	"emac",	IBM405GP_EMAC0_BASE,	 9 }, /* XXX: really irq 9..15 */
-	{ IBM405GPR,	"gpio",	IBM405GP_GPIO0_BASE,	-1 },
+	{ IBM405GPR,	"gpio_opb",IBM405GP_GPIO0_BASE,	-1 },
 	{ IBM405GPR,	"gpiic",IBM405GP_IIC0_BASE,	 2 },
 	{ IBM405GPR,	"wdog",	-1,	        	-1 },
 	{ 0,		 NULL }
@@ -127,7 +127,7 @@
     opb_match, opb_attach, NULL, NULL);
 
 static struct powerpc_bus_space opb_tag = {
-	_BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE,
+	_BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE,
 	0x0, IBM405GP_UART0_BASE, 0x1000
 };
 static char ex_storage[EXTENT_FIXED_STORAGE_SIZE(8)]

--------------060303010804030506010404--