Home | History | Annotate | Download | only in pl011
      1 /*
      2  * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are met:
      6  *
      7  * Redistributions of source code must retain the above copyright notice, this
      8  * list of conditions and the following disclaimer.
      9  *
     10  * Redistributions in binary form must reproduce the above copyright notice,
     11  * this list of conditions and the following disclaimer in the documentation
     12  * and/or other materials provided with the distribution.
     13  *
     14  * Neither the name of ARM nor the names of its contributors may be used
     15  * to endorse or promote products derived from this software without specific
     16  * prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
     22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28  * POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 #include <arch.h>
     31 #include <asm_macros.S>
     32 #include <pl011.h>
     33 
     34 	.globl	console_init
     35 	.globl	console_putc
     36 	.globl	console_core_init
     37 	.globl	console_core_putc
     38 	.globl	console_getc
     39 
     40 	/*
     41 	 *  The console base is in the data section and not in .bss
     42 	 *  even though it is zero-init. In particular, this allows
     43 	 *  the console functions to start using this variable before
     44 	 *  the runtime memory is initialized for images which do not
     45 	 *  need to copy the .data section from ROM to RAM.
     46 	 */
     47 .section .data.console_base ; .align 3
     48 	console_base: .quad 0x0
     49 
     50 	/* -----------------------------------------------
     51 	 * int console_init(unsigned long base_addr,
     52 	 * unsigned int uart_clk, unsigned int baud_rate)
     53 	 * Function to initialize the console without a
     54 	 * C Runtime to print debug information. It saves
     55 	 * the console base to the data section.
     56 	 * In: x0 - console base address
     57 	 *     w1 - Uart clock in Hz
     58 	 *     w2 - Baud rate
     59 	 * out: return 1 on success.
     60 	 * Clobber list : x1 - x3
     61 	 * -----------------------------------------------
     62 	 */
     63 func console_init
     64 	adrp	x3, console_base
     65 	str	x0, [x3, :lo12:console_base]
     66 	b	console_core_init
     67 
     68 	/* -----------------------------------------------
     69 	 * int console_core_init(unsigned long base_addr,
     70 	 * unsigned int uart_clk, unsigned int baud_rate)
     71 	 * Function to initialize the console without a
     72 	 * C Runtime to print debug information. This
     73 	 * function will be accessed by console_init and
     74 	 * crash reporting.
     75 	 * In: x0 - console base address
     76 	 *     w1 - Uart clock in Hz
     77 	 *     w2 - Baud rate
     78 	 * Out: return 1 on success
     79 	 * Clobber list : x1, x2
     80 	 * -----------------------------------------------
     81 	 */
     82 func console_core_init
     83 	/* Check the input base address */
     84 	cbz	x0, init_fail
     85 	/* Check baud rate and uart clock for sanity */
     86 	cbz	w1, init_fail
     87 	cbz	w2, init_fail
     88 	/* Program the baudrate */
     89 	/* Divisor =  (Uart clock * 4) / baudrate */
     90 	lsl	w1, w1, #2
     91 	udiv	w2, w1, w2
     92 	/* IBRD = Divisor >> 6 */
     93 	lsr	w1, w2, #6
     94 	/* Write the IBRD */
     95 	str	w1, [x0, #UARTIBRD]
     96 	/* FBRD = Divisor & 0x3F */
     97 	and	w1, w2, #0x3f
     98 	/* Write the FBRD */
     99 	str	w1, [x0, #UARTFBRD]
    100 	mov	w1, #PL011_LINE_CONTROL
    101 	str	w1, [x0, #UARTLCR_H]
    102 	/* Clear any pending errors */
    103 	str	wzr, [x0, #UARTECR]
    104 	/* Enable tx, rx, and uart overall */
    105 	mov	w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN)
    106 	str	w1, [x0, #UARTCR]
    107 	mov	w0, #1
    108 init_fail:
    109 	ret
    110 
    111 	/* ---------------------------------------------
    112 	 * int console_putc(int c)
    113 	 * Function to output a character over the
    114 	 * console. It returns the character printed on
    115 	 * success or -1 on error.
    116 	 * In : x0 - character to be printed
    117 	 * Out : return -1 on error else return character.
    118 	 * Clobber list : x1, x2
    119 	 * ---------------------------------------------
    120 	 */
    121 func console_putc
    122 	adrp	x2, console_base
    123 	ldr	x1, [x2, :lo12:console_base]
    124 	b	console_core_putc
    125 
    126 	/* --------------------------------------------------------
    127 	 * int console_core_putc(int c, unsigned int base_addr)
    128 	 * Function to output a character over the console. It
    129 	 * returns the character printed on success or -1 on error.
    130 	 * In : w0 - character to be printed
    131 	 *      x1 - console base address
    132 	 * Out : return -1 on error else return character.
    133 	 * Clobber list : x2
    134 	 * --------------------------------------------------------
    135 	 */
    136 func console_core_putc
    137 	/* Check the input parameter */
    138 	cbz	x1, putc_error
    139 	/* Prepend '\r' to '\n' */
    140 	cmp	w0, #0xA
    141 	b.ne	2f
    142 1:
    143 	/* Check if the transmit FIFO is full */
    144 	ldr	w2, [x1, #UARTFR]
    145 	tbnz	w2, #PL011_UARTFR_TXFF_BIT, 1b
    146 	mov	w2, #0xD
    147 	str	w2, [x1, #UARTDR]
    148 2:
    149 	/* Check if the transmit FIFO is full */
    150 	ldr	w2, [x1, #UARTFR]
    151 	tbnz	w2, #PL011_UARTFR_TXFF_BIT, 2b
    152 	str	w0, [x1, #UARTDR]
    153 	ret
    154 putc_error:
    155 	mov	w0, #-1
    156 	ret
    157 
    158 	/* ---------------------------------------------
    159 	 * int console_getc(void)
    160 	 * Function to get a character from the console.
    161 	 * It returns the character grabbed on success
    162 	 * or -1 on error.
    163 	 * Clobber list : x0, x1
    164 	 * ---------------------------------------------
    165 	 */
    166 func console_getc
    167 	adrp	x0, console_base
    168 	ldr	x1, [x0, :lo12:console_base]
    169 	cbz	x1, getc_error
    170 1:
    171 	/* Check if the receive FIFO is empty */
    172 	ldr	w0, [x1, #UARTFR]
    173 	tbnz	w0, #PL011_UARTFR_RXFE_BIT, 1b
    174 	ldr	w0, [x1, #UARTDR]
    175 	ret
    176 getc_error:
    177 	mov	w0, #-1
    178 	ret
    179