From 41f941a78ee929406bcda6c3f80ea6d554e5a48b Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Sat, 14 Dec 2019 20:42:06 +0000 Subject: [PATCH] Fix GPIO pull up/down for Pi4B Based on this raspi-gpio commit[1] the 2711 chip uses a different method for pull up/down. This change implements that same method. With this change, wiringPi now works for the Pi4B with the subset of functionality used by zynthian. [1] https://github.com/RPi-Distro/raspi-gpio/commit/80fa7d04eafb3ea34fc6f2d32de5f1873b5fb369?diff=unified --- wiringPi/wiringPi.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 2d581e9..76f5684 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -214,7 +214,7 @@ volatile unsigned int *_wiringPiTimerIrqRaw ; // The base address of the GPIO memory mapped hardware IO #define GPIO_PERI_BASE_OLD 0x20000000 -#define GPIO_PERI_BASE_2708 0x3F000000 +#define GPIO_PERI_BASE_2835 0x3F000000 #define GPIO_PERI_BASE_2711 0xFE000000 static volatile unsigned int piGpioBase = 0 ; @@ -543,6 +543,14 @@ static uint8_t gpioToFEN [] = #define GPPUD 37 +/* 2711 has a different mechanism for pin pull-up/down/enable */ +#define GPPUPPDN0 57 /* Pin pull-up/down for pins 15:0 */ +#define GPPUPPDN1 58 /* Pin pull-up/down for pins 31:16 */ +#define GPPUPPDN2 59 /* Pin pull-up/down for pins 47:32 */ +#define GPPUPPDN3 60 /* Pin pull-up/down for pins 57:48 */ + +static volatile unsigned int piGpioPupOffset = 0 ; + // gpioToPUDCLK // (Word) offset to the Pull Up Down Clock regsiter @@ -1509,11 +1517,36 @@ void pullUpDnControl (int pin, int pud) else if (wiringPiMode != WPI_MODE_GPIO) return ; - *(gpio + GPPUD) = pud & 3 ; delayMicroseconds (5) ; - *(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ; + if (piGpioPupOffset == GPPUPPDN0) + { + // Pi 4B pull up/down method + int pullreg = GPPUPPDN0 + (pin>>4); + int pullshift = (pin & 0xf) << 1; + unsigned int pullbits; + unsigned int pull; + + switch (pud) + { + case PUD_OFF: pull = 0; break; + case PUD_UP: pull = 1; break; + case PUD_DOWN: pull = 2; break; + default: return ; /* An illegal value */ + } - *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ; - *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ; + pullbits = *(gpio + pullreg); + pullbits &= ~(3 << pullshift); + pullbits |= (pull << pullshift); + *(gpio + pullreg) = pullbits; + } + else + { + // legacy pull up/down method + *(gpio + GPPUD) = pud & 3 ; delayMicroseconds (5) ; + *(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ; + + *(gpio + GPPUD) = 0 ; delayMicroseconds (5) ; + *(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ; + } } else // Extension module { @@ -2270,14 +2303,17 @@ int wiringPiSetup (void) case PI_ALPHA: case PI_MODEL_CM: case PI_MODEL_ZERO: case PI_MODEL_ZERO_W: piGpioBase = GPIO_PERI_BASE_OLD ; + piGpioPupOffset = GPPUD ; break ; case PI_MODEL_4B: piGpioBase = GPIO_PERI_BASE_2711 ; + piGpioPupOffset = GPPUPPDN0 ; break ; default: - piGpioBase = GPIO_PERI_BASE_2708 ; + piGpioBase = GPIO_PERI_BASE_2835 ; + piGpioPupOffset = GPPUD ; break ; }