diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index 84678957538..ac911f4b18b 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -210,6 +210,26 @@ config ARCH_CHIP_JH7110 ---help--- StarFive JH7110 SoC. +config ARCH_CHIP_BL808 + bool "Bouffalo Lab BL808" + select ARCH_RV64 + select ARCH_RV_ISA_M + select ARCH_RV_ISA_A + select ARCH_RV_ISA_C + select ARCH_HAVE_FPU + select ARCH_HAVE_DPFPU + select ARCH_HAVE_MULTICPU + select ARCH_HAVE_MPU + select ARCH_HAVE_MMU + select ARCH_MMU_TYPE_SV39 + select ARCH_HAVE_ADDRENV + select ARCH_NEED_ADDRENV_MAPPING + select ARCH_HAVE_S_MODE + select ONESHOT + select ALARM_ARCH + ---help--- + Bouffalo Lab BL808 SoC. + config ARCH_CHIP_RISCV_CUSTOM bool "Custom RISC-V chip" select ARCH_CHIP_CUSTOM @@ -260,6 +280,7 @@ config ARCH_CHIP default "qemu-rv" if ARCH_CHIP_QEMU_RV default "hpm6750" if ARCH_CHIP_HPM6750 default "jh7110" if ARCH_CHIP_JH7110 + default "bl808" if ARCH_CHIP_BL808 config ARCH_RISCV_INTXCPT_EXTENSIONS bool "RISC-V Integer Context Extensions" @@ -425,4 +446,7 @@ endif if ARCH_CHIP_JH7110 source "arch/risc-v/src/jh7110/Kconfig" endif +if ARCH_CHIP_BL808 +source "arch/risc-v/src/bl808/Kconfig" +endif endif diff --git a/arch/risc-v/include/bl808/chip.h b/arch/risc-v/include/bl808/chip.h new file mode 100644 index 00000000000..27e71ac06e7 --- /dev/null +++ b/arch/risc-v/include/bl808/chip.h @@ -0,0 +1,24 @@ +/**************************************************************************** + * arch/risc-v/include/bl808/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_INCLUDE_BL808_CHIP_H +#define __ARCH_RISCV_INCLUDE_BL808_CHIP_H + +#endif /* __ARCH_RISCV_INCLUDE_BL808_CHIP_H */ diff --git a/arch/risc-v/include/bl808/irq.h b/arch/risc-v/include/bl808/irq.h new file mode 100644 index 00000000000..b99b1535d69 --- /dev/null +++ b/arch/risc-v/include/bl808/irq.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * arch/risc-v/include/bl808/irq.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_INCLUDE_BL808_IRQ_H +#define __ARCH_RISCV_INCLUDE_BL808_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Map RISC-V exception code to NuttX IRQ */ + +#define NR_IRQS (RISCV_IRQ_SEXT + 57) + +#define BL808_IRQ_NUM_BASE (16) + +#define BL808_IRQ_UART3 (RISCV_IRQ_SEXT + BL808_IRQ_NUM_BASE + 4) + +#endif /* __ARCH_RISCV_INCLUDE_BL808_IRQ_H */ diff --git a/arch/risc-v/src/bl808/Kconfig b/arch/risc-v/src/bl808/Kconfig new file mode 100644 index 00000000000..5435169ee9f --- /dev/null +++ b/arch/risc-v/src/bl808/Kconfig @@ -0,0 +1,16 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +comment "BL808 Configuration Options" + +menu "BL808 Peripheral Support" + +config BL808_UART3 + bool "UART 3" + default n + select UART3_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +endmenu diff --git a/arch/risc-v/src/bl808/Make.defs b/arch/risc-v/src/bl808/Make.defs new file mode 100644 index 00000000000..61a4f41280e --- /dev/null +++ b/arch/risc-v/src/bl808/Make.defs @@ -0,0 +1,30 @@ +############################################################################ +# arch/risc-v/src/bl808/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include common/Make.defs + +# Specify our HEAD assembly file. This will be linked as +# the first object file, so it will appear at address 0 +HEAD_ASRC = bl808_head.S + +# Specify our C code within this directory to be included +CHIP_CSRCS = bl808_start.c bl808_irq_dispatch.c bl808_irq.c +CHIP_CSRCS += bl808_timerisr.c bl808_allocateheap.c +CHIP_CSRCS += bl808_mm_init.c bl808_pgalloc.c bl808_serial.c diff --git a/arch/risc-v/src/bl808/bl808_allocateheap.c b/arch/risc-v/src/bl808/bl808_allocateheap.c new file mode 100644 index 00000000000..e5f9ae00cad --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_allocateheap.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_allocateheap.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include "riscv_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define KRAM_END KSRAM_END + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * This function will be called to dynamically set aside the heap region. + * + * For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and + * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the + * size of the unprotected, user-space heap. + * + * If a protected kernel-space heap is provided, the kernel heap must be + * allocated (and protected) by an analogous up_allocate_kheap(). + * + * The following memory map is assumed for the flat build: + * + * .data region. Size determined at link time. + * .bss region Size determined at link time. + * IDLE thread stack. Size determined by CONFIG_IDLETHREAD_STACKSIZE. + * Heap. Extends to the end of User SRAM. + * + * The following memory map is assumed for the protect build. + * The kernel and user space have it's own dedicated heap space. + * + * User .data region Size determined at link time + * User .bss region Size determined at link time + * User heap Extends to the end of User SRAM + * Kernel .data region Size determined at link time + * Kernel .bss region Size determined at link time + * Kernel IDLE thread stack Size determined by CONFIG_IDLETHREAD_STACKSIZE + * Kernel heap Size determined by CONFIG_MM_KERNEL_HEAPSIZE + * + ****************************************************************************/ + +void up_allocate_kheap(void **heap_start, size_t *heap_size) +{ + /* Return the heap settings */ + + *heap_start = (void *)g_idle_topstack; + *heap_size = KRAM_END - g_idle_topstack; +} diff --git a/arch/risc-v/src/bl808/bl808_head.S b/arch/risc-v/src/bl808/bl808_head.S new file mode 100644 index 00000000000..3b825864026 --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_head.S @@ -0,0 +1,143 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_head.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "chip.h" +#include "riscv_internal.h" + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + /* Exported Symbols */ + + .section .text + .global __start + +__start: + + /* DO NOT MODIFY. Image Header expected by Linux bootloaders. + * + * This `li` instruction has no meaningful effect except that + * its opcode forms the magic "MZ" signature of a PE/COFF file + * that is required for UEFI applications. + * + * Some bootloaders check the magic "MZ" to see if the image is a valid + * Linux image. But modifying the bootLoader is unnecessary unless we + * need to do a customized secure boot. So we just put "MZ" in the + * header to make the bootloader happy. + */ + + c.li s4, -13 /* Magic Signature "MZ" (2 bytes) */ + j real_start /* Jump to Kernel Start (2 bytes) */ + .long 0 /* Executable Code padded to 8 bytes */ + .quad 0x200000 /* Image load offset from start of RAM */ + .quad _ebss - __start /* Effective size of kernel image */ + .quad 0 /* Kernel flags, little-endian */ + .long 2 /* Version of this header */ + .long 0 /* Reserved */ + .quad 0 /* Reserved */ + .ascii "RISCV\x00\x00\x00" /* Magic number, "RISCV" (8 bytes) */ + .ascii "RSC\x05" /* Magic number 2, "RSC\x05" (4 bytes) */ + .long 0 /* Reserved for PE COFF offset */ + +real_start: + + /* Set stack pointer to the idle thread stack */ + + bnez a0, 1f + la sp, BL808_IDLESTACK_TOP + j 2f +1: + + /* Load the number of CPUs that the kernel supports */ + +#ifdef CONFIG_SMP + li t1, CONFIG_SMP_NCPUS +#else + li t1, 1 +#endif + + /* If a0 (hartid) >= t1 (the number of CPUs), stop here */ + + blt a0, t1, 3f + csrw sie, zero + wfi + +3: + /* To get g_cpu_basestack[hartid], must get g_cpu_basestack first */ + + la t0, g_cpu_basestack + + /* Offset = pointer width * hart id */ + +#ifdef CONFIG_ARCH_RV32 + slli t1, a0, 2 +#else + slli t1, a0, 3 +#endif + add t0, t0, t1 + + /* Load idle stack base to sp */ + + REGLOAD sp, 0(t0) + + /* + * sp (stack top) = sp + idle stack size - XCPTCONTEXT_SIZE + * + * Note: Reserve some space used by up_initial_state since we are already + * running and using the per CPU idle stack. + */ + + li t0, STACK_ALIGN_UP(CONFIG_IDLETHREAD_STACKSIZE - XCPTCONTEXT_SIZE) + add sp, sp, t0 + +2: + + /* Disable all interrupts (i.e. timer, external) in sie */ + + csrw sie, zero + + la t0, __trap_vec + csrw stvec, t0 + + /* Jump to bl808_start */ + + jal x1, bl808_start + + /* We shouldn't return from _start */ + + .global _init + .global _fini + +_init: +_fini: + + /* These don't have to do anything since we use init_array/fini_array. */ + + ret diff --git a/arch/risc-v/src/bl808/bl808_irq.c b/arch/risc-v/src/bl808/bl808_irq.c new file mode 100644 index 00000000000..1e52f1580d6 --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_irq.c @@ -0,0 +1,201 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_irq.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "riscv_internal.h" +#include "chip.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + uintptr_t claim; + + /* Disable S-Mode interrupts */ + + up_irq_save(); + + /* Attach the common interrupt handler */ + + riscv_exception_attach(); + + /* Disable all global interrupts */ + + putreg32(0x0, BL808_PLIC_ENABLE1); + putreg32(0x0, BL808_PLIC_ENABLE2); + + /* Clear pendings in PLIC */ + + claim = getreg32(BL808_PLIC_CLAIM); + putreg32(claim, BL808_PLIC_CLAIM); + + /* Colorize the interrupt stack for debug purposes */ + +#if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 15 + size_t intstack_size = (CONFIG_ARCH_INTERRUPTSTACK & ~15); + riscv_stack_color(g_intstackalloc, intstack_size); +#endif + + /* Set priority for all global interrupts to 1 (lowest) */ + + int id; + + for (id = 1; id <= NR_IRQS; id++) + { + putreg32(1, (uintptr_t)(BL808_PLIC_PRIORITY + 4 * id)); + } + + /* Set irq threshold to 0 (permits all global interrupts) */ + + putreg32(0, BL808_PLIC_THRESHOLD); + +#ifdef CONFIG_SMP + /* Clear RISCV_IPI for CPU0 */ + + putreg32(0, RISCV_IPI); + + up_enable_irq(RISCV_IRQ_SOFT); +#endif + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + + /* And finally, enable interrupts */ + + up_irq_enable(); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + int extirq; + + if (irq == RISCV_IRQ_SOFT) + { + /* Read sstatus & clear software interrupt enable in sie */ + + CLEAR_CSR(CSR_IE, IE_SIE); + } + else if (irq == RISCV_IRQ_TIMER) + { + /* Read sstatus & clear timer interrupt enable in sie */ + + CLEAR_CSR(CSR_IE, IE_TIE); + } + else if (irq > RISCV_IRQ_EXT) + { + extirq = irq - RISCV_IRQ_EXT; + + /* Clear enable bit for the irq */ + + if (0 <= extirq && extirq <= 63) + { + modifyreg32(BL808_PLIC_ENABLE1 + (4 * (extirq / 32)), + 1 << (extirq % 32), 0); + } + else + { + PANIC(); + } + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + int extirq; + + if (irq == RISCV_IRQ_SOFT) + { + /* Read sstatus & set software interrupt enable in sie */ + + SET_CSR(CSR_IE, IE_SIE); + } + else if (irq == RISCV_IRQ_TIMER) + { + /* Read sstatus & set timer interrupt enable in sie */ + + SET_CSR(CSR_IE, IE_TIE); + } + else if (irq > RISCV_IRQ_EXT) + { + extirq = irq - RISCV_IRQ_EXT; + + /* Set enable bit for the irq */ + + if (0 <= extirq && extirq <= 63) + { + modifyreg32(BL808_PLIC_ENABLE1 + (4 * (extirq / 32)), + 0, 1 << (extirq % 32)); + } + else + { + PANIC(); + } + } +} + +irqstate_t up_irq_enable(void) +{ + irqstate_t oldstat; + + /* Enable external interrupts (sie) */ + + SET_CSR(CSR_IE, IE_EIE); + + /* Read and enable global interrupts (sie) in sstatus */ + + oldstat = READ_AND_SET_CSR(CSR_STATUS, STATUS_IE); + + return oldstat; +} diff --git a/arch/risc-v/src/bl808/bl808_irq_dispatch.c b/arch/risc-v/src/bl808/bl808_irq_dispatch.c new file mode 100644 index 00000000000..298b947b35d --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_irq_dispatch.c @@ -0,0 +1,84 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_irq_dispatch.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "riscv_internal.h" +#include "hardware/bl808_memorymap.h" +#include "hardware/bl808_plic.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define RV_IRQ_MASK 59 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * riscv_dispatch_irq + ****************************************************************************/ + +void *riscv_dispatch_irq(uintptr_t vector, uintptr_t *regs) +{ + int irq = (vector >> RV_IRQ_MASK) | (vector & 0xf); + + /* Firstly, check if the irq is machine external interrupt */ + + if (RISCV_IRQ_EXT == irq) + { + uintptr_t val = getreg32(BL808_PLIC_CLAIM); + + /* Add the value to nuttx irq which is offset to the mext */ + + irq += val; + } + + /* EXT means no interrupt */ + + if (RISCV_IRQ_EXT != irq) + { + /* Deliver the IRQ */ + + regs = riscv_doirq(irq, regs); + } + + if (RISCV_IRQ_EXT <= irq) + { + /* Then write PLIC_CLAIM to clear pending in PLIC */ + + putreg32(irq - RISCV_IRQ_EXT, BL808_PLIC_CLAIM); + } + + return regs; +} diff --git a/arch/risc-v/src/bl808/bl808_memorymap.h b/arch/risc-v/src/bl808/bl808_memorymap.h new file mode 100644 index 00000000000..7dff2e7795c --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_memorymap.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_memorymap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_BL808_BL808_MEMORYMAP_H +#define __ARCH_RISCV_SRC_BL808_BL808_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "riscv_common_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Idle thread stack starts from _ebss */ + +#ifndef __ASSEMBLY__ +#define BL808_IDLESTACK_BASE (uintptr_t)_ebss +#else +#define BL808_IDLESTACK_BASE _ebss +#endif + +#define BL808_IDLESTACK_SIZE (CONFIG_IDLETHREAD_STACKSIZE & ~3) +#define BL808_IDLESTACK_TOP (BL808_IDLESTACK_BASE + BL808_IDLESTACK_SIZE) + +#endif /* __ARCH_RISCV_SRC_BL808_BL808_MEMORYMAP_H */ diff --git a/arch/risc-v/src/bl808/bl808_mm_init.c b/arch/risc-v/src/bl808/bl808_mm_init.c new file mode 100644 index 00000000000..2a0ee3d29b2 --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_mm_init.c @@ -0,0 +1,298 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_mm_init.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include + +#include "bl808_memorymap.h" + +#include "riscv_internal.h" +#include "riscv_mmu.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* T-Head C906 MMU requires Strong Order and Shareable for I/O Memory */ + +#define MMU_THEAD_SHAREABLE (1ul << 60) +#define MMU_THEAD_STRONG_ORDER (1ul << 63) +#define MMU_THEAD_IO_FLAGS (MMU_IO_FLAGS | MMU_THEAD_SHAREABLE | \ + MMU_THEAD_STRONG_ORDER) + +/* Map the I/O and PLIC Memory with vaddr = paddr mappings */ + +#define MMU_IO_BASE (0x00000000ul) +#define MMU_IO_SIZE (0x40000000ul) + +#define MMU_INT_BASE (0xe0000000ul) +#define MMU_INT_SIZE (0x10000000ul) + +/* Physical and virtual addresses to page tables (vaddr = paddr mapping) */ + +#define PGT_L1_PBASE (uintptr_t)&m_l1_pgtable +#define PGT_L2_PBASE (uintptr_t)&m_l2_pgtable +#define PGT_L2_INT_PBASE (uintptr_t)&m_l2_int_pgtable +#define PGT_L3_PBASE (uintptr_t)&m_l3_pgtable +#define PGT_L1_VBASE PGT_L1_PBASE +#define PGT_L2_VBASE PGT_L2_PBASE +#define PGT_L2_INT_VBASE PGT_L2_INT_PBASE +#define PGT_L3_VBASE PGT_L3_PBASE + +#define PGT_L1_SIZE (512) /* Enough to map 512 GiB */ +#define PGT_L2_SIZE (512) /* Enough to map 1 GiB */ +#define PGT_L2_INT_SIZE (512) /* Enough to map 1 GiB */ +#define PGT_L3_SIZE (1024) /* Enough to map 4 MiB (2MiB x 2) */ + +#define SLAB_COUNT (sizeof(m_l3_pgtable) / RV_MMU_PAGE_SIZE) + +#define KMM_PAGE_SIZE RV_MMU_L3_PAGE_SIZE +#define KMM_PBASE PGT_L3_PBASE +#define KMM_PBASE_IDX 3 +#define KMM_SPBASE PGT_L2_PBASE +#define KMM_SPBASE_IDX 2 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct pgalloc_slab_s +{ + sq_entry_t *next; + void *memory; +}; +typedef struct pgalloc_slab_s pgalloc_slab_t; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Kernel mappings simply here, mapping is vaddr=paddr */ + +static size_t m_l1_pgtable[PGT_L1_SIZE] locate_data(".pgtables"); +static size_t m_l2_pgtable[PGT_L2_SIZE] locate_data(".pgtables"); +static size_t m_l2_int_pgtable[PGT_L2_INT_SIZE] locate_data(".pgtables"); +static size_t m_l3_pgtable[PGT_L3_SIZE] locate_data(".pgtables"); + +/* Kernel mappings (L1 base) */ + +uintptr_t g_kernel_mappings = PGT_L1_VBASE; +uintptr_t g_kernel_pgt_pbase = PGT_L1_PBASE; + +/* L3 page table allocator */ + +static sq_queue_t g_free_slabs; +static pgalloc_slab_t g_slabs[SLAB_COUNT]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: slab_init + * + * Description: + * Initialize slab allocator for L2 or L3 page table entries. + * L2 Page table is used for SV32. L3 is used for SV39. + * + * Input Parameters: + * start - Beginning of the L2 or L3 page table pool + * + ****************************************************************************/ + +static void slab_init(uintptr_t start) +{ + int i; + + sq_init(&g_free_slabs); + + for (i = 0; i < SLAB_COUNT; i++) + { + g_slabs[i].memory = (void *)start; + sq_addlast((sq_entry_t *)&g_slabs[i], (sq_queue_t *)&g_free_slabs); + start += RV_MMU_PAGE_SIZE; + } +} + +/**************************************************************************** + * Name: slab_alloc + * + * Description: + * Allocate single slab for L2/L3 page table entry. + * L2 Page table is used for SV32. L3 is used for SV39. + * + ****************************************************************************/ + +static uintptr_t slab_alloc(void) +{ + pgalloc_slab_t *slab = (pgalloc_slab_t *)sq_remfirst(&g_free_slabs); + return slab ? (uintptr_t)slab->memory : 0; +} + +/**************************************************************************** + * Name: map_region + * + * Description: + * Map a region of physical memory to the L3 page table + * + * Input Parameters: + * paddr - Beginning of the physical address mapping + * vaddr - Beginning of the virtual address mapping + * size - Size of the region in bytes + * mmuflags - The MMU flags to use in the mapping + * + ****************************************************************************/ + +static void map_region(uintptr_t paddr, uintptr_t vaddr, size_t size, + uint32_t mmuflags) +{ + uintptr_t endaddr; + uintptr_t pbase; + int npages; + int i; + int j; + + /* How many pages */ + + npages = (size + RV_MMU_PAGE_MASK) >> RV_MMU_PAGE_SHIFT; + endaddr = vaddr + size; + + for (i = 0; i < npages; i += RV_MMU_PAGE_ENTRIES) + { + /* See if a mapping exists */ + + pbase = mmu_pte_to_paddr(mmu_ln_getentry(KMM_SPBASE_IDX, + KMM_SPBASE, vaddr)); + if (!pbase) + { + /* No, allocate 1 page, this must not fail */ + + pbase = slab_alloc(); + DEBUGASSERT(pbase); + + /* Map it to the new table */ + + mmu_ln_setentry(KMM_SPBASE_IDX, KMM_SPBASE, pbase, vaddr, + MMU_UPGT_FLAGS); + } + + /* Then add the mappings */ + + for (j = 0; j < RV_MMU_PAGE_ENTRIES && vaddr < endaddr; j++) + { + mmu_ln_setentry(KMM_PBASE_IDX, pbase, paddr, vaddr, mmuflags); + paddr += KMM_PAGE_SIZE; + vaddr += KMM_PAGE_SIZE; + } + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bl808_kernel_mappings + * + * Description: + * Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up the kernel + * MMU mappings. + * + ****************************************************************************/ + +void bl808_kernel_mappings(void) +{ + /* Initialize slab allocator for the L2/L3 page tables */ + + slab_init(KMM_PBASE); + + /* Begin mapping memory to MMU; note that at this point the MMU is not yet + * active, so the page table virtual addresses are actually physical + * addresses and so forth. M-mode does not perform translations anyhow, so + * this mapping is quite simple to do + */ + + /* Map I/O region, use enough large page tables for the IO region. */ + + binfo("map I/O regions\n"); + mmu_ln_map_region(1, PGT_L1_VBASE, MMU_IO_BASE, MMU_IO_BASE, + MMU_IO_SIZE, MMU_THEAD_IO_FLAGS); + + /* Map the PLIC with L2 page table */ + + binfo("map PLIC with L2 page table\n"); + mmu_ln_map_region(2, PGT_L2_INT_PBASE, MMU_INT_BASE, MMU_INT_BASE, + MMU_INT_SIZE, MMU_THEAD_IO_FLAGS); + + /* Connect the L1 and PLIC L2 page tables */ + + binfo("connect the L1 and PLIC L2 page tables\n"); + mmu_ln_setentry(1, PGT_L1_VBASE, PGT_L2_INT_PBASE, MMU_INT_BASE, PTE_G); + + /* Map the kernel text and data for L2/L3 */ + + binfo("map kernel text\n"); + map_region(KFLASH_START, KFLASH_START, KFLASH_SIZE, MMU_KTEXT_FLAGS); + + binfo("map kernel data\n"); + map_region(KSRAM_START, KSRAM_START, KSRAM_SIZE, MMU_KDATA_FLAGS); + + /* Connect the L1 and L2 page tables for the kernel text and data */ + + binfo("connect the L1 and L2 page tables\n"); + mmu_ln_setentry(1, PGT_L1_VBASE, PGT_L2_PBASE, KFLASH_START, PTE_G); + + /* Map the page pool */ + + binfo("map the page pool\n"); + mmu_ln_map_region(2, PGT_L2_VBASE, PGPOOL_START, PGPOOL_START, PGPOOL_SIZE, + MMU_KDATA_FLAGS); +} + +/**************************************************************************** + * Name: bl808_mm_init + * + * Description: + * Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up kernel MMU + * mappings. Function also sets the first address environment (satp value). + * + ****************************************************************************/ + +void bl808_mm_init(void) +{ + /* Setup the kernel mappings */ + + bl808_kernel_mappings(); + + /* Enable MMU (note: system is still in M-mode) */ + + binfo("mmu_enable: satp=%" PRIuPTR "\n", g_kernel_pgt_pbase); + mmu_enable(g_kernel_pgt_pbase, 0); +} diff --git a/arch/risc-v/src/bl808/bl808_mm_init.h b/arch/risc-v/src/bl808/bl808_mm_init.h new file mode 100644 index 00000000000..aac25fb5e3d --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_mm_init.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_mm_init.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISC_V_SRC_BL808_BL808_MM_INIT_H +#define __ARCH_RISC_V_SRC_BL808_BL808_MM_INIT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "riscv_mmu.h" + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: bl808_kernel_mappings + * + * Description: + * Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up the kernel + * MMU mappings. + * + ****************************************************************************/ + +void bl808_kernel_mappings(void); + +/**************************************************************************** + * Name: bl808_mm_init + * + * Description: + * Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up kernel MMU + * mappings. Function also sets the first address environment (satp value). + * + ****************************************************************************/ + +void bl808_mm_init(void); + +#endif /* __ARCH_RISC_V_SRC_BL808_BL808_MM_INIT_H */ diff --git a/arch/risc-v/src/bl808/bl808_pgalloc.c b/arch/risc-v/src/bl808/bl808_pgalloc.c new file mode 100644 index 00000000000..30a571ce823 --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_pgalloc.c @@ -0,0 +1,53 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_pgalloc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_pgheap + * + * Description: + * If there is a page allocator in the configuration, then this function + * must be provided by the platform-specific code. The OS initialization + * logic will call this function early in the initialization sequence to + * get the page heap information needed to configure the page allocator. + * + ****************************************************************************/ + +void up_allocate_pgheap(void **heap_start, size_t *heap_size) +{ + DEBUGASSERT(heap_start && heap_size); + + *heap_start = (void *)PGPOOL_START; + *heap_size = (size_t)PGPOOL_SIZE; +} diff --git a/arch/risc-v/src/bl808/bl808_serial.c b/arch/risc-v/src/bl808/bl808_serial.c new file mode 100644 index 00000000000..6fc541fc70d --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_serial.c @@ -0,0 +1,788 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_serial.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "hardware/bl808_uart.h" +#include "riscv_internal.h" +#include "chip.h" +#include "bl808_serial.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CONSOLE_DEV g_uart3port /* UART3 is console */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct uart_config_s +{ + uint8_t idx; /* Uart idx */ + uint32_t baud; /* Configured baud */ + uint8_t iflow_ctl; /* Input flow control supported */ + uint8_t oflow_ctl; /* Output flow control supported. */ + uint8_t data_bits; /* Number of bits per word */ + bool stop_bits; /* true=2 stop bits; false=1 stop bit */ + uint8_t parity; /* Parity selection: 0=none, 1=odd, 2=even */ +}; + +struct bl808_uart_s +{ + uint8_t irq; /* IRQ associated with this UART */ + struct uart_config_s config; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Serial driver methods */ + +static int bl808_setup(struct uart_dev_s *dev); +static void bl808_shutdown(struct uart_dev_s *dev); +static int bl808_attach(struct uart_dev_s *dev); +static void bl808_detach(struct uart_dev_s *dev); +static int bl808_ioctl(struct file *filep, int cmd, unsigned long arg); +static int bl808_receive(struct uart_dev_s *dev, unsigned int *status); +static void bl808_rxint(struct uart_dev_s *dev, bool enable); +static bool bl808_rxavailable(struct uart_dev_s *dev); +static void bl808_send(struct uart_dev_s *dev, int ch); +static void bl808_txint(struct uart_dev_s *dev, bool enable); +static bool bl808_txready(struct uart_dev_s *dev); +static bool bl808_txempty(struct uart_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uart_ops_s g_uart_ops = +{ + .setup = bl808_setup, + .shutdown = bl808_shutdown, + .attach = bl808_attach, + .detach = bl808_detach, + .ioctl = bl808_ioctl, + .receive = bl808_receive, + .rxint = bl808_rxint, + .rxavailable = bl808_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = bl808_send, + .txint = bl808_txint, + .txready = bl808_txready, + .txempty = bl808_txempty, +}; + +/* I/O buffers */ + +static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE]; +static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE]; + +static struct bl808_uart_s g_uart3priv = +{ + .irq = BL808_IRQ_UART3, + .config = + { + .idx = 3, + .baud = CONFIG_UART3_BAUD, + .parity = CONFIG_UART3_PARITY, + .data_bits = CONFIG_UART3_BITS, + .stop_bits = CONFIG_UART3_2STOP, + +#ifdef CONFIG_UART3_IFLOWCONTROL + .iflow_ctl = CONFIG_UART3_IFLOWCONTROL, +#else + .iflow_ctl = 0, +#endif + +#ifdef CONFIG_UART3_OFLOWCONTROL + .oflow_ctl = CONFIG_UART3_OFLOWCONTROL, +#else + .oflow_ctl = 0, +#endif + }, +}; + +static uart_dev_t g_uart3port = +{ + .isconsole = 1, + .recv = + { + .size = CONFIG_UART3_RXBUFSIZE, + .buffer = g_uart3rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART3_TXBUFSIZE, + .buffer = g_uart3txbuffer, + }, + .ops = &g_uart_ops, + .priv = (void *)&g_uart3priv, +}; + +static struct uart_dev_s *const g_uart_devs[] = +{ + [0] = &g_uart3port, +}; + +/**************************************************************************** + * Name: uart_interrupt + * + * Description: + * This is the UART interrupt handler. It will be invoked when an + * interrupt is received on the 'irq'. It should call uart_xmitchars or + * uart_recvchars to perform the appropriate data transfers. The + * interrupt handling logic must be able to map the 'arg' to the + * appropriate uart_dev_s structure in order to call these functions. + * + ****************************************************************************/ + +static int __uart_interrupt(int irq, void *context, void *arg) +{ + uart_dev_t *dev = (uart_dev_t *)arg; + struct bl808_uart_s *priv = dev->priv; + uint8_t uart_idx = priv->config.idx; + uint32_t int_status; + uint32_t int_mask; + + int_status = getreg32(BL808_UART_INT_STS(uart_idx)); + int_mask = getreg32(BL808_UART_INT_MASK(uart_idx)); + + /* Length of uart rx data transfer arrived interrupt */ + + if ((int_status & UART_INT_STS_URX_END_INT) && + !(int_mask & UART_INT_MASK_CR_URX_END_MASK)) + { + putreg32(UART_INT_CLEAR_CR_URX_END_CLR, + BL808_UART_INT_CLEAR(uart_idx)); + + /* Receive Data ready */ + + uart_recvchars(dev); + } + + /* Tx fifo ready interrupt,auto-cleared when data is pushed */ + + if ((int_status & UART_INT_STS_UTX_FIFO_INT) && + !(int_mask & UART_INT_MASK_CR_UTX_FIFO_MASK)) + { + /* Transmit data request interrupt */ + + uart_xmitchars(dev); + } + + /* Rx fifo ready interrupt,auto-cleared when data is popped */ + + if ((int_status & UART_INT_STS_URX_FIFO_INT) && + !(int_mask & UART_INT_MASK_CR_URX_FIFO_MASK)) + { + /* Receive Data ready */ + + uart_recvchars(dev); + } + + return OK; +} + +/**************************************************************************** + * Name: bl808_uart_configure + * + * Description: + * Configure the UART baud, bits, parity, etc. + * + ****************************************************************************/ + +static void bl808_uart_configure(const struct uart_config_s *config) +{ + /* Assume that U-Boot Bootloader has already configured the UART */ +} + +/**************************************************************************** + * Name: bl808_setup + * + * Description: + * Configure the UART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int bl808_setup(struct uart_dev_s *dev) +{ + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + + bl808_uart_configure(&priv->config); + return OK; +} + +/**************************************************************************** + * Name: bl808_shutdown + * + * Description: + * Disable the UART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void bl808_shutdown(struct uart_dev_s *dev) +{ + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + uint8_t uart_idx = priv->config.idx; + + /* Disable uart before config */ + + modifyreg32(BL808_UART_UTX_CONFIG(uart_idx), UART_UTX_CONFIG_CR_EN, 0); + modifyreg32(BL808_UART_URX_CONFIG(uart_idx), UART_URX_CONFIG_CR_EN, 0); +} + +/**************************************************************************** + * Name: bl808_attach + * + * Description: + * Configure the UART to operation in interrupt driven mode. This method + * is called when the serial port is opened. Normally, this is just after + * the the setup() method is called, however, the serial console may + * operate in a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled by the attach method (unless the + * hardware supports multiple levels of interrupt enabling). The RX and TX + * interrupts are not enabled until the txint() and rxint() are called. + * + ****************************************************************************/ + +static int bl808_attach(struct uart_dev_s *dev) +{ + int ret; + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + + ret = irq_attach(priv->irq, __uart_interrupt, (void *)dev); + if (ret == OK) + { + up_enable_irq(priv->irq); + } + + return ret; +} + +/**************************************************************************** + * Name: bl808_detach + * + * Description: + * Detach UART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The + * exception is the serial console which is never shutdown. + * + ****************************************************************************/ + +static void bl808_detach(struct uart_dev_s *dev) +{ + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + + /* Disable interrupts */ + + up_disable_irq(priv->irq); + + /* Detach from the interrupt */ + + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: bl808_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int bl808_ioctl(struct file *filep, int cmd, unsigned long arg) +{ +#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) + struct inode * inode = filep->f_inode; + struct uart_dev_s *dev = inode->i_private; +#endif + int ret = OK; + + switch (cmd) + { +#ifdef CONFIG_SERIAL_TERMIOS + case TCGETS: + do + { + struct termios * termiosp = (struct termios *)arg; + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + termiosp->c_cflag = 0; + + /* Return parity */ + + termiosp->c_cflag = ((priv->config.parity != 0) ? PARENB : 0) | + ((priv->config.parity == 1) ? PARODD : 0); + + /* Return stop bits */ + + termiosp->c_cflag |= (priv->config.stop_bits) ? CSTOPB : 0; + + /* Return flow control */ + + termiosp->c_cflag |= (priv->config.iflow_ctl) ? CRTS_IFLOW : 0; + termiosp->c_cflag |= (priv->config.oflow_ctl) ? CCTS_OFLOW : 0; + + /* Return baud */ + + cfsetispeed(termiosp, priv->config.baud); + + /* Return number of bits */ + + switch (priv->config.data_bits) + { + case 5: + termiosp->c_cflag |= CS5; + break; + + case 6: + termiosp->c_cflag |= CS6; + break; + + case 7: + termiosp->c_cflag |= CS7; + break; + + default: + case 8: + termiosp->c_cflag |= CS8; + break; + } + } + while (0); + break; + + case TCSETS: + do + { + struct termios * termiosp = (struct termios *)arg; + struct bl808_uart_s * priv = (struct bl808_uart_s *)dev->priv; + struct uart_config_s config; + uint32_t tmp_val; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Decode baud. */ + + ret = OK; + config.baud = cfgetispeed(termiosp); + + /* Decode number of bits */ + + switch (termiosp->c_cflag & CSIZE) + { + case CS5: + config.data_bits = 5; + break; + + case CS6: + config.data_bits = 6; + break; + + case CS7: + config.data_bits = 7; + break; + + case CS8: + config.data_bits = 8; + break; + + default: + ret = -EINVAL; + break; + } + + /* Decode parity */ + + if ((termiosp->c_cflag & PARENB) != 0) + { + config.parity = (termiosp->c_cflag & PARODD) ? 1 : 2; + } + else + { + config.parity = 0; + } + + /* Decode stop bits */ + + config.stop_bits = (termiosp->c_cflag & CSTOPB) != 0; + + /* Decode flow control */ + + if (priv->config.idx == 3) + { +#ifdef CONFIG_UART3_IFLOWCONTROL + config.iflow_ctl = (termiosp->c_cflag & CRTS_IFLOW) != 0; +#endif +#ifdef CONFIG_UART3_OFLOWCONTROL + config.oflow_ctl = (termiosp->c_cflag & CCTS_OFLOW) != 0; +#endif + } + + /* Verify that all settings are valid before committing */ + + if (ret == OK) + { + /* Commit */ + + memcpy(&priv->config, &config, sizeof(config)); + + /* effect the changes immediately - note that we do not + * implement TCSADRAIN / TCSAFLUSH + */ + + tmp_val = getreg32(BL808_UART_INT_MASK(config.idx)); + bl808_uart_configure(&config); + putreg32(tmp_val, BL808_UART_INT_MASK(config.idx)); + } + } + while (0); + break; +#endif /* CONFIG_SERIAL_TERMIOS */ + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: bl808_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the UART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +static int bl808_receive(struct uart_dev_s *dev, unsigned int *status) +{ + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + uint8_t uart_idx = priv->config.idx; + int rxdata; + + /* Return status information */ + + if (status) + { + *status = 0; /* We are not yet tracking serial errors */ + } + + /* if uart fifo cnts > 0 */ + + if (getreg32(BL808_UART_FIFO_CONFIG_1(uart_idx)) & + UART_FIFO_CONFIG_1_RX_CNT_MASK) + { + rxdata = getreg32(BL808_UART_FIFO_RDATA(uart_idx)) & + UART_FIFO_RDATA_MASK; + } + else + { + rxdata = -1; + } + return rxdata; +} + +/**************************************************************************** + * Name: bl808_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void bl808_rxint(struct uart_dev_s *dev, bool enable) +{ + uint32_t int_mask; + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + uint8_t uart_idx = priv->config.idx; + irqstate_t flags = enter_critical_section(); + + if (enable) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + int_mask = getreg32(BL808_UART_INT_MASK(uart_idx)); + int_mask &= ~(UART_INT_MASK_CR_URX_FIFO_MASK); + int_mask &= ~(UART_INT_MASK_CR_URX_END_MASK); + putreg32(int_mask, BL808_UART_INT_MASK(uart_idx)); +#endif + } + else + { + int_mask = getreg32(BL808_UART_INT_MASK(uart_idx)); + int_mask |= UART_INT_MASK_CR_URX_FIFO_MASK; + int_mask |= UART_INT_MASK_CR_URX_END_MASK; + putreg32(int_mask, BL808_UART_INT_MASK(uart_idx)); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: bl808_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +static bool bl808_rxavailable(struct uart_dev_s *dev) +{ + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + uint8_t uart_idx = priv->config.idx; + + /* Return true is data is available in the receive data buffer */ + + return (getreg32(BL808_UART_FIFO_CONFIG_1(uart_idx)) & + UART_FIFO_CONFIG_1_RX_CNT_MASK) != 0; +} + +/**************************************************************************** + * Name: bl808_send + * + * Description: + * This method will send one byte on the UART. + * + ****************************************************************************/ + +static void bl808_send(struct uart_dev_s *dev, int ch) +{ + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + uint8_t uart_idx = priv->config.idx; + + /* Wait for FIFO to be empty */ + + while ((getreg32(BL808_UART_FIFO_CONFIG_1(uart_idx)) & + UART_FIFO_CONFIG_1_TX_CNT_MASK) == 0); + + putreg32(ch, BL808_UART_FIFO_WDATA(uart_idx)); +} + +/**************************************************************************** + * Name: bl808_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void bl808_txint(struct uart_dev_s *dev, bool enable) +{ + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + uint8_t uart_idx = priv->config.idx; + irqstate_t flags; + uint32_t int_mask; + + flags = enter_critical_section(); + + if (enable) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + /* Enable the TX interrupt */ + + int_mask = getreg32(BL808_UART_INT_MASK(uart_idx)); + int_mask &= ~(UART_INT_MASK_CR_UTX_FIFO_MASK); + putreg32(int_mask, BL808_UART_INT_MASK(uart_idx)); + + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + + uart_xmitchars(dev); +#endif + } + else + { + /* Disable the TX interrupt */ + + int_mask = getreg32(BL808_UART_INT_MASK(uart_idx)); + int_mask |= UART_INT_MASK_CR_UTX_FIFO_MASK; + putreg32(int_mask, BL808_UART_INT_MASK(uart_idx)); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: bl808_txready + * + * Description: + * Return true if the transmit data register is not full + * + ****************************************************************************/ + +static bool bl808_txready(struct uart_dev_s *dev) +{ + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + uint8_t uart_idx = priv->config.idx; + + /* Return TRUE if the TX FIFO is not full */ + + return (getreg32(BL808_UART_FIFO_CONFIG_1(uart_idx)) & + UART_FIFO_CONFIG_1_TX_CNT_MASK) != 0; +} + +/**************************************************************************** + * Name: bl808_txempty + * + * Description: + * Return true if the transmit data register is empty + * + ****************************************************************************/ + +static bool bl808_txempty(struct uart_dev_s *dev) +{ + struct bl808_uart_s *priv = (struct bl808_uart_s *)dev->priv; + uint8_t uart_idx = priv->config.idx; + + return (getreg32(BL808_UART_FIFO_CONFIG_1(uart_idx)) & + UART_FIFO_CONFIG_1_TX_CNT_MASK) == 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bl808_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before riscv_serialinit. NOTE: This function depends on GPIO pin + * configuration performed in up_consoleinit() and main clock + * initialization performed in up_clkinitialize(). + * + ****************************************************************************/ + +void bl808_earlyserialinit(void) +{ + /* Configuration whichever one is the console */ + + CONSOLE_DEV.isconsole = true; + bl808_setup(&CONSOLE_DEV); +} + +/**************************************************************************** + * Name: bl808_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that riscv_earlyserialinit was called previously. + * + ****************************************************************************/ + +void bl808_serialinit(void) +{ + int i; + char devname[16]; + + /* Register the console */ + + uart_register("/dev/console", &CONSOLE_DEV); + + /* Register all UARTs */ + + strlcpy(devname, "/dev/ttySx", sizeof(devname)); + for (i = 0; i < sizeof(g_uart_devs) / sizeof(g_uart_devs[0]); i++) + { + if (g_uart_devs[i] == 0) + { + continue; + } + + /* Don't create a device for the console - we did that above */ + + if (g_uart_devs[i]->isconsole) + { + continue; + } + + /* Register USARTs as devices in increasing order */ + + devname[9] = '0' + i; + uart_register(devname, g_uart_devs[i]); + } +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ + struct uart_dev_s *priv = CONSOLE_DEV.priv; + irqstate_t flags = enter_critical_section(); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + bl808_send(priv, '\r'); + } + + bl808_send(priv, ch); + leave_critical_section(flags); + return ch; +} diff --git a/arch/risc-v/src/bl808/bl808_serial.h b/arch/risc-v/src/bl808/bl808_serial.h new file mode 100644 index 00000000000..361d94c09a2 --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_serial.h @@ -0,0 +1,53 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_serial.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISC_V_SRC_BL808_BL808_SERIAL_H +#define __ARCH_RISC_V_SRC_BL808_BL808_SERIAL_H + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: bl808_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before riscv_serialinit. NOTE: This function depends on GPIO pin + * configuration performed in up_consoleinit() and main clock + * initialization performed in up_clkinitialize(). + * + ****************************************************************************/ + +void bl808_earlyserialinit(void); + +/**************************************************************************** + * Name: bl808_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that riscv_earlyserialinit was called previously. + * + ****************************************************************************/ + +void bl808_serialinit(void); + +#endif /* __ARCH_RISC_V_SRC_BL808_BL808_SERIAL_H */ diff --git a/arch/risc-v/src/bl808/bl808_start.c b/arch/risc-v/src/bl808/bl808_start.c new file mode 100644 index 00000000000..62fedf2acb5 --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_start.c @@ -0,0 +1,327 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_start.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include + +#include +#include + +#include "riscv_internal.h" +#include "chip.h" +#include "bl808_mm_init.h" +#include "bl808_memorymap.h" +#include "bl808_serial.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +#define showprogress(c) up_putc(c) +#else +#define showprogress(c) +#endif + +/**************************************************************************** + * Extern Function Declarations + ****************************************************************************/ + +extern void __trap_vec(void); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* NOTE: g_idle_topstack needs to point the top of the idle stack + * for CPU0 and this value is used in up_initial_state() + */ + +uintptr_t g_idle_topstack = BL808_IDLESTACK_TOP; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bl808_copy_overlap + * + * Description: + * Copy an overlapping memory region. dest overlaps with src + count. + * + * Input Parameters: + * dest - Destination address + * src - Source address + * count - Number of bytes to copy + * + ****************************************************************************/ + +static void bl808_copy_overlap(uint8_t *dest, const uint8_t *src, + size_t count) +{ + uint8_t *d = dest + count - 1; + const uint8_t *s = src + count - 1; + + if (dest <= src) + { + _err("dest and src should overlap"); + PANIC(); + } + + while (count--) + { + volatile uint8_t c = *s; /* Prevent compiler optimization */ + *d = c; + d--; + s--; + } +} + +/**************************************************************************** + * Name: bl808_copy_ramdisk + * + * Description: + * Copy the RAM Disk from NuttX Image to RAM Disk Region. + * + ****************************************************************************/ + +static void bl808_copy_ramdisk(void) +{ + const char *header = "-rom1fs-"; + const uint8_t *limit = (uint8_t *)BL808_IDLESTACK_TOP + (256 * 1024); + uint8_t *ramdisk_addr = NULL; + uint8_t *addr; + uint32_t size; + + /* After _edata, search for "-rom1fs-". This is the RAM Disk Address. + * Limit search to 256 KB after Idle Stack Top. + */ + + binfo("_edata=%p, _sbss=%p, _ebss=%p, BL808_IDLESTACK_TOP=%p\n", + (void *)_edata, (void *)_sbss, (void *)_ebss, + (void *)BL808_IDLESTACK_TOP); + for (addr = _edata; addr < limit; addr++) + { + if (memcmp(addr, header, strlen(header)) == 0) + { + ramdisk_addr = addr; + break; + } + } + + /* Stop if RAM Disk is missing */ + + binfo("ramdisk_addr=%p\n", ramdisk_addr); + if (ramdisk_addr == NULL) + { + _err("Missing RAM Disk. Check the initrd padding."); + PANIC(); + } + + /* RAM Disk must be after Idle Stack, to prevent overwriting */ + + if (ramdisk_addr <= (uint8_t *)BL808_IDLESTACK_TOP) + { + const size_t pad = (size_t)BL808_IDLESTACK_TOP - (size_t)ramdisk_addr; + _err("RAM Disk must be after Idle Stack. Increase initrd padding " + "by %ul bytes.", pad); + PANIC(); + } + + /* Read the Filesystem Size from the next 4 bytes (Big Endian) */ + + size = (ramdisk_addr[8] << 24) + (ramdisk_addr[9] << 16) + + (ramdisk_addr[10] << 8) + ramdisk_addr[11] + 0x1f0; + binfo("size=%d\n", size); + + /* Filesystem Size must be less than RAM Disk Memory Region */ + + if (size > (size_t)__ramdisk_size) + { + _err("RAM Disk Region too small. Increase by %ul bytes.\n", + size - (size_t)__ramdisk_size); + PANIC(); + } + + /* Copy the RAM Disk from NuttX Image to RAM Disk Region. + * __ramdisk_start overlaps with ramdisk_addr + size. + */ + + bl808_copy_overlap(__ramdisk_start, ramdisk_addr, size); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bl808_clear_bss + * + * Description: + * Clear .bss. We'll do this inline (vs. calling memset) just to be + * certain that there are no issues with the state of global variables. + * + ****************************************************************************/ + +void bl808_clear_bss(void) +{ + uint32_t *dest; + + for (dest = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; ) + { + *dest++ = 0; + } +} + +/**************************************************************************** + * Name: bl808_start_s + * + * Description: + * Start the NuttX Kernel. Assume that we are in RISC-V Supervisor Mode. + * + * Input Parameters: + * mhartid - Hart ID + * + ****************************************************************************/ + +void bl808_start_s(int mhartid) +{ + /* Configure FPU */ + + riscv_fpuconfig(); + + if (mhartid > 0) + { + goto cpux; + } + + showprogress('A'); + +#ifdef USE_EARLYSERIALINIT + riscv_earlyserialinit(); +#endif + + showprogress('B'); + + /* Do board initialization */ + + showprogress('C'); + + /* Setup page tables for kernel and enable MMU */ + + bl808_mm_init(); + + /* Call nx_start() */ + + nx_start(); + +cpux: + +#ifdef CONFIG_SMP + riscv_cpu_boot(mhartid); +#endif + + while (true) + { + asm("WFI"); + } +} + +/**************************************************************************** + * Name: bl808_start + * + * Description: + * Start the NuttX Kernel. Called by Boot Code. + * + * Input Parameters: + * mhartid - Hart ID + * + ****************************************************************************/ + +void bl808_start(int mhartid) +{ + DEBUGASSERT(mhartid == 0); /* Only Hart 0 supported for now */ + + if (0 == mhartid) + { + /* Clear the BSS */ + + bl808_clear_bss(); + + /* Copy the RAM Disk */ + + bl808_copy_ramdisk(); + + /* Initialize the per CPU areas */ + + riscv_percpu_add_hart(mhartid); + } + + /* Disable MMU */ + + WRITE_CSR(satp, 0x0); + + /* Set the trap vector for S-mode */ + + WRITE_CSR(stvec, (uintptr_t)__trap_vec); + + /* Start S-mode */ + + bl808_start_s(mhartid); +} + +/**************************************************************************** + * Name: riscv_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before riscv_serialinit. NOTE: This function depends on GPIO pin + * configuration performed in up_consoleinit() and main clock + * initialization performed in up_clkinitialize(). + * + ****************************************************************************/ + +void riscv_earlyserialinit(void) +{ + bl808_earlyserialinit(); +} + +/**************************************************************************** + * Name: riscv_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that riscv_earlyserialinit was called previously. + * + ****************************************************************************/ + +void riscv_serialinit(void) +{ + bl808_serialinit(); +} diff --git a/arch/risc-v/src/bl808/bl808_timerisr.c b/arch/risc-v/src/bl808/bl808_timerisr.c new file mode 100644 index 00000000000..6b3db6eafd2 --- /dev/null +++ b/arch/risc-v/src/bl808/bl808_timerisr.c @@ -0,0 +1,106 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/bl808_timerisr.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "riscv_internal.h" +#include "riscv_mtimer.h" +#include "riscv_percpu.h" +#include "hardware/bl808_memorymap.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint32_t g_stimer_pending = false; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bl808_ssoft_interrupt + * + * Description: + * This function is S-mode software interrupt handler to proceed + * the OS timer + * + ****************************************************************************/ + +static int bl808_ssoft_interrupt(int irq, void *context, void *arg) +{ + /* Cleaer Supervisor Software Interrupt */ + + CLEAR_CSR(sip, SIP_SSIP); + + if (g_stimer_pending) + { + g_stimer_pending = false; + + /* Proceed the OS timer */ + + nxsched_process_timer(); + } +#ifdef CONFIG_SMP + else + { + /* We assume IPI has been issued */ + + riscv_pause_handler(irq, context, arg); + } +#endif + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize + * the timer interrupt. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + irq_attach(RISCV_IRQ_SSOFT, bl808_ssoft_interrupt, NULL); + up_enable_irq(RISCV_IRQ_SSOFT); +} diff --git a/arch/risc-v/src/bl808/chip.h b/arch/risc-v/src/bl808/chip.h new file mode 100644 index 00000000000..4afaaa224ea --- /dev/null +++ b/arch/risc-v/src/bl808/chip.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_BL808_CHIP_H +#define __ARCH_RISCV_SRC_BL808_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include the chip capabilities file */ + +#include + +#include "bl808_memorymap.h" + +#include "hardware/bl808_memorymap.h" +#include "hardware/bl808_plic.h" + +#include "riscv_internal.h" +#include "riscv_percpu.h" + +/**************************************************************************** + * Macro Definitions + ****************************************************************************/ + +#ifdef __ASSEMBLY__ + +/**************************************************************************** + * Name: setintstack + * + * Description: + * Set the current stack pointer to the "top" the correct interrupt stack + * for the current CPU. + * + ****************************************************************************/ + +#if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 15 +.macro setintstack tmp0, tmp1 + riscv_mhartid \tmp0 + li \tmp1, STACK_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK) + mul \tmp1, \tmp0, \tmp1 + la \tmp0, g_intstacktop + sub sp, \tmp0, \tmp1 +.endm +#endif /* CONFIG_SMP && CONFIG_ARCH_INTERRUPTSTACK > 15 */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 15 +#if !defined(CONFIG_SMP) && defined(CONFIG_ARCH_USE_S_MODE) +.macro setintstack tmp0, tmp1 + csrr \tmp0, CSR_SCRATCH + REGLOAD sp, RISCV_PERCPU_IRQSTACK(\tmp0) +.endm +#endif /* !defined(CONFIG_SMP) && defined(CONFIG_ARCH_USE_S_MODE) */ +#endif /* CONFIG_ARCH_INTERRUPTSTACK > 15 */ + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_BL808_CHIP_H */ diff --git a/arch/risc-v/src/bl808/hardware/bl808_memorymap.h b/arch/risc-v/src/bl808/hardware/bl808_memorymap.h new file mode 100644 index 00000000000..c68d224adeb --- /dev/null +++ b/arch/risc-v/src/bl808/hardware/bl808_memorymap.h @@ -0,0 +1,33 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/hardware/bl808_memorymap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_MEMORYMAP_H +#define __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_MEMORYMAP_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Base Address ****************************************************/ + +#define BL808_UART3_BASE 0x30002000ul +#define BL808_PLIC_BASE 0xe0000000ul + +#endif /* __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_MEMORYMAP_H */ diff --git a/arch/risc-v/src/bl808/hardware/bl808_plic.h b/arch/risc-v/src/bl808/hardware/bl808_plic.h new file mode 100644 index 00000000000..4493273862a --- /dev/null +++ b/arch/risc-v/src/bl808/hardware/bl808_plic.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/hardware/bl808_plic.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_PLIC_H +#define __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_PLIC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Interrupt Priority */ + +#define BL808_PLIC_PRIORITY (BL808_PLIC_BASE + 0x000000) + +/* Hart 0 S-Mode Interrupt Enable */ + +#define BL808_PLIC_ENABLE1 (BL808_PLIC_BASE + 0x002080) +#define BL808_PLIC_ENABLE2 (BL808_PLIC_BASE + 0x002084) + +/* Hart 0 S-Mode Priority Threshold */ + +#define BL808_PLIC_THRESHOLD (BL808_PLIC_BASE + 0x201000) + +/* Hart 0 S-Mode Claim / Complete */ + +#define BL808_PLIC_CLAIM (BL808_PLIC_BASE + 0x201004) + +#endif /* __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_PLIC_H */ diff --git a/arch/risc-v/src/bl808/hardware/bl808_uart.h b/arch/risc-v/src/bl808/hardware/bl808_uart.h new file mode 100644 index 00000000000..5f993a6e824 --- /dev/null +++ b/arch/risc-v/src/bl808/hardware/bl808_uart.h @@ -0,0 +1,189 @@ +/**************************************************************************** + * arch/risc-v/src/bl808/hardware/bl808_uart.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_UART_H +#define __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_UART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "bl808_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Only UART3 is supported */ + +#define BL808_UART_BASE(n) (UNUSED(n), BL808_UART3_BASE) + +/* Register offsets *********************************************************/ + +#define BL808_UART_UTX_CONFIG_OFFSET 0x000000 /* utx_config */ +#define BL808_UART_URX_CONFIG_OFFSET 0x000004 /* urx_config */ +#define BL808_UART_BIT_PRD_OFFSET 0x000008 /* uart_bit_prd */ +#define BL808_UART_DATA_CONFIG_OFFSET 0x00000c /* data_config */ +#define BL808_UART_UTX_IR_POSITION_OFFSET 0x000010 /* utx_ir_position */ +#define BL808_UART_URX_IR_POSITION_OFFSET 0x000014 /* urx_ir_position */ +#define BL808_UART_URX_RTO_TIMER_OFFSET 0x000018 /* urx_rto_timer */ +#define BL808_UART_INT_STS_OFFSET 0x000020 /* UART interrupt status */ +#define BL808_UART_INT_MASK_OFFSET 0x000024 /* UART interrupt mask */ +#define BL808_UART_INT_CLEAR_OFFSET 0x000028 /* UART interrupt clear */ +#define BL808_UART_INT_EN_OFFSET 0x00002c /* UART interrupt enable */ +#define BL808_UART_STATUS_OFFSET 0x000030 /* uart_status */ +#define BL808_UART_STS_URX_ABR_PRD_OFFSET 0x000034 /* sts_urx_abr_prd */ +#define BL808_UART_FIFO_CONFIG_0_OFFSET 0x000080 /* uart_fifo_config_0 */ +#define BL808_UART_FIFO_CONFIG_1_OFFSET 0x000084 /* uart_fifo_config_1 */ +#define BL808_UART_FIFO_WDATA_OFFSET 0x000088 /* uart_fifo_wdata */ +#define BL808_UART_FIFO_RDATA_OFFSET 0x00008c /* uart_fifo_rdata */ + +/* Register definitions *****************************************************/ + +#define BL808_UART_UTX_CONFIG(n) (BL808_UART_BASE(n) + BL808_UART_UTX_CONFIG_OFFSET) +#define BL808_UART_URX_CONFIG(n) (BL808_UART_BASE(n) + BL808_UART_URX_CONFIG_OFFSET) +#define BL808_UART_BIT_PRD(n) (BL808_UART_BASE(n) + BL808_UART_BIT_PRD_OFFSET) +#define BL808_UART_DATA_CONFIG(n) (BL808_UART_BASE(n) + BL808_UART_DATA_CONFIG_OFFSET) +#define BL808_UART_UTX_IR_POSITION(n) (BL808_UART_BASE(n) + BL808_UART_UTX_IR_POSITION_OFFSET) +#define BL808_UART_URX_IR_POSITION(n) (BL808_UART_BASE(n) + BL808_UART_URX_IR_POSITION_OFFSET) +#define BL808_UART_URX_RTO_TIMER(n) (BL808_UART_BASE(n) + BL808_UART_URX_RTO_TIMER_OFFSET) +#define BL808_UART_INT_STS(n) (BL808_UART_BASE(n) + BL808_UART_INT_STS_OFFSET) +#define BL808_UART_INT_MASK(n) (BL808_UART_BASE(n) + BL808_UART_INT_MASK_OFFSET) +#define BL808_UART_INT_CLEAR(n) (BL808_UART_BASE(n) + BL808_UART_INT_CLEAR_OFFSET) +#define BL808_UART_INT_EN(n) (BL808_UART_BASE(n) + BL808_UART_INT_EN_OFFSET) +#define BL808_UART_STATUS(n) (BL808_UART_BASE(n) + BL808_UART_STATUS_OFFSET) +#define BL808_UART_STS_URX_ABR_PRD(n) (BL808_UART_BASE(n) + BL808_UART_STS_URX_ABR_PRD_OFFSET) +#define BL808_UART_FIFO_CONFIG_0(n) (BL808_UART_BASE(n) + BL808_UART_FIFO_CONFIG_0_OFFSET) +#define BL808_UART_FIFO_CONFIG_1(n) (BL808_UART_BASE(n) + BL808_UART_FIFO_CONFIG_1_OFFSET) +#define BL808_UART_FIFO_WDATA(n) (BL808_UART_BASE(n) + BL808_UART_FIFO_WDATA_OFFSET) +#define BL808_UART_FIFO_RDATA(n) (BL808_UART_BASE(n) + BL808_UART_FIFO_RDATA_OFFSET) + +/* Register bit definitions *************************************************/ + +#define UART_UTX_CONFIG_CR_LEN_SHIFT (16) +#define UART_UTX_CONFIG_CR_LEN_MASK (0xffff << UART_UTX_CONFIG_CR_LEN_SHIFT) +#define UART_UTX_CONFIG_CR_BIT_CNT_P_SHIFT (12) +#define UART_UTX_CONFIG_CR_BIT_CNT_P_MASK (0x03 << UART_UTX_CONFIG_CR_BIT_CNT_P_SHIFT) +#define UART_UTX_CONFIG_CR_BIT_CNT_D_SHIFT (8) +#define UART_UTX_CONFIG_CR_BIT_CNT_D_MASK (0x07 << UART_UTX_CONFIG_CR_BIT_CNT_D_SHIFT) +#define UART_UTX_CONFIG_CR_IR_INV (1 << 7) +#define UART_UTX_CONFIG_CR_IR_EN (1 << 6) +#define UART_UTX_CONFIG_CR_PRT_SEL (1 << 5) +#define UART_UTX_CONFIG_CR_PRT_EN (1 << 4) +#define UART_UTX_CONFIG_CR_FRM_EN (1 << 2) +#define UART_UTX_CONFIG_CR_CTS_EN (1 << 1) +#define UART_UTX_CONFIG_CR_EN (1 << 0) + +#define UART_URX_CONFIG_CR_LEN_SHIFT (16) +#define UART_URX_CONFIG_CR_LEN_MASK (0xffff << UART_URX_CONFIG_CR_LEN_SHIFT) +#define UART_URX_CONFIG_CR_DEG_CNT_SHIFT (12) +#define UART_URX_CONFIG_CR_DEG_CNT_MASK (0x0f << UART_URX_CONFIG_CR_DEG_CNT_SHIFT) +#define UART_URX_CONFIG_CR_DEG_EN (1 << 11) +#define UART_URX_CONFIG_CR_BIT_CNT_D_SHIFT (8) +#define UART_URX_CONFIG_CR_BIT_CNT_D_MASK (0x07 << UART_URX_CONFIG_CR_BIT_CNT_D_SHIFT) +#define UART_URX_CONFIG_CR_IR_INV (1 << 7) +#define UART_URX_CONFIG_CR_IR_EN (1 << 6) +#define UART_URX_CONFIG_CR_PRT_SEL (1 << 5) +#define UART_URX_CONFIG_CR_PRT_EN (1 << 4) +#define UART_URX_CONFIG_CR_ABR_EN (1 << 3) +#define UART_URX_CONFIG_CR_RTS_SW_VAL (1 << 2) +#define UART_URX_CONFIG_CR_RTS_SW_MODE (1 << 1) +#define UART_URX_CONFIG_CR_EN (1 << 0) + +#define UART_BIT_PRD_CR_URX_BIT_SHIFT (16) +#define UART_BIT_PRD_CR_URX_BIT_MASK (0xffff << UART_BIT_PRD_CR_URX_BIT_SHIFT) +#define UART_BIT_PRD_CR_UTX_BIT_MASK (0xffff) + +#define UART_DATA_CONFIG_CR_UART_BIT_INV (1 << 0) + +#define UART_UTX_IR_POSITION_CR_IR_POS_P_SHIFT (16) +#define UART_UTX_IR_POSITION_CR_IR_POS_P_MASK (0xffff << UART_UTX_IR_POSITION_CR_IR_POS_P_SHIFT) +#define UART_UTX_IR_POSITION_CR_IR_POS_S_MASK (0xffff) + +#define UART_URX_IR_POSITION_CR_IR_POS_S_MASK (0xffff) + +#define UART_URX_RTO_TIMER_CR_RTO_VALUE_MASK (0xff) + +#define UART_INT_STS_URX_FER_INT (1 << 7) +#define UART_INT_STS_UTX_FER_INT (1 << 6) +#define UART_INT_STS_URX_PCE_INT (1 << 5) +#define UART_INT_STS_URX_RTO_INT (1 << 4) +#define UART_INT_STS_URX_FIFO_INT (1 << 3) +#define UART_INT_STS_UTX_FIFO_INT (1 << 2) +#define UART_INT_STS_URX_END_INT (1 << 1) +#define UART_INT_STS_UTX_END_INT (1 << 0) + +#define UART_INT_MASK_CR_URX_FER_MASK (1 << 7) +#define UART_INT_MASK_CR_UTX_FER_MASK (1 << 6) +#define UART_INT_MASK_CR_URX_PCE_MASK (1 << 5) +#define UART_INT_MASK_CR_URX_RTO_MASK (1 << 4) +#define UART_INT_MASK_CR_URX_FIFO_MASK (1 << 3) +#define UART_INT_MASK_CR_UTX_FIFO_MASK (1 << 2) +#define UART_INT_MASK_CR_URX_END_MASK (1 << 1) +#define UART_INT_MASK_CR_UTX_END_MASK (1 << 0) + +#define UART_INT_CLEAR_RSVD_7 (1 << 7) +#define UART_INT_CLEAR_RSVD_6 (1 << 6) +#define UART_INT_CLEAR_CR_URX_PCE_CLR (1 << 5) +#define UART_INT_CLEAR_CR_URX_RTO_CLR (1 << 4) +#define UART_INT_CLEAR_RSVD_3 (1 << 3) +#define UART_INT_CLEAR_RSVD_2 (1 << 2) +#define UART_INT_CLEAR_CR_URX_END_CLR (1 << 1) +#define UART_INT_CLEAR_CR_UTX_END_CLR (1 << 0) + +#define UART_INT_EN_CR_URX_FER_EN (1 << 7) +#define UART_INT_EN_CR_UTX_FER_EN (1 << 6) +#define UART_INT_EN_CR_URX_PCE_EN (1 << 5) +#define UART_INT_EN_CR_URX_RTO_EN (1 << 4) +#define UART_INT_EN_CR_URX_FIFO_EN (1 << 3) +#define UART_INT_EN_CR_UTX_FIFO_EN (1 << 2) +#define UART_INT_EN_CR_URX_END_EN (1 << 1) +#define UART_INT_EN_CR_UTX_END_EN (1 << 0) + +#define UART_STATUS_STS_URX_BUS_BUSY (1 << 1) +#define UART_STATUS_STS_UTX_BUS_BUSY (1 << 0) + +#define UART_STS_URX_ABR_PRD_0X55_SHIFT (16) +#define UART_STS_URX_ABR_PRD_0X55_MASK (0xffff << UART_STS_URX_ABR_PRD_0X55_SHIFT) +#define UART_STS_URX_ABR_PRD_START_MASK (0xffff) + +#define UART_FIFO_CONFIG_0_RX_UNDERFLOW (1 << 7) +#define UART_FIFO_CONFIG_0_RX_OVERFLOW (1 << 6) +#define UART_FIFO_CONFIG_0_TX_UNDERFLOW (1 << 5) +#define UART_FIFO_CONFIG_0_TX_OVERFLOW (1 << 4) +#define UART_FIFO_CONFIG_0_RX_CLR (1 << 3) +#define UART_FIFO_CONFIG_0_TX_CLR (1 << 2) +#define UART_FIFO_CONFIG_0_DMA_RX_EN (1 << 1) +#define UART_FIFO_CONFIG_0_DMA_TX_EN (1 << 0) + +#define UART_FIFO_CONFIG_1_RX_TH_SHIFT (24) +#define UART_FIFO_CONFIG_1_RX_TH_MASK (0x1f << UART_FIFO_CONFIG_1_RX_TH_SHIFT) +#define UART_FIFO_CONFIG_1_TX_TH_SHIFT (16) +#define UART_FIFO_CONFIG_1_TX_TH_MASK (0x1f << UART_FIFO_CONFIG_1_TX_TH_SHIFT) +#define UART_FIFO_CONFIG_1_RX_CNT_SHIFT (8) +#define UART_FIFO_CONFIG_1_RX_CNT_MASK (0x3f << UART_FIFO_CONFIG_1_RX_CNT_SHIFT) +#define UART_FIFO_CONFIG_1_TX_CNT_MASK (0x3f) + +#define UART_FIFO_WDATA_MASK (0xff) + +#define UART_FIFO_RDATA_MASK (0xff) + +#endif /* __ARCH_RISCV_SRC_BL808_HARDWARE_BL808_UART_H */