1 // SPDX-License-Identifier: GPL-2.0
4 * (C) 2020 EPAM Systems Inc.
12 #include <linux/bug.h>
15 #include <xen/events.h>
17 #include <xen/interface/sched.h>
18 #include <xen/interface/hvm/hvm_op.h>
19 #include <xen/interface/hvm/params.h>
20 #include <xen/interface/io/console.h>
21 #include <xen/interface/io/ring.h>
23 DECLARE_GLOBAL_DATA_PTR;
28 * struct xen_uart_priv - Structure representing a Xen UART info
29 * @intf: Console I/O interface for Xen guest OSes
30 * @evtchn: Console event channel
32 struct xen_uart_priv {
33 struct xencons_interface *intf;
37 int xen_serial_setbrg(struct udevice *dev, int baudrate)
42 static int xen_serial_probe(struct udevice *dev)
44 struct xen_uart_priv *priv = dev_get_priv(dev);
49 ret = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &val);
50 if (ret < 0 || val == 0)
56 ret = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &val);
64 priv->intf = (struct xencons_interface *)(gfn << XEN_PAGE_SHIFT);
69 static int xen_serial_pending(struct udevice *dev, bool input)
71 struct xen_uart_priv *priv = dev_get_priv(dev);
72 struct xencons_interface *intf = priv->intf;
74 if (!input || intf->in_cons == intf->in_prod)
80 static int xen_serial_getc(struct udevice *dev)
82 struct xen_uart_priv *priv = dev_get_priv(dev);
83 struct xencons_interface *intf = priv->intf;
84 XENCONS_RING_IDX cons;
87 while (intf->in_cons == intf->in_prod)
91 mb(); /* get pointers before reading ring */
93 c = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
95 mb(); /* read ring before consuming */
98 notify_remote_via_evtchn(priv->evtchn);
103 static int __write_console(struct udevice *dev, const char *data, int len)
105 struct xen_uart_priv *priv = dev_get_priv(dev);
106 struct xencons_interface *intf = priv->intf;
107 XENCONS_RING_IDX cons, prod;
110 cons = intf->out_cons;
111 prod = intf->out_prod;
112 mb(); /* Update pointer */
114 WARN_ON((prod - cons) > sizeof(intf->out));
116 while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
117 intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
119 mb(); /* Update data before pointer */
120 intf->out_prod = prod;
123 notify_remote_via_evtchn(priv->evtchn);
128 static int write_console(struct udevice *dev, const char *data, int len)
131 * Make sure the whole buffer is emitted, polling if
132 * necessary. We don't ever want to rely on the hvc daemon
133 * because the most interesting console output is when the
134 * kernel is crippled.
137 int sent = __write_console(dev, data, len);
143 HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
149 static int xen_serial_putc(struct udevice *dev, const char ch)
151 write_console(dev, &ch, 1);
156 static const struct dm_serial_ops xen_serial_ops = {
157 .putc = xen_serial_putc,
158 .getc = xen_serial_getc,
159 .pending = xen_serial_pending,
162 #if CONFIG_IS_ENABLED(OF_CONTROL)
163 static const struct udevice_id xen_serial_ids[] = {
164 { .compatible = "xen,xen" },
169 U_BOOT_DRIVER(serial_xen) = {
170 .name = "serial_xen",
172 #if CONFIG_IS_ENABLED(OF_CONTROL)
173 .of_match = xen_serial_ids,
175 .priv_auto_alloc_size = sizeof(struct xen_uart_priv),
176 .probe = xen_serial_probe,
177 .ops = &xen_serial_ops,
178 #if !CONFIG_IS_ENABLED(OF_CONTROL)
179 .flags = DM_FLAG_PRE_RELOC,