+++ /dev/null
-#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