Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * Copyright (C) 2015 Imagination Technologies
0004  * Author: Paul Burton <paul.burton@mips.com>
0005  */
0006 
0007 #include <asm/addrspace.h>
0008 #include <asm/asm.h>
0009 #include <asm/asm-offsets.h>
0010 #include <asm/mipsregs.h>
0011 #include <asm/regdef.h>
0012 #include <linux/serial_reg.h>
0013 
0014 #define UART_TX_OFS (UART_TX << CONFIG_MIPS_CPS_NS16550_SHIFT)
0015 #define UART_LSR_OFS    (UART_LSR << CONFIG_MIPS_CPS_NS16550_SHIFT)
0016 
0017 #if CONFIG_MIPS_CPS_NS16550_WIDTH == 1
0018 # define UART_L     lb
0019 # define UART_S     sb
0020 #elif CONFIG_MIPS_CPS_NS16550_WIDTH == 2
0021 # define UART_L     lh
0022 # define UART_S     sh
0023 #elif CONFIG_MIPS_CPS_NS16550_WIDTH == 4
0024 # define UART_L     lw
0025 # define UART_S     sw
0026 #else
0027 # define UART_L     lb
0028 # define UART_S     sb
0029 #endif
0030 
0031 /**
0032  * _mips_cps_putc() - write a character to the UART
0033  * @a0: ASCII character to write
0034  * @t9: UART base address
0035  */
0036 LEAF(_mips_cps_putc)
0037 1:  UART_L      t0, UART_LSR_OFS(t9)
0038     andi        t0, t0, UART_LSR_TEMT
0039     beqz        t0, 1b
0040     UART_S      a0, UART_TX_OFS(t9)
0041     jr      ra
0042     END(_mips_cps_putc)
0043 
0044 /**
0045  * _mips_cps_puts() - write a string to the UART
0046  * @a0: pointer to NULL-terminated ASCII string
0047  * @t9: UART base address
0048  *
0049  * Write a null-terminated ASCII string to the UART.
0050  */
0051 NESTED(_mips_cps_puts, 0, ra)
0052     move        s7, ra
0053     move        s6, a0
0054 
0055 1:  lb      a0, 0(s6)
0056     beqz        a0, 2f
0057     jal     _mips_cps_putc
0058     PTR_ADDIU   s6, s6, 1
0059     b       1b
0060 
0061 2:  jr      s7
0062     END(_mips_cps_puts)
0063 
0064 /**
0065  * _mips_cps_putx4 - write a 4b hex value to the UART
0066  * @a0: the 4b value to write to the UART
0067  * @t9: UART base address
0068  *
0069  * Write a single hexadecimal character to the UART.
0070  */
0071 NESTED(_mips_cps_putx4, 0, ra)
0072     andi        a0, a0, 0xf
0073     li      t0, '0'
0074     blt     a0, 10, 1f
0075     li      t0, 'a'
0076     addiu       a0, a0, -10
0077 1:  addu        a0, a0, t0
0078     b       _mips_cps_putc
0079     END(_mips_cps_putx4)
0080 
0081 /**
0082  * _mips_cps_putx8 - write an 8b hex value to the UART
0083  * @a0: the 8b value to write to the UART
0084  * @t9: UART base address
0085  *
0086  * Write an 8 bit value (ie. 2 hexadecimal characters) to the UART.
0087  */
0088 NESTED(_mips_cps_putx8, 0, ra)
0089     move        s3, ra
0090     move        s2, a0
0091     srl     a0, a0, 4
0092     jal     _mips_cps_putx4
0093     move        a0, s2
0094     move        ra, s3
0095     b       _mips_cps_putx4
0096     END(_mips_cps_putx8)
0097 
0098 /**
0099  * _mips_cps_putx16 - write a 16b hex value to the UART
0100  * @a0: the 16b value to write to the UART
0101  * @t9: UART base address
0102  *
0103  * Write a 16 bit value (ie. 4 hexadecimal characters) to the UART.
0104  */
0105 NESTED(_mips_cps_putx16, 0, ra)
0106     move        s5, ra
0107     move        s4, a0
0108     srl     a0, a0, 8
0109     jal     _mips_cps_putx8
0110     move        a0, s4
0111     move        ra, s5
0112     b       _mips_cps_putx8
0113     END(_mips_cps_putx16)
0114 
0115 /**
0116  * _mips_cps_putx32 - write a 32b hex value to the UART
0117  * @a0: the 32b value to write to the UART
0118  * @t9: UART base address
0119  *
0120  * Write a 32 bit value (ie. 8 hexadecimal characters) to the UART.
0121  */
0122 NESTED(_mips_cps_putx32, 0, ra)
0123     move        s7, ra
0124     move        s6, a0
0125     srl     a0, a0, 16
0126     jal     _mips_cps_putx16
0127     move        a0, s6
0128     move        ra, s7
0129     b       _mips_cps_putx16
0130     END(_mips_cps_putx32)
0131 
0132 #ifdef CONFIG_64BIT
0133 
0134 /**
0135  * _mips_cps_putx64 - write a 64b hex value to the UART
0136  * @a0: the 64b value to write to the UART
0137  * @t9: UART base address
0138  *
0139  * Write a 64 bit value (ie. 16 hexadecimal characters) to the UART.
0140  */
0141 NESTED(_mips_cps_putx64, 0, ra)
0142     move        sp, ra
0143     move        s8, a0
0144     dsrl32      a0, a0, 0
0145     jal     _mips_cps_putx32
0146     move        a0, s8
0147     move        ra, sp
0148     b       _mips_cps_putx32
0149     END(_mips_cps_putx64)
0150 
0151 #define _mips_cps_putxlong _mips_cps_putx64
0152 
0153 #else /* !CONFIG_64BIT */
0154 
0155 #define _mips_cps_putxlong _mips_cps_putx32
0156 
0157 #endif /* !CONFIG_64BIT */
0158 
0159 /**
0160  * mips_cps_bev_dump() - dump relevant exception state to UART
0161  * @a0: pointer to NULL-terminated ASCII string naming the exception
0162  *
0163  * Write information that may be useful in debugging an exception to the
0164  * UART configured by CONFIG_MIPS_CPS_NS16550_*. As this BEV exception
0165  * will only be run if something goes horribly wrong very early during
0166  * the bringup of a core and it is very likely to be unsafe to perform
0167  * memory accesses at that point (cache state indeterminate, EVA may not
0168  * be configured, coherence may be disabled) let alone have a stack,
0169  * this is all written in assembly using only registers & unmapped
0170  * uncached access to the UART registers.
0171  */
0172 LEAF(mips_cps_bev_dump)
0173     move        s0, ra
0174     move        s1, a0
0175 
0176     li      t9, CKSEG1ADDR(CONFIG_MIPS_CPS_NS16550_BASE)
0177 
0178     PTR_LA      a0, str_newline
0179     jal     _mips_cps_puts
0180     PTR_LA      a0, str_bev
0181     jal     _mips_cps_puts
0182     move        a0, s1
0183     jal     _mips_cps_puts
0184     PTR_LA      a0, str_newline
0185     jal     _mips_cps_puts
0186     PTR_LA      a0, str_newline
0187     jal     _mips_cps_puts
0188 
0189 #define DUMP_COP0_REG(reg, name, sz, _mfc0)     \
0190     PTR_LA      a0, 8f;             \
0191     jal     _mips_cps_puts;         \
0192     _mfc0       a0, reg;            \
0193     jal     _mips_cps_putx##sz;     \
0194     PTR_LA      a0, str_newline;        \
0195     jal     _mips_cps_puts;         \
0196     TEXT(name)
0197 
0198     DUMP_COP0_REG(CP0_CAUSE,    "Cause:    0x", 32, mfc0)
0199     DUMP_COP0_REG(CP0_STATUS,   "Status:   0x", 32, mfc0)
0200     DUMP_COP0_REG(CP0_EBASE,    "EBase:    0x", long, MFC0)
0201     DUMP_COP0_REG(CP0_BADVADDR, "BadVAddr: 0x", long, MFC0)
0202     DUMP_COP0_REG(CP0_BADINSTR, "BadInstr: 0x", 32, mfc0)
0203 
0204     PTR_LA      a0, str_newline
0205     jal     _mips_cps_puts
0206     jr      s0
0207     END(mips_cps_bev_dump)
0208 
0209 .pushsection    .data
0210 str_bev: .asciiz "BEV Exception: "
0211 str_newline: .asciiz "\r\n"
0212 .popsection