Add flash support for SiFive's Freedom E platforms
[openocd.git] / contrib / loaders / flash / fespi / fespi.S
blobd68e65ef81d1816bb17b102f3c9b113ac43ae288
1 #define SPIFLASH_READ_STATUS    0x05 // Read Status Register
2 #define SPIFLASH_BSY_BIT                0x00000001 // WIP Bit of SPI SR on SMI SR
4 // Register offsets
5 #define FESPI_REG_FMT             0x40
6 #define FESPI_REG_TXFIFO          0x48
7 #define FESPI_REG_RXFIFO          0x4c
8 #define FESPI_REG_IP              0x74
10 // Fields
11 #define FESPI_IP_TXWM             0x1
12 #define FESPI_FMT_DIR(x)          (((x) & 0x1) << 3)
14 // To enter, jump to the start of command_table (ie. offset 0).
15 //      a0 - FESPI base address
16 //      a1 - start address of buffer
18 // The buffer contains a "program" in byte sequences. The first byte in a
19 // sequence determines the operation. Some operation will read more data from
20 // the program, while some will not. The operation byte is the offset into
21 // command_table, so eg. 4 means exit, 8 means transmit, and so on.
23                 .global _start
24 _start:
25 command_table:
26                 j       main            // 0
27                 ebreak                  // 4
28                 j       tx              // 8
29                 j       txwm_wait       // 12
30                 j       write_reg       // 16
31                 j               wip_wait                // 20
32                 j               set_dir                 // 24
34 // Execute the program.
35 main:
36                 lbu     t0, 0(a1)
37                 addi    a1, a1, 1
38                 la      t1, command_table
39                 add     t0, t0, t1
40                 jr      t0
42 // Read 1 byte the contains the number of bytes to transmit. Then read those
43 // bytes from the program and transmit them one by one.
44 tx:
45                 lbu     t1, 0(a1)       // read number of bytes to transmit
46                 addi    a1, a1, 1
47 1:      lw      t0, FESPI_REG_TXFIFO(a0)        // wait for FIFO clear
48                 bltz    t0, 1b
49                 lbu     t0, 0(a1)       // Load byte to write
50                 sw      t0, FESPI_REG_TXFIFO(a0)
51                 addi    a1, a1, 1
52                 addi    t1, t1, -1
53                 bgtz    t1, 1b
54                 j       main
56 // Wait until TXWM is set.
57 txwm_wait:
58 1:      lw      t0, FESPI_REG_IP(a0)
59                 andi    t0, t0, FESPI_IP_TXWM
60                 beqz    t0, 1b
61                 j       main
63 // Read 1 byte that contains the offset of the register to write, and 1 byte
64 // that contains the data to write.
65 write_reg:
66                 lbu     t0, 0(a1)       // read register to write
67                 add     t0, t0, a0
68                 lbu     t1, 1(a1)       // read value to write
69                 addi    a1, a1, 2
70                 sw      t1, 0(t0)
71                 j       main
73 wip_wait:
74                 li              a2, SPIFLASH_READ_STATUS
75                 jal             txrx_byte
76                 // discard first result
77 1:              li              a2, 0
78                 jal             txrx_byte
79                 andi    t0, a2, SPIFLASH_BSY_BIT
80                 bnez    t0, 1b
81                 j               main
83 txrx_byte:      // transmit the byte in a2, receive a bit into a2
84                 lw      t0, FESPI_REG_TXFIFO(a0)        // wait for FIFO clear
85                 bltz    t0, txrx_byte
86                 sw      a2, FESPI_REG_TXFIFO(a0)
87 1:              lw              a2, FESPI_REG_RXFIFO(a0)
88                 bltz    a2, 1b
89                 ret
91 set_dir:
92                 lw              t0, FESPI_REG_FMT(a0)
93                 li              t1, ~(FESPI_FMT_DIR(0xFFFFFFFF))
94                 and             t0, t0, t1
95                 lbu     t1, 0(a1)       // read value to OR in
96                 addi    a1, a1, 1
97                 or              t0, t0, t1
98                 sw              t0, FESPI_REG_FMT(a0)
99                 j               main