Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/broadcom Handle BCM2838 (bcm2711) SoC pecularit...



details:   https://anonhg.NetBSD.org/src/rev/76fced6d1e98
branches:  trunk
changeset: 454793:76fced6d1e98
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Sat Sep 28 07:24:52 2019 +0000

description:
Handle BCM2838 (bcm2711) SoC pecularities.

diffstat:

 sys/arch/arm/broadcom/bcm2835_gpio.c    |  105 +++++++++++++++++++++----------
 sys/arch/arm/broadcom/bcm2835_gpioreg.h |   10 ++-
 2 files changed, 78 insertions(+), 37 deletions(-)

diffs (242 lines):

diff -r 247f0caedaa5 -r 76fced6d1e98 sys/arch/arm/broadcom/bcm2835_gpio.c
--- a/sys/arch/arm/broadcom/bcm2835_gpio.c      Sat Sep 28 07:10:55 2019 +0000
+++ b/sys/arch/arm/broadcom/bcm2835_gpio.c      Sat Sep 28 07:24:52 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bcm2835_gpio.c,v 1.12 2019/05/10 08:28:50 skrll Exp $  */
+/*     $NetBSD: bcm2835_gpio.c,v 1.13 2019/09/28 07:24:52 mlelstv Exp $        */
 
 /*-
  * Copyright (c) 2013, 2014, 2017 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_gpio.c,v 1.12 2019/05/10 08:28:50 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_gpio.c,v 1.13 2019/09/28 07:24:52 mlelstv Exp $");
 
 /*
  * Driver for BCM2835 GPIO
@@ -65,7 +65,9 @@
 #define DPRINTF(l, x)
 #endif
 
-#define        BCMGPIO_MAXPINS 54
+#define BCM2835_GPIO_MAXPINS 54
+#define BCM2838_GPIO_MAXPINS 58
+#define        BCMGPIO_MAXPINS BCM2838_GPIO_MAXPINS
 
 struct bcmgpio_eint {
         int                    (*eint_func)(void *);
@@ -101,6 +103,9 @@
 
        /* For interrupt support. */
        struct bcmgpio_bank     sc_banks[BCMGPIO_NBANKS];
+
+       bool                    sc_is2835;      /* for pullup on 2711 */
+       u_int                   sc_maxpins;
 };
 
 struct bcmgpio_pin {
@@ -216,7 +221,7 @@
        for (int i = 0; i < npins; i++) {
                const u_int pin = be32toh(pins[i]);
 
-               if (pin > BCMGPIO_MAXPINS)
+               if (pin > sc->sc_maxpins)
                        continue;
                if (pull) {
                        const int value = be32toh(pull[npull == 1 ? 0 : i]);
@@ -254,6 +259,7 @@
        int error;
        int pin;
        int bank;
+       uint32_t reg;
 
        const int phandle = faa->faa_phandle;
        if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
@@ -263,19 +269,25 @@
 
        sc->sc_dev = self;
 
-       aprint_naive("\n");
-       aprint_normal(": GPIO controller\n");
-
        sc->sc_iot = faa->faa_bst;
        error = bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh);
        if (error) {
-               aprint_error_dev(self, "couldn't map registers\n");
+               aprint_error_dev(self, ": couldn't map registers\n");
                return;
        }
 
        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
 
-       for (pin = 0; pin < BCMGPIO_MAXPINS; pin++) {
+       /* BCM2835, BCM2836, BCM2837 return 'gpio' in this unused register */
+       reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCM2838_GPIO_GPPUPPDN(3));
+       sc->sc_is2835 = reg == 0x6770696f;
+       sc->sc_maxpins = sc->sc_is2835 ? BCM2835_GPIO_MAXPINS
+                                      : BCM2838_GPIO_MAXPINS;
+
+       aprint_naive("\n");
+       aprint_normal(": GPIO controller %s\n", sc->sc_is2835 ? "2835" : "2838");
+
+       for (pin = 0; pin < sc->sc_maxpins; pin++) {
                sc->sc_gpio_pins[pin].pin_num = pin;
                /*
                 * find out pins still available for GPIO
@@ -329,13 +341,13 @@
                        aprint_normal_dev(self,
                            "pins %d..%d interrupting on %s\n",
                            bank * 32,
-                           MIN((bank * 32) + 31, BCMGPIO_MAXPINS),
+                           MIN((bank * 32) + 31, sc->sc_maxpins),
                            intrstr);
                } else {
                        aprint_error_dev(self,
                            "failed to establish interrupt for pins %d..%d\n",
                            bank * 32,
-                           MIN((bank * 32) + 31, BCMGPIO_MAXPINS));
+                           MIN((bank * 32) + 31, sc->sc_maxpins));
                }
        }
 
@@ -364,7 +376,7 @@
 
        gba.gba_gc = &sc->sc_gpio_gc;
        gba.gba_pins = &sc->sc_gpio_pins[0];
-       gba.gba_npins = BCMGPIO_MAXPINS;
+       gba.gba_npins = sc->sc_maxpins;
        (void) config_found_ia(self, "gpiobus", &gba, gpiobus_print);
 }
 
@@ -657,8 +669,9 @@
 static bool
 bcmgpio_gpio_intrstr(void *vsc, int pin, int irqmode, char *buf, size_t buflen)
 {
+       struct bcmgpio_softc * const sc = vsc;
 
-       if (pin < 0 || pin >= BCMGPIO_MAXPINS)
+       if (pin < 0 || pin >= sc->sc_maxpins)
                return (false);
 
        snprintf(buf, buflen, "GPIO %d", pin);
@@ -797,15 +810,48 @@
 
        KASSERT(mutex_owned(&sc->sc_lock));
 
-       const u_int mask = 1 << (pin % BCM2835_GPIO_GPPUD_PINS_PER_REGISTER);
-       const u_int regid = (pin / BCM2835_GPIO_GPPUD_PINS_PER_REGISTER);
+       u_int mask, regid;
+       uint32_t reg;
+
+       if (sc->sc_is2835) {
+               mask = 1 << (pin % BCM2835_GPIO_GPPUD_PINS_PER_REGISTER);
+               regid = (pin / BCM2835_GPIO_GPPUD_PINS_PER_REGISTER);
 
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCM2835_GPIO_GPPUD, pud);
-       delay(1);
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCM2835_GPIO_GPPUDCLK(regid), mask);
-       delay(1);
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCM2835_GPIO_GPPUD, 0);
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCM2835_GPIO_GPPUDCLK(regid), 0);
+printf("2835: pin=%u, pud=%u, regid=%u, mask=%08x\n",pin,pud,regid,mask);
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+                   BCM2835_GPIO_GPPUD, pud);
+               delay(1);
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+                   BCM2835_GPIO_GPPUDCLK(regid), mask);
+               delay(1);
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+                   BCM2835_GPIO_GPPUD, 0);
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+                   BCM2835_GPIO_GPPUDCLK(regid), 0);
+       } else {
+               mask = BCM2838_GPIO_GPPUD_MASK(pin);
+               regid = BCM2838_GPIO_GPPUD_REGID(pin);
+
+               switch (pud) {
+               case BCM2835_GPIO_GPPUD_PULLUP:
+                       pud = BCM2838_GPIO_GPPUD_PULLUP;
+                       break;
+               case BCM2835_GPIO_GPPUD_PULLDOWN:
+                       pud = BCM2838_GPIO_GPPUD_PULLDOWN;
+                       break;
+               default:
+                       pud = BCM2838_GPIO_GPPUD_PULLOFF;
+                       break;
+               }
+printf("2838: pin=%u, pud=%u, regid=%u, mask=%08x\n",pin,pud,regid,mask);
+
+               reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+                   BCM2838_GPIO_GPPUPPDN(regid));
+               reg &= ~mask;
+               reg |= __SHIFTIN(pud, mask);
+               bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+                   BCM2838_GPIO_GPPUPPDN(regid), reg);
+       }
 }
 
 
@@ -866,20 +912,7 @@
                cmd = BCM2835_GPIO_GPPUD_PULLOFF;
        }
 
-       /* set up control signal */
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCM2835_GPIO_GPPUD, cmd);
-       delay(1); /* wait 150 cycles */
-       /* set clock signal */
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh,
-           BCM2835_GPIO_GPPUDCLK(pin / BCM2835_GPIO_GPLEV_PINS_PER_REGISTER),
-           1 << (pin % BCM2835_GPIO_GPPUD_PINS_PER_REGISTER));
-       delay(1); /* wait 150 cycles */
-       /* reset control signal and clock */
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh,
-           BCM2835_GPIO_GPPUD, BCM2835_GPIO_GPPUD_PULLOFF);
-       bus_space_write_4(sc->sc_iot, sc->sc_ioh,
-           BCM2835_GPIO_GPPUDCLK(pin / BCM2835_GPIO_GPLEV_PINS_PER_REGISTER),
-           0);
+       bcm283x_pin_setpull(sc, pin, cmd);
        mutex_exit(&sc->sc_lock);
 }
 
@@ -896,7 +929,7 @@
        const u_int pin = be32toh(gpio[1]);
        const bool actlo = be32toh(gpio[2]) & 1;
 
-       if (pin >= BCMGPIO_MAXPINS)
+       if (pin >= sc->sc_maxpins)
                return NULL;
 
        gpin = kmem_alloc(sizeof(*gpin), KM_SLEEP);
diff -r 247f0caedaa5 -r 76fced6d1e98 sys/arch/arm/broadcom/bcm2835_gpioreg.h
--- a/sys/arch/arm/broadcom/bcm2835_gpioreg.h   Sat Sep 28 07:10:55 2019 +0000
+++ b/sys/arch/arm/broadcom/bcm2835_gpioreg.h   Sat Sep 28 07:24:52 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bcm2835_gpioreg.h,v 1.4 2017/12/10 21:38:26 skrll Exp $        */
+/*     $NetBSD: bcm2835_gpioreg.h,v 1.5 2019/09/28 07:24:52 mlelstv Exp $      */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -48,6 +48,7 @@
 #define BCM2835_GPIO_GPAFEN(x) (0x088 + (x) * sizeof(uint32_t))
 
 #define BCM2835_GPIO_GPPUD     (0x094)
+
 /* brcm,pull property */
 #define  BCM2835_GPIO_GPPUD_PULLOFF    0x0
 #define  BCM2835_GPIO_GPPUD_PULLDOWN   0x1
@@ -55,6 +56,13 @@
 #define BCM2835_GPIO_GPPUDCLK(x)       (0x098 + (x) * sizeof(uint32_t))
 #define BCM2835_GPIO_GPPUD_PINS_PER_REGISTER 32
 
+#define  BCM2838_GPIO_GPPUD_PULLOFF    0x0
+#define  BCM2838_GPIO_GPPUD_PULLDOWN   0x2
+#define  BCM2838_GPIO_GPPUD_PULLUP     0x1
+#define BCM2838_GPIO_GPPUPPDN(x)       (0x0e4 + (x) * sizeof(uint32_t))
+#define BCM2838_GPIO_GPPUD_REGID(n)    ((n) / 16)
+#define BCM2838_GPIO_GPPUD_MASK(n)     (0x3 << ((n) % 16)*2)
+
 /* brcm,function property */
 #define BCM2835_GPIO_IN                0
 #define BCM2835_GPIO_OUT       1



Home | Main Index | Thread Index | Old Index