Browse Source

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
Steve Baker 4 years ago
parent
commit
41f941a78e
1 changed files with 42 additions and 6 deletions
  1. 42 6
      wiringPi/wiringPi.c

+ 42 - 6
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 ;
   }