boot.S 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * boot.S
  3. *
  4. * SPI boot code
  5. *
  6. * Copyright (C) 2019 Sylvain Munaut <tnt@246tNt.com>
  7. *
  8. * Permission to use, copy, modify, and/or distribute this software for any
  9. * purpose with or without fee is hereby granted, provided that the above
  10. * copyright notice and this permission notice appear in all copies.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  13. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  14. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  15. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  16. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  17. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  18. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19. */
  20. #ifndef FLASH_APP_ADDR
  21. #define FLASH_APP_ADDR 0x00100000
  22. #endif
  23. .section .text.start
  24. .global _start
  25. _start:
  26. #ifdef BOOT_DEBUG
  27. // Set UART divisor
  28. li a0, 0x81000004
  29. li a1, 22
  30. sw a1, 0(a0)
  31. // Output 'a'
  32. li a0, 0x81000000
  33. li a1, 97
  34. sw a1, 0(a0)
  35. #endif
  36. // SPI init
  37. jal spi_init
  38. #ifdef BOOT_DEBUG
  39. // Output 'b'
  40. li a0, 0x81000000
  41. li a1, 98
  42. sw a1, 0(a0)
  43. #endif
  44. li a0, 0x00020000
  45. #ifdef SPRAM128K
  46. li a1, 0x00020000
  47. #else
  48. li a1, 0x00010000
  49. #endif
  50. li a2, FLASH_APP_ADDR
  51. jal spi_flash_read
  52. #ifdef BOOT_DEBUG
  53. // Output 'c'
  54. li a0, 0x81000000
  55. li a1, 99
  56. sw a1, 0(a0)
  57. #endif
  58. // Setup reboot code
  59. li t0, 0x0002006f
  60. sw t0, 0(zero)
  61. // Jump to main code
  62. j 0x00020000
  63. .equ SPI_BASE, 0x82000000
  64. .equ SPICR0, 4 * 0x08
  65. .equ SPICR1, 4 * 0x09
  66. .equ SPICR2, 4 * 0x0a
  67. .equ SPIBR, 4 * 0x0b
  68. .equ SPISR, 4 * 0x0c
  69. .equ SPITXDR, 4 * 0x0d
  70. .equ SPIRXDR, 4 * 0x0e
  71. .equ SPICSR, 4 * 0x0f
  72. spi_init:
  73. li a0, SPI_BASE
  74. li a1, 0xff
  75. sw a1, SPICR0(a0)
  76. li a1, 0x80
  77. sw a1, SPICR1(a0)
  78. li a1, 0xc0
  79. sw a1, SPICR2(a0)
  80. li a1, 0x03
  81. sw a1, SPIBR(a0)
  82. li a1, 0x0f
  83. sw a1, SPICSR(a0)
  84. ret
  85. // Params:
  86. // a0 - destination pointer
  87. // a1 - length (bytes)
  88. // a2 - flash offset
  89. //
  90. spi_flash_read:
  91. // Save params
  92. mv s0, a0
  93. mv s1, a1
  94. mv s2, ra
  95. // Setup CS
  96. li t0, SPI_BASE
  97. li t1, 0x0e
  98. sw t1, SPICSR(t0)
  99. // Send command
  100. li a0, 0x03
  101. jal _spi_do_one
  102. srli a0, a2, 16
  103. and a0, a0, 0xff
  104. jal _spi_do_one
  105. srli a0, a2, 8
  106. and a0, a0, 0xff
  107. jal _spi_do_one
  108. and a0, a2, 0xff
  109. jal _spi_do_one
  110. // Read loop
  111. _spi_loop:
  112. li a0, 0x00
  113. jal _spi_do_one
  114. sb a0, 0(s0)
  115. addi s0, s0, 1
  116. addi s1, s1, -1
  117. bne s1, zero, _spi_loop
  118. // Release CS
  119. li t0, SPI_BASE
  120. li t1, 0x0f
  121. sw t1, SPICSR(t0)
  122. // Done
  123. jr s2
  124. // Params: a0 - Data to TX
  125. // Returns: a0 - RX data
  126. // Clobbers t0, t1
  127. _spi_do_one:
  128. li t0, SPI_BASE
  129. li t1, 0x08
  130. // Write TX data
  131. sw a0, SPITXDR(t0)
  132. // Wait for RXRDY
  133. 1:
  134. lw a0, SPISR(t0)
  135. and a0, a0, t1
  136. bne a0, t1, 1b
  137. // Read RX data
  138. lw a0, SPIRXDR(t0)
  139. // Done
  140. ret