Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 38 additions & 48 deletions chipflow_lib/software/drivers/spiflash.S
Original file line number Diff line number Diff line change
@@ -1,67 +1,57 @@

.global flashio_worker_begin
.global flashio_worker_end

.balign 4

flashio_worker_begin:
# a0 ... address of SPI ctrl reg
# a0 ... flash base address
# a1 ... data pointer
# a2 ... data length
# a3 ... optional WREN cmd (0 = disable)

# Set CS high, IO0 is output
li t1, 0x120
sh t1, 0(a0)

# Enable Manual SPI Ctrl
sb zero, 3(a0)

# Send optional WREN cmd
beqz a3, flashio_worker_L1
li t5, 8
andi t2, a3, 0xff
flashio_worker_L4:
srli t4, t2, 7
sb t4, 0(a0)
ori t4, t4, 0x10
sb t4, 0(a0)
slli t2, t2, 1
andi t2, t2, 0xff
addi t5, t5, -1
bnez t5, flashio_worker_L4
sb t1, 0(a0)

# SPI transfer
flashio_worker_L1:
beqz a2, flashio_worker_L3
li t5, 8
lbu t2, 0(a1)
flashio_worker_L2:
srli t4, t2, 7
sb t4, 0(a0)
ori t4, t4, 0x10
sb t4, 0(a0)
lbu t4, 0(a0)
andi t4, t4, 2
srli t4, t4, 1
slli t2, t2, 1
or t2, t2, t4
andi t2, t2, 0xff
addi t5, t5, -1
bnez t5, flashio_worker_L2
sb t2, 0(a1)
mv t3, ra

# address of SPI ctrl reg
li a0, 0xb0000000
# enter bypass mode
lbu t1, 0(a0)
ori t1, t1, 0x1
sb t1, 0(a0)
call flashio_wait_bypass_ready

beqz a3, flashio_xfer

sb a3, 8(a0) # send wren
call flashio_wait_bypass_ready
li t1, 2 # deselect
sb t1, 4(a0)
call flashio_wait_bypass_ready

flashio_xfer:
beqz a2, flashio_done
lbu t1, 0(a1)
sb t1, 8(a0) # tx data
call flashio_wait_bypass_ready
lbu t1, 12(a0) # rx data
sb t1, 0(a1)
addi a1, a1, 1
addi a2, a2, -1
j flashio_worker_L1
flashio_worker_L3:
j flashio_xfer

# Back to MEMIO mode
li t1, 0x80
sb t1, 3(a0)
flashio_done:
# exit bypass mode
lbu t1, 0(a0)
andi t1, t1, 0xFE
sb t1, 0(a0)

fence.i
mv ra, t3
ret

flashio_wait_bypass_ready:
lbu t1, 4(a0)
andi t1, t1, 0x1
beqz t1, flashio_wait_bypass_ready
ret

.balign 4
Expand Down
17 changes: 9 additions & 8 deletions chipflow_lib/software/drivers/spiflash.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@ extern uint32_t flashio_worker_end;

void spiflash_io(volatile spiflash_regs_t *flash, uint8_t *data, int len, uint8_t wrencmd) {
// Flash can't be accessed during IO, so copy to RAM and run that
volatile uint32_t func[&flashio_worker_end - &flashio_worker_begin];
volatile uint32_t func[&flashio_worker_end - &flashio_worker_begin];

uint32_t *src_ptr = &flashio_worker_begin;
volatile uint32_t *dst_ptr = func;
// Can't execute off flash while talking to it, so copy IO code to SRAM
uint32_t *src_ptr = &flashio_worker_begin;
volatile uint32_t *dst_ptr = func;

while (src_ptr != &flashio_worker_end)
*(dst_ptr++) = *(src_ptr++);
while (src_ptr != &flashio_worker_end)
*(dst_ptr++) = *(src_ptr++);

__asm__ volatile ("fence.i" : : : "memory");
__asm__ volatile ("fence.i" : : : "memory");

((void(*)(volatile spiflash_regs_t *, uint8_t*, uint32_t, uint32_t))func)(flash, data, len, wrencmd);
((void(*)(uint8_t*, uint8_t*, uint32_t, uint32_t))func)((uint8_t*)flash, data, len, wrencmd);
}

uint32_t spiflash_read_id(volatile spiflash_regs_t *flash) {
Expand Down Expand Up @@ -69,5 +70,5 @@ void spiflash_set_qspi_flag(volatile spiflash_regs_t *flash) {
}

void spiflash_set_quad_mode(volatile spiflash_regs_t *flash) {
flash->ctrl = (flash->ctrl & ~0x007f0000) | 0x00240000;
flash->config = (0x3U << 3U) | (0x03U << 1U); // 3 dummy byte, X4 mode
}
5 changes: 4 additions & 1 deletion chipflow_lib/software/drivers/spiflash.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
#define ISSI_ID 0x60

typedef struct __attribute__((packed, aligned(4))) {
uint32_t ctrl;
uint32_t config;
uint32_t raw_control;
uint32_t raw_tx_data;
uint32_t raw_rx_data;
} spiflash_regs_t;

void spiflash_io(volatile spiflash_regs_t *flash, uint8_t *data, int len, uint8_t wrencmd);
Expand Down
Loading