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