12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 230650239SAlistair Popple /* 330650239SAlistair Popple * A udbg backend which logs messages and reads input from in memory 430650239SAlistair Popple * buffers. 530650239SAlistair Popple * 630650239SAlistair Popple * The console output can be read from memcons_output which is a 730650239SAlistair Popple * circular buffer whose next write position is stored in memcons.output_pos. 830650239SAlistair Popple * 930650239SAlistair Popple * Input may be passed by writing into the memcons_input buffer when it is 1030650239SAlistair Popple * empty. The input buffer is empty when both input_pos == input_start and 1130650239SAlistair Popple * *input_start == '\0'. 1230650239SAlistair Popple * 1330650239SAlistair Popple * Copyright (C) 2003-2005 Anton Blanchard and Milton Miller, IBM Corp 1430650239SAlistair Popple * Copyright (C) 2013 Alistair Popple, IBM Corp 1530650239SAlistair Popple */ 1630650239SAlistair Popple 1730650239SAlistair Popple #include <linux/kernel.h> 1830650239SAlistair Popple #include <asm/barrier.h> 1930650239SAlistair Popple #include <asm/page.h> 2030650239SAlistair Popple #include <asm/processor.h> 2130650239SAlistair Popple #include <asm/udbg.h> 2230650239SAlistair Popple 2330650239SAlistair Popple struct memcons { 2430650239SAlistair Popple char *output_start; 2530650239SAlistair Popple char *output_pos; 2630650239SAlistair Popple char *output_end; 2730650239SAlistair Popple char *input_start; 2830650239SAlistair Popple char *input_pos; 2930650239SAlistair Popple char *input_end; 3030650239SAlistair Popple }; 3130650239SAlistair Popple 3230650239SAlistair Popple static char memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE]; 3330650239SAlistair Popple static char memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE]; 3430650239SAlistair Popple 3530650239SAlistair Popple struct memcons memcons = { 3630650239SAlistair Popple .output_start = memcons_output, 3730650239SAlistair Popple .output_pos = memcons_output, 3830650239SAlistair Popple .output_end = &memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE], 3930650239SAlistair Popple .input_start = memcons_input, 4030650239SAlistair Popple .input_pos = memcons_input, 4130650239SAlistair Popple .input_end = &memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE], 4230650239SAlistair Popple }; 4330650239SAlistair Popple memcons_putc(char c)4430650239SAlistair Popplevoid memcons_putc(char c) 4530650239SAlistair Popple { 4630650239SAlistair Popple char *new_output_pos; 4730650239SAlistair Popple 4830650239SAlistair Popple *memcons.output_pos = c; 4930650239SAlistair Popple wmb(); 5030650239SAlistair Popple new_output_pos = memcons.output_pos + 1; 5130650239SAlistair Popple if (new_output_pos >= memcons.output_end) 5230650239SAlistair Popple new_output_pos = memcons.output_start; 5330650239SAlistair Popple 5430650239SAlistair Popple memcons.output_pos = new_output_pos; 5530650239SAlistair Popple } 5630650239SAlistair Popple memcons_getc_poll(void)5730650239SAlistair Poppleint memcons_getc_poll(void) 5830650239SAlistair Popple { 5930650239SAlistair Popple char c; 6030650239SAlistair Popple char *new_input_pos; 6130650239SAlistair Popple 6230650239SAlistair Popple if (*memcons.input_pos) { 6330650239SAlistair Popple c = *memcons.input_pos; 6430650239SAlistair Popple 6530650239SAlistair Popple new_input_pos = memcons.input_pos + 1; 6630650239SAlistair Popple if (new_input_pos >= memcons.input_end) 6730650239SAlistair Popple new_input_pos = memcons.input_start; 6830650239SAlistair Popple else if (*new_input_pos == '\0') 6930650239SAlistair Popple new_input_pos = memcons.input_start; 7030650239SAlistair Popple 7130650239SAlistair Popple *memcons.input_pos = '\0'; 7230650239SAlistair Popple wmb(); 7330650239SAlistair Popple memcons.input_pos = new_input_pos; 7430650239SAlistair Popple return c; 7530650239SAlistair Popple } 7630650239SAlistair Popple 7730650239SAlistair Popple return -1; 7830650239SAlistair Popple } 7930650239SAlistair Popple memcons_getc(void)8030650239SAlistair Poppleint memcons_getc(void) 8130650239SAlistair Popple { 8230650239SAlistair Popple int c; 8330650239SAlistair Popple 8430650239SAlistair Popple while (1) { 8530650239SAlistair Popple c = memcons_getc_poll(); 8630650239SAlistair Popple if (c == -1) 8730650239SAlistair Popple cpu_relax(); 8830650239SAlistair Popple else 8930650239SAlistair Popple break; 9030650239SAlistair Popple } 9130650239SAlistair Popple 9230650239SAlistair Popple return c; 9330650239SAlistair Popple } 9430650239SAlistair Popple udbg_init_memcons(void)95*6c552983SNick Childvoid __init udbg_init_memcons(void) 9630650239SAlistair Popple { 9730650239SAlistair Popple udbg_putc = memcons_putc; 9830650239SAlistair Popple udbg_getc = memcons_getc; 9930650239SAlistair Popple udbg_getc_poll = memcons_getc_poll; 10030650239SAlistair Popple } 101