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
|
||||
-------------
|
||||
|
||||
ADUC702x, AT91SAM, ATH79, AVR, CFI, DSP5680xx, EFM32, EM357, eSi-TSMC,
|
||||
FM3, FM4, Kinetis, LPC8xx/LPC1xxx/LPC2xxx/LPC541xx, LPC2900, LPCSPIFI,
|
||||
Marvell QSPI, Milandr, NIIET, NuMicro, PIC32mx, PSoC4, PSoC5LP, SiM3x,
|
||||
Stellaris, STM32, STMSMI, STR7x, STR9x, nRF51; NAND controllers of
|
||||
AT91SAM9, LPC3180, LPC32xx, i.MX31, MXC, NUC910, Orion/Kirkwood,
|
||||
S3C24xx, S3C6400, XMC1xxx, XMC4xxx.
|
||||
ADUC702x, AT91SAM, ATH79, AVR, CFI, DSP5680xx, EFM32, EM357, eSi-TSMC, FM3,
|
||||
FM4, Freedom E SPI, Kinetis, LPC8xx/LPC1xxx/LPC2xxx/LPC541xx, LPC2900,
|
||||
LPCSPIFI, Marvell QSPI, Milandr, NIIET, NuMicro, PIC32mx, PSoC4, PSoC5LP,
|
||||
SiM3x, Stellaris, STM32, STMSMI, STR7x, STR9x, nRF51; NAND controllers of
|
||||
AT91SAM9, LPC3180, LPC32xx, i.MX31, MXC, NUC910, Orion/Kirkwood, S3C24xx,
|
||||
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
|
||||
|
||||
@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)
|
||||
|
||||
@deffn {Flash Driver} aduc702x
|
||||
|
|
|
@ -27,6 +27,7 @@ NOR_DRIVERS = \
|
|||
%D%/em357.c \
|
||||
%D%/esirisc_flash.c \
|
||||
%D%/faux.c \
|
||||
%D%/fespi.c \
|
||||
%D%/fm3.c \
|
||||
%D%/fm4.c \
|
||||
%D%/jtagspi.c \
|
||||
|
|
|
@ -42,6 +42,7 @@ extern struct flash_driver esirisc_flash;
|
|||
extern struct flash_driver faux_flash;
|
||||
extern struct flash_driver fm3_flash;
|
||||
extern struct flash_driver fm4_flash;
|
||||
extern struct flash_driver fespi_flash;
|
||||
extern struct flash_driver jtagspi_flash;
|
||||
extern struct flash_driver kinetis_flash;
|
||||
extern struct flash_driver kinetis_ke_flash;
|
||||
|
@ -109,6 +110,7 @@ static struct flash_driver *flash_drivers[] = {
|
|||
&faux_flash,
|
||||
&fm3_flash,
|
||||
&fm4_flash,
|
||||
&fespi_flash,
|
||||
&jtagspi_flash,
|
||||
&kinetis_flash,
|
||||
&kinetis_ke_flash,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue