Index: src/pidp8i/gpio-common.c.in ================================================================== --- src/pidp8i/gpio-common.c.in +++ src/pidp8i/gpio-common.c.in @@ -1,9 +1,9 @@ /* * gpio-common.c: functions common to both gpio.c and gpio-nls.c * - * Copyright © 2015 Oscar Vermeulen, © 2016-2019 by Warren Young + * Copyright © 2015, 2019 Oscar Vermeulen, © 2016-2019 by Warren Young * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, @@ -580,24 +580,74 @@ INP_GPIO (ledrows[row]); } } -//// init_pidp8i_gpio ////////////////////////////////////////////////// -// Initialize the GPIO pins to the initial states required by -// gpio_thread(). It's a separate exported function so that scanswitch -// can also use it. - -void init_pidp8i_gpio (void) -{ - // Set GPIO pins to their starting state - turn_on_pidp8i_leds (); - for (size_t i = 0; i < NROWS; i++) { // Define rows as input - INP_GPIO (rows[i]); - } - - // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs +//// init_bcm2711_gpio ///////////////////////////////////////////////// +// Called from init_pidp8i_gpio() when it sees that it's running on a Pi +// 4 which uses the BCM 2711 GPIO peripheral, which behaves differently +// than GPIO was done in all prior Pi models. This code is based on +// https://github.com/RPi-Distro/raspi-gpio/blob/master/raspi-gpio.c +// +// Note that there is no "serial mod" handling here: no one has come up +// with such a hardware hack for the Pi 4 yet, and no one has verified +// that you can do one of the existing ones atop the Pi 4. + +static void init_bcm2711_gpio (void) +{ + int gpiox, pullreg, pullshift; + unsigned int pullbits, pull; + + // Configure "columns" GPIO pins + for (size_t i = 0; i < 12; ++i) { + gpiox = cols[i]; + pullreg = GPPUPPDN0 + (gpiox>>4); + pullshift = (gpiox & 0xf) << 1; + pull = 1; + + pullbits = *(gpio.addr + pullreg); + pullbits &= ~(3 << pullshift); + pullbits |= (pull << pullshift); + *(gpio.addr + pullreg) = pullbits; + } + + // Configure "rows" GPIO pins + for (size_t i = 0; i < 3; ++i) { + gpiox = rows[i]; + pullreg = GPPUPPDN0 + (gpiox>>4); + pullshift = (gpiox & 0xf) << 1; + pull = 0; + + pullbits = *(gpio.addr + pullreg); + pullbits &= ~(3 << pullshift); + pullbits |= (pull << pullshift); + *(gpio.addr + pullreg) = pullbits; + } + + // Configure "ledrows" GPIO pins + for (size_t i = 0; i < 6; ++i) { + gpiox = ledrows[i]; + pullreg = GPPUPPDN0 + (gpiox>>4); + pullshift = (gpiox & 0xf) << 1; + pull = 0; + + pullbits = *(gpio.addr + pullreg); + pullbits &= ~(3 << pullshift); + pullbits |= (pull << pullshift); + *(gpio.addr + pullreg) = pullbits; + } +} + + +//// init_bcm2835_gpio ///////////////////////////////////////////////// +// Called from init_pidp8i_gpio() when it sees that it's running on a Pi +// 3 or older. This is the "classic" Pi GPIO mode. See page 101 in the +// peripheral's datasheet and // http://elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs + +static void init_bcm2835_gpio (void) +{ + // Configure "columns" GPIO pins GPIO_PULL = 2; // pull-up usleep(1); // must wait 150 cycles #if defined(PCB_SERIAL_MOD_OV) || defined(PCB_SERIAL_MOD_JLW) // The Oscar Vermeulen and James L-W serial mods rearrange the PiDP-8/I // GPIO matrix to use Pi GPIO pins 2..13, freeing up the hardware @@ -611,29 +661,52 @@ GPIO_PULL = 0; // reset GPPUD register usleep(1); GPIO_PULLCLK0 = 0; // remove clock usleep(1); // probably unnecessary - // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs - GPIO_PULL = 1; // pull-down to avoid ghosting (dec2015) - usleep(1); // must wait 150 cycles - GPIO_PULLCLK0 = 0x0ff00000; // selects GPIO pins 20..27 - usleep(1); - GPIO_PULL = 0; // reset GPPUD register - usleep(1); - GPIO_PULLCLK0 = 0; // remove clock - usleep(1); // probably unnecessary - - // BCM2835 ARM Peripherals PDF p 101 & elinux.org/RPi_Low-level_peripherals#Internal_Pull-Ups_.26_Pull-Downs + // Configure "rows" GPIO pins GPIO_PULL = 0; // no pull-up no pull down just float usleep(1); // must wait 150 cycles GPIO_PULLCLK0 = 0x070000; // selects GPIO pins 16..18 usleep(1); GPIO_PULL = 0; // reset GPPUD register usleep(1); GPIO_PULLCLK0 = 0; // remove clock usleep(1); // probably unnecessary + + // Configure "ledrows" GPIO pins + GPIO_PULL = 1; // pull-down to avoid ghosting + usleep(1); // must wait 150 cycles + GPIO_PULLCLK0 = 0x0ff00000; // selects GPIO pins 20..27 + usleep(1); + GPIO_PULL = 0; // reset GPPUD register + usleep(1); + GPIO_PULLCLK0 = 0; // remove clock + usleep(1); // probably unnecessary +} + + +//// init_pidp8i_gpio ////////////////////////////////////////////////// +// Initialize the GPIO pins to the initial states required by +// gpio_thread(). It's a separate exported function so that scanswitch +// can also use it. + +void init_pidp8i_gpio (void) +{ + // Set GPIO pins to their starting state + turn_on_pidp8i_leds (); + for (size_t i = 0; i < NROWS; i++) { // Define rows as input + INP_GPIO (rows[i]); + } + + // Configure GPIO pin pull-ups + if (gpio.addr_p == 0xfe200000) { + init_bcm2711_gpio(); + } + else { + init_bcm2835_gpio(); + } } //// gpio_thread /////////////////////////////////////////////////////// // The GPIO thread entry point: initializes GPIO and then calls Index: src/pidp8i/gpio-common.h ================================================================== --- src/pidp8i/gpio-common.h +++ src/pidp8i/gpio-common.h @@ -1,9 +1,9 @@ /* * gpio-common.h: public interface for the PiDP-8/I's GPIO module * - * Copyright © 2015-2017 Oscar Vermeulen and Warren Young + * Copyright © 2015, 2019 by Oscar Vermeulen, © 2016-2019 by Warren Young * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, @@ -51,10 +51,16 @@ #define GPIO_READ(g) *(pgpio->addr + 13) &= (1<<(g)) #define GPIO_PULL *(pgpio->addr + 37) // pull up/pull down #define GPIO_PULLCLK0 *(pgpio->addr + 38) // pull up/pull down clock +// Pi 4 GPIO pull up/down peripheral I/O offsets. Based on +// https://github.com/RPi-Distro/raspi-gpio/blob/master/raspi-gpio.c +#define GPPUPPDN0 57 // pins 15:0 +#define GPPUPPDN1 58 // pins 31:16 +#define GPPUPPDN2 59 // pins 47:32 +#define GPPUPPDN3 60 // pins 57:48 // Switch masks, SSn, used against switchstatus[n] #define SS0_SR_B11 04000 #define SS0_SR_B10 02000 #define SS0_SR_B09 01000