Updates to Freedom SoCs

This commit is contained in:
Shreesha Srinath
2017-08-18 18:21:04 -07:00
committed by Yunsup Lee
parent f4375c2266
commit ec70d85cbc
64 changed files with 1713 additions and 3449 deletions

Binary file not shown.

47
bootrom/sdboot/Makefile Normal file
View File

@ -0,0 +1,47 @@
# RISCV environment variable must be set
CC=$(RISCV)/bin/riscv64-unknown-elf-gcc
OBJCOPY=$(RISCV)/bin/riscv64-unknown-elf-objcopy
CFLAGS=-march=rv64imac -mcmodel=medany -O2 -std=gnu11 -Wall -nostartfiles
CFLAGS+= -fno-common -g -DENTROPY=0 -mabi=lp64 -DNONSMP_HART=0
CFLAGS+= -I $(BOOTROM_DIR)/include -I.
LFLAGS=-static -nostdlib -L $(BOOTROM_DIR)/linker -T sdboot.elf.lds
dtb := $(BUILD_DIR)/$(CONFIG).dtb
$(dtb): $(BUILD_DIR)/$(CONFIG).dts
dtc -I dts -O dtb -o $@ $<
.PHONY: dtb
dtb: $(dtb)
elf := $(BUILD_DIR)/sdboot.elf
$(elf): $(dtb) head.S kprintf.c sd.c
$(CC) $(CFLAGS) -DDEVICE_TREE='"$(dtb)"' $(LFLAGS) -o $@ head.S sd.c kprintf.c
.PHONY: elf
elf: $(elf)
bin := $(BUILD_DIR)/sdboot.bin
$(bin): $(elf)
$(OBJCOPY) -O binary $< $@
.PHONY: bin
bin: $(bin)
hex := $(BUILD_DIR)/sdboot.hex
$(hex): $(bin)
od -t x4 -An -w4 -v $< > $@
.PHONY: hex
hex: $(hex)
romgen := $(BUILD_DIR)/rom.v
$(romgen): $(hex)
$(rocketchip_dir)/scripts/vlsi_rom_gen $(ROMCONF) $< > $@
.PHONY: romgen
romgen: $(romgen)
.PHONY: clean
clean::
rm -rf $(hex) $(elf)

9
bootrom/sdboot/common.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _SDBOOT_COMMON_H
#define _SDBOOT_COMMON_H
#ifndef PAYLOAD_DEST
#define PAYLOAD_DEST MEMORY_MEM_ADDR
#endif
#endif

18
bootrom/sdboot/head.S Normal file
View File

@ -0,0 +1,18 @@
// See LICENSE for license details.
#include <platform.h>
#include "common.h"
.section .text.init
.option norvc
.globl _prog_start
_prog_start:
li sp, (PAYLOAD_DEST + 0x7fff000)
call main
csrr a0, mhartid
la a1, dtb
li s1, PAYLOAD_DEST
jr s1
.section .rodata
dtb:
.incbin DEVICE_TREE

View File

@ -0,0 +1,36 @@
// See LICENSE for license details.
#ifndef _RISCV_BITS_H
#define _RISCV_BITS_H
#define likely(x) __builtin_expect((x), 1)
#define unlikely(x) __builtin_expect((x), 0)
#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b))
#define ROUNDDOWN(a, b) ((a)/(b)*(b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1)))
#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
#define STR(x) XSTR(x)
#define XSTR(x) #x
#if __riscv_xlen == 64
# define SLL32 sllw
# define STORE sd
# define LOAD ld
# define LWU lwu
# define LOG_REGBYTES 3
#else
# define SLL32 sll
# define STORE sw
# define LOAD lw
# define LWU lw
# define LOG_REGBYTES 2
#endif
#define REGBYTES (1 << LOG_REGBYTES)
#endif

View File

@ -0,0 +1,18 @@
// See LICENSE for license details.
/* Derived from <linux/const.h> */
#ifndef _SIFIVE_CONST_H
#define _SIFIVE_CONST_H
#ifdef __ASSEMBLER__
#define _AC(X,Y) X
#define _AT(T,X) X
#else
#define _AC(X,Y) (X##Y)
#define _AT(T,X) ((T)(X))
#endif /* !__ASSEMBLER__*/
#define _BITUL(x) (_AC(1,UL) << (x))
#define _BITULL(x) (_AC(1,ULL) << (x))
#endif /* _SIFIVE_CONST_H */

View File

@ -0,0 +1,14 @@
// See LICENSE for license details.
#ifndef _SIFIVE_CLINT_H
#define _SIFIVE_CLINT_H
#define CLINT_MSIP 0x0000
#define CLINT_MSIP_size 0x4
#define CLINT_MTIMECMP 0x4000
#define CLINT_MTIMECMP_size 0x8
#define CLINT_MTIME 0xBFF8
#define CLINT_MTIME_size 0x8
#endif /* _SIFIVE_CLINT_H */

View File

@ -0,0 +1,24 @@
// See LICENSE for license details.
#ifndef _SIFIVE_GPIO_H
#define _SIFIVE_GPIO_H
#define GPIO_INPUT_VAL (0x00)
#define GPIO_INPUT_EN (0x04)
#define GPIO_OUTPUT_EN (0x08)
#define GPIO_OUTPUT_VAL (0x0C)
#define GPIO_PULLUP_EN (0x10)
#define GPIO_DRIVE (0x14)
#define GPIO_RISE_IE (0x18)
#define GPIO_RISE_IP (0x1C)
#define GPIO_FALL_IE (0x20)
#define GPIO_FALL_IP (0x24)
#define GPIO_HIGH_IE (0x28)
#define GPIO_HIGH_IP (0x2C)
#define GPIO_LOW_IE (0x30)
#define GPIO_LOW_IP (0x34)
#define GPIO_IOF_EN (0x38)
#define GPIO_IOF_SEL (0x3C)
#define GPIO_OUTPUT_XOR (0x40)
#endif /* _SIFIVE_GPIO_H */

View File

@ -0,0 +1,31 @@
// See LICENSE for license details.
#ifndef PLIC_H
#define PLIC_H
#include <const.h>
// 32 bits per source
#define PLIC_PRIORITY_OFFSET _AC(0x0000,UL)
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
// 1 bit per source (1 address)
#define PLIC_PENDING_OFFSET _AC(0x1000,UL)
#define PLIC_PENDING_SHIFT_PER_SOURCE 0
//0x80 per target
#define PLIC_ENABLE_OFFSET _AC(0x2000,UL)
#define PLIC_ENABLE_SHIFT_PER_TARGET 7
#define PLIC_THRESHOLD_OFFSET _AC(0x200000,UL)
#define PLIC_CLAIM_OFFSET _AC(0x200004,UL)
#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12
#define PLIC_CLAIM_SHIFT_PER_TARGET 12
#define PLIC_MAX_SOURCE 1023
#define PLIC_SOURCE_MASK 0x3FF
#define PLIC_MAX_TARGET 15871
#define PLIC_TARGET_MASK 0x3FFF
#endif /* PLIC_H */

View File

@ -0,0 +1,79 @@
// See LICENSE for license details.
#ifndef _SIFIVE_SPI_H
#define _SIFIVE_SPI_H
/* Register offsets */
#define SPI_REG_SCKDIV 0x00
#define SPI_REG_SCKMODE 0x04
#define SPI_REG_CSID 0x10
#define SPI_REG_CSDEF 0x14
#define SPI_REG_CSMODE 0x18
#define SPI_REG_DCSSCK 0x28
#define SPI_REG_DSCKCS 0x2a
#define SPI_REG_DINTERCS 0x2c
#define SPI_REG_DINTERXFR 0x2e
#define SPI_REG_FMT 0x40
#define SPI_REG_TXFIFO 0x48
#define SPI_REG_RXFIFO 0x4c
#define SPI_REG_TXCTRL 0x50
#define SPI_REG_RXCTRL 0x54
#define SPI_REG_FCTRL 0x60
#define SPI_REG_FFMT 0x64
#define SPI_REG_IE 0x70
#define SPI_REG_IP 0x74
/* Fields */
#define SPI_SCK_POL 0x1
#define SPI_SCK_PHA 0x2
#define SPI_FMT_PROTO(x) ((x) & 0x3)
#define SPI_FMT_ENDIAN(x) (((x) & 0x1) << 2)
#define SPI_FMT_DIR(x) (((x) & 0x1) << 3)
#define SPI_FMT_LEN(x) (((x) & 0xf) << 16)
/* TXCTRL register */
#define SPI_TXWM(x) ((x) & 0xffff)
/* RXCTRL register */
#define SPI_RXWM(x) ((x) & 0xffff)
#define SPI_IP_TXWM 0x1
#define SPI_IP_RXWM 0x2
#define SPI_FCTRL_EN 0x1
#define SPI_INSN_CMD_EN 0x1
#define SPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1)
#define SPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4)
#define SPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8)
#define SPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10)
#define SPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12)
#define SPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16)
#define SPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24)
#define SPI_TXFIFO_FULL (1 << 31)
#define SPI_RXFIFO_EMPTY (1 << 31)
/* Values */
#define SPI_CSMODE_AUTO 0
#define SPI_CSMODE_HOLD 2
#define SPI_CSMODE_OFF 3
#define SPI_DIR_RX 0
#define SPI_DIR_TX 1
#define SPI_PROTO_S 0
#define SPI_PROTO_D 1
#define SPI_PROTO_Q 2
#define SPI_ENDIAN_MSB 0
#define SPI_ENDIAN_LSB 1
#endif /* _SIFIVE_SPI_H */

View File

@ -0,0 +1,28 @@
// See LICENSE for license details.
#ifndef _SIFIVE_UART_H
#define _SIFIVE_UART_H
/* Register offsets */
#define UART_REG_TXFIFO 0x00
#define UART_REG_RXFIFO 0x04
#define UART_REG_TXCTRL 0x08
#define UART_REG_RXCTRL 0x0c
#define UART_REG_IE 0x10
#define UART_REG_IP 0x14
#define UART_REG_DIV 0x18
/* TXCTRL register */
#define UART_TXEN 0x1
#define UART_TXNSTOP 0x2
#define UART_TXWM(x) (((x) & 0xffff) << 16)
/* RXCTRL register */
#define UART_RXEN 0x1
#define UART_RXWM(x) (((x) & 0xffff) << 16)
/* IP register */
#define UART_IP_TXWM 0x1
#define UART_IP_RXWM 0x2
#endif /* _SIFIVE_UART_H */

View File

@ -0,0 +1,99 @@
// See LICENSE for license details.
#ifndef _SIFIVE_PLATFORM_H
#define _SIFIVE_PLATFORM_H
#include "const.h"
#include "riscv_test_defaults.h"
#include "devices/clint.h"
#include "devices/gpio.h"
#include "devices/plic.h"
#include "devices/spi.h"
#include "devices/uart.h"
// Some things missing from the official encoding.h
#if __riscv_xlen == 32
#define MCAUSE_INT 0x80000000UL
#define MCAUSE_CAUSE 0x7FFFFFFFUL
#else
#define MCAUSE_INT 0x8000000000000000UL
#define MCAUSE_CAUSE 0x7FFFFFFFFFFFFFFFUL
#endif
/****************************************************************************
* Platform definitions
*****************************************************************************/
// CPU info
#define NUM_CORES 1
#define GLOBAL_INT_SIZE 15
#define GLOBAL_INT_MAX_PRIORITY 7
// Memory map
#define AXI_PCIE_HOST_1_00_A_CTRL_ADDR _AC(0x50000000,UL)
#define AXI_PCIE_HOST_1_00_A_CTRL_SIZE _AC(0x4000000,UL)
#define CLINT_CTRL_ADDR _AC(0x2000000,UL)
#define CLINT_CTRL_SIZE _AC(0x10000,UL)
#define DEBUG_CTRL_ADDR _AC(0x0,UL)
#define DEBUG_CTRL_SIZE _AC(0x1000,UL)
#define ERROR_MEM_ADDR _AC(0x3000,UL)
#define ERROR_MEM_SIZE _AC(0x1000,UL)
#define GPIO_CTRL_ADDR _AC(0x54002000,UL)
#define GPIO_CTRL_SIZE _AC(0x1000,UL)
#define MASKROM_MEM_ADDR _AC(0x10000,UL)
#define MASKROM_MEM_SIZE _AC(0x2000,UL)
#define MEMORY_MEM_ADDR _AC(0x80000000,UL)
#define MEMORY_MEM_SIZE _AC(0x40000000,UL)
#define PLIC_CTRL_ADDR _AC(0xc000000,UL)
#define PLIC_CTRL_SIZE _AC(0x4000000,UL)
#define SPI_CTRL_ADDR _AC(0x54001000,UL)
#define SPI_CTRL_SIZE _AC(0x1000,UL)
#define TEST_CTRL_ADDR _AC(0x4000,UL)
#define TEST_CTRL_SIZE _AC(0x1000,UL)
#define UART_CTRL_ADDR _AC(0x54000000,UL)
#define UART_CTRL_SIZE _AC(0x1000,UL)
// IOF masks
// Interrupt numbers
#define UART_INT_BASE 1
#define SPI_INT_BASE 2
#define GPIO_INT_BASE 3
#define AXI_PCIE_HOST_1_00_A_INT_BASE 7
// Helper functions
#define _REG64(p, i) (*(volatile uint64_t *)((p) + (i)))
#define _REG32(p, i) (*(volatile uint32_t *)((p) + (i)))
#define _REG16(p, i) (*(volatile uint16_t *)((p) + (i)))
// Bulk set bits in `reg` to either 0 or 1.
// E.g. SET_BITS(MY_REG, 0x00000007, 0) would generate MY_REG &= ~0x7
// E.g. SET_BITS(MY_REG, 0x00000007, 1) would generate MY_REG |= 0x7
#define SET_BITS(reg, mask, value) if ((value) == 0) { (reg) &= ~(mask); } else { (reg) |= (mask); }
#define AXI_PCIE_HOST_1_00_A_REG(offset) _REG32(AXI_PCIE_HOST_1_00_A_CTRL_ADDR, offset)
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
#define DEBUG_REG(offset) _REG32(DEBUG_CTRL_ADDR, offset)
#define ERROR_REG(offset) _REG32(ERROR_CTRL_ADDR, offset)
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
#define MASKROM_REG(offset) _REG32(MASKROM_CTRL_ADDR, offset)
#define MEMORY_REG(offset) _REG32(MEMORY_CTRL_ADDR, offset)
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
#define SPI_REG(offset) _REG32(SPI_CTRL_ADDR, offset)
#define TEST_REG(offset) _REG32(TEST_CTRL_ADDR, offset)
#define UART_REG(offset) _REG32(UART_CTRL_ADDR, offset)
#define AXI_PCIE_HOST_1_00_A_REG64(offset) _REG64(AXI_PCIE_HOST_1_00_A_CTRL_ADDR, offset)
#define CLINT_REG64(offset) _REG64(CLINT_CTRL_ADDR, offset)
#define DEBUG_REG64(offset) _REG64(DEBUG_CTRL_ADDR, offset)
#define ERROR_REG64(offset) _REG64(ERROR_CTRL_ADDR, offset)
#define GPIO_REG64(offset) _REG64(GPIO_CTRL_ADDR, offset)
#define MASKROM_REG64(offset) _REG64(MASKROM_CTRL_ADDR, offset)
#define MEMORY_REG64(offset) _REG64(MEMORY_CTRL_ADDR, offset)
#define PLIC_REG64(offset) _REG64(PLIC_CTRL_ADDR, offset)
#define SPI_REG64(offset) _REG64(SPI_CTRL_ADDR, offset)
#define TEST_REG64(offset) _REG64(TEST_CTRL_ADDR, offset)
#define UART_REG64(offset) _REG64(UART_CTRL_ADDR, offset)
// Misc
#endif /* _SIFIVE_PLATFORM_H */

View File

@ -0,0 +1,81 @@
// See LICENSE for license details.
#ifndef _RISCV_TEST_DEFAULTS_H
#define _RISCV_TEST_DEFAULTS_H
#define TESTNUM x28
#define TESTBASE 0x4000
#define RVTEST_RV32U \
.macro init; \
.endm
#define RVTEST_RV64U \
.macro init; \
.endm
#define RVTEST_RV32UF \
.macro init; \
/* If FPU exists, initialize FCSR. */ \
csrr t0, misa; \
andi t0, t0, 1 << ('F' - 'A'); \
beqz t0, 1f; \
/* Enable FPU if it exists. */ \
li t0, MSTATUS_FS; \
csrs mstatus, t0; \
fssr x0; \
1: ; \
.endm
#define RVTEST_RV64UF \
.macro init; \
/* If FPU exists, initialize FCSR. */ \
csrr t0, misa; \
andi t0, t0, 1 << ('F' - 'A'); \
beqz t0, 1f; \
/* Enable FPU if it exists. */ \
li t0, MSTATUS_FS; \
csrs mstatus, t0; \
fssr x0; \
1: ; \
.endm
#define RVTEST_CODE_BEGIN \
.section .text.init; \
.globl _prog_start; \
_prog_start: \
init;
#define RVTEST_CODE_END \
unimp
#define RVTEST_PASS \
fence; \
li t0, TESTBASE; \
li t1, 0x5555; \
sw t1, 0(t0); \
1: \
j 1b;
#define RVTEST_FAIL \
li t0, TESTBASE; \
li t1, 0x3333; \
slli a0, a0, 16; \
add a0, a0, t1; \
sw a0, 0(t0); \
1: \
j 1b;
#define EXTRA_DATA
#define RVTEST_DATA_BEGIN \
EXTRA_DATA \
.align 4; .global begin_signature; begin_signature:
#define RVTEST_DATA_END \
_msg_init: .asciz "RUN\r\n"; \
_msg_pass: .asciz "PASS"; \
_msg_fail: .asciz "FAIL "; \
_msg_end: .asciz "\r\n"; \
.align 4; .global end_signature; end_signature:
#endif /* _RISCV_TEST_DEFAULTS_H */

View File

@ -0,0 +1,17 @@
// See LICENSE for license details.
#ifndef _SECTIONS_H
#define _SECTIONS_H
extern unsigned char _rom[];
extern unsigned char _rom_end[];
extern unsigned char _ram[];
extern unsigned char _ram_end[];
extern unsigned char _ftext[];
extern unsigned char _etext[];
extern unsigned char _fbss[];
extern unsigned char _ebss[];
extern unsigned char _end[];
#endif /* _SECTIONS_H */

75
bootrom/sdboot/kprintf.c Normal file
View File

@ -0,0 +1,75 @@
// See LICENSE for license details.
#include <stdarg.h>
#include <stdint.h>
#include <stdbool.h>
#include "kprintf.h"
static inline void _kputs(const char *s)
{
char c;
for (; (c = *s) != '\0'; s++)
kputc(c);
}
void kputs(const char *s)
{
_kputs(s);
kputc('\r');
kputc('\n');
}
void kprintf(const char *fmt, ...)
{
va_list vl;
bool is_format, is_long, is_char;
char c;
va_start(vl, fmt);
is_format = false;
is_long = false;
is_char = false;
while ((c = *fmt++) != '\0') {
if (is_format) {
switch (c) {
case 'l':
is_long = true;
continue;
case 'h':
is_char = true;
continue;
case 'x': {
unsigned long n;
long i;
if (is_long) {
n = va_arg(vl, unsigned long);
i = (sizeof(unsigned long) << 3) - 4;
} else {
n = va_arg(vl, unsigned int);
i = is_char ? 4 : (sizeof(unsigned int) << 3) - 4;
}
for (; i >= 0; i -= 4) {
long d;
d = (n >> i) & 0xF;
kputc(d < 10 ? '0' + d : 'a' + d - 10);
}
break;
}
case 's':
_kputs(va_arg(vl, const char *));
break;
case 'c':
kputc(va_arg(vl, int));
break;
}
is_format = false;
is_long = false;
is_char = false;
} else if (c == '%') {
is_format = true;
} else {
kputc(c);
}
}
va_end(vl);
}

49
bootrom/sdboot/kprintf.h Normal file
View File

@ -0,0 +1,49 @@
// See LICENSE for license details.
#ifndef _SDBOOT_KPRINTF_H
#define _SDBOOT_KPRINTF_H
#include <platform.h>
#include <stdint.h>
#define REG32(p, i) ((p)[(i) >> 2])
#ifndef UART_CTRL_ADDR
#ifndef UART_NUM
#define UART_NUM 0
#endif
#define _CONCAT3(A, B, C) A ## B ## C
#define _UART_CTRL_ADDR(UART_NUM) _CONCAT3(UART, UART_NUM, _CTRL_ADDR)
#define UART_CTRL_ADDR _UART_CTRL_ADDR(UART_NUM)
#endif
static volatile uint32_t * const uart = (void *)(UART_CTRL_ADDR);
static inline void kputc(char c)
{
volatile uint32_t *tx = &REG32(uart, UART_REG_TXFIFO);
#ifdef __riscv_atomic
int32_t r;
do {
__asm__ __volatile__ (
"amoor.w %0, %2, %1\n"
: "=r" (r), "+A" (*tx)
: "r" (c));
} while (r < 0);
#else
while ((int32_t)(*tx) < 0);
*tx = c;
#endif
}
extern void kputs(const char *);
extern void kprintf(const char *, ...);
#ifdef DEBUG
#define dprintf(s, ...) kprintf((s), ##__VA_ARGS__)
#define dputs(s) kputs((s))
#else
#define dprintf(s, ...) do { } while (0)
#define dputs(s) do { } while (0)
#endif
#endif /* _SDBOOT_KPRINTF_H */

View File

@ -0,0 +1,14 @@
MEMORY
{
debug_ctrl (rwx) : ORIGIN = 0x0, LENGTH = 0x1000
error_mem (rw) : ORIGIN = 0x3000, LENGTH = 0x1000
test_ctrl (rw) : ORIGIN = 0x4000, LENGTH = 0x1000
maskrom_mem (rx) : ORIGIN = 0x10000, LENGTH = 0x2000
clint_ctrl (rw) : ORIGIN = 0x2000000, LENGTH = 0x10000
plic_ctrl (rw) : ORIGIN = 0xc000000, LENGTH = 0x4000000
axi_pcie_host_1_00_a_ctrl (rw) : ORIGIN = 0x50000000, LENGTH = 0x4000000
uart_ctrl (rw) : ORIGIN = 0x54000000, LENGTH = 0x1000
spi_ctrl (rw) : ORIGIN = 0x54001000, LENGTH = 0x1000
gpio_ctrl (rw) : ORIGIN = 0x54002000, LENGTH = 0x1000
memory_mem (rwx) : ORIGIN = 0x80000000, LENGTH = 0x40000000
}

View File

@ -0,0 +1,79 @@
OUTPUT_ARCH("riscv")
ENTRY(_prog_start)
INCLUDE memory.lds
PHDRS
{
text PT_LOAD;
data PT_LOAD;
bss PT_LOAD;
}
SECTIONS
{
PROVIDE(_ram = ORIGIN(memory_mem));
PROVIDE(_ram_end = _ram + LENGTH(memory_mem));
.text ALIGN((ORIGIN(maskrom_mem) + 0x0), 8) : AT(ALIGN((ORIGIN(maskrom_mem) + 0x0), 8)) {
PROVIDE(_ftext = .);
*(.text.init)
*(.text.unlikely .text.unlikely.*)
*(.text .text.* .gnu.linkonce.t.*)
PROVIDE(_etext = .);
. += 0x40; /* to create a gap between .text and .data b/c ifetch can fetch ahead from .data */
} >maskrom_mem :text
.eh_frame ALIGN((ADDR(.text) + SIZEOF(.text)), 8) : AT(ALIGN((LOADADDR(.text) + SIZEOF(.text)), 8)) {
*(.eh_frame)
} >maskrom_mem :text
.rodata ALIGN((ADDR(.eh_frame) + SIZEOF(.eh_frame)), 8) : AT(ALIGN((LOADADDR(.eh_frame) + SIZEOF(.eh_frame)), 8)) ALIGN_WITH_INPUT {
*(.rodata .rodata.* .gnu.linkonce.r.*)
} >maskrom_mem :data
.srodata ALIGN((ADDR(.rodata) + SIZEOF(.rodata)), 8) : AT(ALIGN((LOADADDR(.rodata) + SIZEOF(.rodata)), 8)) ALIGN_WITH_INPUT {
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata.*)
} >maskrom_mem :data
.data ALIGN((ADDR(.srodata) + SIZEOF(.srodata)), 8) : AT(ALIGN((LOADADDR(.srodata) + SIZEOF(.srodata)), 8)) ALIGN_WITH_INPUT {
*(.data .data.* .gnu.linkonce.d.*)
*(.tohost) /* TODO: Support sections that aren't explicitly listed in this linker script */
} >maskrom_mem :data
.sdata ALIGN((ADDR(.data) + SIZEOF(.data)), 8) : AT(ALIGN((LOADADDR(.data) + SIZEOF(.data)), 8)) ALIGN_WITH_INPUT {
*(.sdata .sdata.* .gnu.linkonce.s.*)
} >maskrom_mem :data
PROVIDE(_data = ADDR(.rodata));
PROVIDE(_data_lma = LOADADDR(.rodata));
PROVIDE(_edata = .);
.bss ALIGN((ORIGIN(memory_mem) + 0x0), 8) : AT(ALIGN((ORIGIN(memory_mem) + 0x0), 8)) ALIGN(8) {
PROVIDE(_fbss = .);
PROVIDE(__global_pointer$ = . + 0x7C0);
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.bss .bss.* .gnu.linkonce.b.*)
. = ALIGN(8);
PROVIDE(_ebss = .);
} >memory_mem :bss
PROVIDE(_end = .);
/*
* heap_stack_region_usable_end: (ORIGIN(memory_mem) + LENGTH(memory_mem))
* heap_stack_min_size: 4096
* heap_stack_max_size: 1048576
*/
PROVIDE(_sp = ALIGN(MIN((ORIGIN(memory_mem) + LENGTH(memory_mem)), _ebss + 1048576) - 7, 8));
PROVIDE(_heap_end = _sp - 2048);
/* This section is a noop and is only used for the ASSERT */
.stack : {
ASSERT(_sp >= (_ebss + 4096), "Error: No room left for the heap and stack");
}
}

225
bootrom/sdboot/sd.c Normal file
View File

@ -0,0 +1,225 @@
// See LICENSE for license details.
#include <stdint.h>
#include <platform.h>
#include "common.h"
#define DEBUG
#include "kprintf.h"
#define MAX_CORES 8
#define PAYLOAD_SIZE (16 << 11)
#define F_CLK 50000000UL
static volatile uint32_t * const spi = (void *)(SPI_CTRL_ADDR);
static inline uint8_t spi_xfer(uint8_t d)
{
int32_t r;
REG32(spi, SPI_REG_TXFIFO) = d;
do {
r = REG32(spi, SPI_REG_RXFIFO);
} while (r < 0);
return r;
}
static inline uint8_t sd_dummy(void)
{
return spi_xfer(0xFF);
}
static uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc)
{
unsigned long n;
uint8_t r;
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_HOLD;
sd_dummy();
spi_xfer(cmd);
spi_xfer(arg >> 24);
spi_xfer(arg >> 16);
spi_xfer(arg >> 8);
spi_xfer(arg);
spi_xfer(crc);
n = 1000;
do {
r = sd_dummy();
if (!(r & 0x80)) {
// dprintf("sd:cmd: %hx\r\n", r);
goto done;
}
} while (--n > 0);
kputs("sd_cmd: timeout");
done:
return r;
}
static inline void sd_cmd_end(void)
{
sd_dummy();
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
}
static void sd_poweron(void)
{
long i;
REG32(spi, SPI_REG_SCKDIV) = (F_CLK / 300000UL);
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_OFF;
for (i = 10; i > 0; i--) {
sd_dummy();
}
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
}
static int sd_cmd0(void)
{
int rc;
dputs("CMD0");
rc = (sd_cmd(0x40, 0, 0x95) != 0x01);
sd_cmd_end();
return rc;
}
static int sd_cmd8(void)
{
int rc;
dputs("CMD8");
rc = (sd_cmd(0x48, 0x000001AA, 0x87) != 0x01);
sd_dummy(); /* command version; reserved */
sd_dummy(); /* reserved */
rc |= ((sd_dummy() & 0xF) != 0x1); /* voltage */
rc |= (sd_dummy() != 0xAA); /* check pattern */
sd_cmd_end();
return rc;
}
static void sd_cmd55(void)
{
sd_cmd(0x77, 0, 0x65);
sd_cmd_end();
}
static int sd_acmd41(void)
{
uint8_t r;
dputs("ACMD41");
do {
sd_cmd55();
r = sd_cmd(0x69, 0x40000000, 0x77); /* HCS = 1 */
} while (r == 0x01);
return (r != 0x00);
}
static int sd_cmd58(void)
{
int rc;
dputs("CMD58");
rc = (sd_cmd(0x7A, 0, 0xFD) != 0x00);
rc |= ((sd_dummy() & 0x80) != 0x80); /* Power up status */
sd_dummy();
sd_dummy();
sd_dummy();
sd_cmd_end();
return rc;
}
static int sd_cmd16(void)
{
int rc;
dputs("CMD16");
rc = (sd_cmd(0x50, 0x200, 0x15) != 0x00);
sd_cmd_end();
return rc;
}
static uint16_t crc16_round(uint16_t crc, uint8_t data) {
crc = (uint8_t)(crc >> 8) | (crc << 8);
crc ^= data;
crc ^= (uint8_t)(crc >> 4) & 0xf;
crc ^= crc << 12;
crc ^= (crc & 0xff) << 5;
return crc;
}
#define SPIN_SHIFT 6
#define SPIN_UPDATE(i) (!((i) & ((1 << SPIN_SHIFT)-1)))
#define SPIN_INDEX(i) (((i) >> SPIN_SHIFT) & 0x3)
static const char spinner[] = { '-', '/', '|', '\\' };
static int copy(void)
{
volatile uint8_t *p = (void *)(PAYLOAD_DEST);
long i = PAYLOAD_SIZE;
int rc = 0;
dputs("CMD18");
kprintf("LOADING ");
REG32(spi, SPI_REG_SCKDIV) = (F_CLK / 20000000UL);
if (sd_cmd(0x52, 0, 0xE1) != 0x00) {
sd_cmd_end();
return 1;
}
do {
uint16_t crc, crc_exp;
long n;
crc = 0;
n = 512;
while (sd_dummy() != 0xFE);
do {
uint8_t x = sd_dummy();
*p++ = x;
crc = crc16_round(crc, x);
} while (--n > 0);
crc_exp = ((uint16_t)sd_dummy() << 8);
crc_exp |= sd_dummy();
if (crc != crc_exp) {
kputs("\b- CRC mismatch ");
rc = 1;
break;
}
if (SPIN_UPDATE(i)) {
kputc('\b');
kputc(spinner[SPIN_INDEX(i)]);
}
} while (--i > 0);
sd_cmd_end();
sd_cmd(0x4C, 0, 0x01);
sd_cmd_end();
kputs("\b ");
return rc;
}
int main(void)
{
REG32(uart, UART_REG_TXCTRL) = UART_TXEN;
kputs("INIT");
sd_poweron();
if (sd_cmd0() ||
sd_cmd8() ||
sd_acmd41() ||
sd_cmd58() ||
sd_cmd16() ||
copy()) {
kputs("ERROR");
return 1;
}
kputs("BOOT");
__asm__ __volatile__ ("fence.i" : : : "memory");
return 0;
}

Binary file not shown.

45
bootrom/xip/Makefile Normal file
View File

@ -0,0 +1,45 @@
# RISCV environment variable must be set
CC=$(RISCV)/bin/riscv64-unknown-elf-gcc
OBJCOPY=$(RISCV)/bin/riscv64-unknown-elf-objcopy
CFLAGS=-march=rv32imac -mabi=ilp32 -O2 -std=gnu11 -Wall -I. -nostartfiles -fno-common -g
LFLAGS=-static -nostdlib
dtb := $(BUILD_DIR)/$(CONFIG).dtb
$(dtb): $(BUILD_DIR)/$(CONFIG).dts
dtc -I dts -O dtb -o $@ $<
.PHONY: dtb
dtb: $(dtb)
elf := $(BUILD_DIR)/xip.elf
$(elf): xip.S $(dtb)
$(CC) $(CFLAGS) -DXIP_TARGET_ADDR=0x20400000 -DDEVICE_TREE='"$(dtb)"' $(LFLAGS) -o $@ $<
.PHONY: elf
elf: $(elf)
bin := $(BUILD_DIR)/xip.bin
$(bin): $(elf)
$(OBJCOPY) -O binary $< $@
.PHONY: bin
bin: $(bin)
hex := $(BUILD_DIR)/xip.hex
$(hex): $(bin)
od -t x4 -An -w4 -v $< > $@
.PHONY: hex
hex: $(hex)
romgen := $(BUILD_DIR)/rom.v
$(romgen): $(hex)
$(rocketchip_dir)/scripts/vlsi_rom_gen $(ROMCONF) $< > $@
.PHONY: romgen
romgen: $(romgen)
.PHONY: clean
clean::
rm -rf $(hex) $(elf)

View File

@ -2,25 +2,15 @@
// Execute in place
// Jump directly to XIP_TARGET_ADDR
.text
.section .text.init
.option norvc
.globl _start
_start:
j 1f
nop
nop
#ifdef CONFIG_STRING
.word cfg_string
#else
.word 0 // Filled in by GenerateBootROM in Chisel
#endif
1:
csrr a0, mhartid
la a1, dtb
li t0, XIP_TARGET_ADDR
jr t0
.section .rodata
#ifdef CONFIG_STRING
cfg_string:
.incbin CONFIG_STRING
#endif
dtb:
.incbin DEVICE_TREE