/* SPDX-License-Identifier: GPL-2.0-or-later */1/*2* Copyright (C) 2015 Imagination Technologies3* Author: Paul Burton <[email protected]>4*/56#include <asm/addrspace.h>7#include <asm/asm.h>8#include <asm/asm-offsets.h>9#include <asm/mipsregs.h>10#include <asm/regdef.h>11#include <linux/serial_reg.h>1213#define UART_TX_OFS (UART_TX << CONFIG_MIPS_CPS_NS16550_SHIFT)14#define UART_LSR_OFS (UART_LSR << CONFIG_MIPS_CPS_NS16550_SHIFT)1516#if CONFIG_MIPS_CPS_NS16550_WIDTH == 117# define UART_L lb18# define UART_S sb19#elif CONFIG_MIPS_CPS_NS16550_WIDTH == 220# define UART_L lh21# define UART_S sh22#elif CONFIG_MIPS_CPS_NS16550_WIDTH == 423# define UART_L lw24# define UART_S sw25#else26# define UART_L lb27# define UART_S sb28#endif2930/**31* _mips_cps_putc() - write a character to the UART32* @a0: ASCII character to write33* @t9: UART base address34*/35LEAF(_mips_cps_putc)361: UART_L t0, UART_LSR_OFS(t9)37andi t0, t0, UART_LSR_TEMT38beqz t0, 1b39UART_S a0, UART_TX_OFS(t9)40jr ra41END(_mips_cps_putc)4243/**44* _mips_cps_puts() - write a string to the UART45* @a0: pointer to NULL-terminated ASCII string46* @t9: UART base address47*48* Write a null-terminated ASCII string to the UART.49*/50NESTED(_mips_cps_puts, 0, ra)51move s7, ra52move s6, a053541: lb a0, 0(s6)55beqz a0, 2f56jal _mips_cps_putc57PTR_ADDIU s6, s6, 158b 1b59602: jr s761END(_mips_cps_puts)6263/**64* _mips_cps_putx4 - write a 4b hex value to the UART65* @a0: the 4b value to write to the UART66* @t9: UART base address67*68* Write a single hexadecimal character to the UART.69*/70NESTED(_mips_cps_putx4, 0, ra)71andi a0, a0, 0xf72li t0, '0'73blt a0, 10, 1f74li t0, 'a'75addiu a0, a0, -10761: addu a0, a0, t077b _mips_cps_putc78END(_mips_cps_putx4)7980/**81* _mips_cps_putx8 - write an 8b hex value to the UART82* @a0: the 8b value to write to the UART83* @t9: UART base address84*85* Write an 8 bit value (ie. 2 hexadecimal characters) to the UART.86*/87NESTED(_mips_cps_putx8, 0, ra)88move s3, ra89move s2, a090srl a0, a0, 491jal _mips_cps_putx492move a0, s293move ra, s394b _mips_cps_putx495END(_mips_cps_putx8)9697/**98* _mips_cps_putx16 - write a 16b hex value to the UART99* @a0: the 16b value to write to the UART100* @t9: UART base address101*102* Write a 16 bit value (ie. 4 hexadecimal characters) to the UART.103*/104NESTED(_mips_cps_putx16, 0, ra)105move s5, ra106move s4, a0107srl a0, a0, 8108jal _mips_cps_putx8109move a0, s4110move ra, s5111b _mips_cps_putx8112END(_mips_cps_putx16)113114/**115* _mips_cps_putx32 - write a 32b hex value to the UART116* @a0: the 32b value to write to the UART117* @t9: UART base address118*119* Write a 32 bit value (ie. 8 hexadecimal characters) to the UART.120*/121NESTED(_mips_cps_putx32, 0, ra)122move s7, ra123move s6, a0124srl a0, a0, 16125jal _mips_cps_putx16126move a0, s6127move ra, s7128b _mips_cps_putx16129END(_mips_cps_putx32)130131#ifdef CONFIG_64BIT132133/**134* _mips_cps_putx64 - write a 64b hex value to the UART135* @a0: the 64b value to write to the UART136* @t9: UART base address137*138* Write a 64 bit value (ie. 16 hexadecimal characters) to the UART.139*/140NESTED(_mips_cps_putx64, 0, ra)141move sp, ra142move s8, a0143dsrl32 a0, a0, 0144jal _mips_cps_putx32145move a0, s8146move ra, sp147b _mips_cps_putx32148END(_mips_cps_putx64)149150#define _mips_cps_putxlong _mips_cps_putx64151152#else /* !CONFIG_64BIT */153154#define _mips_cps_putxlong _mips_cps_putx32155156#endif /* !CONFIG_64BIT */157158/**159* mips_cps_bev_dump() - dump relevant exception state to UART160* @a0: pointer to NULL-terminated ASCII string naming the exception161*162* Write information that may be useful in debugging an exception to the163* UART configured by CONFIG_MIPS_CPS_NS16550_*. As this BEV exception164* will only be run if something goes horribly wrong very early during165* the bringup of a core and it is very likely to be unsafe to perform166* memory accesses at that point (cache state indeterminate, EVA may not167* be configured, coherence may be disabled) let alone have a stack,168* this is all written in assembly using only registers & unmapped169* uncached access to the UART registers.170*/171LEAF(mips_cps_bev_dump)172move s0, ra173move s1, a0174175li t9, CKSEG1ADDR(CONFIG_MIPS_CPS_NS16550_BASE)176177PTR_LA a0, str_newline178jal _mips_cps_puts179PTR_LA a0, str_bev180jal _mips_cps_puts181move a0, s1182jal _mips_cps_puts183PTR_LA a0, str_newline184jal _mips_cps_puts185PTR_LA a0, str_newline186jal _mips_cps_puts187188#define DUMP_COP0_REG(reg, name, sz, _mfc0) \189PTR_LA a0, 8f; \190jal _mips_cps_puts; \191_mfc0 a0, reg; \192jal _mips_cps_putx##sz; \193PTR_LA a0, str_newline; \194jal _mips_cps_puts; \195TEXT(name)196197DUMP_COP0_REG(CP0_CAUSE, "Cause: 0x", 32, mfc0)198DUMP_COP0_REG(CP0_STATUS, "Status: 0x", 32, mfc0)199DUMP_COP0_REG(CP0_EBASE, "EBase: 0x", long, MFC0)200DUMP_COP0_REG(CP0_BADVADDR, "BadVAddr: 0x", long, MFC0)201DUMP_COP0_REG(CP0_BADINSTR, "BadInstr: 0x", 32, mfc0)202203PTR_LA a0, str_newline204jal _mips_cps_puts205jr s0206END(mips_cps_bev_dump)207208.pushsection .data209str_bev: .asciiz "BEV Exception: "210str_newline: .asciiz "\r\n"211.popsection212213214