From: Soby Mathew Date: Tue, 24 Jun 2014 11:28:41 +0000 (+0100) Subject: Introduce asm console functions in TF X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=fce5f7501afad3fb1aa0cbff3c3d666e2c0f36f9;p=project%2Fbcm63xx%2Fatf.git Introduce asm console functions in TF This patch replaces the pl011 console family of functions with their equivalents defined in assembly. The baud rate is defined by the PL011_BAUDRATE macro and IBRD and FBRD values for pl011 are computed statically. This patch will enable us to invoke the console functions without the C Runtime Stack. Change-Id: Ic3f7b7370ded38bf9020bf746b362081b76642c7 --- diff --git a/drivers/arm/pl011/pl011.c b/drivers/arm/pl011/pl011.c deleted file mode 100644 index e296c23f..00000000 --- a/drivers/arm/pl011/pl011.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -void pl011_setbaudrate(unsigned long base_addr, unsigned int baudrate) -{ - unsigned int divisor; - assert(baudrate); - divisor = (PL011_CLK_IN_HZ * 4) / baudrate; - pl011_write_ibrd(base_addr, divisor >> 6); - pl011_write_fbrd(base_addr, divisor & 0x3F); -} diff --git a/drivers/arm/pl011/pl011_console.S b/drivers/arm/pl011/pl011_console.S new file mode 100644 index 00000000..bf26b6b0 --- /dev/null +++ b/drivers/arm/pl011/pl011_console.S @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + + .globl console_init + .globl console_putc + .globl console_core_init + .globl console_core_putc + .globl console_getc + + /* + * The console base is in the data section and not in .bss + * even though it is zero-init. In particular, this allows + * the console functions to start using this variable before + * the runtime memory is initialized for images which do not + * need to copy the .data section from ROM to RAM. + */ +.section .data.console_base ; .align 3 + console_base: .quad 0x0 + + /* --------------------------------------------- + * int console_init(unsigned long base_addr) + * Function to initialize the console without a + * C Runtime to print debug information. It saves + * the console base to the data section. + * In: x0 - console base address + * out: return 1 on success. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func console_init + adrp x1, console_base + str x0, [x1, :lo12:console_base] + b console_core_init + + /* --------------------------------------------- + * int console_core_init(unsigned long base_addr) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * Out: return 1 on success + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func console_core_init + /* Check the input base address */ + cbz x0, init_fail + /* Program the baudrate */ +#if defined(PL011_INTEGER) && defined(PL011_FRACTIONAL) + mov w1, #PL011_INTEGER + str w1, [x0, #UARTIBRD] + mov w1, #PL011_FRACTIONAL + str w1, [x0, #UARTFBRD] +#else +.set BRD, ((PL011_CLK_IN_HZ << 2) / PL011_BAUDRATE) + /* Write the IBRD */ + mov w1, #((BRD >> 6) & 0xffff) +.if BRD>=0x400000 + movk w1, #(BRD >> 22), LSL #16 +.endif + str w1, [x0, #UARTIBRD] + /* Write the FBRD */ + mov w1, #(BRD & 0x3f) + str w1, [x0, #UARTFBRD] +#endif + mov w1, #PL011_LINE_CONTROL + str w1, [x0, #UARTLCR_H] + /* Clear any pending errors */ + str wzr, [x0, #UARTECR] + /* Enable tx, rx, and uart overall */ + mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN) + str w1, [x0, #UARTCR] + mov w0, #1 +init_fail: + ret + + /* --------------------------------------------- + * int console_putc(int c) + * Function to output a character over the + * console. It returns the character printed on + * success or -1 on error. + * In : x0 - character to be printed + * Out : return -1 on error else return character. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func console_putc + adrp x2, console_base + ldr x1, [x2, :lo12:console_base] + b console_core_putc + + /* -------------------------------------------------------- + * int console_core_putc(int c, unsigned long base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : x0 - character to be printed + * x1 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_core_putc + /* Check the input parameter */ + cbz x1, putc_error + /* Prepend '\r' to '\n' */ + cmp x0, #0xA + b.ne 2f +1: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #UARTFR] + tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b + mov w2, #0xD + str w2, [x1, #UARTDR] +2: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #UARTFR] + tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b + str w0, [x1, #UARTDR] + ret +putc_error: + mov w0, #-1 + ret + + /* --------------------------------------------- + * int console_getc(void) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on error. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_getc + adrp x0, console_base + ldr x1, [x0, :lo12:console_base] + cbz x1, getc_error +1: + /* Check if the receive FIFO is empty */ + ldr w0, [x1, #UARTFR] + tbnz w0, #PL011_UARTFR_RXFE_BIT, 1b + ldr w0, [x1, #UARTDR] + ret +getc_error: + mov w0, #-1 + ret diff --git a/drivers/arm/pl011/pl011_console.c b/drivers/arm/pl011/pl011_console.c deleted file mode 100644 index 81897cab..00000000 --- a/drivers/arm/pl011/pl011_console.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -static unsigned long uart_base; - -void console_init(unsigned long base_addr) -{ - /* TODO: assert() internally calls printf() and will result in - * an infinite loop. This needs to be fixed with some kind of - * exception mechanism or early panic support. This also applies - * to the other assert() calls below. - */ - assert(base_addr); - - /* Initialise internal base address variable */ - uart_base = base_addr; - - /* Baud Rate */ -#if defined(PL011_INTEGER) && defined(PL011_FRACTIONAL) - pl011_write_ibrd(uart_base, PL011_INTEGER); - pl011_write_fbrd(uart_base, PL011_FRACTIONAL); -#else - pl011_setbaudrate(uart_base, PL011_BAUDRATE); -#endif - - pl011_write_lcr_h(uart_base, PL011_LINE_CONTROL); - - /* Clear any pending errors */ - pl011_write_ecr(uart_base, 0); - - /* Enable tx, rx, and uart overall */ - pl011_write_cr(uart_base, PL011_UARTCR_RXE | PL011_UARTCR_TXE | - PL011_UARTCR_UARTEN); - -} - -#define WAIT_UNTIL_UART_FREE(base) \ - while ((pl011_read_fr(base) & PL011_UARTFR_TXFF)) \ - continue - -int console_putc(int c) -{ - /* If the console has not been initialized then return an error - * code. Asserting here would result in recursion and stack - * exhaustion - */ - if (!uart_base) - return -1; - - if (c == '\n') { - WAIT_UNTIL_UART_FREE(uart_base); - pl011_write_dr(uart_base, '\r'); - } - - WAIT_UNTIL_UART_FREE(uart_base); - pl011_write_dr(uart_base, c); - return c; -} - -int console_getc(void) -{ - assert(uart_base); - - while ((pl011_read_fr(uart_base) & PL011_UARTFR_RXFE) != 0) - ; - return pl011_read_dr(uart_base); -} diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h index 281330e4..e01d8b28 100644 --- a/include/drivers/arm/pl011.h +++ b/include/drivers/arm/pl011.h @@ -31,9 +31,6 @@ #ifndef __PL011_H__ #define __PL011_H__ -#include - - /* PL011 Registers */ #define UARTDR 0x000 #define UARTRSR 0x004 @@ -68,6 +65,9 @@ #define PL011_UARTFR_DSR (1 << 1) /* Data set ready */ #define PL011_UARTFR_CTS (1 << 0) /* Clear to send */ +#define PL011_UARTFR_TXFF_BIT 5 /* Transmit FIFO full bit in UARTFR register */ +#define PL011_UARTFR_RXFE_BIT 4 /* Receive FIFO empty bit in UARTFR register */ + /* Control reg bits */ #define PL011_UARTCR_CTSEN (1 << 15) /* CTS hardware flow control enable */ #define PL011_UARTCR_RTSEN (1 << 14) /* RTS hardware flow control enable */ @@ -103,58 +103,4 @@ #define PL011_UARTLCR_H_PEN (1 << 1) /* Parity Enable */ #define PL011_UARTLCR_H_BRK (1 << 0) /* Send break */ -/******************************************************************************* - * Pl011 CPU interface accessors for writing registers - ******************************************************************************/ - -static inline void pl011_write_ibrd(unsigned long base, unsigned int val) -{ - mmio_write_32(base + UARTIBRD, val); -} - -static inline void pl011_write_fbrd(unsigned long base, unsigned int val) -{ - mmio_write_32(base + UARTFBRD, val); -} - -static inline void pl011_write_lcr_h(unsigned long base, unsigned int val) -{ - mmio_write_32(base + UARTLCR_H, val); -} - -static inline void pl011_write_ecr(unsigned long base, unsigned int val) -{ - mmio_write_32(base + UARTECR, val); -} - -static inline void pl011_write_cr(unsigned long base, unsigned int val) -{ - mmio_write_32(base + UARTCR, val); -} - -static inline void pl011_write_dr(unsigned long base, unsigned int val) -{ - mmio_write_32(base + UARTDR, val); -} - -/******************************************************************************* - * Pl011 CPU interface accessors for reading registers - ******************************************************************************/ - -static inline unsigned int pl011_read_fr(unsigned long base) -{ - return mmio_read_32(base + UARTFR); -} - -static inline unsigned int pl011_read_dr(unsigned long base) -{ - return mmio_read_32(base + UARTDR); -} - -/******************************************************************************* - * Function prototypes - ******************************************************************************/ - -void pl011_setbaudrate(unsigned long base_addr, unsigned int baudrate); - #endif /* __PL011_H__ */ diff --git a/plat/fvp/platform.mk b/plat/fvp/platform.mk index b22a3393..f6275b78 100644 --- a/plat/fvp/platform.mk +++ b/plat/fvp/platform.mk @@ -45,8 +45,7 @@ $(eval $(call add_define,TSP_RAM_LOCATION_ID)) PLAT_INCLUDES := -Iplat/fvp/include/ -PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/pl011.c \ - drivers/arm/pl011/pl011_console.c \ +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/pl011_console.S \ drivers/io/io_fip.c \ drivers/io/io_memmap.c \ drivers/io/io_semihosting.c \