boot.S 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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
  24. start:
  25. #ifdef BOOT_DEBUG
  26. // Set UART divisor
  27. li a0, 0x81000004
  28. li a1, 23
  29. sw a1, 0(a0)
  30. // Output 'a'
  31. li a0, 0x81000000
  32. li a1, 97
  33. sw a1, 0(a0)
  34. #endif
  35. // SPI init
  36. jal spi_init
  37. #ifdef BOOT_DEBUG
  38. // Output 'b'
  39. li a0, 0x81000000
  40. li a1, 98
  41. sw a1, 0(a0)
  42. #endif
  43. li a0, 0x00010000
  44. li a1, 0x00010000
  45. li a2, FLASH_APP_ADDR
  46. jal spi_flash_read
  47. #ifdef BOOT_DEBUG
  48. // Output 'c'
  49. li a0, 0x81000000
  50. li a1, 99
  51. sw a1, 0(a0)
  52. #endif
  53. // Setup reboot code
  54. li t0, 0x0001006f
  55. sw t0, 0(zero)
  56. // Jump to main code
  57. j 0x00010000
  58. .equ SPI_BASE, 0x82000000
  59. .equ SPICR0, 4 * 0x08
  60. .equ SPICR1, 4 * 0x09
  61. .equ SPICR2, 4 * 0x0a
  62. .equ SPIBR, 4 * 0x0b
  63. .equ SPISR, 4 * 0x0c
  64. .equ SPITXDR, 4 * 0x0d
  65. .equ SPIRXDR, 4 * 0x0e
  66. .equ SPICSR, 4 * 0x0f
  67. spi_init:
  68. li a0, SPI_BASE
  69. li a1, 0xff
  70. sw a1, SPICR0(a0)
  71. li a1, 0x80
  72. sw a1, SPICR1(a0)
  73. li a1, 0xc0
  74. sw a1, SPICR2(a0)
  75. li a1, 0x03
  76. sw a1, SPIBR(a0)
  77. li a1, 0x0f
  78. sw a1, SPICSR(a0)
  79. ret
  80. // Params:
  81. // a0 - destination pointer
  82. // a1 - length (bytes)
  83. // a2 - flash offset
  84. //
  85. spi_flash_read:
  86. // Save params
  87. mv s0, a0
  88. mv s1, a1
  89. mv s2, ra
  90. // Setup CS
  91. li t0, SPI_BASE
  92. li t1, 0x0e
  93. sw t1, SPICSR(t0)
  94. // Send command
  95. li a0, 0x03
  96. jal _spi_do_one
  97. srli a0, a2, 16
  98. and a0, a0, 0xff
  99. jal _spi_do_one
  100. srli a0, a2, 8
  101. and a0, a0, 0xff
  102. jal _spi_do_one
  103. and a0, a2, 0xff
  104. jal _spi_do_one
  105. // Read loop
  106. _spi_loop:
  107. li a0, 0x00
  108. jal _spi_do_one
  109. sb a0, 0(s0)
  110. addi s0, s0, 1
  111. addi s1, s1, -1
  112. bne s1, zero, _spi_loop
  113. // Release CS
  114. li t0, SPI_BASE
  115. li t1, 0x0f
  116. sw t1, SPICSR(t0)
  117. // Done
  118. jr s2
  119. // Params: a0 - Data to TX
  120. // Returns: a0 - RX data
  121. // Clobbers t0, t1
  122. _spi_do_one:
  123. li t0, SPI_BASE
  124. li t1, 0x08
  125. // Write TX data
  126. sw a0, SPITXDR(t0)
  127. // Wait for RXRDY
  128. 1:
  129. lw a0, SPISR(t0)
  130. and a0, a0, t1
  131. bne a0, t1, 1b
  132. // Read RX data
  133. lw a0, SPIRXDR(t0)
  134. // Done
  135. ret