1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * A udbg backend which logs messages and reads input from in memory 4*4882a593Smuzhiyun * buffers. 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * The console output can be read from memcons_output which is a 7*4882a593Smuzhiyun * circular buffer whose next write position is stored in memcons.output_pos. 8*4882a593Smuzhiyun * 9*4882a593Smuzhiyun * Input may be passed by writing into the memcons_input buffer when it is 10*4882a593Smuzhiyun * empty. The input buffer is empty when both input_pos == input_start and 11*4882a593Smuzhiyun * *input_start == '\0'. 12*4882a593Smuzhiyun * 13*4882a593Smuzhiyun * Copyright (C) 2003-2005 Anton Blanchard and Milton Miller, IBM Corp 14*4882a593Smuzhiyun * Copyright (C) 2013 Alistair Popple, IBM Corp 15*4882a593Smuzhiyun */ 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun #include <linux/kernel.h> 18*4882a593Smuzhiyun #include <asm/barrier.h> 19*4882a593Smuzhiyun #include <asm/page.h> 20*4882a593Smuzhiyun #include <asm/processor.h> 21*4882a593Smuzhiyun #include <asm/udbg.h> 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun struct memcons { 24*4882a593Smuzhiyun char *output_start; 25*4882a593Smuzhiyun char *output_pos; 26*4882a593Smuzhiyun char *output_end; 27*4882a593Smuzhiyun char *input_start; 28*4882a593Smuzhiyun char *input_pos; 29*4882a593Smuzhiyun char *input_end; 30*4882a593Smuzhiyun }; 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun static char memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE]; 33*4882a593Smuzhiyun static char memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE]; 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun struct memcons memcons = { 36*4882a593Smuzhiyun .output_start = memcons_output, 37*4882a593Smuzhiyun .output_pos = memcons_output, 38*4882a593Smuzhiyun .output_end = &memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE], 39*4882a593Smuzhiyun .input_start = memcons_input, 40*4882a593Smuzhiyun .input_pos = memcons_input, 41*4882a593Smuzhiyun .input_end = &memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE], 42*4882a593Smuzhiyun }; 43*4882a593Smuzhiyun memcons_putc(char c)44*4882a593Smuzhiyunvoid memcons_putc(char c) 45*4882a593Smuzhiyun { 46*4882a593Smuzhiyun char *new_output_pos; 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun *memcons.output_pos = c; 49*4882a593Smuzhiyun wmb(); 50*4882a593Smuzhiyun new_output_pos = memcons.output_pos + 1; 51*4882a593Smuzhiyun if (new_output_pos >= memcons.output_end) 52*4882a593Smuzhiyun new_output_pos = memcons.output_start; 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun memcons.output_pos = new_output_pos; 55*4882a593Smuzhiyun } 56*4882a593Smuzhiyun memcons_getc_poll(void)57*4882a593Smuzhiyunint memcons_getc_poll(void) 58*4882a593Smuzhiyun { 59*4882a593Smuzhiyun char c; 60*4882a593Smuzhiyun char *new_input_pos; 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun if (*memcons.input_pos) { 63*4882a593Smuzhiyun c = *memcons.input_pos; 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun new_input_pos = memcons.input_pos + 1; 66*4882a593Smuzhiyun if (new_input_pos >= memcons.input_end) 67*4882a593Smuzhiyun new_input_pos = memcons.input_start; 68*4882a593Smuzhiyun else if (*new_input_pos == '\0') 69*4882a593Smuzhiyun new_input_pos = memcons.input_start; 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun *memcons.input_pos = '\0'; 72*4882a593Smuzhiyun wmb(); 73*4882a593Smuzhiyun memcons.input_pos = new_input_pos; 74*4882a593Smuzhiyun return c; 75*4882a593Smuzhiyun } 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun return -1; 78*4882a593Smuzhiyun } 79*4882a593Smuzhiyun memcons_getc(void)80*4882a593Smuzhiyunint memcons_getc(void) 81*4882a593Smuzhiyun { 82*4882a593Smuzhiyun int c; 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun while (1) { 85*4882a593Smuzhiyun c = memcons_getc_poll(); 86*4882a593Smuzhiyun if (c == -1) 87*4882a593Smuzhiyun cpu_relax(); 88*4882a593Smuzhiyun else 89*4882a593Smuzhiyun break; 90*4882a593Smuzhiyun } 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun return c; 93*4882a593Smuzhiyun } 94*4882a593Smuzhiyun udbg_init_memcons(void)95*4882a593Smuzhiyunvoid udbg_init_memcons(void) 96*4882a593Smuzhiyun { 97*4882a593Smuzhiyun udbg_putc = memcons_putc; 98*4882a593Smuzhiyun udbg_getc = memcons_getc; 99*4882a593Smuzhiyun udbg_getc_poll = memcons_getc_poll; 100*4882a593Smuzhiyun } 101