boot.S 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * boot.S
  3. *
  4. * SPI boot code
  5. *
  6. * Copyright (C) 2019-2022 Sylvain Munaut <tnt@246tNt.com>
  7. * SPDX-License-Identifier: MIT
  8. */
  9. // #define BOOT_DEBUG
  10. #ifndef FLASH_APP_ADDR
  11. #define FLASH_APP_ADDR 0x00100000
  12. #endif
  13. .equ UART_BASE, 0x81000000
  14. .section .text.start
  15. .global _start
  16. _start:
  17. #ifdef BOOT_DEBUG
  18. // Set UART divisor
  19. li a0, UART_BASE
  20. li a1, 22
  21. sw a1, 4(a0)
  22. // Output 'a'
  23. li a1, 97
  24. sw a1, 0(a0)
  25. #endif
  26. // SPI init
  27. jal spi_init
  28. #ifdef BOOT_DEBUG
  29. // Output 'b'
  30. li a0, UART_BASE
  31. li a1, 98
  32. sw a1, 0(a0)
  33. #endif
  34. li a0, 0x00020000
  35. #ifdef SPRAM128K
  36. li a1, 0x00020000
  37. #else
  38. li a1, 0x00010000
  39. #endif
  40. li a2, FLASH_APP_ADDR
  41. jal spi_flash_read
  42. #ifdef BOOT_DEBUG
  43. // Output 'c'
  44. li a0, UART_BASE
  45. li a1, 99
  46. sw a1, 0(a0)
  47. #endif
  48. // Setup reboot code
  49. li t0, 0x0002006f
  50. sw t0, 0(zero)
  51. // Jump to main code
  52. j 0x00020000
  53. // ---------------------------------------------------------------------------
  54. // SPI code
  55. // ---------------------------------------------------------------------------
  56. // Register definitions
  57. .equ SPI_BASE, 0x82000000
  58. .equ SPICR0, 4 * 0x08
  59. .equ SPICR1, 4 * 0x09
  60. .equ SPICR2, 4 * 0x0a
  61. .equ SPIBR, 4 * 0x0b
  62. .equ SPISR, 4 * 0x0c
  63. .equ SPITXDR, 4 * 0x0d
  64. .equ SPIRXDR, 4 * 0x0e
  65. .equ SPICSR, 4 * 0x0f
  66. // Initializes te SPI hardware
  67. //
  68. // Clobbers a0, a1
  69. spi_init:
  70. li a0, SPI_BASE
  71. li a1, 0xff
  72. sw a1, SPICR0(a0)
  73. li a1, 0x80
  74. sw a1, SPICR1(a0)
  75. li a1, 0xc0
  76. sw a1, SPICR2(a0)
  77. li a1, 0x03
  78. sw a1, SPIBR(a0)
  79. li a1, 0x0f
  80. sw a1, SPICSR(a0)
  81. ret
  82. // Reads a block of memory from SPI flash
  83. //
  84. // Params:
  85. // a0 - destination pointer
  86. // a1 - length (bytes)
  87. // a2 - flash offset
  88. // Clobbers t0, t1, s0, s1, s2
  89. spi_flash_read:
  90. // Save params
  91. mv s0, a0
  92. mv s1, a1
  93. mv s2, ra
  94. // Setup CS
  95. li t0, SPI_BASE
  96. li t1, 0x0e
  97. sw t1, SPICSR(t0)
  98. // Send command
  99. li a0, 0x03
  100. jal _spi_do_one
  101. srli a0, a2, 16
  102. and a0, a0, 0xff
  103. jal _spi_do_one
  104. srli a0, a2, 8
  105. and a0, a0, 0xff
  106. jal _spi_do_one
  107. and a0, a2, 0xff
  108. jal _spi_do_one
  109. // Read loop
  110. _spi_loop:
  111. li a0, 0x00
  112. jal _spi_do_one
  113. sb a0, 0(s0)
  114. addi s0, s0, 1
  115. addi s1, s1, -1
  116. bne s1, zero, _spi_loop
  117. // Release CS
  118. li t0, SPI_BASE
  119. li t1, 0x0f
  120. sw t1, SPICSR(t0)
  121. // Done
  122. jr s2
  123. // Performs a single 8 bit SPI xfer
  124. //
  125. // Params: a0 - Data to TX
  126. // Returns: a0 - RX data
  127. // Clobbers t0, t1
  128. _spi_do_one:
  129. li t0, SPI_BASE
  130. li t1, 0x08
  131. // Write TX data
  132. sw a0, SPITXDR(t0)
  133. // Wait for RXRDY
  134. 1:
  135. lw a0, SPISR(t0)
  136. and a0, a0, t1
  137. bne a0, t1, 1b
  138. // Read RX data
  139. lw a0, SPIRXDR(t0)
  140. // Done
  141. ret