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 v6 6/7] lib: utils/serial: Support multiple UART8250 devices
Date: Thu, 18 Dec 2025 02:42:42 -0800 [thread overview]
Message-ID: <20251218104243.562667-7-ganboing@gmail.com> (raw)
In-Reply-To: <20251218104243.562667-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-18 10:44 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-18 10:42 [PATCH v6 0/7] Initial ESWIN/EIC7700 and Hifive P550 support Bo Gan
2025-12-18 10:42 ` [PATCH v6 1/7] lib: sbi_hart_pmp: make sbi_hart_pmp_fence public Bo Gan
2025-12-18 14:35 ` Anup Patel
2025-12-18 10:42 ` [PATCH v6 2/7] lib: sbi_domain: add sbi_domain_get_oldpmp_flags Bo Gan
2025-12-18 14:36 ` Anup Patel
2025-12-18 10:42 ` [PATCH v6 3/7] lib: sbi_domain: make is_region_subset public Bo Gan
2025-12-18 14:38 ` Anup Patel
2025-12-18 10:42 ` [PATCH v6 4/7] lib: sbi: give platform choice of using single memregion to cover OpenSBI Bo Gan
2025-12-21 14:46 ` Anup Patel
2025-12-18 10:42 ` [PATCH v6 5/7] platform: generic: eswin: add EIC7700 Bo Gan
2025-12-21 14:49 ` Anup Patel
2025-12-18 10:42 ` Bo Gan [this message]
2025-12-18 10:42 ` [PATCH v6 7/7] platform: generic: eswin: Add shutdown/reboot support for Hifive Premier P550 Bo Gan
2025-12-21 6:49 ` Bo Gan
2025-12-21 15:38 ` Anup Patel
2025-12-21 15:38 ` [PATCH v6 0/7] Initial ESWIN/EIC7700 and Hifive P550 support Anup Patel
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=20251218104243.562667-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox