diff options
-rw-r--r-- | include/sbi_utils/serial/fdt_serial.h | 28 | ||||
-rw-r--r-- | lib/utils/serial/fdt_serial.c | 109 | ||||
-rw-r--r-- | lib/utils/serial/fdt_serial_htif.c | 24 | ||||
-rw-r--r-- | lib/utils/serial/fdt_serial_sifive.c | 38 | ||||
-rw-r--r-- | lib/utils/serial/fdt_serial_uart8250.c | 39 | ||||
-rw-r--r-- | lib/utils/serial/objects.mk | 4 |
6 files changed, 242 insertions, 0 deletions
diff --git a/include/sbi_utils/serial/fdt_serial.h b/include/sbi_utils/serial/fdt_serial.h new file mode 100644 index 0000000..08f9799 --- /dev/null +++ b/include/sbi_utils/serial/fdt_serial.h @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#ifndef __FDT_SERIAL_H__ +#define __FDT_SERIAL_H__ + +#include <sbi/sbi_types.h> + +struct fdt_serial { + const struct fdt_match *match_table; + int (*init)(void *fdt, int nodeoff, const struct fdt_match *match); + void (*putc)(char ch); + int (*getc)(void); +}; + +void fdt_serial_putc(char ch); + +int fdt_serial_getc(void); + +int fdt_serial_init(void); + +#endif diff --git a/lib/utils/serial/fdt_serial.c b/lib/utils/serial/fdt_serial.c new file mode 100644 index 0000000..ae1aeea --- /dev/null +++ b/lib/utils/serial/fdt_serial.c @@ -0,0 +1,109 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#include <libfdt.h> +#include <sbi/sbi_scratch.h> +#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/serial/fdt_serial.h> + +extern struct fdt_serial fdt_serial_uart8250; +extern struct fdt_serial fdt_serial_sifive; +extern struct fdt_serial fdt_serial_htif; + +static struct fdt_serial *serial_drivers[] = { + &fdt_serial_uart8250, + &fdt_serial_sifive, + &fdt_serial_htif, +}; + +static void dummy_putc(char ch) +{ +} + +static int dummy_getc(void) +{ + return -1; +} + +static struct fdt_serial dummy = { + .match_table = NULL, + .init = NULL, + .putc = dummy_putc, + .getc = dummy_getc, +}; + +static struct fdt_serial *current_driver = &dummy; + +void fdt_serial_putc(char ch) +{ + current_driver->putc(ch); +} + +int fdt_serial_getc(void) +{ + return current_driver->getc(); +} + +int fdt_serial_init(void) +{ + const void *prop; + struct fdt_serial *drv; + const struct fdt_match *match; + int pos, noff = -1, len, coff, rc; + void *fdt = sbi_scratch_thishart_arg1_ptr(); + + /* Find offset of node pointed by stdout-path */ + coff = fdt_path_offset(fdt, "/chosen"); + if (-1 < coff) { + prop = fdt_getprop(fdt, coff, "stdout-path", &len); + if (prop && len) + noff = fdt_path_offset(fdt, prop); + } + + /* First check DT node pointed by stdout-path */ + for (pos = 0; pos < array_size(serial_drivers) && -1 < noff; pos++) { + drv = serial_drivers[pos]; + + match = fdt_match_node(fdt, noff, drv->match_table); + if (!match) + continue; + + if (drv->init) { + rc = drv->init(fdt, noff, match); + if (rc) + return rc; + } + current_driver = drv; + break; + } + + /* Check if we found desired driver */ + if (current_driver != &dummy) + goto done; + + /* Lastly check all DT nodes */ + for (pos = 0; pos < array_size(serial_drivers); pos++) { + drv = serial_drivers[pos]; + + noff = fdt_find_match(fdt, drv->match_table, &match); + if (noff < 0) + continue; + + if (drv->init) { + rc = drv->init(fdt, noff, match); + if (rc) + return rc; + } + current_driver = drv; + break; + } + +done: + return 0; +} diff --git a/lib/utils/serial/fdt_serial_htif.c b/lib/utils/serial/fdt_serial_htif.c new file mode 100644 index 0000000..32d6953 --- /dev/null +++ b/lib/utils/serial/fdt_serial_htif.c @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/serial/fdt_serial.h> +#include <sbi_utils/sys/htif.h> + +static const struct fdt_match serial_htif_match[] = { + { .compatible = "ucb,htif0" }, + { }, +}; + +struct fdt_serial fdt_serial_htif = { + .match_table = serial_htif_match, + .init = NULL, + .getc = htif_getc, + .putc = htif_putc +}; diff --git a/lib/utils/serial/fdt_serial_sifive.c b/lib/utils/serial/fdt_serial_sifive.c new file mode 100644 index 0000000..9e487a2 --- /dev/null +++ b/lib/utils/serial/fdt_serial_sifive.c @@ -0,0 +1,38 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/serial/fdt_serial.h> +#include <sbi_utils/serial/sifive-uart.h> + +static int serial_sifive_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int rc; + struct platform_uart_data uart; + + rc = fdt_parse_sifive_uart_node(fdt, nodeoff, &uart); + if (rc) + return rc; + + return sifive_uart_init(uart.addr, uart.freq, uart.baud); +} + +static const struct fdt_match serial_sifive_match[] = { + { .compatible = "sifive,fu540-c000-uart" }, + { .compatible = "sifive,uart0" }, + { }, +}; + +struct fdt_serial fdt_serial_sifive = { + .match_table = serial_sifive_match, + .init = serial_sifive_init, + .getc = sifive_uart_getc, + .putc = sifive_uart_putc +}; diff --git a/lib/utils/serial/fdt_serial_uart8250.c b/lib/utils/serial/fdt_serial_uart8250.c new file mode 100644 index 0000000..5030b82 --- /dev/null +++ b/lib/utils/serial/fdt_serial_uart8250.c @@ -0,0 +1,39 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel <anup.patel@wdc.com> + */ + +#include <sbi_utils/fdt/fdt_helper.h> +#include <sbi_utils/serial/fdt_serial.h> +#include <sbi_utils/serial/uart8250.h> + +static int serial_uart8250_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int rc; + struct platform_uart_data uart; + + rc = fdt_parse_uart8250_node(fdt, nodeoff, &uart); + if (rc) + return rc; + + return uart8250_init(uart.addr, uart.freq, uart.baud, + uart.reg_shift, uart.reg_io_width); +} + +static const struct fdt_match serial_uart8250_match[] = { + { .compatible = "ns16550" }, + { .compatible = "ns16550a" }, + { }, +}; + +struct fdt_serial fdt_serial_uart8250 = { + .match_table = serial_uart8250_match, + .init = serial_uart8250_init, + .getc = uart8250_getc, + .putc = uart8250_putc +}; diff --git a/lib/utils/serial/objects.mk b/lib/utils/serial/objects.mk index 5b22031..d81663b 100644 --- a/lib/utils/serial/objects.mk +++ b/lib/utils/serial/objects.mk @@ -7,5 +7,9 @@ # Anup Patel <anup.patel@wdc.com> # +libsbiutils-objs-y += serial/fdt_serial.o +libsbiutils-objs-y += serial/fdt_serial_htif.o +libsbiutils-objs-y += serial/fdt_serial_sifive.o +libsbiutils-objs-y += serial/fdt_serial_uart8250.o libsbiutils-objs-y += serial/sifive-uart.o libsbiutils-objs-y += serial/uart8250.o |