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