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