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