root/arch/mips/kernel/cps-vec-ns16550.S

/* [<][>][^][v][top][bottom][index][help] */
   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 /**
  18  * _mips_cps_putc() - write a character to the UART
  19  * @a0: ASCII character to write
  20  * @t9: UART base address
  21  */
  22 LEAF(_mips_cps_putc)
  23 1:      lw              t0, UART_LSR_OFS(t9)
  24         andi            t0, t0, UART_LSR_TEMT
  25         beqz            t0, 1b
  26         sb              a0, UART_TX_OFS(t9)
  27         jr              ra
  28         END(_mips_cps_putc)
  29 
  30 /**
  31  * _mips_cps_puts() - write a string to the UART
  32  * @a0: pointer to NULL-terminated ASCII string
  33  * @t9: UART base address
  34  *
  35  * Write a null-terminated ASCII string to the UART.
  36  */
  37 NESTED(_mips_cps_puts, 0, ra)
  38         move            s7, ra
  39         move            s6, a0
  40 
  41 1:      lb              a0, 0(s6)
  42         beqz            a0, 2f
  43         jal             _mips_cps_putc
  44         PTR_ADDIU       s6, s6, 1
  45         b               1b
  46 
  47 2:      jr              s7
  48         END(_mips_cps_puts)
  49 
  50 /**
  51  * _mips_cps_putx4 - write a 4b hex value to the UART
  52  * @a0: the 4b value to write to the UART
  53  * @t9: UART base address
  54  *
  55  * Write a single hexadecimal character to the UART.
  56  */
  57 NESTED(_mips_cps_putx4, 0, ra)
  58         andi            a0, a0, 0xf
  59         li              t0, '0'
  60         blt             a0, 10, 1f
  61         li              t0, 'a'
  62         addiu           a0, a0, -10
  63 1:      addu            a0, a0, t0
  64         b               _mips_cps_putc
  65         END(_mips_cps_putx4)
  66 
  67 /**
  68  * _mips_cps_putx8 - write an 8b hex value to the UART
  69  * @a0: the 8b value to write to the UART
  70  * @t9: UART base address
  71  *
  72  * Write an 8 bit value (ie. 2 hexadecimal characters) to the UART.
  73  */
  74 NESTED(_mips_cps_putx8, 0, ra)
  75         move            s3, ra
  76         move            s2, a0
  77         srl             a0, a0, 4
  78         jal             _mips_cps_putx4
  79         move            a0, s2
  80         move            ra, s3
  81         b               _mips_cps_putx4
  82         END(_mips_cps_putx8)
  83 
  84 /**
  85  * _mips_cps_putx16 - write a 16b hex value to the UART
  86  * @a0: the 16b value to write to the UART
  87  * @t9: UART base address
  88  *
  89  * Write a 16 bit value (ie. 4 hexadecimal characters) to the UART.
  90  */
  91 NESTED(_mips_cps_putx16, 0, ra)
  92         move            s5, ra
  93         move            s4, a0
  94         srl             a0, a0, 8
  95         jal             _mips_cps_putx8
  96         move            a0, s4
  97         move            ra, s5
  98         b               _mips_cps_putx8
  99         END(_mips_cps_putx16)
 100 
 101 /**
 102  * _mips_cps_putx32 - write a 32b hex value to the UART
 103  * @a0: the 32b value to write to the UART
 104  * @t9: UART base address
 105  *
 106  * Write a 32 bit value (ie. 8 hexadecimal characters) to the UART.
 107  */
 108 NESTED(_mips_cps_putx32, 0, ra)
 109         move            s7, ra
 110         move            s6, a0
 111         srl             a0, a0, 16
 112         jal             _mips_cps_putx16
 113         move            a0, s6
 114         move            ra, s7
 115         b               _mips_cps_putx16
 116         END(_mips_cps_putx32)
 117 
 118 #ifdef CONFIG_64BIT
 119 
 120 /**
 121  * _mips_cps_putx64 - write a 64b hex value to the UART
 122  * @a0: the 64b value to write to the UART
 123  * @t9: UART base address
 124  *
 125  * Write a 64 bit value (ie. 16 hexadecimal characters) to the UART.
 126  */
 127 NESTED(_mips_cps_putx64, 0, ra)
 128         move            sp, ra
 129         move            s8, a0
 130         dsrl32          a0, a0, 0
 131         jal             _mips_cps_putx32
 132         move            a0, s8
 133         move            ra, sp
 134         b               _mips_cps_putx32
 135         END(_mips_cps_putx64)
 136 
 137 #define _mips_cps_putxlong _mips_cps_putx64
 138 
 139 #else /* !CONFIG_64BIT */
 140 
 141 #define _mips_cps_putxlong _mips_cps_putx32
 142 
 143 #endif /* !CONFIG_64BIT */
 144 
 145 /**
 146  * mips_cps_bev_dump() - dump relevant exception state to UART
 147  * @a0: pointer to NULL-terminated ASCII string naming the exception
 148  *
 149  * Write information that may be useful in debugging an exception to the
 150  * UART configured by CONFIG_MIPS_CPS_NS16550_*. As this BEV exception
 151  * will only be run if something goes horribly wrong very early during
 152  * the bringup of a core and it is very likely to be unsafe to perform
 153  * memory accesses at that point (cache state indeterminate, EVA may not
 154  * be configured, coherence may be disabled) let alone have a stack,
 155  * this is all written in assembly using only registers & unmapped
 156  * uncached access to the UART registers.
 157  */
 158 LEAF(mips_cps_bev_dump)
 159         move            s0, ra
 160         move            s1, a0
 161 
 162         li              t9, CKSEG1ADDR(CONFIG_MIPS_CPS_NS16550_BASE)
 163 
 164         PTR_LA          a0, str_newline
 165         jal             _mips_cps_puts
 166         PTR_LA          a0, str_bev
 167         jal             _mips_cps_puts
 168         move            a0, s1
 169         jal             _mips_cps_puts
 170         PTR_LA          a0, str_newline
 171         jal             _mips_cps_puts
 172         PTR_LA          a0, str_newline
 173         jal             _mips_cps_puts
 174 
 175 #define DUMP_COP0_REG(reg, name, sz, _mfc0)             \
 176         PTR_LA          a0, 8f;                         \
 177         jal             _mips_cps_puts;                 \
 178         _mfc0           a0, reg;                        \
 179         jal             _mips_cps_putx##sz;             \
 180         PTR_LA          a0, str_newline;                \
 181         jal             _mips_cps_puts;                 \
 182         TEXT(name)
 183 
 184         DUMP_COP0_REG(CP0_CAUSE,    "Cause:    0x", 32, mfc0)
 185         DUMP_COP0_REG(CP0_STATUS,   "Status:   0x", 32, mfc0)
 186         DUMP_COP0_REG(CP0_EBASE,    "EBase:    0x", long, MFC0)
 187         DUMP_COP0_REG(CP0_BADVADDR, "BadVAddr: 0x", long, MFC0)
 188         DUMP_COP0_REG(CP0_BADINSTR, "BadInstr: 0x", 32, mfc0)
 189 
 190         PTR_LA          a0, str_newline
 191         jal             _mips_cps_puts
 192         jr              s0
 193         END(mips_cps_bev_dump)
 194 
 195 .pushsection    .data
 196 str_bev: .asciiz "BEV Exception: "
 197 str_newline: .asciiz "\r\n"
 198 .popsection

/* [<][>][^][v][top][bottom][index][help] */