xref: /linux/arch/mips/kernel/cps-vec-ns16550.S (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
12874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
2609cf6f2SPaul Burton/*
3609cf6f2SPaul Burton * Copyright (C) 2015 Imagination Technologies
4fb615d61SPaul Burton * Author: Paul Burton <paul.burton@mips.com>
5609cf6f2SPaul Burton */
6609cf6f2SPaul Burton
7609cf6f2SPaul Burton#include <asm/addrspace.h>
8609cf6f2SPaul Burton#include <asm/asm.h>
9609cf6f2SPaul Burton#include <asm/asm-offsets.h>
10609cf6f2SPaul Burton#include <asm/mipsregs.h>
11609cf6f2SPaul Burton#include <asm/regdef.h>
12609cf6f2SPaul Burton#include <linux/serial_reg.h>
13609cf6f2SPaul Burton
14609cf6f2SPaul Burton#define UART_TX_OFS	(UART_TX << CONFIG_MIPS_CPS_NS16550_SHIFT)
15609cf6f2SPaul Burton#define UART_LSR_OFS	(UART_LSR << CONFIG_MIPS_CPS_NS16550_SHIFT)
16609cf6f2SPaul Burton
17*ad42e0a8SSerge Semin#if CONFIG_MIPS_CPS_NS16550_WIDTH == 1
18*ad42e0a8SSerge Semin# define UART_L		lb
19*ad42e0a8SSerge Semin# define UART_S		sb
20*ad42e0a8SSerge Semin#elif CONFIG_MIPS_CPS_NS16550_WIDTH == 2
21*ad42e0a8SSerge Semin# define UART_L		lh
22*ad42e0a8SSerge Semin# define UART_S		sh
23*ad42e0a8SSerge Semin#elif CONFIG_MIPS_CPS_NS16550_WIDTH == 4
24*ad42e0a8SSerge Semin# define UART_L		lw
25*ad42e0a8SSerge Semin# define UART_S		sw
26*ad42e0a8SSerge Semin#else
27*ad42e0a8SSerge Semin# define UART_L		lb
28*ad42e0a8SSerge Semin# define UART_S		sb
29*ad42e0a8SSerge Semin#endif
30*ad42e0a8SSerge Semin
31609cf6f2SPaul Burton/**
32609cf6f2SPaul Burton * _mips_cps_putc() - write a character to the UART
33609cf6f2SPaul Burton * @a0: ASCII character to write
34609cf6f2SPaul Burton * @t9: UART base address
35609cf6f2SPaul Burton */
36609cf6f2SPaul BurtonLEAF(_mips_cps_putc)
37*ad42e0a8SSerge Semin1:	UART_L		t0, UART_LSR_OFS(t9)
38609cf6f2SPaul Burton	andi		t0, t0, UART_LSR_TEMT
39609cf6f2SPaul Burton	beqz		t0, 1b
40*ad42e0a8SSerge Semin	UART_S		a0, UART_TX_OFS(t9)
41609cf6f2SPaul Burton	jr		ra
42609cf6f2SPaul Burton	END(_mips_cps_putc)
43609cf6f2SPaul Burton
44609cf6f2SPaul Burton/**
45609cf6f2SPaul Burton * _mips_cps_puts() - write a string to the UART
46609cf6f2SPaul Burton * @a0: pointer to NULL-terminated ASCII string
47609cf6f2SPaul Burton * @t9: UART base address
48609cf6f2SPaul Burton *
49609cf6f2SPaul Burton * Write a null-terminated ASCII string to the UART.
50609cf6f2SPaul Burton */
51609cf6f2SPaul BurtonNESTED(_mips_cps_puts, 0, ra)
52609cf6f2SPaul Burton	move		s7, ra
53609cf6f2SPaul Burton	move		s6, a0
54609cf6f2SPaul Burton
55609cf6f2SPaul Burton1:	lb		a0, 0(s6)
56609cf6f2SPaul Burton	beqz		a0, 2f
57609cf6f2SPaul Burton	jal		_mips_cps_putc
58609cf6f2SPaul Burton	PTR_ADDIU	s6, s6, 1
59609cf6f2SPaul Burton	b		1b
60609cf6f2SPaul Burton
61609cf6f2SPaul Burton2:	jr		s7
62609cf6f2SPaul Burton	END(_mips_cps_puts)
63609cf6f2SPaul Burton
64609cf6f2SPaul Burton/**
65609cf6f2SPaul Burton * _mips_cps_putx4 - write a 4b hex value to the UART
66609cf6f2SPaul Burton * @a0: the 4b value to write to the UART
67609cf6f2SPaul Burton * @t9: UART base address
68609cf6f2SPaul Burton *
69609cf6f2SPaul Burton * Write a single hexadecimal character to the UART.
70609cf6f2SPaul Burton */
71609cf6f2SPaul BurtonNESTED(_mips_cps_putx4, 0, ra)
72609cf6f2SPaul Burton	andi		a0, a0, 0xf
73609cf6f2SPaul Burton	li		t0, '0'
74609cf6f2SPaul Burton	blt		a0, 10, 1f
75609cf6f2SPaul Burton	li		t0, 'a'
76609cf6f2SPaul Burton	addiu		a0, a0, -10
77609cf6f2SPaul Burton1:	addu		a0, a0, t0
78609cf6f2SPaul Burton	b		_mips_cps_putc
79609cf6f2SPaul Burton	END(_mips_cps_putx4)
80609cf6f2SPaul Burton
81609cf6f2SPaul Burton/**
82609cf6f2SPaul Burton * _mips_cps_putx8 - write an 8b hex value to the UART
83609cf6f2SPaul Burton * @a0: the 8b value to write to the UART
84609cf6f2SPaul Burton * @t9: UART base address
85609cf6f2SPaul Burton *
86609cf6f2SPaul Burton * Write an 8 bit value (ie. 2 hexadecimal characters) to the UART.
87609cf6f2SPaul Burton */
88609cf6f2SPaul BurtonNESTED(_mips_cps_putx8, 0, ra)
89609cf6f2SPaul Burton	move		s3, ra
90609cf6f2SPaul Burton	move		s2, a0
91609cf6f2SPaul Burton	srl		a0, a0, 4
92609cf6f2SPaul Burton	jal		_mips_cps_putx4
93609cf6f2SPaul Burton	move		a0, s2
94609cf6f2SPaul Burton	move		ra, s3
95609cf6f2SPaul Burton	b		_mips_cps_putx4
96609cf6f2SPaul Burton	END(_mips_cps_putx8)
97609cf6f2SPaul Burton
98609cf6f2SPaul Burton/**
99609cf6f2SPaul Burton * _mips_cps_putx16 - write a 16b hex value to the UART
100609cf6f2SPaul Burton * @a0: the 16b value to write to the UART
101609cf6f2SPaul Burton * @t9: UART base address
102609cf6f2SPaul Burton *
103609cf6f2SPaul Burton * Write a 16 bit value (ie. 4 hexadecimal characters) to the UART.
104609cf6f2SPaul Burton */
105609cf6f2SPaul BurtonNESTED(_mips_cps_putx16, 0, ra)
106609cf6f2SPaul Burton	move		s5, ra
107609cf6f2SPaul Burton	move		s4, a0
108609cf6f2SPaul Burton	srl		a0, a0, 8
109609cf6f2SPaul Burton	jal		_mips_cps_putx8
110609cf6f2SPaul Burton	move		a0, s4
111609cf6f2SPaul Burton	move		ra, s5
112609cf6f2SPaul Burton	b		_mips_cps_putx8
113609cf6f2SPaul Burton	END(_mips_cps_putx16)
114609cf6f2SPaul Burton
115609cf6f2SPaul Burton/**
116609cf6f2SPaul Burton * _mips_cps_putx32 - write a 32b hex value to the UART
117609cf6f2SPaul Burton * @a0: the 32b value to write to the UART
118609cf6f2SPaul Burton * @t9: UART base address
119609cf6f2SPaul Burton *
120609cf6f2SPaul Burton * Write a 32 bit value (ie. 8 hexadecimal characters) to the UART.
121609cf6f2SPaul Burton */
122609cf6f2SPaul BurtonNESTED(_mips_cps_putx32, 0, ra)
123609cf6f2SPaul Burton	move		s7, ra
124609cf6f2SPaul Burton	move		s6, a0
125609cf6f2SPaul Burton	srl		a0, a0, 16
126609cf6f2SPaul Burton	jal		_mips_cps_putx16
127609cf6f2SPaul Burton	move		a0, s6
128609cf6f2SPaul Burton	move		ra, s7
129609cf6f2SPaul Burton	b		_mips_cps_putx16
130609cf6f2SPaul Burton	END(_mips_cps_putx32)
131609cf6f2SPaul Burton
132609cf6f2SPaul Burton#ifdef CONFIG_64BIT
133609cf6f2SPaul Burton
134609cf6f2SPaul Burton/**
135609cf6f2SPaul Burton * _mips_cps_putx64 - write a 64b hex value to the UART
136609cf6f2SPaul Burton * @a0: the 64b value to write to the UART
137609cf6f2SPaul Burton * @t9: UART base address
138609cf6f2SPaul Burton *
139609cf6f2SPaul Burton * Write a 64 bit value (ie. 16 hexadecimal characters) to the UART.
140609cf6f2SPaul Burton */
141609cf6f2SPaul BurtonNESTED(_mips_cps_putx64, 0, ra)
142609cf6f2SPaul Burton	move		sp, ra
143609cf6f2SPaul Burton	move		s8, a0
144609cf6f2SPaul Burton	dsrl32		a0, a0, 0
145609cf6f2SPaul Burton	jal		_mips_cps_putx32
146609cf6f2SPaul Burton	move		a0, s8
147609cf6f2SPaul Burton	move		ra, sp
148609cf6f2SPaul Burton	b		_mips_cps_putx32
149609cf6f2SPaul Burton	END(_mips_cps_putx64)
150609cf6f2SPaul Burton
151609cf6f2SPaul Burton#define _mips_cps_putxlong _mips_cps_putx64
152609cf6f2SPaul Burton
153609cf6f2SPaul Burton#else /* !CONFIG_64BIT */
154609cf6f2SPaul Burton
155609cf6f2SPaul Burton#define _mips_cps_putxlong _mips_cps_putx32
156609cf6f2SPaul Burton
157609cf6f2SPaul Burton#endif /* !CONFIG_64BIT */
158609cf6f2SPaul Burton
159609cf6f2SPaul Burton/**
160609cf6f2SPaul Burton * mips_cps_bev_dump() - dump relevant exception state to UART
161609cf6f2SPaul Burton * @a0: pointer to NULL-terminated ASCII string naming the exception
162609cf6f2SPaul Burton *
163609cf6f2SPaul Burton * Write information that may be useful in debugging an exception to the
164609cf6f2SPaul Burton * UART configured by CONFIG_MIPS_CPS_NS16550_*. As this BEV exception
165609cf6f2SPaul Burton * will only be run if something goes horribly wrong very early during
166609cf6f2SPaul Burton * the bringup of a core and it is very likely to be unsafe to perform
167609cf6f2SPaul Burton * memory accesses at that point (cache state indeterminate, EVA may not
168609cf6f2SPaul Burton * be configured, coherence may be disabled) let alone have a stack,
169609cf6f2SPaul Burton * this is all written in assembly using only registers & unmapped
170609cf6f2SPaul Burton * uncached access to the UART registers.
171609cf6f2SPaul Burton */
172609cf6f2SPaul BurtonLEAF(mips_cps_bev_dump)
173609cf6f2SPaul Burton	move		s0, ra
174609cf6f2SPaul Burton	move		s1, a0
175609cf6f2SPaul Burton
176609cf6f2SPaul Burton	li		t9, CKSEG1ADDR(CONFIG_MIPS_CPS_NS16550_BASE)
177609cf6f2SPaul Burton
178609cf6f2SPaul Burton	PTR_LA		a0, str_newline
179609cf6f2SPaul Burton	jal		_mips_cps_puts
180609cf6f2SPaul Burton	PTR_LA		a0, str_bev
181609cf6f2SPaul Burton	jal		_mips_cps_puts
182609cf6f2SPaul Burton	move		a0, s1
183609cf6f2SPaul Burton	jal		_mips_cps_puts
184609cf6f2SPaul Burton	PTR_LA		a0, str_newline
185609cf6f2SPaul Burton	jal		_mips_cps_puts
186609cf6f2SPaul Burton	PTR_LA		a0, str_newline
187609cf6f2SPaul Burton	jal		_mips_cps_puts
188609cf6f2SPaul Burton
189609cf6f2SPaul Burton#define DUMP_COP0_REG(reg, name, sz, _mfc0)		\
190609cf6f2SPaul Burton	PTR_LA		a0, 8f;				\
191609cf6f2SPaul Burton	jal		_mips_cps_puts;			\
192609cf6f2SPaul Burton	_mfc0		a0, reg;			\
193609cf6f2SPaul Burton	jal		_mips_cps_putx##sz;		\
194609cf6f2SPaul Burton	PTR_LA		a0, str_newline;		\
195609cf6f2SPaul Burton	jal		_mips_cps_puts;			\
196609cf6f2SPaul Burton	TEXT(name)
197609cf6f2SPaul Burton
198609cf6f2SPaul Burton	DUMP_COP0_REG(CP0_CAUSE,    "Cause:    0x", 32, mfc0)
199609cf6f2SPaul Burton	DUMP_COP0_REG(CP0_STATUS,   "Status:   0x", 32, mfc0)
200609cf6f2SPaul Burton	DUMP_COP0_REG(CP0_EBASE,    "EBase:    0x", long, MFC0)
201609cf6f2SPaul Burton	DUMP_COP0_REG(CP0_BADVADDR, "BadVAddr: 0x", long, MFC0)
202609cf6f2SPaul Burton	DUMP_COP0_REG(CP0_BADINSTR, "BadInstr: 0x", 32, mfc0)
203609cf6f2SPaul Burton
204609cf6f2SPaul Burton	PTR_LA		a0, str_newline
205609cf6f2SPaul Burton	jal		_mips_cps_puts
206609cf6f2SPaul Burton	jr		s0
207609cf6f2SPaul Burton	END(mips_cps_bev_dump)
208609cf6f2SPaul Burton
209609cf6f2SPaul Burton.pushsection	.data
210609cf6f2SPaul Burtonstr_bev: .asciiz "BEV Exception: "
211609cf6f2SPaul Burtonstr_newline: .asciiz "\r\n"
212609cf6f2SPaul Burton.popsection
213