Add flash support for SiFive's Freedom E platforms
Valgrind and Clang Static Analyzer have no complaints about this change. Change-Id: I7757615ec52448372bdc57729cdf97c7016d97e8 Signed-off-by: Tim Newsome <tim@sifive.com> Reviewed-on: http://openocd.zylin.com/4656 Tested-by: jenkins Reviewed-by: Philipp Guehring <pg@futureware.at> Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
This commit is contained in:
parent
42d8fa899c
commit
31ea7037b3
12
README
12
README
|
@ -123,12 +123,12 @@ EJTAG, NDS32, XScale, Intel Quark.
|
||||||
Flash drivers
|
Flash drivers
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
ADUC702x, AT91SAM, ATH79, AVR, CFI, DSP5680xx, EFM32, EM357, eSi-TSMC,
|
ADUC702x, AT91SAM, ATH79, AVR, CFI, DSP5680xx, EFM32, EM357, eSi-TSMC, FM3,
|
||||||
FM3, FM4, Kinetis, LPC8xx/LPC1xxx/LPC2xxx/LPC541xx, LPC2900, LPCSPIFI,
|
FM4, Freedom E SPI, Kinetis, LPC8xx/LPC1xxx/LPC2xxx/LPC541xx, LPC2900,
|
||||||
Marvell QSPI, Milandr, NIIET, NuMicro, PIC32mx, PSoC4, PSoC5LP, SiM3x,
|
LPCSPIFI, Marvell QSPI, Milandr, NIIET, NuMicro, PIC32mx, PSoC4, PSoC5LP,
|
||||||
Stellaris, STM32, STMSMI, STR7x, STR9x, nRF51; NAND controllers of
|
SiM3x, Stellaris, STM32, STMSMI, STR7x, STR9x, nRF51; NAND controllers of
|
||||||
AT91SAM9, LPC3180, LPC32xx, i.MX31, MXC, NUC910, Orion/Kirkwood,
|
AT91SAM9, LPC3180, LPC32xx, i.MX31, MXC, NUC910, Orion/Kirkwood, S3C24xx,
|
||||||
S3C24xx, S3C6400, XMC1xxx, XMC4xxx.
|
S3C6400, XMC1xxx, XMC4xxx.
|
||||||
|
|
||||||
|
|
||||||
==================
|
==================
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
BIN2C = ../../../../src/helper/bin2char.sh
|
||||||
|
|
||||||
|
CROSS_COMPILE ?= riscv64-unknown-elf-
|
||||||
|
|
||||||
|
CC=$(CROSS_COMPILE)gcc
|
||||||
|
OBJCOPY=$(CROSS_COMPILE)objcopy
|
||||||
|
OBJDUMP=$(CROSS_COMPILE)objdump
|
||||||
|
|
||||||
|
CFLAGS = -march=rv32i -mabi=ilp32 -x assembler-with-cpp -nostdlib -nostartfiles
|
||||||
|
|
||||||
|
all: fespi.inc
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
|
||||||
|
%.elf: %.S
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
%.lst: %.elf
|
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
%.bin: %.elf
|
||||||
|
$(OBJCOPY) -Obinary $< $@
|
||||||
|
|
||||||
|
%.inc: %.bin
|
||||||
|
$(BIN2C) < $< > $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -f *.elf *.lst *.bin *.inc
|
|
@ -0,0 +1,99 @@
|
||||||
|
#define SPIFLASH_READ_STATUS 0x05 // Read Status Register
|
||||||
|
#define SPIFLASH_BSY_BIT 0x00000001 // WIP Bit of SPI SR on SMI SR
|
||||||
|
|
||||||
|
// Register offsets
|
||||||
|
#define FESPI_REG_FMT 0x40
|
||||||
|
#define FESPI_REG_TXFIFO 0x48
|
||||||
|
#define FESPI_REG_RXFIFO 0x4c
|
||||||
|
#define FESPI_REG_IP 0x74
|
||||||
|
|
||||||
|
// Fields
|
||||||
|
#define FESPI_IP_TXWM 0x1
|
||||||
|
#define FESPI_FMT_DIR(x) (((x) & 0x1) << 3)
|
||||||
|
|
||||||
|
// To enter, jump to the start of command_table (ie. offset 0).
|
||||||
|
// a0 - FESPI base address
|
||||||
|
// a1 - start address of buffer
|
||||||
|
|
||||||
|
// The buffer contains a "program" in byte sequences. The first byte in a
|
||||||
|
// sequence determines the operation. Some operation will read more data from
|
||||||
|
// the program, while some will not. The operation byte is the offset into
|
||||||
|
// command_table, so eg. 4 means exit, 8 means transmit, and so on.
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
command_table:
|
||||||
|
j main // 0
|
||||||
|
ebreak // 4
|
||||||
|
j tx // 8
|
||||||
|
j txwm_wait // 12
|
||||||
|
j write_reg // 16
|
||||||
|
j wip_wait // 20
|
||||||
|
j set_dir // 24
|
||||||
|
|
||||||
|
// Execute the program.
|
||||||
|
main:
|
||||||
|
lbu t0, 0(a1)
|
||||||
|
addi a1, a1, 1
|
||||||
|
la t1, command_table
|
||||||
|
add t0, t0, t1
|
||||||
|
jr t0
|
||||||
|
|
||||||
|
// Read 1 byte the contains the number of bytes to transmit. Then read those
|
||||||
|
// bytes from the program and transmit them one by one.
|
||||||
|
tx:
|
||||||
|
lbu t1, 0(a1) // read number of bytes to transmit
|
||||||
|
addi a1, a1, 1
|
||||||
|
1: lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
|
||||||
|
bltz t0, 1b
|
||||||
|
lbu t0, 0(a1) // Load byte to write
|
||||||
|
sw t0, FESPI_REG_TXFIFO(a0)
|
||||||
|
addi a1, a1, 1
|
||||||
|
addi t1, t1, -1
|
||||||
|
bgtz t1, 1b
|
||||||
|
j main
|
||||||
|
|
||||||
|
// Wait until TXWM is set.
|
||||||
|
txwm_wait:
|
||||||
|
1: lw t0, FESPI_REG_IP(a0)
|
||||||
|
andi t0, t0, FESPI_IP_TXWM
|
||||||
|
beqz t0, 1b
|
||||||
|
j main
|
||||||
|
|
||||||
|
// Read 1 byte that contains the offset of the register to write, and 1 byte
|
||||||
|
// that contains the data to write.
|
||||||
|
write_reg:
|
||||||
|
lbu t0, 0(a1) // read register to write
|
||||||
|
add t0, t0, a0
|
||||||
|
lbu t1, 1(a1) // read value to write
|
||||||
|
addi a1, a1, 2
|
||||||
|
sw t1, 0(t0)
|
||||||
|
j main
|
||||||
|
|
||||||
|
wip_wait:
|
||||||
|
li a2, SPIFLASH_READ_STATUS
|
||||||
|
jal txrx_byte
|
||||||
|
// discard first result
|
||||||
|
1: li a2, 0
|
||||||
|
jal txrx_byte
|
||||||
|
andi t0, a2, SPIFLASH_BSY_BIT
|
||||||
|
bnez t0, 1b
|
||||||
|
j main
|
||||||
|
|
||||||
|
txrx_byte: // transmit the byte in a2, receive a bit into a2
|
||||||
|
lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
|
||||||
|
bltz t0, txrx_byte
|
||||||
|
sw a2, FESPI_REG_TXFIFO(a0)
|
||||||
|
1: lw a2, FESPI_REG_RXFIFO(a0)
|
||||||
|
bltz a2, 1b
|
||||||
|
ret
|
||||||
|
|
||||||
|
set_dir:
|
||||||
|
lw t0, FESPI_REG_FMT(a0)
|
||||||
|
li t1, ~(FESPI_FMT_DIR(0xFFFFFFFF))
|
||||||
|
and t0, t0, t1
|
||||||
|
lbu t1, 0(a1) // read value to OR in
|
||||||
|
addi a1, a1, 1
|
||||||
|
or t0, t0, t1
|
||||||
|
sw t0, FESPI_REG_FMT(a0)
|
||||||
|
j main
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* Autogenerated with ../../../../src/helper/bin2char.sh */
|
||||||
|
0x6f,0x00,0xc0,0x01,0x73,0x00,0x10,0x00,0x6f,0x00,0xc0,0x02,0x6f,0x00,0x00,0x05,
|
||||||
|
0x6f,0x00,0xc0,0x05,0x6f,0x00,0x00,0x07,0x6f,0x00,0x00,0x0a,0x83,0xc2,0x05,0x00,
|
||||||
|
0x93,0x85,0x15,0x00,0x17,0x03,0x00,0x00,0x13,0x03,0xc3,0xfd,0xb3,0x82,0x62,0x00,
|
||||||
|
0x67,0x80,0x02,0x00,0x03,0xc3,0x05,0x00,0x93,0x85,0x15,0x00,0x83,0x22,0x85,0x04,
|
||||||
|
0xe3,0xce,0x02,0xfe,0x83,0xc2,0x05,0x00,0x23,0x24,0x55,0x04,0x93,0x85,0x15,0x00,
|
||||||
|
0x13,0x03,0xf3,0xff,0xe3,0x44,0x60,0xfe,0x6f,0xf0,0x5f,0xfc,0x83,0x22,0x45,0x07,
|
||||||
|
0x93,0xf2,0x12,0x00,0xe3,0x8c,0x02,0xfe,0x6f,0xf0,0x5f,0xfb,0x83,0xc2,0x05,0x00,
|
||||||
|
0xb3,0x82,0xa2,0x00,0x03,0xc3,0x15,0x00,0x93,0x85,0x25,0x00,0x23,0xa0,0x62,0x00,
|
||||||
|
0x6f,0xf0,0xdf,0xf9,0x13,0x06,0x50,0x00,0xef,0x00,0x80,0x01,0x13,0x06,0x00,0x00,
|
||||||
|
0xef,0x00,0x00,0x01,0x93,0x72,0x16,0x00,0xe3,0x9a,0x02,0xfe,0x6f,0xf0,0x1f,0xf8,
|
||||||
|
0x83,0x22,0x85,0x04,0xe3,0xce,0x02,0xfe,0x23,0x24,0xc5,0x04,0x03,0x26,0xc5,0x04,
|
||||||
|
0xe3,0x4e,0x06,0xfe,0x67,0x80,0x00,0x00,0x83,0x22,0x05,0x04,0x13,0x03,0x70,0xff,
|
||||||
|
0xb3,0xf2,0x62,0x00,0x03,0xc3,0x05,0x00,0x93,0x85,0x15,0x00,0xb3,0xe2,0x62,0x00,
|
||||||
|
0x23,0x20,0x55,0x04,0x6f,0xf0,0x9f,0xf4,
|
|
@ -5365,6 +5365,17 @@ flash bank flash2 ath79 0x20000000 0 0 0 $_TARGETNAME cs2
|
||||||
|
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Flash Driver} fespi
|
||||||
|
@cindex Freedom E SPI
|
||||||
|
@cindex fespi
|
||||||
|
|
||||||
|
SiFive's Freedom E SPI controller, used in HiFive and other boards.
|
||||||
|
|
||||||
|
@example
|
||||||
|
flash bank $_FLASHNAME fespi 0x20000000 0 0 0 $_TARGETNAME
|
||||||
|
@end example
|
||||||
|
@end deffn
|
||||||
|
|
||||||
@subsection Internal Flash (Microcontrollers)
|
@subsection Internal Flash (Microcontrollers)
|
||||||
|
|
||||||
@deffn {Flash Driver} aduc702x
|
@deffn {Flash Driver} aduc702x
|
||||||
|
|
|
@ -27,6 +27,7 @@ NOR_DRIVERS = \
|
||||||
%D%/em357.c \
|
%D%/em357.c \
|
||||||
%D%/esirisc_flash.c \
|
%D%/esirisc_flash.c \
|
||||||
%D%/faux.c \
|
%D%/faux.c \
|
||||||
|
%D%/fespi.c \
|
||||||
%D%/fm3.c \
|
%D%/fm3.c \
|
||||||
%D%/fm4.c \
|
%D%/fm4.c \
|
||||||
%D%/jtagspi.c \
|
%D%/jtagspi.c \
|
||||||
|
|
|
@ -42,6 +42,7 @@ extern struct flash_driver esirisc_flash;
|
||||||
extern struct flash_driver faux_flash;
|
extern struct flash_driver faux_flash;
|
||||||
extern struct flash_driver fm3_flash;
|
extern struct flash_driver fm3_flash;
|
||||||
extern struct flash_driver fm4_flash;
|
extern struct flash_driver fm4_flash;
|
||||||
|
extern struct flash_driver fespi_flash;
|
||||||
extern struct flash_driver jtagspi_flash;
|
extern struct flash_driver jtagspi_flash;
|
||||||
extern struct flash_driver kinetis_flash;
|
extern struct flash_driver kinetis_flash;
|
||||||
extern struct flash_driver kinetis_ke_flash;
|
extern struct flash_driver kinetis_ke_flash;
|
||||||
|
@ -109,6 +110,7 @@ static struct flash_driver *flash_drivers[] = {
|
||||||
&faux_flash,
|
&faux_flash,
|
||||||
&fm3_flash,
|
&fm3_flash,
|
||||||
&fm4_flash,
|
&fm4_flash,
|
||||||
|
&fespi_flash,
|
||||||
&jtagspi_flash,
|
&jtagspi_flash,
|
||||||
&kinetis_flash,
|
&kinetis_flash,
|
||||||
&kinetis_ke_flash,
|
&kinetis_ke_flash,
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue