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