Linux Audio

Check our new training course

In-person Linux kernel drivers training

Jun 16-20, 2025
Register
Loading...
Note: File does not exist in v3.1.
  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