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--