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