Module Name: src Committed By: mlelstv Date: Sat Sep 28 07:24:52 UTC 2019
Modified Files: src/sys/arch/arm/broadcom: bcm2835_gpio.c bcm2835_gpioreg.h Log Message: Handle BCM2838 (bcm2711) SoC pecularities. To generate a diff of this commit: cvs rdiff -u -r1.12 -r1.13 src/sys/arch/arm/broadcom/bcm2835_gpio.c cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/broadcom/bcm2835_gpioreg.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/broadcom/bcm2835_gpio.c diff -u src/sys/arch/arm/broadcom/bcm2835_gpio.c:1.12 src/sys/arch/arm/broadcom/bcm2835_gpio.c:1.13 --- src/sys/arch/arm/broadcom/bcm2835_gpio.c:1.12 Fri May 10 08:28:50 2019 +++ src/sys/arch/arm/broadcom/bcm2835_gpio.c Sat Sep 28 07:24:52 2019 @@ -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 @@ int bcm2835gpiodebug = 3; #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 @@ struct bcmgpio_softc { /* 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 @@ bcm283x_pinctrl_set_config(device_t dev, 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 @@ bcmgpio_attach(device_t parent, device_t 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 @@ bcmgpio_attach(device_t parent, device_t 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 @@ bcmgpio_attach(device_t parent, device_t 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 @@ bcmgpio_attach(device_t parent, device_t 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 @@ bcmgpio_gpio_intr_disestablish(void *vsc 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 @@ bcm283x_pin_setpull(const struct bcmgpio 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; - 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); + if (sc->sc_is2835) { + mask = 1 << (pin % BCM2835_GPIO_GPPUD_PINS_PER_REGISTER); + regid = (pin / BCM2835_GPIO_GPPUD_PINS_PER_REGISTER); + +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 @@ bcm2835gpio_gpio_pin_ctl(void *arg, int 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 @@ bcmgpio_fdt_acquire(device_t dev, const 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); Index: src/sys/arch/arm/broadcom/bcm2835_gpioreg.h diff -u src/sys/arch/arm/broadcom/bcm2835_gpioreg.h:1.4 src/sys/arch/arm/broadcom/bcm2835_gpioreg.h:1.5 --- src/sys/arch/arm/broadcom/bcm2835_gpioreg.h:1.4 Sun Dec 10 21:38:26 2017 +++ src/sys/arch/arm/broadcom/bcm2835_gpioreg.h Sat Sep 28 07:24:52 2019 @@ -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