1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2011 The Chromium OS Authors.
7 * This provide a test serial port. It provides an emulated serial port where
8 * a test program and read out the serial output and inject serial input for
19 #include <linux/compiler.h>
20 #include <asm/state.h>
22 DECLARE_GLOBAL_DATA_PTR;
24 struct sandbox_serial_platdata {
25 int colour; /* Text colour to use for output, -1 for none */
29 * struct sandbox_serial_priv - Private data for this driver
31 * @buf: holds input characters available to be read by this driver
33 struct sandbox_serial_priv {
40 * output_ansi_colour() - Output an ANSI colour code
42 * @colour: Colour to output (0-7)
44 static void output_ansi_colour(int colour)
46 char ansi_code[] = "\x1b[1;3Xm";
48 ansi_code[5] = '0' + colour;
49 os_write(1, ansi_code, sizeof(ansi_code) - 1);
52 static void output_ansi_reset(void)
54 os_write(1, "\x1b[0m", 4);
57 static int sandbox_serial_probe(struct udevice *dev)
59 struct sandbox_state *state = state_get_current();
60 struct sandbox_serial_priv *priv = dev_get_priv(dev);
62 if (state->term_raw != STATE_TERM_COOKED)
63 os_tty_raw(0, state->term_raw == STATE_TERM_RAW_WITH_SIGS);
64 priv->start_of_line = 0;
66 if (state->term_raw != STATE_TERM_RAW)
68 membuff_init(&priv->buf, priv->serial_buf, sizeof(priv->serial_buf));
73 static int sandbox_serial_remove(struct udevice *dev)
75 struct sandbox_serial_platdata *plat = dev->plat;
77 if (plat->colour != -1)
83 static int sandbox_serial_putc(struct udevice *dev, const char ch)
85 struct sandbox_serial_priv *priv = dev_get_priv(dev);
86 struct sandbox_serial_platdata *plat = dev->plat;
88 /* With of-platdata we don't real the colour correctly, so disable it */
89 if (!CONFIG_IS_ENABLED(OF_PLATDATA) && priv->start_of_line &&
91 priv->start_of_line = false;
92 output_ansi_colour(plat->colour);
97 priv->start_of_line = true;
102 static int sandbox_serial_pending(struct udevice *dev, bool input)
104 struct sandbox_serial_priv *priv = dev_get_priv(dev);
113 if (!IS_ENABLED(CONFIG_SPL_BUILD))
115 avail = membuff_putraw(&priv->buf, 100, false, &data);
117 return 1; /* buffer full */
119 count = os_read(0, data, avail);
121 membuff_putraw(&priv->buf, count, true, &data);
123 return membuff_avail(&priv->buf);
126 static int sandbox_serial_getc(struct udevice *dev)
128 struct sandbox_serial_priv *priv = dev_get_priv(dev);
130 if (!sandbox_serial_pending(dev, true))
131 return -EAGAIN; /* buffer empty */
133 return membuff_getbyte(&priv->buf);
136 #ifdef CONFIG_DEBUG_UART_SANDBOX
138 #include <debug_uart.h>
140 static inline void _debug_uart_init(void)
144 static inline void _debug_uart_putc(int ch)
151 #endif /* CONFIG_DEBUG_UART_SANDBOX */
153 static int sandbox_serial_getconfig(struct udevice *dev, uint *serial_config)
155 uint config = SERIAL_DEFAULT_CONFIG;
160 *serial_config = config;
165 static int sandbox_serial_setconfig(struct udevice *dev, uint serial_config)
167 u8 parity = SERIAL_GET_PARITY(serial_config);
168 u8 bits = SERIAL_GET_BITS(serial_config);
169 u8 stop = SERIAL_GET_STOP(serial_config);
171 if (bits != SERIAL_8_BITS || stop != SERIAL_ONE_STOP ||
172 parity != SERIAL_PAR_NONE)
173 return -ENOTSUPP; /* not supported in driver*/
178 static int sandbox_serial_getinfo(struct udevice *dev,
179 struct serial_device_info *serial_info)
181 struct serial_device_info info = {
182 .type = SERIAL_CHIP_UNKNOWN,
183 .addr_space = SERIAL_ADDRESS_SPACE_IO,
184 .addr = SERIAL_DEFAULT_ADDRESS,
188 .clock = SERIAL_DEFAULT_CLOCK,
199 static const char * const ansi_colour[] = {
200 "black", "red", "green", "yellow", "blue", "megenta", "cyan",
204 static int sandbox_serial_ofdata_to_platdata(struct udevice *dev)
206 struct sandbox_serial_platdata *plat = dev->plat;
210 if (CONFIG_IS_ENABLED(OF_PLATDATA))
213 colour = dev_read_string(dev, "sandbox,text-colour");
215 for (i = 0; i < ARRAY_SIZE(ansi_colour); i++) {
216 if (!strcmp(colour, ansi_colour[i])) {
226 static const struct dm_serial_ops sandbox_serial_ops = {
227 .putc = sandbox_serial_putc,
228 .pending = sandbox_serial_pending,
229 .getc = sandbox_serial_getc,
230 .getconfig = sandbox_serial_getconfig,
231 .setconfig = sandbox_serial_setconfig,
232 .getinfo = sandbox_serial_getinfo,
235 static const struct udevice_id sandbox_serial_ids[] = {
236 { .compatible = "sandbox,serial" },
240 U_BOOT_DRIVER(sandbox_serial) = {
241 .name = "sandbox_serial",
243 .of_match = sandbox_serial_ids,
244 .ofdata_to_platdata = sandbox_serial_ofdata_to_platdata,
245 .plat_auto = sizeof(struct sandbox_serial_platdata),
246 .priv_auto = sizeof(struct sandbox_serial_priv),
247 .probe = sandbox_serial_probe,
248 .remove = sandbox_serial_remove,
249 .ops = &sandbox_serial_ops,
250 .flags = DM_FLAG_PRE_RELOC,
253 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
254 static const struct sandbox_serial_platdata platdata_non_fdt = {
258 U_BOOT_DEVICE(serial_sandbox_non_fdt) = {
259 .name = "sandbox_serial",
260 .plat = &platdata_non_fdt,