You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

100 lines
2.7 KiB

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