1*91f16700Schasinglulu/* 2*91f16700Schasinglulu * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu#include <asm_macros.S> 7*91f16700Schasinglulu#include <console_macros.S> 8*91f16700Schasinglulu 9*91f16700Schasinglulu /* 10*91f16700Schasinglulu * This file contains a skeleton console driver that can be used as a 11*91f16700Schasinglulu * basis for a real console driver. Console drivers in Trusted Firmware 12*91f16700Schasinglulu * can be instantiated multiple times. Each instance is described by a 13*91f16700Schasinglulu * separate console_t structure which must be registered with the common 14*91f16700Schasinglulu * console framework via console_register(). Console drivers should 15*91f16700Schasinglulu * define a console_xxx_register() function that initializes a new 16*91f16700Schasinglulu * console_t structure passed in from the caller and registers it after 17*91f16700Schasinglulu * initializing the console hardware. Drivers may define their own 18*91f16700Schasinglulu * structures extending console_t to store private driver information. 19*91f16700Schasinglulu * Console drivers *MUST* ensure that the console callbacks they 20*91f16700Schasinglulu * implement only change registers allowed in the clobber lists defined 21*91f16700Schasinglulu * in this file. (Note that in addition to the explicit clobber lists, 22*91f16700Schasinglulu * any function may always clobber the intra-procedure-call register 23*91f16700Schasinglulu * r12, but may never depend on it retaining its value across any 24*91f16700Schasinglulu * function call.) 25*91f16700Schasinglulu */ 26*91f16700Schasinglulu 27*91f16700Schasinglulu .globl console_xxx_register 28*91f16700Schasinglulu .globl console_xxx_putc 29*91f16700Schasinglulu .globl console_xxx_getc 30*91f16700Schasinglulu .globl console_xxx_flush 31*91f16700Schasinglulu 32*91f16700Schasinglulu /* ----------------------------------------------- 33*91f16700Schasinglulu * int console_xxx_register(console_xxx_t *console, 34*91f16700Schasinglulu * ...additional parameters as desired...) 35*91f16700Schasinglulu * Function to initialize and register the console. 36*91f16700Schasinglulu * The caller needs to pass an empty console_xxx_t 37*91f16700Schasinglulu * structure in which *MUST* be allocated in 38*91f16700Schasinglulu * persistent memory (e.g. a global or static local 39*91f16700Schasinglulu * variable, *NOT* on the stack). 40*91f16700Schasinglulu * In : r0 - pointer to empty console_t structure 41*91f16700Schasinglulu * r1 through r7: additional parameters as desired 42*91f16700Schasinglulu * Out: r0 - 1 on success, 0 on error 43*91f16700Schasinglulu * Clobber list : r0 - r7 44*91f16700Schasinglulu * ----------------------------------------------- 45*91f16700Schasinglulu */ 46*91f16700Schasinglulufunc console_xxx_register 47*91f16700Schasinglulu /* 48*91f16700Schasinglulu * Store parameters (e.g. hardware base address) in driver-specific 49*91f16700Schasinglulu * console_xxx_t structure field if they will need to be retrieved 50*91f16700Schasinglulu * by later console callback (e.g. putc). 51*91f16700Schasinglulu * Example: 52*91f16700Schasinglulu */ 53*91f16700Schasinglulu str r1, [r0, #CONSOLE_T_BASE] 54*91f16700Schasinglulu str r2, [r0, #CONSOLE_T_XXX_SOME_OTHER_VALUE] 55*91f16700Schasinglulu 56*91f16700Schasinglulu /* 57*91f16700Schasinglulu * Initialize console hardware, using r1 - r7 parameters as needed. 58*91f16700Schasinglulu * Keep console_t pointer in r0 for later. 59*91f16700Schasinglulu */ 60*91f16700Schasinglulu 61*91f16700Schasinglulu /* 62*91f16700Schasinglulu * Macro to finish up registration and return (needs valid r0 + lr). 63*91f16700Schasinglulu * If any of the argument is unspecified, then the corresponding 64*91f16700Schasinglulu * entry in console_t is set to 0. 65*91f16700Schasinglulu */ 66*91f16700Schasinglulu finish_console_register xxx putc=1, getc=ENABLE_CONSOLE_GETC, flush=1 67*91f16700Schasinglulu 68*91f16700Schasinglulu /* Jump here if hardware init fails or parameters are invalid. */ 69*91f16700Schasingluluregister_fail: 70*91f16700Schasinglulu mov r0, #0 71*91f16700Schasinglulu bx lr 72*91f16700Schasingluluendfunc console_xxx_register 73*91f16700Schasinglulu 74*91f16700Schasinglulu /* -------------------------------------------------------- 75*91f16700Schasinglulu * int console_xxx_putc(int c, console_xxx_t *console) 76*91f16700Schasinglulu * Function to output a character over the console. It 77*91f16700Schasinglulu * returns the character printed on success or -1 on error. 78*91f16700Schasinglulu * In : r0 - character to be printed 79*91f16700Schasinglulu * r1 - pointer to console_t struct 80*91f16700Schasinglulu * Out: r0 - printed character on success, < 0 on error. 81*91f16700Schasinglulu * Clobber list : r0, r1, r2 82*91f16700Schasinglulu * -------------------------------------------------------- 83*91f16700Schasinglulu */ 84*91f16700Schasinglulufunc console_xxx_putc 85*91f16700Schasinglulu /* 86*91f16700Schasinglulu * Retrieve values we need (e.g. hardware base address) from 87*91f16700Schasinglulu * console_xxx_t structure pointed to by r1. 88*91f16700Schasinglulu * Example: 89*91f16700Schasinglulu */ 90*91f16700Schasinglulu ldr r1, [r1, #CONSOLE_T_BASE] 91*91f16700Schasinglulu 92*91f16700Schasinglulu /* 93*91f16700Schasinglulu * Write r0 to hardware. 94*91f16700Schasinglulu */ 95*91f16700Schasinglulu 96*91f16700Schasinglulu bx lr 97*91f16700Schasinglulu 98*91f16700Schasinglulu /* Jump here if output fails for any reason. */ 99*91f16700Schasingluluputc_error: 100*91f16700Schasinglulu mov r0, #-1 101*91f16700Schasinglulu bx lr 102*91f16700Schasingluluendfunc console_xxx_putc 103*91f16700Schasinglulu 104*91f16700Schasinglulu /* --------------------------------------------- 105*91f16700Schasinglulu * int console_xxx_getc(console_xxx_t *console) 106*91f16700Schasinglulu * Function to get a character from the console. 107*91f16700Schasinglulu * Even though console_getc() is blocking, this 108*91f16700Schasinglulu * callback has to be non-blocking and always 109*91f16700Schasinglulu * return immediately to allow polling multiple 110*91f16700Schasinglulu * drivers concurrently. 111*91f16700Schasinglulu * Returns the character grabbed on success, 112*91f16700Schasinglulu * ERROR_NO_PENDING_CHAR if no character was 113*91f16700Schasinglulu * available at this time, or any value 114*91f16700Schasinglulu * between -2 and -127 if there was an error. 115*91f16700Schasinglulu * In : r0 - pointer to console_t struct 116*91f16700Schasinglulu * Out: r0 - character on success, 117*91f16700Schasinglulu * ERROR_NO_PENDING_CHAR if no char, 118*91f16700Schasinglulu * < -1 on error 119*91f16700Schasinglulu * Clobber list : r0, r1 120*91f16700Schasinglulu * --------------------------------------------- 121*91f16700Schasinglulu */ 122*91f16700Schasinglulufunc console_xxx_getc 123*91f16700Schasinglulu /* 124*91f16700Schasinglulu * Retrieve values we need (e.g. hardware base address) from 125*91f16700Schasinglulu * console_xxx_t structure pointed to by r0. 126*91f16700Schasinglulu * Example: 127*91f16700Schasinglulu */ 128*91f16700Schasinglulu ldr r1, [r0, #CONSOLE_T_BASE] 129*91f16700Schasinglulu 130*91f16700Schasinglulu /* 131*91f16700Schasinglulu * Try to read character into r0 from hardware. 132*91f16700Schasinglulu */ 133*91f16700Schasinglulu 134*91f16700Schasinglulu bx lr 135*91f16700Schasinglulu 136*91f16700Schasinglulu /* Jump here if there is no character available at this time. */ 137*91f16700Schasinglulugetc_no_char: 138*91f16700Schasinglulu mov r0, #ERROR_NO_PENDING_CHAR 139*91f16700Schasinglulu bx lr 140*91f16700Schasinglulu 141*91f16700Schasinglulu /* Jump here if there was any hardware error. */ 142*91f16700Schasinglulugetc_error: 143*91f16700Schasinglulu mov r0, #-2 /* may pick error codes between -2 and -127 */ 144*91f16700Schasinglulu bx lr 145*91f16700Schasingluluendfunc console_xxx_getc 146*91f16700Schasinglulu 147*91f16700Schasinglulu /* --------------------------------------------- 148*91f16700Schasinglulu * int console_xxx_flush(console_xxx_t *console) 149*91f16700Schasinglulu * Function to force a write of all buffered 150*91f16700Schasinglulu * data that hasn't been output. 151*91f16700Schasinglulu * In : r0 - pointer to console_xxx_t struct 152*91f16700Schasinglulu * Out: void 153*91f16700Schasinglulu * Clobber list : r0, r1, r2, r3, r4, r5 154*91f16700Schasinglulu * --------------------------------------------- 155*91f16700Schasinglulu */ 156*91f16700Schasinglulufunc console_xxx_flush 157*91f16700Schasinglulu /* 158*91f16700Schasinglulu * Retrieve values we need (e.g. hardware base address) from 159*91f16700Schasinglulu * console_xxx_t structure pointed to by r0. 160*91f16700Schasinglulu * Example: 161*91f16700Schasinglulu */ 162*91f16700Schasinglulu ldr r1, [r0, #CONSOLE_T_BASE] 163*91f16700Schasinglulu 164*91f16700Schasinglulu /* 165*91f16700Schasinglulu * Flush all remaining output from hardware FIFOs. Do not return until 166*91f16700Schasinglulu * all data has been flushed or there was an unrecoverable error. 167*91f16700Schasinglulu */ 168*91f16700Schasinglulu 169*91f16700Schasinglulu bx lr 170*91f16700Schasingluluendfunc console_xxx_flush 171