xref: /rk3399_rockchip-uboot/drivers/serial/serial_efi.c (revision 275854baeeec02e37c8f8bf718f94090f2a531ff)
1*275854baSSimon Glass /*
2*275854baSSimon Glass  * Copyright (c) 2015 Google, Inc
3*275854baSSimon Glass  * Written by Simon Glass <sjg@chromium.org>
4*275854baSSimon Glass  *
5*275854baSSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
6*275854baSSimon Glass  */
7*275854baSSimon Glass 
8*275854baSSimon Glass #include <common.h>
9*275854baSSimon Glass #include <debug_uart.h>
10*275854baSSimon Glass #include <dm.h>
11*275854baSSimon Glass #include <efi.h>
12*275854baSSimon Glass #include <efi_api.h>
13*275854baSSimon Glass #include <errno.h>
14*275854baSSimon Glass #include <fdtdec.h>
15*275854baSSimon Glass #include <linux/compiler.h>
16*275854baSSimon Glass #include <asm/io.h>
17*275854baSSimon Glass #include <serial.h>
18*275854baSSimon Glass 
19*275854baSSimon Glass /* Information about the efi console */
20*275854baSSimon Glass struct serial_efi_priv {
21*275854baSSimon Glass 	struct efi_simple_input_interface *con_in;
22*275854baSSimon Glass 	struct efi_simple_text_output_protocol *con_out;
23*275854baSSimon Glass 	struct efi_input_key key;
24*275854baSSimon Glass 	bool have_key;
25*275854baSSimon Glass };
26*275854baSSimon Glass 
27*275854baSSimon Glass int serial_efi_setbrg(struct udevice *dev, int baudrate)
28*275854baSSimon Glass {
29*275854baSSimon Glass 	return 0;
30*275854baSSimon Glass }
31*275854baSSimon Glass 
32*275854baSSimon Glass static int serial_efi_get_key(struct serial_efi_priv *priv)
33*275854baSSimon Glass {
34*275854baSSimon Glass 	int ret;
35*275854baSSimon Glass 
36*275854baSSimon Glass 	if (priv->have_key)
37*275854baSSimon Glass 		return 0;
38*275854baSSimon Glass 	ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key);
39*275854baSSimon Glass 	if (ret == EFI_NOT_READY)
40*275854baSSimon Glass 		return -EAGAIN;
41*275854baSSimon Glass 	else if (ret != EFI_SUCCESS)
42*275854baSSimon Glass 		return -EIO;
43*275854baSSimon Glass 
44*275854baSSimon Glass 	priv->have_key = true;
45*275854baSSimon Glass 
46*275854baSSimon Glass 	return 0;
47*275854baSSimon Glass }
48*275854baSSimon Glass 
49*275854baSSimon Glass static int serial_efi_getc(struct udevice *dev)
50*275854baSSimon Glass {
51*275854baSSimon Glass 	struct serial_efi_priv *priv = dev_get_priv(dev);
52*275854baSSimon Glass 	int ret, ch;
53*275854baSSimon Glass 
54*275854baSSimon Glass 	ret = serial_efi_get_key(priv);
55*275854baSSimon Glass 	if (ret)
56*275854baSSimon Glass 		return ret;
57*275854baSSimon Glass 
58*275854baSSimon Glass 	priv->have_key = false;
59*275854baSSimon Glass 	ch = priv->key.unicode_char;
60*275854baSSimon Glass 
61*275854baSSimon Glass 	/*
62*275854baSSimon Glass 	 * Unicode char 8 (for backspace) is never returned. Instead we get a
63*275854baSSimon Glass 	 * key scan code of 8. Handle this so that backspace works correctly
64*275854baSSimon Glass 	 * in the U-Boot command line.
65*275854baSSimon Glass 	 */
66*275854baSSimon Glass 	if (!ch && priv->key.scan_code == 8)
67*275854baSSimon Glass 		ch = 8;
68*275854baSSimon Glass 	debug(" [%x %x %x] ", ch, priv->key.unicode_char, priv->key.scan_code);
69*275854baSSimon Glass 
70*275854baSSimon Glass 	return ch;
71*275854baSSimon Glass }
72*275854baSSimon Glass 
73*275854baSSimon Glass static int serial_efi_putc(struct udevice *dev, const char ch)
74*275854baSSimon Glass {
75*275854baSSimon Glass 	struct serial_efi_priv *priv = dev_get_priv(dev);
76*275854baSSimon Glass 	uint16_t ucode[2];
77*275854baSSimon Glass 	int ret;
78*275854baSSimon Glass 
79*275854baSSimon Glass 	ucode[0] = ch;
80*275854baSSimon Glass 	ucode[1] = '\0';
81*275854baSSimon Glass 	ret = priv->con_out->output_string(priv->con_out, ucode);
82*275854baSSimon Glass 	if (ret)
83*275854baSSimon Glass 		return -EIO;
84*275854baSSimon Glass 
85*275854baSSimon Glass 	return 0;
86*275854baSSimon Glass }
87*275854baSSimon Glass 
88*275854baSSimon Glass static int serial_efi_pending(struct udevice *dev, bool input)
89*275854baSSimon Glass {
90*275854baSSimon Glass 	struct serial_efi_priv *priv = dev_get_priv(dev);
91*275854baSSimon Glass 	int ret;
92*275854baSSimon Glass 
93*275854baSSimon Glass 	/* We assume that EFI will stall if its output buffer fills up */
94*275854baSSimon Glass 	if (!input)
95*275854baSSimon Glass 		return 0;
96*275854baSSimon Glass 
97*275854baSSimon Glass 	ret = serial_efi_get_key(priv);
98*275854baSSimon Glass 	if (ret == -EAGAIN)
99*275854baSSimon Glass 		return 0;
100*275854baSSimon Glass 	else if (ret)
101*275854baSSimon Glass 		return ret;
102*275854baSSimon Glass 
103*275854baSSimon Glass 	return 1;
104*275854baSSimon Glass }
105*275854baSSimon Glass 
106*275854baSSimon Glass /*
107*275854baSSimon Glass  * There is nothing to init here since the EFI console is already running by
108*275854baSSimon Glass  * the time we enter U-Boot.
109*275854baSSimon Glass  */
110*275854baSSimon Glass void debug_uart_init(void)
111*275854baSSimon Glass {
112*275854baSSimon Glass }
113*275854baSSimon Glass 
114*275854baSSimon Glass static inline void _debug_uart_putc(int ch)
115*275854baSSimon Glass {
116*275854baSSimon Glass 	struct efi_system_table *sys_table = efi_get_sys_table();
117*275854baSSimon Glass 	uint16_t ucode[2];
118*275854baSSimon Glass 
119*275854baSSimon Glass 	ucode[0] = ch;
120*275854baSSimon Glass 	ucode[1] = '\0';
121*275854baSSimon Glass 	sys_table->con_out->output_string(sys_table->con_out, ucode);
122*275854baSSimon Glass }
123*275854baSSimon Glass 
124*275854baSSimon Glass DEBUG_UART_FUNCS
125*275854baSSimon Glass 
126*275854baSSimon Glass static int serial_efi_probe(struct udevice *dev)
127*275854baSSimon Glass {
128*275854baSSimon Glass 	struct efi_system_table *table = efi_get_sys_table();
129*275854baSSimon Glass 	struct serial_efi_priv *priv = dev_get_priv(dev);
130*275854baSSimon Glass 
131*275854baSSimon Glass 	priv->con_in = table->con_in;
132*275854baSSimon Glass 	priv->con_out = table->con_out;
133*275854baSSimon Glass 
134*275854baSSimon Glass 	return 0;
135*275854baSSimon Glass }
136*275854baSSimon Glass 
137*275854baSSimon Glass static const struct dm_serial_ops serial_efi_ops = {
138*275854baSSimon Glass 	.putc = serial_efi_putc,
139*275854baSSimon Glass 	.getc = serial_efi_getc,
140*275854baSSimon Glass 	.pending = serial_efi_pending,
141*275854baSSimon Glass 	.setbrg = serial_efi_setbrg,
142*275854baSSimon Glass };
143*275854baSSimon Glass 
144*275854baSSimon Glass static const struct udevice_id serial_efi_ids[] = {
145*275854baSSimon Glass 	{ .compatible = "efi,uart" },
146*275854baSSimon Glass 	{ }
147*275854baSSimon Glass };
148*275854baSSimon Glass 
149*275854baSSimon Glass U_BOOT_DRIVER(serial_efi) = {
150*275854baSSimon Glass 	.name	= "serial_efi",
151*275854baSSimon Glass 	.id	= UCLASS_SERIAL,
152*275854baSSimon Glass 	.of_match = serial_efi_ids,
153*275854baSSimon Glass 	.priv_auto_alloc_size = sizeof(struct serial_efi_priv),
154*275854baSSimon Glass 	.probe = serial_efi_probe,
155*275854baSSimon Glass 	.ops	= &serial_efi_ops,
156*275854baSSimon Glass 	.flags = DM_FLAG_PRE_RELOC,
157*275854baSSimon Glass };
158