blob: 0e59a9bfdc752aa2ab3870c6dcf9cef229c59558 [file] [log] [blame]
Jiaxun Yang076c3a42024-06-18 14:56:06 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com>
4 */
5
6#include <dm.h>
7#include <malloc.h>
8#include <serial.h>
9
10#include <asm/platform/simcall.h>
11
12/**
13 * struct simc_serial_priv - Semihosting serial private data
14 * @counter: Counter used to fake pending every other call
15 */
16struct simc_serial_priv {
17 unsigned int counter;
18};
19
20static int simc_serial_getc(struct udevice *dev)
21{
22 char ch = 0;
23
24 simc_read(0, &ch, sizeof(ch));
25
26 return ch;
27}
28
29static int simc_serial_putc(struct udevice *dev, const char ch)
30{
31 char str[2] = {0};
32
33 str[0] = ch;
34 simc_write(1, str, 1);
35
36 return 0;
37}
38
39static int simc_serial_pending(struct udevice *dev, bool input)
40{
41 struct simc_serial_priv *priv = dev_get_priv(dev);
42
43 if (input) {
44 int res = simc_poll(0);
45 return res < 0 ? priv->counter++ & 1 : res;
46 }
47
48 return false;
49}
50
51static ssize_t smh_serial_puts(struct udevice *dev, const char *s, size_t len)
52{
53 int ret;
54
55 ret = simc_write(1, s, len);
56
57 return ret;
58}
59
60static const struct dm_serial_ops simc_serial_ops = {
61 .putc = simc_serial_putc,
62 .puts = smh_serial_puts,
63 .getc = simc_serial_getc,
64 .pending = simc_serial_pending,
65};
66
67U_BOOT_DRIVER(simc_serial) = {
68 .name = "serial_xtensa_semihosting",
69 .id = UCLASS_SERIAL,
70 .priv_auto = sizeof(struct simc_serial_priv),
71 .ops = &simc_serial_ops,
72 .flags = DM_FLAG_PRE_RELOC,
73};
74
75U_BOOT_DRVINFO(simc_serial) = {
76 .name = "serial_xtensa_semihosting",
77};
78
79#if CONFIG_IS_ENABLED(DEBUG_UART_XTENSA_SEMIHOSTING)
80#include <debug_uart.h>
81
82static inline void _debug_uart_init(void)
83{
84}
85
86static inline void _debug_uart_putc(int c)
87{
88 simc_serial_putc(NULL, c);
89}
90
91DEBUG_UART_FUNCS
92#endif