From: Bo Gan <ganboing@gmail.com>
To: opensbi@lists.infradead.org
Cc: linmin@eswincomputing.com, pinkesh.vaghela@einfochips.com,
gaohan@iscas.ac.cn, samuel@sholland.org, wangxiang@iscas.ac.cn
Subject: [PATCH v5 6/7] lib: utils/serial: Support multiple UART8250 devices
Date: Wed, 17 Dec 2025 05:29:58 -0800 [thread overview]
Message-ID: <20251217132959.545197-7-ganboing@gmail.com> (raw)
In-Reply-To: <20251217132959.545197-1-ganboing@gmail.com>
Previously we assume only 1 UART8250 instance can be used. Now we support
multiple instances by introducing counterpart functions to putc/getc/init
which take an extra *dev parameter, and name them as uart8250_device_xyz()
The original functions without the *dev parameter will operate on the
default instance exactly the same as before, so no changes on the caller
is required.
Note: uart8250_device_init only does device initialization without the
console registration logic.
Signed-off-by: Bo Gan <ganboing@gmail.com>
---
include/sbi_utils/serial/uart8250.h | 16 +++++
lib/utils/serial/uart8250.c | 104 ++++++++++++++++------------
2 files changed, 75 insertions(+), 45 deletions(-)
diff --git a/include/sbi_utils/serial/uart8250.h b/include/sbi_utils/serial/uart8250.h
index 70cd2912..78c0e614 100644
--- a/include/sbi_utils/serial/uart8250.h
+++ b/include/sbi_utils/serial/uart8250.h
@@ -14,6 +14,22 @@
#define UART_CAP_UUE BIT(0) /* Check UUE capability for XScale PXA UARTs */
+struct uart8250_device {
+ volatile char *base;
+ u32 in_freq;
+ u32 baudrate;
+ u32 reg_width;
+ u32 reg_shift;
+};
+
+int uart8250_device_getc(struct uart8250_device *dev);
+
+void uart8250_device_putc(struct uart8250_device *dev, char ch);
+
+void uart8250_device_init(struct uart8250_device *dev, unsigned long base,
+ u32 in_freq, u32 baudrate, u32 reg_shift,
+ u32 reg_width, u32 reg_offset, u32 caps);
+
int uart8250_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift,
u32 reg_width, u32 reg_offset, u32 caps);
diff --git a/lib/utils/serial/uart8250.c b/lib/utils/serial/uart8250.c
index bb209c9a..d65f127d 100644
--- a/lib/utils/serial/uart8250.c
+++ b/lib/utils/serial/uart8250.c
@@ -47,97 +47,111 @@
/* clang-format on */
-static volatile char *uart8250_base;
-static u32 uart8250_in_freq;
-static u32 uart8250_baudrate;
-static u32 uart8250_reg_width;
-static u32 uart8250_reg_shift;
+static struct uart8250_device uart8250_dev;
-static u32 get_reg(u32 num)
+static u32 get_reg(struct uart8250_device *dev, u32 num)
{
- u32 offset = num << uart8250_reg_shift;
+ u32 offset = num << dev->reg_shift;
- if (uart8250_reg_width == 1)
- return readb(uart8250_base + offset);
- else if (uart8250_reg_width == 2)
- return readw(uart8250_base + offset);
+ if (dev->reg_width == 1)
+ return readb(dev->base + offset);
+ else if (dev->reg_width == 2)
+ return readw(dev->base + offset);
else
- return readl(uart8250_base + offset);
+ return readl(dev->base + offset);
}
-static void set_reg(u32 num, u32 val)
+static void set_reg(struct uart8250_device *dev, u32 num, u32 val)
{
- u32 offset = num << uart8250_reg_shift;
+ u32 offset = num << dev->reg_shift;
- if (uart8250_reg_width == 1)
- writeb(val, uart8250_base + offset);
- else if (uart8250_reg_width == 2)
- writew(val, uart8250_base + offset);
+ if (dev->reg_width == 1)
+ writeb(val, dev->base + offset);
+ else if (dev->reg_width == 2)
+ writew(val, dev->base + offset);
else
- writel(val, uart8250_base + offset);
+ writel(val, dev->base + offset);
}
-static void uart8250_putc(char ch)
+void uart8250_device_putc(struct uart8250_device *dev, char ch)
{
- while ((get_reg(UART_LSR_OFFSET) & UART_LSR_THRE) == 0)
+ while ((get_reg(dev, UART_LSR_OFFSET) & UART_LSR_THRE) == 0)
;
- set_reg(UART_THR_OFFSET, ch);
+ set_reg(dev, UART_THR_OFFSET, ch);
}
-static int uart8250_getc(void)
+static void uart8250_putc(char ch)
{
- if (get_reg(UART_LSR_OFFSET) & UART_LSR_DR)
- return get_reg(UART_RBR_OFFSET);
+ return uart8250_device_putc(&uart8250_dev, ch);
+}
+
+int uart8250_device_getc(struct uart8250_device *dev)
+{
+ if (get_reg(dev, UART_LSR_OFFSET) & UART_LSR_DR)
+ return get_reg(dev, UART_RBR_OFFSET);
return -1;
}
+static int uart8250_getc(void)
+{
+ return uart8250_device_getc(&uart8250_dev);
+}
+
static struct sbi_console_device uart8250_console = {
.name = "uart8250",
.console_putc = uart8250_putc,
.console_getc = uart8250_getc
};
-int uart8250_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift,
- u32 reg_width, u32 reg_offset, u32 caps)
+void uart8250_device_init(struct uart8250_device *dev, unsigned long base,
+ u32 in_freq, u32 baudrate, u32 reg_shift,
+ u32 reg_width, u32 reg_offset, u32 caps)
{
u16 bdiv = 0;
- uart8250_base = (volatile char *)base + reg_offset;
- uart8250_reg_shift = reg_shift;
- uart8250_reg_width = reg_width;
- uart8250_in_freq = in_freq;
- uart8250_baudrate = baudrate;
+ dev->base = (volatile char *)base + reg_offset;
+ dev->reg_shift = reg_shift;
+ dev->reg_width = reg_width;
+ dev->in_freq = in_freq;
+ dev->baudrate = baudrate;
- if (uart8250_baudrate) {
- bdiv = (uart8250_in_freq + 8 * uart8250_baudrate) /
- (16 * uart8250_baudrate);
+ if (dev->baudrate) {
+ bdiv = (dev->in_freq + 8 * dev->baudrate) /
+ (16 * dev->baudrate);
}
/* Disable all interrupts */
- set_reg(UART_IER_OFFSET, (caps & UART_CAP_UUE) ?
+ set_reg(dev, UART_IER_OFFSET, (caps & UART_CAP_UUE) ?
UART_IER_UUE : 0x00);
/* Enable DLAB */
- set_reg(UART_LCR_OFFSET, 0x80);
+ set_reg(dev, UART_LCR_OFFSET, 0x80);
if (bdiv) {
/* Set divisor low byte */
- set_reg(UART_DLL_OFFSET, bdiv & 0xff);
+ set_reg(dev, UART_DLL_OFFSET, bdiv & 0xff);
/* Set divisor high byte */
- set_reg(UART_DLM_OFFSET, (bdiv >> 8) & 0xff);
+ set_reg(dev, UART_DLM_OFFSET, (bdiv >> 8) & 0xff);
}
/* 8 bits, no parity, one stop bit */
- set_reg(UART_LCR_OFFSET, 0x03);
+ set_reg(dev, UART_LCR_OFFSET, 0x03);
/* Enable FIFO */
- set_reg(UART_FCR_OFFSET, 0x01);
+ set_reg(dev, UART_FCR_OFFSET, 0x01);
/* No modem control DTR RTS */
- set_reg(UART_MCR_OFFSET, 0x00);
+ set_reg(dev, UART_MCR_OFFSET, 0x00);
/* Clear line status and read receive buffer */
- if (get_reg(UART_LSR_OFFSET) & UART_LSR_DR)
- get_reg(UART_RBR_OFFSET);
+ if (get_reg(dev, UART_LSR_OFFSET) & UART_LSR_DR)
+ get_reg(dev, UART_RBR_OFFSET);
/* Set scratchpad */
- set_reg(UART_SCR_OFFSET, 0x00);
+ set_reg(dev, UART_SCR_OFFSET, 0x00);
+}
+
+int uart8250_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift,
+ u32 reg_width, u32 reg_offset, u32 caps)
+{
+ uart8250_device_init(&uart8250_dev, base, in_freq, baudrate,
+ reg_shift, reg_width, reg_offset, caps);
sbi_console_set_device(&uart8250_console);
--
2.34.1
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
next prev parent reply other threads:[~2025-12-17 13:32 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-17 13:29 [PATCH v5 0/7] Initial ESWIN/EIC7700 and Hifive P550 support Bo Gan
2025-12-17 13:29 ` [PATCH v5 1/7] lib: sbi_hart_pmp: make sbi_hart_pmp_fence public Bo Gan
2025-12-17 13:29 ` [PATCH v5 2/7] lib: sbi_domain: add sbi_domain_get_oldpmp_flags Bo Gan
2025-12-17 13:29 ` [PATCH v5 3/7] lib: sbi_domain: make is_region_subset public Bo Gan
2025-12-17 13:29 ` [PATCH v5 4/7] lib: sbi: give platform choice of using single memregion to cover OpenSBI Bo Gan
2025-12-17 13:29 ` [PATCH v5 5/7] platform: generic: eswin: add EIC7700 Bo Gan
2025-12-17 13:29 ` Bo Gan [this message]
2025-12-17 13:29 ` [PATCH v5 7/7] platform: generic: eswin: Add shutdown/reboot support for Hifive Premier P550 Bo Gan
2025-12-18 11:14 ` [PATCH v5 0/7] Initial ESWIN/EIC7700 and Hifive P550 support Bo Gan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251217132959.545197-7-ganboing@gmail.com \
--to=ganboing@gmail.com \
--cc=gaohan@iscas.ac.cn \
--cc=linmin@eswincomputing.com \
--cc=opensbi@lists.infradead.org \
--cc=pinkesh.vaghela@einfochips.com \
--cc=samuel@sholland.org \
--cc=wangxiang@iscas.ac.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.