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