All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Kettenis <kettenis@openbsd.org>
To: u-boot@lists.denx.de
Cc: sjg@chromium.org, bmeng.cn@gmail.com,
	Mark Kettenis <kettenis@openbsd.org>
Subject: [PATCH v3 4/7] serial: s5p: Add Apple M1 support
Date: Mon, 11 Oct 2021 18:40:31 +0200	[thread overview]
Message-ID: <20211011164034.6421-5-kettenis@openbsd.org> (raw)
In-Reply-To: <20211011164034.6421-1-kettenis@openbsd.org>

Apple M1 SoCs include an S5L UART which is a variant of the S5P
UART.  Add support for this variant and enable it by default
on Apple SoCs.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
---
 arch/arm/Kconfig                    |   1 +
 arch/arm/include/asm/arch-m1/uart.h |  41 +++++++++++
 configs/apple_m1_defconfig          |   4 ++
 drivers/serial/Kconfig              |   4 +-
 drivers/serial/serial_s5p.c         | 104 ++++++++++++++++++++++------
 5 files changed, 130 insertions(+), 24 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-m1/uart.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6b9b50fe05..c3ddd8af52 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -927,6 +927,7 @@ config ARCH_APPLE
 	bool "Apple SoCs"
 	select ARM64
 	select BLK
+	select CLK
 	select CMD_USB
 	select DM
 	select DM_KEYBOARD
diff --git a/arch/arm/include/asm/arch-m1/uart.h b/arch/arm/include/asm/arch-m1/uart.h
new file mode 100644
index 0000000000..d2a17a221e
--- /dev/null
+++ b/arch/arm/include/asm/arch-m1/uart.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2009 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ * Heungjun Kim <riverful.kim@samsung.com>
+ */
+
+#ifndef __ASM_ARCH_UART_H_
+#define __ASM_ARCH_UART_H_
+
+#ifndef __ASSEMBLY__
+/* baudrate rest value */
+union br_rest {
+	unsigned short	slot;		/* udivslot */
+	unsigned char	value;		/* ufracval */
+};
+
+struct s5p_uart {
+	unsigned int	ulcon;
+	unsigned int	ucon;
+	unsigned int	ufcon;
+	unsigned int	umcon;
+	unsigned int	utrstat;
+	unsigned int	uerstat;
+	unsigned int	ufstat;
+	unsigned int	umstat;
+	unsigned int	utxh;
+	unsigned int	urxh;
+	unsigned int	ubrdiv;
+	union br_rest	rest;
+	unsigned char	res3[0x3fd0];
+};
+
+static inline int s5p_uart_divslot(void)
+{
+	return 0;
+}
+
+#endif	/* __ASSEMBLY__ */
+
+#endif
diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig
index 6072e7524c..520d7c7632 100644
--- a/configs/apple_m1_defconfig
+++ b/configs/apple_m1_defconfig
@@ -13,3 +13,7 @@ CONFIG_USE_PREBOOT=y
 CONFIG_PREBOOT="usb start"
 CONFIG_SYS_LOAD_ADDR=0x880000000
 # CONFIG_GENERATE_SMBIOS_TABLE is not set
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_DEBUG_UART_BASE=0x235200000
+CONFIG_DEBUG_UART_CLOCK=240000
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 122a39789c..7ee12901e7 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -290,7 +290,7 @@ config DEBUG_SBI_CONSOLE
 
 config DEBUG_UART_S5P
 	bool "Samsung S5P"
-	depends on ARCH_EXYNOS || ARCH_S5PC1XX
+	depends on ARCH_APPLE || ARCH_EXYNOS || ARCH_S5PC1XX
 	help
 	  Select this to enable a debug UART using the serial_s5p driver. You
 	  will need to provide parameters to make this work. The driver will
@@ -737,7 +737,7 @@ config ROCKCHIP_SERIAL
 
 config S5P_SERIAL
 	bool "Support for Samsung S5P UART"
-	depends on ARCH_EXYNOS || ARCH_S5PC1XX
+	depends on ARCH_APPLE || ARCH_EXYNOS || ARCH_S5PC1XX
 	default y
 	help
 	  Select this to enable Samsung S5P UART support.
diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index 6d09952a5d..53a7b0bd1b 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -14,24 +14,45 @@
 #include <asm/global_data.h>
 #include <linux/compiler.h>
 #include <asm/io.h>
+#if !CONFIG_IS_ENABLED(ARCH_APPLE)
 #include <asm/arch/clk.h>
+#endif
 #include <asm/arch/uart.h>
 #include <serial.h>
 #include <clk.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define RX_FIFO_COUNT_SHIFT	0
-#define RX_FIFO_COUNT_MASK	(0xff << RX_FIFO_COUNT_SHIFT)
-#define RX_FIFO_FULL		(1 << 8)
-#define TX_FIFO_COUNT_SHIFT	16
-#define TX_FIFO_COUNT_MASK	(0xff << TX_FIFO_COUNT_SHIFT)
-#define TX_FIFO_FULL		(1 << 24)
+enum {
+	PORT_S5P = 0,
+	PORT_S5L
+};
+
+#define S5L_RX_FIFO_COUNT_SHIFT	0
+#define S5L_RX_FIFO_COUNT_MASK	(0xf << S5L_RX_FIFO_COUNT_SHIFT)
+#define S5L_RX_FIFO_FULL	(1 << 8)
+#define S5L_TX_FIFO_COUNT_SHIFT	4
+#define S5L_TX_FIFO_COUNT_MASK	(0xf << S5L_TX_FIFO_COUNT_SHIFT)
+#define S5L_TX_FIFO_FULL	(1 << 9)
+
+#define S5P_RX_FIFO_COUNT_SHIFT	0
+#define S5P_RX_FIFO_COUNT_MASK	(0xff << S5P_RX_FIFO_COUNT_SHIFT)
+#define S5P_RX_FIFO_FULL	(1 << 8)
+#define S5P_TX_FIFO_COUNT_SHIFT	16
+#define S5P_TX_FIFO_COUNT_MASK	(0xff << S5P_TX_FIFO_COUNT_SHIFT)
+#define S5P_TX_FIFO_FULL	(1 << 24)
 
 /* Information about a serial port */
 struct s5p_serial_plat {
 	struct s5p_uart *reg;  /* address of registers in physical memory */
+	u8 reg_width;	/* register width */
 	u8 port_id;     /* uart port number */
+	u8 rx_fifo_count_shift;
+	u8 tx_fifo_count_shift;
+	u32 rx_fifo_count_mask;
+	u32 tx_fifo_count_mask;
+	u32 rx_fifo_full;
+	u32 tx_fifo_full;
 };
 
 /*
@@ -71,8 +92,8 @@ static void __maybe_unused s5p_serial_init(struct s5p_uart *uart)
 	writel(0x245, &uart->ucon);
 }
 
-static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, uint uclk,
-					   int baudrate)
+static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, u8 reg_width,
+					   uint uclk, int baudrate)
 {
 	u32 val;
 
@@ -82,6 +103,8 @@ static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, uint uclk,
 
 	if (s5p_uart_divslot())
 		writew(udivslot[val % 16], &uart->rest.slot);
+	else if (reg_width == 4)
+		writel(val % 16, &uart->rest.value);
 	else
 		writeb(val % 16, &uart->rest.value);
 }
@@ -93,7 +116,7 @@ int s5p_serial_setbrg(struct udevice *dev, int baudrate)
 	struct s5p_uart *const uart = plat->reg;
 	u32 uclk;
 
-#ifdef CONFIG_CLK_EXYNOS
+#if CONFIG_IS_ENABLED(CLK_EXYNOS) || CONFIG_IS_ENABLED(ARCH_APPLE)
 	struct clk clk;
 	u32 ret;
 
@@ -105,7 +128,7 @@ int s5p_serial_setbrg(struct udevice *dev, int baudrate)
 	uclk = get_uart_clk(plat->port_id);
 #endif
 
-	s5p_serial_baud(uart, uclk, baudrate);
+	s5p_serial_baud(uart, plat->reg_width, uclk, baudrate);
 
 	return 0;
 }
@@ -144,11 +167,14 @@ static int s5p_serial_getc(struct udevice *dev)
 	struct s5p_serial_plat *plat = dev_get_plat(dev);
 	struct s5p_uart *const uart = plat->reg;
 
-	if (!(readl(&uart->ufstat) & RX_FIFO_COUNT_MASK))
+	if (!(readl(&uart->ufstat) & plat->rx_fifo_count_mask))
 		return -EAGAIN;
 
 	serial_err_check(uart, 0);
-	return (int)(readb(&uart->urxh) & 0xff);
+	if (plat->reg_width == 4)
+		return (int)(readl(&uart->urxh) & 0xff);
+	else
+		return (int)(readb(&uart->urxh) & 0xff);
 }
 
 static int s5p_serial_putc(struct udevice *dev, const char ch)
@@ -156,10 +182,13 @@ static int s5p_serial_putc(struct udevice *dev, const char ch)
 	struct s5p_serial_plat *plat = dev_get_plat(dev);
 	struct s5p_uart *const uart = plat->reg;
 
-	if (readl(&uart->ufstat) & TX_FIFO_FULL)
+	if (readl(&uart->ufstat) & plat->tx_fifo_full)
 		return -EAGAIN;
 
-	writeb(ch, &uart->utxh);
+	if (plat->reg_width == 4)
+		writel(ch, &uart->utxh);
+	else
+		writeb(ch, &uart->utxh);
 	serial_err_check(uart, 1);
 
 	return 0;
@@ -171,15 +200,19 @@ static int s5p_serial_pending(struct udevice *dev, bool input)
 	struct s5p_uart *const uart = plat->reg;
 	uint32_t ufstat = readl(&uart->ufstat);
 
-	if (input)
-		return (ufstat & RX_FIFO_COUNT_MASK) >> RX_FIFO_COUNT_SHIFT;
-	else
-		return (ufstat & TX_FIFO_COUNT_MASK) >> TX_FIFO_COUNT_SHIFT;
+	if (input) {
+		return (ufstat & plat->rx_fifo_count_mask) >>
+			plat->rx_fifo_count_shift;
+	} else {
+		return (ufstat & plat->tx_fifo_count_mask) >>
+			plat->tx_fifo_count_shift;
+	}
 }
 
 static int s5p_serial_of_to_plat(struct udevice *dev)
 {
 	struct s5p_serial_plat *plat = dev_get_plat(dev);
+	const ulong port_type = dev_get_driver_data(dev);
 	fdt_addr_t addr;
 
 	addr = dev_read_addr(dev);
@@ -187,8 +220,26 @@ static int s5p_serial_of_to_plat(struct udevice *dev)
 		return -EINVAL;
 
 	plat->reg = (struct s5p_uart *)addr;
+	plat->reg_width = dev_read_u32_default(dev, "reg-io-width", 1);
 	plat->port_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 					"id", dev_seq(dev));
+
+	if (port_type == PORT_S5L) {
+		plat->rx_fifo_count_shift = S5L_RX_FIFO_COUNT_SHIFT;
+		plat->rx_fifo_count_mask = S5L_RX_FIFO_COUNT_MASK;
+		plat->rx_fifo_full = S5L_RX_FIFO_FULL;
+		plat->tx_fifo_count_shift = S5L_TX_FIFO_COUNT_SHIFT;
+		plat->tx_fifo_count_mask = S5L_TX_FIFO_COUNT_MASK;
+		plat->tx_fifo_full = S5L_TX_FIFO_FULL;
+	} else {
+		plat->rx_fifo_count_shift = S5P_RX_FIFO_COUNT_SHIFT;
+		plat->rx_fifo_count_mask = S5P_RX_FIFO_COUNT_MASK;
+		plat->rx_fifo_full = S5P_RX_FIFO_FULL;
+		plat->tx_fifo_count_shift = S5P_TX_FIFO_COUNT_SHIFT;
+		plat->tx_fifo_count_mask = S5P_TX_FIFO_COUNT_MASK;
+		plat->tx_fifo_full = S5P_TX_FIFO_FULL;
+	}
+
 	return 0;
 }
 
@@ -200,7 +251,8 @@ static const struct dm_serial_ops s5p_serial_ops = {
 };
 
 static const struct udevice_id s5p_serial_ids[] = {
-	{ .compatible = "samsung,exynos4210-uart" },
+	{ .compatible = "samsung,exynos4210-uart",	.data = PORT_S5P },
+	{ .compatible = "apple,s5l-uart",		.data = PORT_S5L },
 	{ }
 };
 
@@ -224,16 +276,24 @@ static inline void _debug_uart_init(void)
 	struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE;
 
 	s5p_serial_init(uart);
-	s5p_serial_baud(uart, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+#if CONFIG_IS_ENABLED(ARCH_APPLE)
+	s5p_serial_baud(uart, 4, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+#else
+	s5p_serial_baud(uart, 1, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+#endif
 }
 
 static inline void _debug_uart_putc(int ch)
 {
 	struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE;
 
-	while (readl(&uart->ufstat) & TX_FIFO_FULL);
-
+#if CONFIG_IS_ENABLED(ARCH_APPLE)
+	while (readl(&uart->ufstat) & S5L_TX_FIFO_FULL);
+	writel(ch, &uart->utxh);
+#else
+	while (readl(&uart->ufstat) & S5P_TX_FIFO_FULL);
 	writeb(ch, &uart->utxh);
+#endif
 }
 
 DEBUG_UART_FUNCS
-- 
2.33.0


  parent reply	other threads:[~2021-10-11 16:41 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-11 16:40 [PATCH v3 0/7] Apple M1 Support Mark Kettenis
2021-10-11 16:40 ` [PATCH v3 1/7] iommu: Add IOMMU uclass Mark Kettenis
2021-10-11 16:40 ` [PATCH v3 2/7] test: Add tests for " Mark Kettenis
2021-10-11 16:40 ` [PATCH v3 3/7] arm: apple: Add initial support for Apple's M1 SoC Mark Kettenis
2021-10-11 16:40 ` Mark Kettenis [this message]
2021-10-11 16:40 ` [PATCH v3 5/7] iommu: Add Apple DART driver Mark Kettenis
2021-10-11 16:40 ` [PATCH v3 6/7] arm: dts: apple: Add preliminary device trees Mark Kettenis
2021-10-11 16:40 ` [PATCH v3 7/7] doc: board: apple: Add Apple M1 documentation Mark Kettenis
2021-10-11 17:01   ` Simon Glass
2021-10-14 20:09     ` Mark Kettenis
2021-10-14 20:43       ` Simon Glass
2021-10-14 22:34         ` François Ozog
2021-10-11 19:10   ` Simon Glass
2021-10-14 20:15     ` Mark Kettenis
2021-10-14 20:43       ` Simon Glass
2021-10-11 19:10 ` [PATCH v3 0/7] Apple M1 Support Simon Glass

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=20211011164034.6421-5-kettenis@openbsd.org \
    --to=kettenis@openbsd.org \
    --cc=bmeng.cn@gmail.com \
    --cc=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /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.