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