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