From: Simon Glass <sjg@chromium.org> The serial driver is currently quite slow since it sets an event and waits for at least 1ms for a keypress, which may never come. On real hardware, the keyboard does not work correctly wihout waiting for events. Reduce the time to 10us which should be enough to provide an opportunity for event processing. QEMU does not actually have this problem, so detect that and skip the processing altogether. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/serial/serial_efi.c | 45 ++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c index 6645520e2ca..89df6a9dbb4 100644 --- a/drivers/serial/serial_efi.c +++ b/drivers/serial/serial_efi.c @@ -12,9 +12,12 @@ #include <fdtdec.h> #include <log.h> #include <linux/compiler.h> +#include <asm/global_data.h> #include <asm/io.h> #include <serial.h> +DECLARE_GLOBAL_DATA_PTR; + /* Information about the efi console */ struct serial_efi_priv { struct efi_simple_text_input_protocol *con_in; @@ -44,26 +47,38 @@ int serial_efi_setbrg(struct udevice *dev, int baudrate) static int serial_efi_get_key(struct serial_efi_priv *priv) { struct efi_simple_text_input_protocol *cin = priv->con_in; - struct efi_event *events[2] = {cin->wait_for_key, priv->timer}; - efi_uintn_t index; efi_status_t ret; if (priv->have_key) return 0; - ret = priv->boot->wait_for_event(2, events, &index); - if (ret) { - log_err("wait_for_event() failed\n"); - return -EAGAIN; + /* For emulators like QEMU, skip the timer wait since USB event + * processing is not needed + */ + if (gd->flags & GD_FLG_EMUL) { + ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key); + if (ret == EFI_NOT_READY) + return -EAGAIN; + else if (ret != EFI_SUCCESS) + return -EIO; + } else { + struct efi_event *events[2] = {cin->wait_for_key, priv->timer}; + efi_uintn_t index; + + ret = priv->boot->wait_for_event(2, events, &index); + if (ret) { + log_err("wait_for_event() failed\n"); + return -EAGAIN; + } + if (index) + return -EAGAIN; + + ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key); + if (ret == EFI_NOT_READY) + return -EAGAIN; + else if (ret != EFI_SUCCESS) + return -EIO; } - if (index) - return -EAGAIN; - - ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key); - if (ret == EFI_NOT_READY) - return -EAGAIN; - else if (ret != EFI_SUCCESS) - return -EIO; priv->have_key = true; @@ -155,7 +170,7 @@ static int serial_efi_probe(struct udevice *dev) if (ret) return -ECOMM; ret = boot->set_timer(priv->timer, EFI_TIMER_PERIODIC, - 1000 * 1000 / 100 /* 1ms in 100ns units */); + 100 /* 10μs in 100ns units */); if (ret) return -ECOMM; -- 2.43.0