From f5b83627d0c61d160f7c87d7b29f50eee929238b Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 8 May 2012 11:55:05 -0500 Subject: [PATCH] rpi gpio: Rework GPIO support * GPIO calls now simplier and more correct * Set UART pins to AUX0 mode --- .../boot/platform/raspberrypi_arm/gpio.cpp | 102 ++++++++++++++++-- .../boot/platform/raspberrypi_arm/gpio.h | 20 ++-- .../boot/platform/raspberrypi_arm/start.c | 2 +- src/system/kernel/arch/arm/uart_pl011.cpp | 1 + 4 files changed, 109 insertions(+), 16 deletions(-) diff --git a/src/system/boot/platform/raspberrypi_arm/gpio.cpp b/src/system/boot/platform/raspberrypi_arm/gpio.cpp index ed6fa1fc50..24a380b19e 100644 --- a/src/system/boot/platform/raspberrypi_arm/gpio.cpp +++ b/src/system/boot/platform/raspberrypi_arm/gpio.cpp @@ -4,22 +4,108 @@ * * Authors: * Alexander von Gluck, kallisti5@unixzen.com + * Gordon Henderson, gordon@drogon.net */ #include "gpio.h" +// Define the shift up for the 3 bits per pin in each GPFSEL port +static uint8_t +kGPIOToShift[] = +{ + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, + 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, +}; + + +// Map a BCM_GPIO pin to it's control port. (GPFSEL 0-5) +static uint8_t +kGPIOToGPFSEL[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + + +// (Word) offset to the GPIO Set registers for each GPIO pin +static uint8_t +kGPIOToGPSET[] = +{ + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +// (Word) offset to the GPIO Clear registers for each GPIO pin +static uint8_t +kGPIOToGPCLR[] = +{ + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +}; + + +/*! + * At GPIO (base) (pin) state set (value) + */ +void +gpio_write(addr_t base, int pin, bool value) +{ + volatile addr_t *gpio = (addr_t*)base; + + if (value == 1) + *(gpio + kGPIOToGPSET[pin]) = 1 << pin; + else + *(gpio + kGPIOToGPCLR[pin]) = 1 << pin; +} + + +/*! + * At GPIO (base) (pin) set mode (mode) + */ +void +gpio_mode(addr_t base, int pin, int mode) +{ + int sel = kGPIOToGPFSEL[pin]; + int shift = kGPIOToShift[pin]; + + volatile addr_t *gpio = (addr_t*)base + sel; + + if (mode == GPIO_IN) + *gpio = (*gpio & ~(7 << shift)); + else if (mode == GPIO_OUT) + *gpio = (*gpio & ~(7 << shift)) | (1 << shift); + else + *gpio = (*gpio & ~(7 << shift)) | (mode << shift); +} + + void gpio_init() { - // Set up pointer to Raspberry Pi GPIO base - gGPIOBase = (volatile unsigned *)GPIO_BASE; - - // Take control of ok led and general use pins + // ** Take control of ok led, and general use pins int pin = 0; - for (pin = 16; pin <= 25; pin++) { - GPIO_IN(pin); - GPIO_OUT(pin); - } + for (pin = 16; pin <= 25; pin++) + gpio_mode(GPIO_BASE, pin, GPIO_OUT); + + // ** Prepare UART pins for serial communication + // Set alternate function 0 on UART pins + gpio_mode(GPIO_BASE, 14, GPIO_ALT0); + gpio_mode(GPIO_BASE, 15, GPIO_ALT0); + + // Pull UART pins to initial state low + gpio_write(GPIO_BASE, 14, 0); + gpio_write(GPIO_BASE, 15, 0); } diff --git a/src/system/boot/platform/raspberrypi_arm/gpio.h b/src/system/boot/platform/raspberrypi_arm/gpio.h index da0f95233f..5228e218c2 100644 --- a/src/system/boot/platform/raspberrypi_arm/gpio.h +++ b/src/system/boot/platform/raspberrypi_arm/gpio.h @@ -9,24 +9,30 @@ #define _SYSTEM_BOOT_PLATFORM_PI_GPIO_H +#include + #include -// Macros for easy GPIO pin access in loader -#define GPIO_IN(g) *(gGPIOBase + ((g)/10)) &= ~(7<<(((g)%10)*3)) -#define GPIO_OUT(g) *(gGPIOBase + ((g)/10)) |= (1<<(((g)%10)*3)) -#define GPIO_SET(g) *(gGPIOBase + 7) = (1<