xref: /rk3399_rockchip-uboot/drivers/serial/sandbox.c (revision 890fcefe2e20b30a3d98f667c2dcfb382b1de2e6)
1 /*
2  * Copyright (c) 2011 The Chromium OS Authors.
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 /*
8  * This provide a test serial port. It provides an emulated serial port where
9  * a test program and read out the serial output and inject serial input for
10  * U-Boot.
11  */
12 
13 #include <common.h>
14 #include <dm.h>
15 #include <fdtdec.h>
16 #include <lcd.h>
17 #include <os.h>
18 #include <serial.h>
19 #include <linux/compiler.h>
20 #include <asm/state.h>
21 
22 DECLARE_GLOBAL_DATA_PTR;
23 
24 /*
25  *
26  *   serial_buf: A buffer that holds keyboard characters for the
27  *		 Sandbox U-boot.
28  *
29  * invariants:
30  *   serial_buf_write		 == serial_buf_read -> empty buffer
31  *   (serial_buf_write + 1) % 16 == serial_buf_read -> full buffer
32  */
33 static char serial_buf[16];
34 static unsigned int serial_buf_write;
35 static unsigned int serial_buf_read;
36 
37 static int sandbox_serial_probe(struct udevice *dev)
38 {
39 	struct sandbox_state *state = state_get_current();
40 
41 	if (state->term_raw != STATE_TERM_COOKED)
42 		os_tty_raw(0, state->term_raw == STATE_TERM_RAW_WITH_SIGS);
43 
44 	return 0;
45 }
46 
47 static int sandbox_serial_putc(struct udevice *dev, const char ch)
48 {
49 	os_write(1, &ch, 1);
50 
51 	return 0;
52 }
53 
54 static unsigned int increment_buffer_index(unsigned int index)
55 {
56 	return (index + 1) % ARRAY_SIZE(serial_buf);
57 }
58 
59 static int sandbox_serial_pending(struct udevice *dev, bool input)
60 {
61 	const unsigned int next_index =
62 		increment_buffer_index(serial_buf_write);
63 	ssize_t count;
64 
65 	if (!input)
66 		return 0;
67 
68 	os_usleep(100);
69 #ifdef CONFIG_LCD
70 	lcd_sync();
71 #endif
72 	if (next_index == serial_buf_read)
73 		return 1;	/* buffer full */
74 
75 	count = os_read_no_block(0, &serial_buf[serial_buf_write], 1);
76 	if (count == 1)
77 		serial_buf_write = next_index;
78 
79 	return serial_buf_write != serial_buf_read;
80 }
81 
82 static int sandbox_serial_getc(struct udevice *dev)
83 {
84 	int result;
85 
86 	if (!sandbox_serial_pending(dev, true))
87 		return -EAGAIN;	/* buffer empty */
88 
89 	result = serial_buf[serial_buf_read];
90 	serial_buf_read = increment_buffer_index(serial_buf_read);
91 	return result;
92 }
93 
94 static const struct dm_serial_ops sandbox_serial_ops = {
95 	.putc = sandbox_serial_putc,
96 	.pending = sandbox_serial_pending,
97 	.getc = sandbox_serial_getc,
98 };
99 
100 static const struct udevice_id sandbox_serial_ids[] = {
101 	{ .compatible = "sandbox,serial" },
102 	{ }
103 };
104 
105 U_BOOT_DRIVER(serial_sandbox) = {
106 	.name	= "serial_sandbox",
107 	.id	= UCLASS_SERIAL,
108 	.of_match = sandbox_serial_ids,
109 	.probe = sandbox_serial_probe,
110 	.ops	= &sandbox_serial_ops,
111 	.flags = DM_FLAG_PRE_RELOC,
112 };
113 
114 U_BOOT_DEVICE(serial_sandbox_non_fdt) = {
115 	.name = "serial_sandbox",
116 };
117