1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
10 #include <semihosting.h>
13 * struct smh_serial_priv - Semihosting serial private data
14 * @infd: stdin file descriptor (or error)
15 * @outfd: stdout file descriptor (or error)
17 struct smh_serial_priv {
22 #if CONFIG_IS_ENABLED(DM_SERIAL)
23 static int smh_serial_getc(struct udevice *dev)
26 struct smh_serial_priv *priv = dev_get_priv(dev);
31 smh_read(priv->infd, &ch, sizeof(ch));
35 static int smh_serial_putc(struct udevice *dev, const char ch)
41 static ssize_t smh_serial_puts(struct udevice *dev, const char *s, size_t len)
44 struct smh_serial_priv *priv = dev_get_priv(dev);
45 unsigned long written;
47 if (priv->outfd < 0) {
50 /* Try and avoid a copy if we can */
56 buf = strndup(s, len);
62 ret = smh_write(priv->outfd, s, len, &written);
68 static const struct dm_serial_ops smh_serial_ops = {
69 .putc = smh_serial_putc,
70 .puts = smh_serial_puts,
71 .getc = smh_serial_getc,
74 static int smh_serial_bind(struct udevice *dev)
76 if (semihosting_enabled())
81 static int smh_serial_probe(struct udevice *dev)
83 struct smh_serial_priv *priv = dev_get_priv(dev);
85 priv->infd = smh_open(":tt", MODE_READ);
86 priv->outfd = smh_open(":tt", MODE_WRITE);
90 U_BOOT_DRIVER(smh_serial) = {
91 .name = "serial_semihosting",
93 .bind = smh_serial_bind,
94 .probe = smh_serial_probe,
95 .priv_auto = sizeof(struct smh_serial_priv),
96 .ops = &smh_serial_ops,
97 .flags = DM_FLAG_PRE_RELOC,
100 U_BOOT_DRVINFO(smh_serial) = {
101 .name = "serial_semihosting",
103 #else /* DM_SERIAL */
104 static int infd = -ENODEV;
105 static int outfd = -ENODEV;
107 static int smh_serial_start(void)
109 infd = smh_open(":tt", MODE_READ);
110 outfd = smh_open(":tt", MODE_WRITE);
114 static int smh_serial_stop(void)
121 static void smh_serial_setbrg(void)
125 static int smh_serial_getc(void)
132 smh_read(infd, &ch, sizeof(ch));
136 static int smh_serial_tstc(void)
141 static void smh_serial_puts(const char *s)
148 smh_write(outfd, s, strlen(s), &unused);
151 struct serial_device serial_smh_device = {
152 .name = "serial_smh",
153 .start = smh_serial_start,
154 .stop = smh_serial_stop,
155 .setbrg = smh_serial_setbrg,
156 .getc = smh_serial_getc,
157 .tstc = smh_serial_tstc,
159 .puts = smh_serial_puts,
162 void smh_serial_initialize(void)
164 if (semihosting_enabled())
165 serial_register(&serial_smh_device);
168 __weak struct serial_device *default_serial_console(void)
170 return &serial_smh_device;
174 #ifdef CONFIG_DEBUG_UART_SEMIHOSTING
175 #include <debug_uart.h>
177 static inline void _debug_uart_init(void)
181 static inline void _debug_uart_putc(int c)