[platform][sifive] add a GPIO driver and switch the target setup to it

This commit is contained in:
Travis Geiselbrecht
2021-01-20 00:13:20 -08:00
parent 7033559d38
commit c55ab00668
7 changed files with 162 additions and 22 deletions

View File

@@ -16,6 +16,7 @@
#define PLIC_BASE 0x0c000000
#define UART0_BASE 0x10010000
#define UART1_BASE 0x10011000
#define GPIO_BASE 0x10060000
#if RISCV_XMODE_OFFSET == RISCV_MACH_OFFSET
#define PLIC_HART_IDX(hart) ((hart) ? ((2 * (hart)) - 1) : 0)

View File

@@ -7,16 +7,33 @@
*/
#pragma once
#define SIFIVE_IRQ_WATCHDOG 1
#define SIFIVE_IRQ_RTC 2
#define SIFIVE_IRQ_UART0 3
#define SIFIVE_IRQ_UART1 4
#define SIFIVE_IRQ_QSPI0 5
#define SIFIVE_IRQ_QSPI1 6
#define SIFIVE_IRQ_QSPI2 7
#define SIFIVE_IRQ_GPIO_BASE 8
#define SIFIVE_IRQ_GPIO(n) (SIFIVE_IRQ_GPIO_BASE+(n))
#define SIFIVE_IRQ_PWM_BASE 40
#define SIFIVE_NUM_IRQS 127
#define SIFIVE_NUM_IRQS 64
#define CLINT_BASE 0x02000000
#define PLIC_BASE 0x0c000000
#define AON_BASE 0x10000000
#define PRCI_BASE 0x10008000
#define OTP_BASE 0x10010000
#define GPIO_BASE 0x10012000
#define UART0_BASE 0x10013000
#define QSPI0_BASE 0x10014000
#define PWM0_BASE 0x10015000
#define UART1_BASE 0x10023000
#define QSPI1_BASE 0x10024000
#define PWM1_BASE 0x10025000
#define QSPI2_BASE 0x10034000
#define PWM2_BASE 0x10035000
#define GPIO_REG_VALUE 0
#define GPIO_REG_INPUT_EN 1
@@ -26,3 +43,6 @@
#define GPIO_REG_IOF_SEL 15
#define PLIC_HART_IDX(hart) 0
#define GPIO_AF0 (1U << 16)
#define GPIO_AF1 (1U << 17)

View File

@@ -9,9 +9,9 @@
#include <target.h>
#include <arch/arch_ops.h>
#include <platform/sifive.h>
#include <dev/gpio.h>
static volatile unsigned int *const prci_base = (unsigned int *)PRCI_BASE;
static volatile unsigned int *const gpio_base = (unsigned int *)GPIO_BASE;
#define GPIO_LED_GREEN 19
#define GPIO_LED_BLUE 21
@@ -28,33 +28,35 @@ void target_early_init(void) {
// lfclock is a 32768Hz crystal, strapped externally
// io function enable for pin 16/17, no IOF for all others
gpio_base[14] = (3<<16);
// set up all the gpios
for (uint i = 0; i < 32; i++) {
switch (i) {
// default to input
default: gpio_config(i, GPIO_INPUT); break;
// turn our LED gpios off
gpio_base[GPIO_REG_PORT] |= (1u << GPIO_LED_GREEN) | (1u << GPIO_LED_BLUE) | (1u << GPIO_LED_RED);
// uart0
case 16: gpio_config(i, GPIO_AF0); break;
case 17: gpio_config(i, GPIO_AF0); break;
// set the led gpios to output
gpio_base[GPIO_REG_OUTPUT_EN] |= (1u << GPIO_LED_GREEN) | (1u << GPIO_LED_BLUE) | (1u << GPIO_LED_RED);
// set the led gpios to output and default to off
case GPIO_LED_GREEN: gpio_set(i, 0); gpio_config(i, GPIO_OUTPUT); break;
case GPIO_LED_RED: gpio_set(i, 0); gpio_config(i, GPIO_OUTPUT); break;
case GPIO_LED_BLUE: gpio_set(i, 0); gpio_config(i, GPIO_OUTPUT); break;
}
}
}
void target_set_debug_led(unsigned int led, bool on) {
uint val = 0;
if (led == 0) {
val = 1u << GPIO_LED_GREEN;
} else if (led == 1) {
val = 1u << GPIO_LED_RED;
} else if (led == 2) {
val = 1u << GPIO_LED_BLUE;
unsigned int gpio;
switch (led) {
default:
case 0: gpio = GPIO_LED_GREEN; break;
case 1: gpio = GPIO_LED_RED; break;
case 2: gpio = GPIO_LED_BLUE; break;
}
// set and clear the LED gpios using atomic instructions
// polarity is inverted
if (on) {
__atomic_fetch_and((int *)&gpio_base[GPIO_REG_PORT], ~val, __ATOMIC_RELAXED);
} else {
__atomic_fetch_or((int *)&gpio_base[GPIO_REG_PORT], val, __ATOMIC_RELAXED);
}
gpio_set(gpio, on ? 1 : 0);
}
void target_init(void) {