xref: /rk3399_rockchip-uboot/drivers/serial/sandbox.c (revision 890fcefe2e20b30a3d98f667c2dcfb382b1de2e6)
17accb6eaSSimon Glass /*
27accb6eaSSimon Glass  * Copyright (c) 2011 The Chromium OS Authors.
37accb6eaSSimon Glass  *
41a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
57accb6eaSSimon Glass  */
67accb6eaSSimon Glass 
77accb6eaSSimon Glass /*
87accb6eaSSimon Glass  * This provide a test serial port. It provides an emulated serial port where
97accb6eaSSimon Glass  * a test program and read out the serial output and inject serial input for
107accb6eaSSimon Glass  * U-Boot.
117accb6eaSSimon Glass  */
127accb6eaSSimon Glass 
137accb6eaSSimon Glass #include <common.h>
14*890fcefeSSimon Glass #include <dm.h>
15*890fcefeSSimon Glass #include <fdtdec.h>
167d95f2a3SSimon Glass #include <lcd.h>
177accb6eaSSimon Glass #include <os.h>
18cef46b77SMarek Vasut #include <serial.h>
19cef46b77SMarek Vasut #include <linux/compiler.h>
20ffb87905SSimon Glass #include <asm/state.h>
217accb6eaSSimon Glass 
22*890fcefeSSimon Glass DECLARE_GLOBAL_DATA_PTR;
23*890fcefeSSimon Glass 
24e101550aSTaylor Hutt /*
25e101550aSTaylor Hutt  *
26e101550aSTaylor Hutt  *   serial_buf: A buffer that holds keyboard characters for the
27e101550aSTaylor Hutt  *		 Sandbox U-boot.
28e101550aSTaylor Hutt  *
29e101550aSTaylor Hutt  * invariants:
30e101550aSTaylor Hutt  *   serial_buf_write		 == serial_buf_read -> empty buffer
31e101550aSTaylor Hutt  *   (serial_buf_write + 1) % 16 == serial_buf_read -> full buffer
32e101550aSTaylor Hutt  */
33e101550aSTaylor Hutt static char serial_buf[16];
34e101550aSTaylor Hutt static unsigned int serial_buf_write;
35e101550aSTaylor Hutt static unsigned int serial_buf_read;
36e101550aSTaylor Hutt 
37*890fcefeSSimon Glass static int sandbox_serial_probe(struct udevice *dev)
387accb6eaSSimon Glass {
39ffb87905SSimon Glass 	struct sandbox_state *state = state_get_current();
40ffb87905SSimon Glass 
41ffb87905SSimon Glass 	if (state->term_raw != STATE_TERM_COOKED)
42ffb87905SSimon Glass 		os_tty_raw(0, state->term_raw == STATE_TERM_RAW_WITH_SIGS);
43*890fcefeSSimon Glass 
447accb6eaSSimon Glass 	return 0;
457accb6eaSSimon Glass }
467accb6eaSSimon Glass 
47*890fcefeSSimon Glass static int sandbox_serial_putc(struct udevice *dev, const char ch)
487accb6eaSSimon Glass {
497accb6eaSSimon Glass 	os_write(1, &ch, 1);
507accb6eaSSimon Glass 
51*890fcefeSSimon Glass 	return 0;
527accb6eaSSimon Glass }
537accb6eaSSimon Glass 
54e101550aSTaylor Hutt static unsigned int increment_buffer_index(unsigned int index)
557accb6eaSSimon Glass {
56e101550aSTaylor Hutt 	return (index + 1) % ARRAY_SIZE(serial_buf);
577accb6eaSSimon Glass }
587accb6eaSSimon Glass 
59*890fcefeSSimon Glass static int sandbox_serial_pending(struct udevice *dev, bool input)
607accb6eaSSimon Glass {
61e101550aSTaylor Hutt 	const unsigned int next_index =
62e101550aSTaylor Hutt 		increment_buffer_index(serial_buf_write);
63e101550aSTaylor Hutt 	ssize_t count;
64e101550aSTaylor Hutt 
65*890fcefeSSimon Glass 	if (!input)
66*890fcefeSSimon Glass 		return 0;
67*890fcefeSSimon Glass 
68e101550aSTaylor Hutt 	os_usleep(100);
697d95f2a3SSimon Glass #ifdef CONFIG_LCD
707d95f2a3SSimon Glass 	lcd_sync();
717d95f2a3SSimon Glass #endif
72e101550aSTaylor Hutt 	if (next_index == serial_buf_read)
73e101550aSTaylor Hutt 		return 1;	/* buffer full */
74e101550aSTaylor Hutt 
75e101550aSTaylor Hutt 	count = os_read_no_block(0, &serial_buf[serial_buf_write], 1);
76e101550aSTaylor Hutt 	if (count == 1)
77e101550aSTaylor Hutt 		serial_buf_write = next_index;
78*890fcefeSSimon Glass 
79e101550aSTaylor Hutt 	return serial_buf_write != serial_buf_read;
80e101550aSTaylor Hutt }
81e101550aSTaylor Hutt 
82*890fcefeSSimon Glass static int sandbox_serial_getc(struct udevice *dev)
83e101550aSTaylor Hutt {
84e101550aSTaylor Hutt 	int result;
85e101550aSTaylor Hutt 
86*890fcefeSSimon Glass 	if (!sandbox_serial_pending(dev, true))
87*890fcefeSSimon Glass 		return -EAGAIN;	/* buffer empty */
88e101550aSTaylor Hutt 
89e101550aSTaylor Hutt 	result = serial_buf[serial_buf_read];
90e101550aSTaylor Hutt 	serial_buf_read = increment_buffer_index(serial_buf_read);
91e101550aSTaylor Hutt 	return result;
927accb6eaSSimon Glass }
93cef46b77SMarek Vasut 
94*890fcefeSSimon Glass static const struct dm_serial_ops sandbox_serial_ops = {
95cef46b77SMarek Vasut 	.putc = sandbox_serial_putc,
96*890fcefeSSimon Glass 	.pending = sandbox_serial_pending,
97cef46b77SMarek Vasut 	.getc = sandbox_serial_getc,
98cef46b77SMarek Vasut };
99cef46b77SMarek Vasut 
100*890fcefeSSimon Glass static const struct udevice_id sandbox_serial_ids[] = {
101*890fcefeSSimon Glass 	{ .compatible = "sandbox,serial" },
102*890fcefeSSimon Glass 	{ }
103*890fcefeSSimon Glass };
104cef46b77SMarek Vasut 
105*890fcefeSSimon Glass U_BOOT_DRIVER(serial_sandbox) = {
106*890fcefeSSimon Glass 	.name	= "serial_sandbox",
107*890fcefeSSimon Glass 	.id	= UCLASS_SERIAL,
108*890fcefeSSimon Glass 	.of_match = sandbox_serial_ids,
109*890fcefeSSimon Glass 	.probe = sandbox_serial_probe,
110*890fcefeSSimon Glass 	.ops	= &sandbox_serial_ops,
111*890fcefeSSimon Glass 	.flags = DM_FLAG_PRE_RELOC,
112*890fcefeSSimon Glass };
113*890fcefeSSimon Glass 
114*890fcefeSSimon Glass U_BOOT_DEVICE(serial_sandbox_non_fdt) = {
115*890fcefeSSimon Glass 	.name = "serial_sandbox",
116*890fcefeSSimon Glass };
117