arch/riscv: Add support for Bouffalo Lab BL808 SoC (T-Head C906)

This PR adds support for the Bouffalo Lab BL808 SoC, based on T-Head C906 64-bit RISC-V Core. This will be used by the upcoming port of NuttX for PINE64 Ox64 SBC.

Most of the code was derived from NuttX for Star64 JH7110. The UART Driver was derived from BL602 NuttX. The source files are explained in the articles here: https://github.com/lupyuen/nuttx-ox64

`Kconfig`: Added ARCH_CHIP_BL808 for BL808 SoC

`include/bl808/chip.h`: BL808 Definitions

`include/bl808/irq.h`: External Interrupts

`src/bl808/chip.h`: Interrupt Stack Macro

`src/bl808/bl808_allocateheap.c`: Kernel Heap

`src/bl808/bl808_head.S`: Linux Header and Boot Code

`src/bl808/bl808_irq.c`: Configure Interrupts

`src/bl808/bl808_irq_dispatch.c`: Dispatch Interrupts

`src/bl808/bl808_memorymap.h`: Memory Map

`src/bl808/bl808_mm_init.c`, `bl808_mm_init.h`: Memory Mgmt

`src/bl808/bl808_pgalloc.c`: Page Allocator

`src/bl808/bl808_serial.c`, `bl808_serial.h`: UART Driver

`src/bl808/bl808_start.c`: Startup Code

`src/bl808/bl808_timerisr.c`: Timer Interrupt

`src/bl808/hardware/bl808_memorymap.h`: PLIC and UART Base Address

`src/bl808/hardware/bl808_plic.h`: PLIC Register Addresses

`src/bl808/hardware/bl808_uart.h`: UART Register Addresses

`src/bl808/Kconfig`: BL808 Config

`src/bl808/Make.defs`: Makefile
This commit is contained in:
Lee Lup Yuen 2023-12-12 09:00:08 +08:00 committed by Xiang Xiao
parent 22b6076f26
commit 614570cdcb
21 changed files with 2723 additions and 0 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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 <nuttx/config.h>
#include <nuttx/kmalloc.h>
#include <nuttx/userspace.h>
#include <nuttx/arch.h>
#include <arch/board/board_memorymap.h>
#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;
}

View file

@ -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 <nuttx/config.h>
#include <arch/arch.h>
#include <arch/irq.h>
#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

View file

@ -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 <nuttx/config.h>
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#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;
}

View file

@ -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 <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <sys/types.h>
#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;
}

View file

@ -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 */

View file

@ -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 <nuttx/config.h>
#include <nuttx/arch.h>
#include <stdint.h>
#include <assert.h>
#include <debug.h>
#include <arch/board/board_memorymap.h>
#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);
}

View file

@ -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 <nuttx/config.h>
#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 */

View file

@ -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 <nuttx/arch.h>
#include <nuttx/config.h>
#include <nuttx/pgalloc.h>
#include <assert.h>
#include <debug.h>
#include <arch/board/board_memorymap.h>
/****************************************************************************
* 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;
}

View file

@ -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 <nuttx/config.h>
#include <nuttx/arch.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/serial/serial.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/serial/tioctl.h>
#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;
}

View file

@ -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 */

View file

@ -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 <nuttx/config.h>
#include <nuttx/init.h>
#include <nuttx/arch.h>
#include <nuttx/serial/uart_16550.h>
#include <debug.h>
#include <arch/board/board.h>
#include <arch/board/board_memorymap.h>
#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();
}

View file

@ -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 <nuttx/config.h>
#include <assert.h>
#include <stdint.h>
#include <time.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/clock.h>
#include <nuttx/init.h>
#include <nuttx/spinlock.h>
#include <nuttx/timers/arch_alarm.h>
#include <arch/board/board.h>
#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);
}

View file

@ -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 <arch/bl808/chip.h>
#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 */

View file

@ -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 */

View file

@ -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 <nuttx/config.h>
/****************************************************************************
* 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 */

View file

@ -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 <nuttx/config.h>
#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 */