Hi,

the patch below adds a 'flags' locator to gpioiic(4). It allows to swap
the SDA and SCL pins assigment during attach.  The current gpio attach
code did only allow for SDA being the lowest numbered pin.

But for instance on geode (cs5536) SCL is gpio pin 3 and SDA is pin 4. 

This is a joint work with mbalmer@NetBSD.

My initial code used the offset as SDA pin number and mask as the SCL
pin number, but Marc conviced me that this is inconsistent with other
gpio attachments and that adding a  flag to swap the pins is the way
to go and fixed my code to implement the flag.

Opinions? ok?

Index: share/man/man4/gpioiic.4
===================================================================
RCS file: /cvs/OpenBSD/src/share/man/man4/gpioiic.4,v
retrieving revision 1.6
diff -u -r1.6 gpioiic.4
--- share/man/man4/gpioiic.4    24 Nov 2008 15:30:21 -0000      1.6
+++ share/man/man4/gpioiic.4    2 Oct 2011 09:15:09 -0000
@@ -21,7 +21,7 @@
 .Nm gpioiic
 .Nd GPIO I2C controller
 .Sh SYNOPSIS
-.Cd "gpioiic* at gpio? offset 0 mask 0x3"
+.Cd "gpioiic* at gpio? offset 0 mask 0x3 flags 0x0"
 .Cd "gpioiic* at gpio?"
 .Cd "iic* at gpioiic?"
 .Sh DESCRIPTION
Index: sys/dev/gpio/files.gpio
===================================================================
RCS file: /cvs/OpenBSD/src/sys/dev/gpio/files.gpio,v
retrieving revision 1.8
diff -u -r1.8 files.gpio
--- sys/dev/gpio/files.gpio     28 Nov 2008 17:42:43 -0000      1.8
+++ sys/dev/gpio/files.gpio     2 Oct 2011 09:15:09 -0000
@@ -1,6 +1,6 @@
 # $OpenBSD: files.gpio,v 1.8 2008/11/28 17:42:43 mbalmer Exp $
 
-define gpio {[offset = -1], [mask = 0]}
+define gpio {[offset = -1], [mask = 0], [flag = 0]}
 
 device gpio: gpio
 attach gpio at gpiobus
Index: sys/dev/gpio/gpio.c
===================================================================
RCS file: /cvs/OpenBSD/src/sys/dev/gpio/gpio.c,v
retrieving revision 1.11
diff -u -r1.11 gpio.c
--- sys/dev/gpio/gpio.c 29 Aug 2009 11:04:56 -0000      1.11
+++ sys/dev/gpio/gpio.c 2 Oct 2011 09:15:09 -0000
@@ -131,6 +131,7 @@
        ga.ga_gpio = aux;
        ga.ga_offset = cf->cf_loc[0];
        ga.ga_mask = cf->cf_loc[1];
+       ga.ga_flags = cf->cf_loc[2];
 
        if (cf->cf_attach->ca_match(parent, cf, &ga) > 0)
                config_attach(parent, cf, &ga, gpio_print);
@@ -282,6 +283,24 @@
        return (-1);
 }
 
+struct device *
+gpio_attach_device(struct device *dev, struct gpio_attach_args *ga)
+{
+       struct gpio_softc *sc = (struct gpio_softc *)dev;
+       struct gpio_dev *gdev;
+       struct device *dv;
+
+       dv = config_found_sm(dev, ga, gpiobus_print, 
+           gpio_submatch);
+       if (dv == NULL) 
+               return NULL;
+       
+       gdev = malloc(sizeof(struct gpio_dev), M_DEVBUF, M_NOWAIT);
+       gdev->sc_dev = dv;
+       LIST_INSERT_HEAD(&sc->sc_devs, gdev, sc_next);
+       return dv;
+}
+
 int
 gpioioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
 {
@@ -406,6 +425,7 @@
                ga.ga_dvname = attach->ga_dvname;
                ga.ga_offset = attach->ga_offset;
                ga.ga_mask = attach->ga_mask;
+               ga.ga_flags = attach->ga_flags;
                dv = config_found_sm((struct device *)sc, &ga, gpiobus_print,
                    gpio_submatch);
                if (dv != NULL) {
Index: sys/dev/gpio/gpioiic.c
===================================================================
RCS file: /cvs/OpenBSD/src/sys/dev/gpio/gpioiic.c,v
retrieving revision 1.8
diff -u -r1.8 gpioiic.c
--- sys/dev/gpio/gpioiic.c      24 Nov 2008 12:12:12 -0000      1.8
+++ sys/dev/gpio/gpioiic.c      2 Oct 2011 09:15:09 -0000
@@ -35,6 +35,9 @@
 #define GPIOIIC_PIN_SCL                1
 #define GPIOIIC_NPINS          2
 
+/* flags */
+#define GPIOIIC_PIN_REVERSE    0x01
+
 #define GPIOIIC_SDA            0x01
 #define GPIOIIC_SCL            0x02
 
@@ -48,6 +51,9 @@
        struct i2c_controller   sc_i2c_tag;
        struct rwlock           sc_i2c_lock;
 
+       int                     sc_pin_sda;
+       int                     sc_pin_scl;
+
        int                     sc_sda;
        int                     sc_scl;
 };
@@ -120,9 +126,17 @@
                printf(": can't map pins\n");
                return;
        }
+       
+       if (ga->ga_flags & GPIOIIC_PIN_REVERSE) {
+               sc->sc_pin_sda = GPIOIIC_PIN_SCL;
+               sc->sc_pin_scl = GPIOIIC_PIN_SDA;
+       } else {
+               sc->sc_pin_sda = GPIOIIC_PIN_SDA;
+               sc->sc_pin_scl = GPIOIIC_PIN_SCL;
+       }
 
        /* Configure SDA pin */
-       caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA);
+       caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, sc->sc_pin_sda);
        if (!(caps & GPIO_PIN_OUTPUT)) {
                printf(": SDA pin is unable to drive output\n");
                goto fail;
@@ -131,7 +145,7 @@
                printf(": SDA pin is unable to read input\n");
                goto fail;
        }
-       printf(": SDA[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SDA]);
+       printf(": SDA[%d]", sc->sc_map.pm_map[sc->sc_pin_sda]);
        sc->sc_sda = GPIO_PIN_OUTPUT;
        if (caps & GPIO_PIN_OPENDRAIN) {
                printf(" open-drain");
@@ -144,15 +158,15 @@
                printf(" pull-up");
                sc->sc_sda |= GPIO_PIN_PULLUP;
        }
-       gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, sc->sc_sda);
+       gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, sc->sc_pin_sda, sc->sc_sda);
 
        /* Configure SCL pin */
-       caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL);
+       caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, sc->sc_pin_scl);
        if (!(caps & GPIO_PIN_OUTPUT)) {
                printf(": SCL pin is unable to drive output\n");
                goto fail;
        }
-       printf(", SCL[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SCL]);
+       printf(", SCL[%d]", sc->sc_map.pm_map[sc->sc_pin_scl]);
        sc->sc_scl = GPIO_PIN_OUTPUT;
        if (caps & GPIO_PIN_OPENDRAIN) {
                printf(" open-drain");
@@ -165,7 +179,7 @@
                printf(" push-pull");
                sc->sc_scl |= GPIO_PIN_PUSHPULL;
        }
-       gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL, sc->sc_scl);
+       gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, sc->sc_pin_scl, sc->sc_scl);
 
        printf("\n");
 
@@ -254,9 +268,9 @@
 {
        struct gpioiic_softc *sc = cookie;
 
-       gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA,
+       gpio_pin_write(sc->sc_gpio, &sc->sc_map, sc->sc_pin_sda,
            bits & GPIOIIC_SDA ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
-       gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL,
+       gpio_pin_write(sc->sc_gpio, &sc->sc_map, sc->sc_pin_scl,
            bits & GPIOIIC_SCL ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
 }
 
@@ -272,7 +286,7 @@
                sda |= GPIO_PIN_TRISTATE;
        if (sc->sc_sda != sda) {
                sc->sc_sda = sda;
-               gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA,
+               gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, sc->sc_pin_sda,
                    sc->sc_sda);
        }
 }
Index: sys/dev/gpio/gpiovar.h
===================================================================
RCS file: /cvs/OpenBSD/src/sys/dev/gpio/gpiovar.h,v
retrieving revision 1.5
diff -u -r1.5 gpiovar.h
--- sys/dev/gpio/gpiovar.h      26 Nov 2008 14:51:20 -0000      1.5
+++ sys/dev/gpio/gpiovar.h      2 Oct 2011 09:15:09 -0000
@@ -61,6 +61,7 @@
        int                     ga_offset;
        u_int32_t               ga_mask;
        char                    *ga_dvname;
+       u_int32_t               ga_flags;
 };
 
 /* GPIO pin map */
@@ -88,5 +89,7 @@
 int    gpio_pin_caps(void *, struct gpio_pinmap *, int);
 
 int    gpio_npins(u_int32_t);
+
+struct device *gpio_attach_device(struct device *, struct gpio_attach_args *);
 
 #endif /* !_DEV_GPIO_GPIOVAR_H_ */
Index: sys/sys/gpio.h
===================================================================
RCS file: /cvs/OpenBSD/src/sys/sys/gpio.h,v
retrieving revision 1.7
diff -u -r1.7 gpio.h
--- sys/sys/gpio.h      26 Nov 2008 14:51:20 -0000      1.7
+++ sys/sys/gpio.h      2 Oct 2011 09:15:09 -0000
@@ -65,6 +65,7 @@
        char ga_dvname[16];     /* device name */
        int ga_offset;          /* pin number */
        u_int32_t ga_mask;      /* binary mask */
+       u_int32_t ga_flags;     /* flags */
 };
 
 #define GPIOINFO               _IOR('G', 0, struct gpio_info)
Index: usr.sbin/gpioctl/gpioctl.8
===================================================================
RCS file: /cvs/OpenBSD/src/usr.sbin/gpioctl/gpioctl.8,v
retrieving revision 1.19
diff -u -r1.19 gpioctl.8
--- usr.sbin/gpioctl/gpioctl.8  5 Dec 2008 15:45:53 -0000       1.19
+++ usr.sbin/gpioctl/gpioctl.8  2 Oct 2011 09:15:09 -0000
@@ -28,6 +28,7 @@
 .Ar device
 .Ar offset
 .Ar mask
+.Op Ar flags
 .Nm gpioctl
 .Op Fl q
 .Ar device
Index: usr.sbin/gpioctl/gpioctl.c
===================================================================
RCS file: /cvs/OpenBSD/src/usr.sbin/gpioctl/gpioctl.c,v
retrieving revision 1.14
diff -u -r1.14 gpioctl.c
--- usr.sbin/gpioctl/gpioctl.c  3 Dec 2008 20:12:44 -0000       1.14
+++ usr.sbin/gpioctl/gpioctl.c  2 Oct 2011 09:15:09 -0000
@@ -44,7 +44,7 @@
 void   pinwrite(int, char *, int);
 void   pinset(int pin, char *name, int flags, char *alias);
 void   unset(int pin, char *name);
-void   devattach(char *, int, u_int32_t);
+void   devattach(char *, int, u_int32_t, u_int32_t);
 void   devdetach(char *);
 
 __dead void usage(void);
@@ -71,10 +71,10 @@
 {
        const struct bitstr *bs;
        long lval;
-       u_int32_t ga_mask = 0;
+       u_int32_t ga_mask = 0, ga_flags = 0;
        int pin, ch, ga_offset = -1, n, fl = 0, value = 0;
        const char *errstr;
-       char *ep, *nam = NULL;
+       char *ep, *flags, *nam = NULL;
        char devn[32];
 
        while ((ch = getopt(argc, argv, "q")) != -1)
@@ -109,12 +109,13 @@
        if (!strcmp(argv[1], "attach")) {
                char *driver, *offset, *mask;
 
-               if (argc != 5)
+               if (argc != 5 && argc != 6)
                        usage();
 
                driver = argv[2];
                offset = argv[3];
                mask = argv[4];
+               flags = argc == 6 ? argv[5] : NULL;
 
                ga_offset = strtonum(offset, 0, INT_MAX, &errstr);
                if (errstr)
@@ -127,7 +128,13 @@
                    || lval == LONG_MIN)) || lval > UINT_MAX)
                        errx(1, "mask out of range");
                ga_mask = lval;
-               devattach(driver, ga_offset, ga_mask);
+               if (flags != NULL) {
+                       lval = strtonum(flags, 0, UINT_MAX, &errstr);
+                       if (errstr)
+                               errx(1, "flags is %s: %s", errstr, flags);
+                       ga_flags = lval;
+               }
+               devattach(driver, ga_offset, ga_mask, ga_flags);
                return 0;
        } else if (!strcmp(argv[1], "detach")) {
                if (argc != 3)
@@ -135,7 +142,7 @@
                devdetach(argv[2]);
        } else {
                char *nm = NULL;
-       
+
                /* expecting a pin number or name */
                pin = strtonum(argv[1], 0, INT_MAX, &errstr);
                if (errstr)
@@ -309,7 +316,7 @@
 }
 
 void
-devattach(char *dvname, int offset, u_int32_t mask)
+devattach(char *dvname, int offset, u_int32_t mask, u_int32_t flags)
 {
        struct gpio_attach attach;
 
@@ -317,6 +324,7 @@
        strlcpy(attach.ga_dvname, dvname, sizeof(attach.ga_dvname));
        attach.ga_offset = offset;
        attach.ga_mask = mask;
+       attach.ga_flags = flags;
        if (ioctl(devfd, GPIOATTACH, &attach) == -1)
                err(1, "GPIOATTACH");
 }
@@ -341,8 +349,8 @@
        fprintf(stderr, "       %s [-q] device pin set [flags] [name]\n",
            __progname);
        fprintf(stderr, "       %s [-q] device pin unset\n", __progname);
-       fprintf(stderr, "       %s [-q] device attach device offset mask\n",
-           __progname);
+       fprintf(stderr, "       %s [-q] device attach device offset mask "
+           "[flags]\n", __progname);
        fprintf(stderr, "       %s [-q] device detach device\n", __progname);
 
        exit(1);


-- 
Matthieu Herrb

Reply via email to