summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSean Anderson <sean.anderson@seco.com>2022-04-04 14:18:00 -0400
committerTom Rini <trini@konsulko.com>2022-04-14 15:39:15 -0400
commit34855b39beb63ca3cdeabbd704ea610268837ced (patch)
treeb3e48c196c19c47ffbfe986b02d40a6aa9f384bd /drivers
parent679190c41a25592103e711718c93d2655d344713 (diff)
serial: smh: Implement puts for DM
This adds an implementation of puts for DM. The implementation is not as clean as for the non-DM puts because we have to handle non-nul-terminated string. We also handle short writes (though these are probably very unusual). Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/serial/Kconfig1
-rw-r--r--drivers/serial/serial_semihosting.c31
2 files changed, 32 insertions, 0 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 6b189f8be05..dc514c95d33 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -834,6 +834,7 @@ config SH_SCIF_CLK_FREQ
config SEMIHOSTING_SERIAL
bool "Semihosting UART support"
depends on SEMIHOSTING && !SERIAL_RX_BUFFER
+ imply SERIAL_PUTS
help
Select this to enable a serial UART using semihosting. Special halt
instructions will be issued which an external debugger (such as a
diff --git a/drivers/serial/serial_semihosting.c b/drivers/serial/serial_semihosting.c
index 62b1b2241b3..4328b3dac5b 100644
--- a/drivers/serial/serial_semihosting.c
+++ b/drivers/serial/serial_semihosting.c
@@ -5,12 +5,14 @@
#include <common.h>
#include <dm.h>
+#include <malloc.h>
#include <serial.h>
#include <semihosting.h>
/**
* struct smh_serial_priv - Semihosting serial private data
* @infd: stdin file descriptor (or error)
+ * @outfd: stdout file descriptor (or error)
*/
struct smh_serial_priv {
int infd;
@@ -36,8 +38,36 @@ static int smh_serial_putc(struct udevice *dev, const char ch)
return 0;
}
+static ssize_t smh_serial_puts(struct udevice *dev, const char *s, size_t len)
+{
+ int ret;
+ struct smh_serial_priv *priv = dev_get_priv(dev);
+ unsigned long written;
+
+ if (priv->outfd < 0) {
+ char *buf;
+
+ /* Try and avoid a copy if we can */
+ if (!s[len + 1]) {
+ smh_puts(s);
+ return len;
+ }
+
+ buf = strndup(s, len);
+ smh_puts(buf);
+ free(buf);
+ return len;
+ }
+
+ ret = smh_write(priv->outfd, s, len, &written);
+ if (written)
+ return written;
+ return ret;
+}
+
static const struct dm_serial_ops smh_serial_ops = {
.putc = smh_serial_putc,
+ .puts = smh_serial_puts,
.getc = smh_serial_getc,
};
@@ -53,6 +83,7 @@ static int smh_serial_probe(struct udevice *dev)
struct smh_serial_priv *priv = dev_get_priv(dev);
priv->infd = smh_open(":tt", MODE_READ);
+ priv->outfd = smh_open(":tt", MODE_WRITE);
return 0;
}