blob: ac54e0167eb63e8eb9189bc1b6b36c2417f789c4 [file] [log] [blame]
Simon Glass479349a2011-10-03 19:26:46 +00001/*
2 * Copyright (c) 2011 The Chromium OS Authors.
Simon Glass479349a2011-10-03 19:26:46 +00003 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Simon Glass479349a2011-10-03 19:26:46 +00005 */
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>
Simon Glasse5870692014-09-04 16:27:27 -060014#include <dm.h>
15#include <fdtdec.h>
Simon Glassb9ddbf42014-02-27 13:26:19 -070016#include <lcd.h>
Simon Glass479349a2011-10-03 19:26:46 +000017#include <os.h>
Marek Vasut289c3002012-09-14 22:33:21 +020018#include <serial.h>
19#include <linux/compiler.h>
Simon Glass678ef472014-02-27 13:26:22 -070020#include <asm/state.h>
Simon Glass479349a2011-10-03 19:26:46 +000021
Simon Glasse5870692014-09-04 16:27:27 -060022DECLARE_GLOBAL_DATA_PTR;
23
Taylor Hutt868aa3a2013-02-24 17:33:13 +000024/*
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 */
33static char serial_buf[16];
34static unsigned int serial_buf_write;
35static unsigned int serial_buf_read;
36
Simon Glasse5870692014-09-04 16:27:27 -060037static int sandbox_serial_probe(struct udevice *dev)
Simon Glass479349a2011-10-03 19:26:46 +000038{
Simon Glass678ef472014-02-27 13:26:22 -070039 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);
Simon Glass479349a2011-10-03 19:26:46 +000043
Simon Glasse5870692014-09-04 16:27:27 -060044 return 0;
Simon Glass479349a2011-10-03 19:26:46 +000045}
46
Simon Glasse5870692014-09-04 16:27:27 -060047static int sandbox_serial_putc(struct udevice *dev, const char ch)
Simon Glass479349a2011-10-03 19:26:46 +000048{
49 os_write(1, &ch, 1);
Simon Glass479349a2011-10-03 19:26:46 +000050
Simon Glasse5870692014-09-04 16:27:27 -060051 return 0;
Simon Glass479349a2011-10-03 19:26:46 +000052}
53
Taylor Hutt868aa3a2013-02-24 17:33:13 +000054static unsigned int increment_buffer_index(unsigned int index)
55{
56 return (index + 1) % ARRAY_SIZE(serial_buf);
57}
58
Simon Glasse5870692014-09-04 16:27:27 -060059static int sandbox_serial_pending(struct udevice *dev, bool input)
Simon Glass479349a2011-10-03 19:26:46 +000060{
Taylor Hutt868aa3a2013-02-24 17:33:13 +000061 const unsigned int next_index =
62 increment_buffer_index(serial_buf_write);
Mike Frysingerd174fd92011-10-26 00:21:01 +000063 ssize_t count;
Simon Glass479349a2011-10-03 19:26:46 +000064
Simon Glasse5870692014-09-04 16:27:27 -060065 if (!input)
66 return 0;
67
Taylor Hutt868aa3a2013-02-24 17:33:13 +000068 os_usleep(100);
Simon Glassb9ddbf42014-02-27 13:26:19 -070069#ifdef CONFIG_LCD
70 lcd_sync();
71#endif
Taylor Hutt868aa3a2013-02-24 17:33:13 +000072 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;
Simon Glasse5870692014-09-04 16:27:27 -060078
Taylor Hutt868aa3a2013-02-24 17:33:13 +000079 return serial_buf_write != serial_buf_read;
Simon Glass479349a2011-10-03 19:26:46 +000080}
81
Simon Glasse5870692014-09-04 16:27:27 -060082static int sandbox_serial_getc(struct udevice *dev)
Simon Glass479349a2011-10-03 19:26:46 +000083{
Taylor Hutt868aa3a2013-02-24 17:33:13 +000084 int result;
85
Simon Glasse5870692014-09-04 16:27:27 -060086 if (!sandbox_serial_pending(dev, true))
87 return -EAGAIN; /* buffer empty */
Taylor Hutt868aa3a2013-02-24 17:33:13 +000088
89 result = serial_buf[serial_buf_read];
90 serial_buf_read = increment_buffer_index(serial_buf_read);
91 return result;
Simon Glass479349a2011-10-03 19:26:46 +000092}
Marek Vasut289c3002012-09-14 22:33:21 +020093
Simon Glasse5870692014-09-04 16:27:27 -060094static const struct dm_serial_ops sandbox_serial_ops = {
95 .putc = sandbox_serial_putc,
96 .pending = sandbox_serial_pending,
97 .getc = sandbox_serial_getc,
Marek Vasut289c3002012-09-14 22:33:21 +020098};
99
Simon Glasse5870692014-09-04 16:27:27 -0600100static const struct udevice_id sandbox_serial_ids[] = {
101 { .compatible = "sandbox,serial" },
102 { }
103};
Marek Vasut289c3002012-09-14 22:33:21 +0200104
Simon Glasse5870692014-09-04 16:27:27 -0600105U_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
114U_BOOT_DEVICE(serial_sandbox_non_fdt) = {
115 .name = "serial_sandbox",
116};