1*2f5307d6SBryan O'Donoghue/* 2*2f5307d6SBryan O'Donoghue * Copyright (c) Linaro 2018 Limited and Contributors. All rights reserved. 3*2f5307d6SBryan O'Donoghue * 4*2f5307d6SBryan O'Donoghue * SPDX-License-Identifier: BSD-3-Clause 5*2f5307d6SBryan O'Donoghue */ 6*2f5307d6SBryan O'Donoghue#include <arch.h> 7*2f5307d6SBryan O'Donoghue#include <asm_macros.S> 8*2f5307d6SBryan O'Donoghue#include <assert_macros.S> 9*2f5307d6SBryan O'Donoghue#include <imx_uart.h> 10*2f5307d6SBryan O'Donoghue#include <platform_def.h> 11*2f5307d6SBryan O'Donoghue 12*2f5307d6SBryan O'Donoghue .globl imx_crash_uart_init 13*2f5307d6SBryan O'Donoghue .globl imx_crash_uart_putc 14*2f5307d6SBryan O'Donoghue 15*2f5307d6SBryan O'Donoghue /* ----------------------------------------------- 16*2f5307d6SBryan O'Donoghue * int imx_crash_uart_init(uintptr_t base_addr, 17*2f5307d6SBryan O'Donoghue * unsigned int uart_clk, unsigned int baud_rate) 18*2f5307d6SBryan O'Donoghue * Function to initialize the console without a 19*2f5307d6SBryan O'Donoghue * C Runtime to print debug information. This 20*2f5307d6SBryan O'Donoghue * function will be accessed by console_init and 21*2f5307d6SBryan O'Donoghue * crash reporting. 22*2f5307d6SBryan O'Donoghue * In: r0 - console base address 23*2f5307d6SBryan O'Donoghue * r1 - Uart clock in Hz 24*2f5307d6SBryan O'Donoghue * r2 - Baud rate 25*2f5307d6SBryan O'Donoghue * Out: return 1 on success else 0 on error 26*2f5307d6SBryan O'Donoghue * Clobber list : r1, r2, r3, r4 27*2f5307d6SBryan O'Donoghue * ----------------------------------------------- 28*2f5307d6SBryan O'Donoghue */ 29*2f5307d6SBryan O'Donoghuefunc imx_crash_uart_init 30*2f5307d6SBryan O'Donoghue /* Free up r1 as a scratch reg */ 31*2f5307d6SBryan O'Donoghue mov r4, r0 32*2f5307d6SBryan O'Donoghue mov r0, r1 33*2f5307d6SBryan O'Donoghue 34*2f5307d6SBryan O'Donoghue /* Reset UART via CR2 */ 35*2f5307d6SBryan O'Donoghue add r1, r4, #IMX_UART_CR2_OFFSET 36*2f5307d6SBryan O'Donoghue movs r3, #0 37*2f5307d6SBryan O'Donoghue str r3, [r4, #IMX_UART_CR2_OFFSET] 38*2f5307d6SBryan O'Donoghue 39*2f5307d6SBryan O'Donoghue /* Wait for reset complete */ 40*2f5307d6SBryan O'Donoghue__wait_cr2_reset: 41*2f5307d6SBryan O'Donoghue ldr r3, [r1, #0] 42*2f5307d6SBryan O'Donoghue ands r3, #IMX_UART_CR2_SRST 43*2f5307d6SBryan O'Donoghue beq __wait_cr2_reset 44*2f5307d6SBryan O'Donoghue 45*2f5307d6SBryan O'Donoghue /* Enable UART */ 46*2f5307d6SBryan O'Donoghue movs r3, #IMX_UART_CR1_UARTEN 47*2f5307d6SBryan O'Donoghue mov r1, r2 48*2f5307d6SBryan O'Donoghue str r3, [r4, #IMX_UART_CR1_OFFSET] 49*2f5307d6SBryan O'Donoghue 50*2f5307d6SBryan O'Donoghue /* 51*2f5307d6SBryan O'Donoghue * Ignore RTC/CTS - disable reset 52*2f5307d6SBryan O'Donoghue * Magic value #16423 => 53*2f5307d6SBryan O'Donoghue * IMX_UART_CR2_IRTS | IMX_UART_CR2_WS | IMX_UART_CR2_TXEN | IMX_UART_CR2_RXEN | IMX_UART_CR2_SRST 54*2f5307d6SBryan O'Donoghue */ 55*2f5307d6SBryan O'Donoghue movw r3, #16423 56*2f5307d6SBryan O'Donoghue str r3, [r4, #IMX_UART_CR2_OFFSET] 57*2f5307d6SBryan O'Donoghue 58*2f5307d6SBryan O'Donoghue /* 59*2f5307d6SBryan O'Donoghue * No parity, autobaud detect-old, rxdmuxsel=1 (fixed i.mx7) 60*2f5307d6SBryan O'Donoghue * Magic value => #132 61*2f5307d6SBryan O'Donoghue * IMX_UART_CR3_ADNIMP | IMX_UART_CR3_RXDMUXSEL 62*2f5307d6SBryan O'Donoghue */ 63*2f5307d6SBryan O'Donoghue movs r3, #132 64*2f5307d6SBryan O'Donoghue str r3, [r4, #IMX_UART_CR3_OFFSET] 65*2f5307d6SBryan O'Donoghue 66*2f5307d6SBryan O'Donoghue /* 67*2f5307d6SBryan O'Donoghue * Set CTS FIFO trigger to 32 bytes bits 15:10 68*2f5307d6SBryan O'Donoghue * Magic value => #32768 69*2f5307d6SBryan O'Donoghue * FIFO trigger bitmask 100000 70*2f5307d6SBryan O'Donoghue * */ 71*2f5307d6SBryan O'Donoghue mov r3, #32768 72*2f5307d6SBryan O'Donoghue str r3, [r4, #IMX_UART_CR4_OFFSET] 73*2f5307d6SBryan O'Donoghue 74*2f5307d6SBryan O'Donoghue /* 75*2f5307d6SBryan O'Donoghue * TX/RX-thresh = 2 bytes, DCE (bit6 = 0), refclk @24MHz / 4 76*2f5307d6SBryan O'Donoghue * Magic value #2562 77*2f5307d6SBryan O'Donoghue * IMX_UART_FCR_TXTL(TX_RX_THRESH) | IMX_UART_FCR_RXTL(TX_RX_THRESH) | IMX_UART_FCR_RFDIV2 78*2f5307d6SBryan O'Donoghue */ 79*2f5307d6SBryan O'Donoghue #ifdef IMX_UART_DTE 80*2f5307d6SBryan O'Donoghue movw r3, #2626 81*2f5307d6SBryan O'Donoghue #else 82*2f5307d6SBryan O'Donoghue movw r3, #2562 83*2f5307d6SBryan O'Donoghue #endif 84*2f5307d6SBryan O'Donoghue str r3, [r4, #IMX_UART_FCR_OFFSET] 85*2f5307d6SBryan O'Donoghue 86*2f5307d6SBryan O'Donoghue /* This BIR should be set to 0x0F prior to writing the BMR */ 87*2f5307d6SBryan O'Donoghue movs r3, #15 88*2f5307d6SBryan O'Donoghue str r3, [r4, #IMX_UART_BIR_OFFSET] 89*2f5307d6SBryan O'Donoghue 90*2f5307d6SBryan O'Donoghue /* Hard-code to 115200 @ 24 MHz */ 91*2f5307d6SBryan O'Donoghue movs r0, #104 92*2f5307d6SBryan O'Donoghue str r0, [r4, #IMX_UART_BMR_OFFSET] 93*2f5307d6SBryan O'Donoghue 94*2f5307d6SBryan O'Donoghue /* Indicate success */ 95*2f5307d6SBryan O'Donoghue movs r0, #1 96*2f5307d6SBryan O'Donoghue bx lr 97*2f5307d6SBryan O'Donoghueendfunc imx_crash_uart_init 98*2f5307d6SBryan O'Donoghue 99*2f5307d6SBryan O'Donoghue /* -------------------------------------------------------- 100*2f5307d6SBryan O'Donoghue * int imx_crash_uart_putc(int c, uintptr_t base_addr) 101*2f5307d6SBryan O'Donoghue * Function to output a character over the console. It 102*2f5307d6SBryan O'Donoghue * returns the character printed on success or -1 on error. 103*2f5307d6SBryan O'Donoghue * In : r0 - character to be printed 104*2f5307d6SBryan O'Donoghue * r1 - console base address 105*2f5307d6SBryan O'Donoghue * Out : return -1 on error else return character. 106*2f5307d6SBryan O'Donoghue * Clobber list : r2 107*2f5307d6SBryan O'Donoghue * -------------------------------------------------------- 108*2f5307d6SBryan O'Donoghue */ 109*2f5307d6SBryan O'Donoghuefunc imx_crash_uart_putc 110*2f5307d6SBryan O'Donoghue /* Output specified character to UART shift-register */ 111*2f5307d6SBryan O'Donoghue str r0, [r1, #IMX_UART_TXD_OFFSET] 112*2f5307d6SBryan O'Donoghue 113*2f5307d6SBryan O'Donoghue /* Wait for transmit IMX_UART_STAT2_OFFSET.IMX_UART_STAT2_TXDC == 1 */ 114*2f5307d6SBryan O'Donoghue__putc_spin_ready: 115*2f5307d6SBryan O'Donoghue ldr r2, [r1, #IMX_UART_STAT2_OFFSET] 116*2f5307d6SBryan O'Donoghue ands r2, #IMX_UART_STAT2_TXDC 117*2f5307d6SBryan O'Donoghue beq __putc_spin_ready 118*2f5307d6SBryan O'Donoghue 119*2f5307d6SBryan O'Donoghue /* Transmit complete do we need to fixup \n to \n\r */ 120*2f5307d6SBryan O'Donoghue cmp r0, #10 121*2f5307d6SBryan O'Donoghue beq __putc_fixup_lf 122*2f5307d6SBryan O'Donoghue 123*2f5307d6SBryan O'Donoghue /* No fixup necessary - exit here */ 124*2f5307d6SBryan O'Donoghue movs r0, #0 125*2f5307d6SBryan O'Donoghue bx lr 126*2f5307d6SBryan O'Donoghue 127*2f5307d6SBryan O'Donoghue /* Fixup \n to \n\r */ 128*2f5307d6SBryan O'Donoghue__putc_fixup_lf: 129*2f5307d6SBryan O'Donoghue movs r0, #13 130*2f5307d6SBryan O'Donoghue b imx_crash_uart_putc 131*2f5307d6SBryan O'Donoghueendfunc imx_crash_uart_putc 132