From 6e053885794658fab02799d97f6384b75f6179d2 Mon Sep 17 00:00:00 2001 From: Payam Date: Tue, 13 Mar 2018 16:49:18 -0700 Subject: [PATCH] [vim2] Initial support for Khadas VIM2 boards --- dev/interrupt/arm_gic/arm_gic.c | 36 ++++ .../arm_gic/include/dev/interrupt/arm_gic.h | 14 ++ platform/amlogic-s912d/include/platform/gic.h | 32 ++++ .../amlogic-s912d/include/platform/s912d.h | 35 ++++ platform/amlogic-s912d/platform.c | 111 +++++++++++ platform/amlogic-s912d/rules.mk | 31 +++ platform/amlogic-s912d/uart.c | 180 ++++++++++++++++++ project/vim2-test.mk | 12 ++ target/vim2/README | 16 ++ target/vim2/rules.mk | 9 + 10 files changed, 476 insertions(+) create mode 100644 platform/amlogic-s912d/include/platform/gic.h create mode 100644 platform/amlogic-s912d/include/platform/s912d.h create mode 100644 platform/amlogic-s912d/platform.c create mode 100644 platform/amlogic-s912d/rules.mk create mode 100644 platform/amlogic-s912d/uart.c create mode 100644 project/vim2-test.mk create mode 100644 target/vim2/README create mode 100644 target/vim2/rules.mk diff --git a/dev/interrupt/arm_gic/arm_gic.c b/dev/interrupt/arm_gic/arm_gic.c index e3bb13ef..e3a49554 100644 --- a/dev/interrupt/arm_gic/arm_gic.c +++ b/dev/interrupt/arm_gic/arm_gic.c @@ -234,6 +234,36 @@ static int arm_gic_max_cpu(void) return (GICREG(0, GICD_TYPER) >> 5) & 0x7; } +static status_t gic_configure_interrupt(unsigned int vector, + enum interrupt_trigger_mode tm, + enum interrupt_polarity pol) +{ + //Only configurable for SPI interrupts + if ((vector >= MAX_INT) || (vector < GIC_BASE_SPI)) { + return ERR_INVALID_ARGS; + } + + if (pol != IRQ_POLARITY_ACTIVE_HIGH) { + // TODO: polarity should actually be configure through a GPIO controller + return ERR_NOT_SUPPORTED; + } + + // type is encoded with two bits, MSB of the two determine type + // 16 irqs encoded per ICFGR register + uint32_t reg_ndx = vector >> 4; + uint32_t bit_shift = ((vector & 0xf) << 1) + 1; + uint32_t reg_val = GICREG(0, GICD_ICFGR(reg_ndx)); + if (tm == IRQ_TRIGGER_MODE_EDGE) { + reg_val |= (1 << bit_shift); + } + else { + reg_val &= ~(1 << bit_shift); + } + GICREG(0, GICD_ICFGR(reg_ndx)) = reg_val; + + return NO_ERROR; +} + void arm_gic_init(void) { int i; @@ -250,6 +280,12 @@ void arm_gic_init(void) } } + // Initialize all the SPIs to edge triggered + for (i = 32; i < MAX_INT; i++) { + gic_configure_interrupt(i, IRQ_TRIGGER_MODE_EDGE, IRQ_POLARITY_ACTIVE_HIGH); + } + + GICREG(0, GICD_CTLR) = 1; // enable GIC0 #if WITH_LIB_SM GICREG(0, GICD_CTLR) = 3; // enable GIC0 ns interrupts diff --git a/dev/interrupt/arm_gic/include/dev/interrupt/arm_gic.h b/dev/interrupt/arm_gic/include/dev/interrupt/arm_gic.h index b40fb077..8c44ffa0 100644 --- a/dev/interrupt/arm_gic/include/dev/interrupt/arm_gic.h +++ b/dev/interrupt/arm_gic/include/dev/interrupt/arm_gic.h @@ -27,6 +27,20 @@ void arm_gic_init(void); +#define GIC_BASE_SGI 0 +#define GIC_BASE_PPI 16 +#define GIC_BASE_SPI 32 + +enum interrupt_trigger_mode { + IRQ_TRIGGER_MODE_EDGE = 0, + IRQ_TRIGGER_MODE_LEVEL = 1, +}; + +enum interrupt_polarity { + IRQ_POLARITY_ACTIVE_HIGH = 0, + IRQ_POLARITY_ACTIVE_LOW = 1, +}; + enum { /* Ignore cpu_mask and forward interrupt to all CPUs other than the current cpu */ ARM_GIC_SGI_FLAG_TARGET_FILTER_NOT_SENDER = 0x1, diff --git a/platform/amlogic-s912d/include/platform/gic.h b/platform/amlogic-s912d/include/platform/gic.h new file mode 100644 index 00000000..31f132b7 --- /dev/null +++ b/platform/amlogic-s912d/include/platform/gic.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 The Fuchsia Authors + * + * 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, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include + +#define GICBASE(n) (GIC_BASE) +#define GICD_OFFSET (0x1000) +#define GICC_OFFSET (0x2000) + +#define MAX_INT 255 \ No newline at end of file diff --git a/platform/amlogic-s912d/include/platform/s912d.h b/platform/amlogic-s912d/include/platform/s912d.h new file mode 100644 index 00000000..af27240d --- /dev/null +++ b/platform/amlogic-s912d/include/platform/s912d.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 The Fuchsia Authors + * + * 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, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#pragma once + +#define SDRAM_BASE (0x0U) +#define AML_S912D_PERIPH_BASE_PHYS (0xC0000000U) +#define AML_S912D_PERIPH_BASE_SIZE (0x20000000U) +#define AML_S912D_PERIPH_BASE_VIRT (0xFFFFFFFFC0000000ULL) + +#define UART0_AO_BASE (AML_S912D_PERIPH_BASE_VIRT + 0x81004c0) +#define GIC_BASE (AML_S912D_PERIPH_BASE_VIRT + 0x4300000) + +#define UART0_IRQ 225 diff --git a/platform/amlogic-s912d/platform.c b/platform/amlogic-s912d/platform.c new file mode 100644 index 00000000..cb0e9792 --- /dev/null +++ b/platform/amlogic-s912d/platform.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018 The Fuchsia Authors + * + * 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, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct arm64_iframe_long arm_platform_iframe_t; + +/* initial memory mappings. parsed by start.S */ +struct mmu_initial_mapping mmu_initial_mappings[] = { + { + .phys = SDRAM_BASE, + .virt = KERNEL_BASE, + .size = MEMSIZE, + .flags = 0, + .name = "memory" + }, + + /* peripherals */ + { + .phys = AML_S912D_PERIPH_BASE_PHYS, + .virt = AML_S912D_PERIPH_BASE_VIRT, + .size = AML_S912D_PERIPH_BASE_SIZE, + .flags = MMU_INITIAL_MAPPING_FLAG_DEVICE, + .name = "peripherals" + }, + /* null entry to terminate the list */ + { 0 } +}; + +static pmm_arena_t arena = { + .name = "sdram", + .base = SDRAM_BASE, + .size = MEMSIZE, + .flags = PMM_ARENA_FLAG_KMAP, +}; + +#define DEBUG_UART 0 + +void platform_dputc(char c) +{ + if (c == '\n') + uart_putc(DEBUG_UART, '\r'); + uart_putc(DEBUG_UART, c); +} + +int platform_dgetc(char *c, bool wait) +{ + int ret = uart_getc(DEBUG_UART, wait); + if (ret == -1) + return -1; + *c = ret; + return 0; +} + +void platform_init(void) +{ + uart_init(); + +} + +void platform_early_init(void) +{ + uart_init_early(); + + /* initialize the interrupt controller */ + arm_gic_init(); + + arm_generic_timer_init(30, 0); + + pmm_add_arena(&arena); + + // TODO: Reserve memory regions if needed +} + diff --git a/platform/amlogic-s912d/rules.mk b/platform/amlogic-s912d/rules.mk new file mode 100644 index 00000000..fd203919 --- /dev/null +++ b/platform/amlogic-s912d/rules.mk @@ -0,0 +1,31 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_DEPS += \ + lib/cbuf \ + lib/fdt \ + dev/interrupt/arm_gic \ + dev/timer/arm_generic \ + +MODULE_SRCS += \ + $(LOCAL_DIR)/platform.c \ + $(LOCAL_DIR)/uart.c \ + +ARCH := arm64 +ARM_CPU := cortex-a53 +MEMBASE := 0 +MEMSIZE := 0x80000000 # 2GB +KERNEL_LOAD_OFFSET := 0x01080000 +LINKER_SCRIPT += \ + $(BUILDDIR)/system-onesegment.ld + +MODULE := $(LOCAL_DIR) + +MODULE_DEPS += \ + app/shell \ + + +WITH_CPP_SUPPORT=true + +include make/module.mk \ No newline at end of file diff --git a/platform/amlogic-s912d/uart.c b/platform/amlogic-s912d/uart.c new file mode 100644 index 00000000..2ddc6fc6 --- /dev/null +++ b/platform/amlogic-s912d/uart.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018 The Fuchsia Authors + * + * 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, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define S912D_UART_WFIFO (0x00) +#define S912D_UART_RFIFO (0x04) +#define S912D_UART_CONTROL (0x08) +#define S912D_UART_STATUS (0x0C) +#define S912D_UART_IRQ_CONTROL (0x10) +#define S912D_UART_REG5 (0x14) + +#define S912D_UART_CONTROL_INVRTS (1 << 31) +#define S912D_UART_CONTROL_MASKERR (1 << 30) +#define S912D_UART_CONTROL_INVCTS (1 << 29) +#define S912D_UART_CONTROL_TXINTEN (1 << 28) +#define S912D_UART_CONTROL_RXINTEN (1 << 27) +#define S912D_UART_CONTROL_INVTX (1 << 26) +#define S912D_UART_CONTROL_INVRX (1 << 25) +#define S912D_UART_CONTROL_CLRERR (1 << 24) +#define S912D_UART_CONTROL_RSTRX (1 << 23) +#define S912D_UART_CONTROL_RSTTX (1 << 22) +#define S912D_UART_CONTROL_XMITLEN (1 << 20) +#define S912D_UART_CONTROL_XMITLEN_MASK (0x3 << 20) +#define S912D_UART_CONTROL_PAREN (1 << 19) +#define S912D_UART_CONTROL_PARTYPE (1 << 18) +#define S912D_UART_CONTROL_STOPLEN (1 << 16) +#define S912D_UART_CONTROL_STOPLEN_MASK (0x3 << 16) +#define S912D_UART_CONTROL_TWOWIRE (1 << 15) +#define S912D_UART_CONTROL_RXEN (1 << 13) +#define S912D_UART_CONTROL_TXEN (1 << 12) +#define S912D_UART_CONTROL_BAUD0 (1 << 0) +#define S912D_UART_CONTROL_BAUD0_MASK (0xfff << 0) + +#define S912D_UART_STATUS_RXBUSY (1 << 26) +#define S912D_UART_STATUS_TXBUSY (1 << 25) +#define S912D_UART_STATUS_RXOVRFLW (1 << 24) +#define S912D_UART_STATUS_CTSLEVEL (1 << 23) +#define S912D_UART_STATUS_TXEMPTY (1 << 22) +#define S912D_UART_STATUS_TXFULL (1 << 21) +#define S912D_UART_STATUS_RXEMPTY (1 << 20) +#define S912D_UART_STATUS_RXFULL (1 << 19) +#define S912D_UART_STATUS_TXOVRFLW (1 << 18) +#define S912D_UART_STATUS_FRAMEERR (1 << 17) +#define S912D_UART_STATUS_PARERR (1 << 16) +#define S912D_UART_STATUS_TXCOUNT_POS (8) +#define S912D_UART_STATUS_TXCOUNT_MASK (0x7f << S912D_UART_STATUS_TXCOUNT_POS) +#define S912D_UART_STATUS_RXCOUNT_POS (0) +#define S912D_UART_STATUS_RXCOUNT_MASK (0x7f << S912D_UART_STATUS_RXCOUNT_POS) + + +#define UARTREG(base, reg) (*(volatile uint32_t*)((base) + (reg))) + +#define RXBUF_SIZE 16 +#define NUM_UART 1 + +static cbuf_t uart_rx_buf; +static uintptr_t uart_base = 0; +static uint32_t uart_irq = 0; + + +int uart_putc(int port, char c) +{ + while (UARTREG(uart_base, S912D_UART_STATUS) & S912D_UART_STATUS_TXFULL) + ; + UARTREG(uart_base, S912D_UART_WFIFO) = c; + + return 0; +} + +int uart_getc(int port, bool wait) +{ + char c; + if (cbuf_read_char(&uart_rx_buf, &c, wait) == 1) { + return c; + } + else { + return -1; + } +} + +void uart_irq_handler(void) +{ + while ( (UARTREG(uart_base, S912D_UART_STATUS) & S912D_UART_STATUS_RXCOUNT_MASK) > 0 ) { + if (cbuf_space_avail(&uart_rx_buf) == 0) { + break; + } + char c = UARTREG(uart_base, S912D_UART_RFIFO); + cbuf_write_char(&uart_rx_buf, c,false); + } +} + +void uart_init_early(void) +{ + uart_base = UART0_AO_BASE; + uart_irq = UART0_IRQ; + + // reset port + UARTREG(uart_base,S912D_UART_CONTROL) |= S912D_UART_CONTROL_RSTRX | + S912D_UART_CONTROL_RSTTX | + S912D_UART_CONTROL_CLRERR; + UARTREG(uart_base,S912D_UART_CONTROL) &= ~(S912D_UART_CONTROL_RSTRX | + S912D_UART_CONTROL_RSTTX | + S912D_UART_CONTROL_CLRERR); + + // enable rx and tx + UARTREG(uart_base,S912D_UART_CONTROL) |= S912D_UART_CONTROL_TXEN | + S912D_UART_CONTROL_RXEN; + + UARTREG(uart_base,S912D_UART_CONTROL) |= S912D_UART_CONTROL_INVRTS | + S912D_UART_CONTROL_RXINTEN | + S912D_UART_CONTROL_TWOWIRE; + +} +void uart_init(void) +{ + uart_base = UART0_AO_BASE; + uart_irq = UART0_IRQ; + + // create a circular buufer to hold rx data + cbuf_initialize(&uart_rx_buf, RXBUF_SIZE); + + // register uart irq + register_int_handler(uart_irq, &uart_irq_handler, NULL); + + // reset port + UARTREG(uart_base,S912D_UART_CONTROL) |= S912D_UART_CONTROL_RSTRX | + S912D_UART_CONTROL_RSTTX | + S912D_UART_CONTROL_CLRERR; + UARTREG(uart_base,S912D_UART_CONTROL) &= ~(S912D_UART_CONTROL_RSTRX | + S912D_UART_CONTROL_RSTTX | + S912D_UART_CONTROL_CLRERR); + + // enable rx and tx + UARTREG(uart_base,S912D_UART_CONTROL) |= S912D_UART_CONTROL_TXEN | + S912D_UART_CONTROL_RXEN; + + UARTREG(uart_base,S912D_UART_CONTROL) |= S912D_UART_CONTROL_INVRTS | + S912D_UART_CONTROL_RXINTEN | + S912D_UART_CONTROL_TWOWIRE; + + // Set to interrupt every 1 rx byte + uint32_t temp2 = UARTREG(uart_base,S912D_UART_IRQ_CONTROL); + temp2 &= 0xffff0000; + temp2 |= (1 << 8) | ( 1 ); + UARTREG(uart_base,S912D_UART_IRQ_CONTROL) = temp2; + + // TODO: Look into adding baud rate support + + // enable interrupts + unmask_interrupt(uart_irq); + +} \ No newline at end of file diff --git a/project/vim2-test.mk b/project/vim2-test.mk new file mode 100644 index 00000000..59122caf --- /dev/null +++ b/project/vim2-test.mk @@ -0,0 +1,12 @@ +# main project for vim2 +LOCAL_DIR := $(GET_LOCAL_DIR) + +TARGET := vim2 + +MODULES += \ + app/shell \ + app/stringtests \ + app/tests \ + lib/cksum \ + lib/debugcommands \ + diff --git a/target/vim2/README b/target/vim2/README new file mode 100644 index 00000000..b2f190c6 --- /dev/null +++ b/target/vim2/README @@ -0,0 +1,16 @@ + +Notes on the KHADAS VIM2 Board +------------------------------- + +http://docs.khadas.com/ + +Run LK on VIM2 +--------------- +Below commands assume the VIM2 board is able to boot into U-Boot. + +- Copy lk.bin from build-vim2-test to a USB flash drive +- Connect the USB flash drive to VIM2 USB-A port +- Boot VIM2 and press enter or space to stop autoboot +- Run the following commands from U-Boot prompt: + usb start; fatload usb 0 0x01080000 lk.bin; go 0x01080000 + diff --git a/target/vim2/rules.mk b/target/vim2/rules.mk new file mode 100644 index 00000000..49326f0d --- /dev/null +++ b/target/vim2/rules.mk @@ -0,0 +1,9 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +GLOBAL_INCLUDES += \ + $(LOCAL_DIR)/include + +PLATFORM := amlogic-s912d + +#include make/module.mk +