xref: /OK3568_Linux_fs/kernel/arch/powerpc/sysdev/udbg_memcons.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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*4882a593Smuzhiyun void 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*4882a593Smuzhiyun int 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*4882a593Smuzhiyun int 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*4882a593Smuzhiyun void 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