mirror of
				https://github.com/riscv-software-src/opensbi
				synced 2025-11-03 21:48:45 +00:00 
			
		
		
		
	lib: utils: Add simple FDT serial framework
We add simple serial framework which will select and use serial driver based on details in FDT passed by previous booting stage. Signed-off-by: Anup Patel <anup.patel@wdc.com> Reviewed-by: Atish Patra <atish.patra@wdc.com>
This commit is contained in:
		
							parent
							
								
									75322a634b
								
							
						
					
					
						commit
						76a89403c8
					
				
							
								
								
									
										28
									
								
								include/sbi_utils/serial/fdt_serial.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								include/sbi_utils/serial/fdt_serial.h
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
							
								
								
									
										109
									
								
								lib/utils/serial/fdt_serial.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								lib/utils/serial/fdt_serial.c
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								lib/utils/serial/fdt_serial_htif.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								lib/utils/serial/fdt_serial_htif.c
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										38
									
								
								lib/utils/serial/fdt_serial_sifive.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								lib/utils/serial/fdt_serial_sifive.c
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										39
									
								
								lib/utils/serial/fdt_serial_uart8250.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								lib/utils/serial/fdt_serial_uart8250.c
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
};
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user