From: AK Sharma <maskachoska@yahoo.com>
To: u-boot@lists.u-boot-project.org
Cc: Christian Marangi <ansuelsmth@gmail.com>,
Daniel Schwierzeck <daniel.schwierzeck@gmail.com>,
Dario Binacchi <dario.binacchi@amarulasolutions.com>,
Frieder Schrempf <frieder.schrempf@kontron.de>,
Jerome Forissier <jerome.forissier@arm.com>,
Marek Vasut <marex@denx.de>,
Michael Trimarchi <michael@amarulasolutions.com>,
Tom Rini <trini@konsulko.com>, AK Sharma <maskachoska@yahoo.com>
Subject: [PATCH v1 03/12] serial: en75xx: add EcoNet/Airoha EN75xx UART driver
Date: Wed, 26 Aug 2026 04:11:58 +0530 [thread overview]
Message-ID: <20260825224330.713151-4-maskachoska@yahoo.com> (raw)
In-Reply-To: <20260825224330.713151-1-maskachoska@yahoo.com>
Add a DM serial driver for the UART on the EcoNet/Airoha EN75xx SoCs.
Signed-off-by: AK Sharma <maskachoska@yahoo.com>
---
drivers/serial/Kconfig | 7 ++
drivers/serial/Makefile | 1 +
drivers/serial/serial_en75xx.c | 170 +++++++++++++++++++++++++++++++++
3 files changed, 178 insertions(+)
create mode 100644 drivers/serial/serial_en75xx.c
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 5f8b98f0..2a8fee98 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1098,6 +1098,13 @@ config ZYNQ_SERIAL
This driver supports the Cadence UART. It is found e.g. in Xilinx
Zynq/ZynqMP.
+config EN75XX_SERIAL
+ bool "EcoNet/Airoha EN75xx serial port support"
+ depends on ARCH_EN75XX
+ help
+ Support the byte-lane 16550-like UART used by EN7512/EN7521/EN7528.
+ The controller also uses a vendor-specific fractional divider.
+
config MTK_SERIAL
bool "MediaTek High-speed UART support"
depends on DM_SERIAL
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 66088b44..75ec49b7 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_OWL_SERIAL) += serial_owl.o
obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o
obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o
+obj-$(CONFIG_EN75XX_SERIAL) += serial_en75xx.o
obj-$(CONFIG_HTIF_CONSOLE) += serial_htif.o
obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o
obj-$(CONFIG_XEN_SERIAL) += serial_xen.o
diff --git a/drivers/serial/serial_en75xx.c b/drivers/serial/serial_en75xx.c
new file mode 100644
index 00000000..8753ce55
--- /dev/null
+++ b/drivers/serial/serial_en75xx.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* EcoNet/Airoha EN75xx UART */
+
+#include <dm.h>
+#include <errno.h>
+#include <serial.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+/* 16550 register indices (the byte/word offset is derived per SoC below) */
+#define R_RBR 0 /* THR / DLL when DLAB=1 */
+#define R_IER 1 /* DLM when DLAB=1 */
+#define R_FCR 2
+#define R_LCR 3
+#define R_MCR 4
+#define R_LSR 5
+#define R_MISCC 9
+#define R_XYD 11 /* EN7512 fractional divider (32-bit) */
+
+#define UART_LCR_DLAB 0x80
+#define UART_LCR_8N1 0x03
+#define UART_LSR_DR 0x01
+#define UART_LSR_THRE 0x20
+
+struct en75xx_serial_plat {
+ void __iomem *base;
+ bool le; /* EN7528: little-endian, 32-bit word access */
+ u32 uartclk; /* EN7528 UART source clock (0 => EN7512) */
+};
+
+/*
+ * EN7512 (big-endian): the 8-bit registers live in the top byte of each
+ * 32-bit word, i.e. byte offset (reg << 2) + 3, byte access.
+ * EN7528 (little-endian, reg-io-width=4, reg-shift=2): 32-bit word access at
+ * (reg << 2), value in the low byte.
+ */
+static u8 uart_rd(struct en75xx_serial_plat *plat, u32 reg)
+{
+ if (plat->le)
+ return readl(plat->base + (reg << 2)) & 0xff;
+
+ return readb(plat->base + (reg << 2) + 3);
+}
+
+static void uart_wr(struct en75xx_serial_plat *plat, u32 reg, u32 val)
+{
+ if (plat->le)
+ writel(val, plat->base + (reg << 2));
+ else
+ writeb(val, plat->base + (reg << 2) + 3);
+}
+
+static void en75xx_serial_hw_init(struct en75xx_serial_plat *plat,
+ int baudrate)
+{
+ if (baudrate <= 0)
+ baudrate = CONFIG_BAUDRATE;
+
+ /*
+ * EN7512 (BE) and EN7528 (LE) share the divider: Y=65000,
+ * X=round(baud*13/25), packed into the 32-bit XYD reg (11 @ +0x2c)
+ * as {X[31:16],Y[15:0]}. 16-bit regs go through uart_wr()
+ * (endian-correct); the XYD store is a native 32-bit write, valid
+ * on both. Live-verified on JCOW407: XYD == 0xEA00FDE8 at 115200.
+ */
+ u32 div_x = DIV_ROUND_CLOSEST((u32)baudrate * 13, 25);
+
+ if (div_x > 0xffff)
+ div_x = 0xffff;
+
+ uart_wr(plat, R_LCR, UART_LCR_DLAB);
+ __raw_writel((div_x << 16) | 65000, plat->base + (R_XYD << 2));
+ uart_wr(plat, R_RBR, 1);
+ uart_wr(plat, R_IER, 0);
+ uart_wr(plat, R_LCR, UART_LCR_8N1);
+ uart_wr(plat, R_FCR, 0x0f);
+ uart_wr(plat, R_MCR, 0);
+ uart_wr(plat, R_MISCC, 0);
+ uart_wr(plat, R_IER, 0);
+}
+
+static int en75xx_serial_putc(struct udevice *dev, const char ch)
+{
+ struct en75xx_serial_plat *plat = dev_get_plat(dev);
+
+ if (!(uart_rd(plat, R_LSR) & UART_LSR_THRE))
+ return -EAGAIN;
+
+ uart_wr(plat, R_RBR, ch);
+ return 0;
+}
+
+static int en75xx_serial_getc(struct udevice *dev)
+{
+ struct en75xx_serial_plat *plat = dev_get_plat(dev);
+
+ if (!(uart_rd(plat, R_LSR) & UART_LSR_DR))
+ return -EAGAIN;
+
+ return uart_rd(plat, R_RBR);
+}
+
+static int en75xx_serial_pending(struct udevice *dev, bool input)
+{
+ struct en75xx_serial_plat *plat = dev_get_plat(dev);
+ u8 lsr = uart_rd(plat, R_LSR);
+
+ if (input)
+ return !!(lsr & UART_LSR_DR);
+
+ return !(lsr & UART_LSR_THRE);
+}
+
+static int en75xx_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct en75xx_serial_plat *plat = dev_get_plat(dev);
+
+ en75xx_serial_hw_init(plat, baudrate);
+ return 0;
+}
+
+static int en75xx_serial_of_to_plat(struct udevice *dev)
+{
+ struct en75xx_serial_plat *plat = dev_get_plat(dev);
+
+ plat->base = dev_remap_addr(dev);
+ if (!plat->base)
+ return -EINVAL;
+
+ plat->le = (bool)dev_get_driver_data(dev);
+ if (plat->le)
+ plat->uartclk = dev_read_u32_default(dev, "clock-frequency",
+ 2000000);
+
+ return 0;
+}
+
+static int en75xx_serial_probe(struct udevice *dev)
+{
+ struct en75xx_serial_plat *plat = dev_get_plat(dev);
+
+ en75xx_serial_hw_init(plat, CONFIG_BAUDRATE);
+ return 0;
+}
+
+static const struct dm_serial_ops en75xx_serial_ops = {
+ .putc = en75xx_serial_putc,
+ .pending = en75xx_serial_pending,
+ .getc = en75xx_serial_getc,
+ .setbrg = en75xx_serial_setbrg,
+};
+
+static const struct udevice_id en75xx_serial_ids[] = {
+ { .compatible = "econet,en7512-uart", .data = 0 },
+ { .compatible = "econet,en7528-uart", .data = 1 },
+ { .compatible = "airoha,en7523-uart", .data = 1 },
+ { }
+};
+
+U_BOOT_DRIVER(serial_en75xx) = {
+ .name = "serial_en75xx",
+ .id = UCLASS_SERIAL,
+ .of_match = en75xx_serial_ids,
+ .of_to_plat = en75xx_serial_of_to_plat,
+ .plat_auto = sizeof(struct en75xx_serial_plat),
+ .probe = en75xx_serial_probe,
+ .ops = &en75xx_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
--
2.53.0
next prev parent reply other threads:[~2026-08-25 22:50 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260825224330.713151-1-maskachoska.ref@yahoo.com>
2026-08-25 22:41 ` [PATCH v1 00/12] mips: add EcoNet/Airoha EN75xx (EN7512/EN7528) SoC support AK Sharma
2026-08-25 22:41 ` [PATCH v1 01/12] mips: en75xx: add EcoNet/Airoha EN75xx " AK Sharma
2026-08-25 22:41 ` [PATCH v1 02/12] mips: en75xx: add TPL and SPL early boot stages AK Sharma
2026-08-25 22:53 ` Tom Rini
2026-08-25 22:41 ` AK Sharma [this message]
2026-08-25 22:41 ` [PATCH v1 04/12] spi: airoha-snfi: add EN7528 SPI-NAND controller support AK Sharma
2026-08-25 22:42 ` [PATCH v1 05/12] mtd: spi-nand: add EN75 BMT bad-block management support AK Sharma
2026-08-25 22:59 ` Tom Rini
2026-08-26 6:47 ` Frieder Schrempf
2026-08-25 22:42 ` [PATCH v1 06/12] net: airoha-eth: add EN7528 Ethernet support AK Sharma
2026-08-25 22:42 ` [PATCH v1 07/12] mtd: env, cmd: add EN75 NAND remap handling AK Sharma
2026-08-25 23:06 ` Tom Rini
2026-08-25 22:42 ` [PATCH v1 08/12] boot: image: add weak hooks for the decompression buffer and flush AK Sharma
2026-08-25 23:05 ` Tom Rini
2026-08-25 22:42 ` [PATCH v1 09/12] mips: dts: add EcoNet EN75xx device trees AK Sharma
2026-08-25 22:55 ` Tom Rini
2026-08-25 22:42 ` [PATCH v1 10/12] board: econet: add EN7512 reference board AK Sharma
2026-08-25 22:42 ` [PATCH v1 11/12] board: econet: add EN7528 board support AK Sharma
2026-08-25 22:57 ` Tom Rini
2026-08-25 23:00 ` Tom Rini
2026-08-25 22:42 ` [PATCH v1 12/12] doc: board: econet: add EN75xx documentation AK Sharma
2026-08-25 23:02 ` [PATCH v1 00/12] mips: add EcoNet/Airoha EN75xx (EN7512/EN7528) SoC support Tom Rini
2026-08-26 14:26 ` Matheus Sampaio Queiroga
2026-08-26 15:05 ` Tom Rini
2026-08-26 15:16 ` AK Sharma
2026-08-26 15:17 ` Tom Rini
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=20260825224330.713151-4-maskachoska@yahoo.com \
--to=maskachoska@yahoo.com \
--cc=ansuelsmth@gmail.com \
--cc=daniel.schwierzeck@gmail.com \
--cc=dario.binacchi@amarulasolutions.com \
--cc=frieder.schrempf@kontron.de \
--cc=jerome.forissier@arm.com \
--cc=marex@denx.de \
--cc=michael@amarulasolutions.com \
--cc=trini@konsulko.com \
--cc=u-boot@lists.u-boot-project.org \
/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.