cps-vec-ns16550.S 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * Copyright (C) 2015 Imagination Technologies
  4. * Author: Paul Burton <[email protected]>
  5. */
  6. #include <asm/addrspace.h>
  7. #include <asm/asm.h>
  8. #include <asm/asm-offsets.h>
  9. #include <asm/mipsregs.h>
  10. #include <asm/regdef.h>
  11. #include <linux/serial_reg.h>
  12. #define UART_TX_OFS (UART_TX << CONFIG_MIPS_CPS_NS16550_SHIFT)
  13. #define UART_LSR_OFS (UART_LSR << CONFIG_MIPS_CPS_NS16550_SHIFT)
  14. #if CONFIG_MIPS_CPS_NS16550_WIDTH == 1
  15. # define UART_L lb
  16. # define UART_S sb
  17. #elif CONFIG_MIPS_CPS_NS16550_WIDTH == 2
  18. # define UART_L lh
  19. # define UART_S sh
  20. #elif CONFIG_MIPS_CPS_NS16550_WIDTH == 4
  21. # define UART_L lw
  22. # define UART_S sw
  23. #else
  24. # define UART_L lb
  25. # define UART_S sb
  26. #endif
  27. /**
  28. * _mips_cps_putc() - write a character to the UART
  29. * @a0: ASCII character to write
  30. * @t9: UART base address
  31. */
  32. LEAF(_mips_cps_putc)
  33. 1: UART_L t0, UART_LSR_OFS(t9)
  34. andi t0, t0, UART_LSR_TEMT
  35. beqz t0, 1b
  36. UART_S a0, UART_TX_OFS(t9)
  37. jr ra
  38. END(_mips_cps_putc)
  39. /**
  40. * _mips_cps_puts() - write a string to the UART
  41. * @a0: pointer to NULL-terminated ASCII string
  42. * @t9: UART base address
  43. *
  44. * Write a null-terminated ASCII string to the UART.
  45. */
  46. NESTED(_mips_cps_puts, 0, ra)
  47. move s7, ra
  48. move s6, a0
  49. 1: lb a0, 0(s6)
  50. beqz a0, 2f
  51. jal _mips_cps_putc
  52. PTR_ADDIU s6, s6, 1
  53. b 1b
  54. 2: jr s7
  55. END(_mips_cps_puts)
  56. /**
  57. * _mips_cps_putx4 - write a 4b hex value to the UART
  58. * @a0: the 4b value to write to the UART
  59. * @t9: UART base address
  60. *
  61. * Write a single hexadecimal character to the UART.
  62. */
  63. NESTED(_mips_cps_putx4, 0, ra)
  64. andi a0, a0, 0xf
  65. li t0, '0'
  66. blt a0, 10, 1f
  67. li t0, 'a'
  68. addiu a0, a0, -10
  69. 1: addu a0, a0, t0
  70. b _mips_cps_putc
  71. END(_mips_cps_putx4)
  72. /**
  73. * _mips_cps_putx8 - write an 8b hex value to the UART
  74. * @a0: the 8b value to write to the UART
  75. * @t9: UART base address
  76. *
  77. * Write an 8 bit value (ie. 2 hexadecimal characters) to the UART.
  78. */
  79. NESTED(_mips_cps_putx8, 0, ra)
  80. move s3, ra
  81. move s2, a0
  82. srl a0, a0, 4
  83. jal _mips_cps_putx4
  84. move a0, s2
  85. move ra, s3
  86. b _mips_cps_putx4
  87. END(_mips_cps_putx8)
  88. /**
  89. * _mips_cps_putx16 - write a 16b hex value to the UART
  90. * @a0: the 16b value to write to the UART
  91. * @t9: UART base address
  92. *
  93. * Write a 16 bit value (ie. 4 hexadecimal characters) to the UART.
  94. */
  95. NESTED(_mips_cps_putx16, 0, ra)
  96. move s5, ra
  97. move s4, a0
  98. srl a0, a0, 8
  99. jal _mips_cps_putx8
  100. move a0, s4
  101. move ra, s5
  102. b _mips_cps_putx8
  103. END(_mips_cps_putx16)
  104. /**
  105. * _mips_cps_putx32 - write a 32b hex value to the UART
  106. * @a0: the 32b value to write to the UART
  107. * @t9: UART base address
  108. *
  109. * Write a 32 bit value (ie. 8 hexadecimal characters) to the UART.
  110. */
  111. NESTED(_mips_cps_putx32, 0, ra)
  112. move s7, ra
  113. move s6, a0
  114. srl a0, a0, 16
  115. jal _mips_cps_putx16
  116. move a0, s6
  117. move ra, s7
  118. b _mips_cps_putx16
  119. END(_mips_cps_putx32)
  120. #ifdef CONFIG_64BIT
  121. /**
  122. * _mips_cps_putx64 - write a 64b hex value to the UART
  123. * @a0: the 64b value to write to the UART
  124. * @t9: UART base address
  125. *
  126. * Write a 64 bit value (ie. 16 hexadecimal characters) to the UART.
  127. */
  128. NESTED(_mips_cps_putx64, 0, ra)
  129. move sp, ra
  130. move s8, a0
  131. dsrl32 a0, a0, 0
  132. jal _mips_cps_putx32
  133. move a0, s8
  134. move ra, sp
  135. b _mips_cps_putx32
  136. END(_mips_cps_putx64)
  137. #define _mips_cps_putxlong _mips_cps_putx64
  138. #else /* !CONFIG_64BIT */
  139. #define _mips_cps_putxlong _mips_cps_putx32
  140. #endif /* !CONFIG_64BIT */
  141. /**
  142. * mips_cps_bev_dump() - dump relevant exception state to UART
  143. * @a0: pointer to NULL-terminated ASCII string naming the exception
  144. *
  145. * Write information that may be useful in debugging an exception to the
  146. * UART configured by CONFIG_MIPS_CPS_NS16550_*. As this BEV exception
  147. * will only be run if something goes horribly wrong very early during
  148. * the bringup of a core and it is very likely to be unsafe to perform
  149. * memory accesses at that point (cache state indeterminate, EVA may not
  150. * be configured, coherence may be disabled) let alone have a stack,
  151. * this is all written in assembly using only registers & unmapped
  152. * uncached access to the UART registers.
  153. */
  154. LEAF(mips_cps_bev_dump)
  155. move s0, ra
  156. move s1, a0
  157. li t9, CKSEG1ADDR(CONFIG_MIPS_CPS_NS16550_BASE)
  158. PTR_LA a0, str_newline
  159. jal _mips_cps_puts
  160. PTR_LA a0, str_bev
  161. jal _mips_cps_puts
  162. move a0, s1
  163. jal _mips_cps_puts
  164. PTR_LA a0, str_newline
  165. jal _mips_cps_puts
  166. PTR_LA a0, str_newline
  167. jal _mips_cps_puts
  168. #define DUMP_COP0_REG(reg, name, sz, _mfc0) \
  169. PTR_LA a0, 8f; \
  170. jal _mips_cps_puts; \
  171. _mfc0 a0, reg; \
  172. jal _mips_cps_putx##sz; \
  173. PTR_LA a0, str_newline; \
  174. jal _mips_cps_puts; \
  175. TEXT(name)
  176. DUMP_COP0_REG(CP0_CAUSE, "Cause: 0x", 32, mfc0)
  177. DUMP_COP0_REG(CP0_STATUS, "Status: 0x", 32, mfc0)
  178. DUMP_COP0_REG(CP0_EBASE, "EBase: 0x", long, MFC0)
  179. DUMP_COP0_REG(CP0_BADVADDR, "BadVAddr: 0x", long, MFC0)
  180. DUMP_COP0_REG(CP0_BADINSTR, "BadInstr: 0x", 32, mfc0)
  181. PTR_LA a0, str_newline
  182. jal _mips_cps_puts
  183. jr s0
  184. END(mips_cps_bev_dump)
  185. .pushsection .data
  186. str_bev: .asciiz "BEV Exception: "
  187. str_newline: .asciiz "\r\n"
  188. .popsection