Module Name:    src
Committed By:   jmcneill
Date:           Mon Sep 13 23:31:23 UTC 2021

Modified Files:
        src/sys/arch/arm/samsung: exynos_uart.c sscom_reg.h
        src/sys/arch/evbarm/conf: GENERIC64 files.generic64

Log Message:
Add support for Apple M1 debug UART.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/samsung/exynos_uart.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/samsung/sscom_reg.h
cvs rdiff -u -r1.184 -r1.185 src/sys/arch/evbarm/conf/GENERIC64
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/evbarm/conf/files.generic64

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/samsung/exynos_uart.c
diff -u src/sys/arch/arm/samsung/exynos_uart.c:1.5 src/sys/arch/arm/samsung/exynos_uart.c:1.6
--- src/sys/arch/arm/samsung/exynos_uart.c:1.5	Sun Mar 14 08:16:57 2021
+++ src/sys/arch/arm/samsung/exynos_uart.c	Mon Sep 13 23:31:23 2021
@@ -1,7 +1,7 @@
-/* $NetBSD: exynos_uart.c,v 1.5 2021/03/14 08:16:57 skrll Exp $ */
+/* $NetBSD: exynos_uart.c,v 1.6 2021/09/13 23:31:23 jmcneill Exp $ */
 
 /*-
- * Copyright (c) 2013-2018 The NetBSD Foundation, Inc.
+ * Copyright (c) 2013-2021 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -33,7 +33,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: exynos_uart.c,v 1.5 2021/03/14 08:16:57 skrll Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exynos_uart.c,v 1.6 2021/09/13 23:31:23 jmcneill Exp $");
 
 #define cn_trap()			\
 	do {				\
@@ -73,6 +73,18 @@ static int	exynos_uart_param(struct tty 
 
 extern struct cfdriver exuart_cd;
 
+enum exynos_uart_type {
+	EXYNOS_UART_SAMSUNG,
+	EXYNOS_UART_APPLE,
+};
+
+struct exynos_uart_config {
+	enum exynos_uart_type type;
+	uint32_t rxfull;
+	uint32_t txfull;
+	uint32_t rxcount;
+};
+
 struct exynos_uart_softc {
 	device_t sc_dev;
 	bus_space_tag_t	sc_bst;
@@ -87,6 +99,8 @@ struct exynos_uart_softc {
 	int sc_ospeed;
 	tcflag_t sc_cflag;
 
+	const struct exynos_uart_config *sc_conf;
+
 	u_char sc_buf[1024];
 };
 
@@ -135,8 +149,23 @@ const struct cdevsw exuart_cdevsw = {
 
 static int exynos_uart_cmajor = -1;
 
+static const struct exynos_uart_config exynos_uart_samsung = {
+	.type = EXYNOS_UART_SAMSUNG,
+	.rxfull = UFSTAT_RXFULL,
+	.txfull = UFSTAT_TXFULL,
+	.rxcount = UFSTAT_RXCOUNT,
+};
+
+static const struct exynos_uart_config exynos_uart_apple = {
+	.type = EXYNOS_UART_APPLE,
+	.rxfull = UFSTAT_S5L_RXFULL,
+	.txfull = UFSTAT_S5L_TXFULL,
+	.rxcount = UFSTAT_S5L_RXCOUNT,
+};
+
 static const struct device_compatible_entry compat_data[] = {
-	{ .compat = "samsung,exynos4210-uart" },
+	{ .compat = "samsung,exynos4210-uart",	.data = &exynos_uart_samsung },
+	{ .compat = "apple,s5l-uart",		.data = &exynos_uart_apple },
 	DEVICE_COMPAT_EOL
 };
 
@@ -163,6 +192,7 @@ exynos_uart_attach(device_t parent, devi
 	int major, minor;
 	bus_addr_t addr;
 	bus_size_t size;
+	uint32_t ucon;
 
 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
 		aprint_error(": couldn't get registers\n");
@@ -187,6 +217,7 @@ exynos_uart_attach(device_t parent, devi
 
 	sc->sc_dev = self;
 	sc->sc_bst = faa->faa_bst;
+	sc->sc_conf = of_compatible_lookup(phandle, compat_data)->data;
 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
 	sc->sc_console = is_console;
 	if (is_console) {
@@ -245,14 +276,21 @@ exynos_uart_attach(device_t parent, devi
 	    __SHIFTIN(1, UFCON_RXTRIGGER) |
 	    UFCON_TXFIFO_RESET | UFCON_RXFIFO_RESET |
 	    UFCON_FIFO_ENABLE);
-	/* Configure PIO mode with RX timeout interrupts */
-	WR4(sc, SSCOM_UCON,
-	    __SHIFTIN(3, UCON_RXTO) |
-	    UCON_TOINT | UCON_ERRINT |
-	    UCON_TXMODE_INT | UCON_RXMODE_INT);
 
-	/* Disable interrupts */
-	WR4(sc, SSCOM_UINTM, ~0u);
+	/* Configure PIO mode with RX timeout interrupts */
+	ucon = UCON_TOINT | UCON_ERRINT |
+	    UCON_TXMODE_INT | UCON_RXMODE_INT;
+	WR4(sc, SSCOM_UCON, ucon);
+
+	switch (sc->sc_conf->type) {
+	case EXYNOS_UART_SAMSUNG:
+		WR4(sc, SSCOM_UCON, ucon | __SHIFTIN(3, UCON_RXTO));
+		/* Disable interrupts */
+		WR4(sc, SSCOM_UINTM, ~0u);
+		break;
+	case EXYNOS_UART_APPLE:
+		break;
+	}
 
 	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
 }
@@ -267,19 +305,19 @@ exynos_uart_cngetc(dev_t dev)
 	s = splserial();
 
 	ufstat = RD4(sc, SSCOM_UFSTAT);
-	if (__SHIFTOUT(ufstat, UFSTAT_RXCOUNT) == 0) {
+	if (__SHIFTOUT(ufstat, sc->sc_conf->rxcount) == 0) {
 		splx(s);
 		return -1;
 	}
 
-	c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, SSCOM_URXH);
+	c = RD4(sc, SSCOM_URXH);
 #if defined(DDB)
 	extern int db_active;
 	if (!db_active)
 #endif
 	{
 		int cn_trapped __unused = 0;
-		cn_check_magic(dev, c, exynos_uart_cnm_state);
+		cn_check_magic(dev, c & 0xff, exynos_uart_cnm_state);
 	}
 
 	splx(s);
@@ -294,10 +332,10 @@ exynos_uart_cnputc(dev_t dev, int c)
 	int s;
 
 	s = splserial();
-	while ((RD4(sc, SSCOM_UFSTAT) & UFSTAT_TXFULL) != 0)
+	while ((RD4(sc, SSCOM_UFSTAT) & sc->sc_conf->txfull) != 0)
 		;
 
-	bus_space_write_1(sc->sc_bst, sc->sc_bsh, SSCOM_UTXH, c);
+	WR4(sc, SSCOM_UTXH, c & 0xff);
 
 	splx(s);
 }
@@ -310,7 +348,7 @@ exynos_uart_cnpollc(dev_t dev, int on)
 
 static void
 exynos_uart_cnattach(bus_space_tag_t bst, bus_space_handle_t bsh,
-    int ospeed, tcflag_t cflag)
+    int ospeed, tcflag_t cflag, const struct exynos_uart_config *conf)
 {
 	struct exynos_uart_softc *sc = &exynos_uart_cnsc;
 
@@ -322,6 +360,7 @@ exynos_uart_cnattach(bus_space_tag_t bst
 	sc->sc_bsh = bsh;
 	sc->sc_ospeed = ospeed;
 	sc->sc_cflag = cflag;
+	sc->sc_conf = conf;
 }
 
 static int
@@ -330,6 +369,7 @@ exynos_uart_open(dev_t dev, int flag, in
 	struct exynos_uart_softc *sc =
 	    device_lookup_private(&exuart_cd, minor(dev));
 	struct tty *tp = sc->sc_tty;
+	uint32_t ucon;
 
 	if (kauth_authorize_device_tty(l->l_cred,
 	    KAUTH_DEVICE_TTY_OPEN, tp) != 0) {
@@ -356,7 +396,16 @@ exynos_uart_open(dev_t dev, int flag, in
 	tp->t_state |= TS_CARR_ON;
 
 	/* Enable RX and error interrupts */
-	WR4(sc, SSCOM_UINTM, ~0u & ~(UINT_RXD|UINT_ERROR));
+	switch (sc->sc_conf->type) {
+	case EXYNOS_UART_SAMSUNG:
+		WR4(sc, SSCOM_UINTM, ~0u & ~(UINT_RXD|UINT_ERROR));
+		break;
+	case EXYNOS_UART_APPLE:
+		ucon = RD4(sc, SSCOM_UCON);
+		ucon |= UCON_S5L_RXTHRESH | UCON_S5L_RX_TIMEOUT;
+		WR4(sc, SSCOM_UCON, ucon);
+		break;
+	}
 
 	mutex_exit(&sc->sc_lock);
 
@@ -369,6 +418,7 @@ exynos_uart_close(dev_t dev, int flag, i
 	struct exynos_uart_softc *sc =
 	    device_lookup_private(&exuart_cd, minor(dev));
 	struct tty *tp = sc->sc_tty;
+	uint32_t ucon;
 
 	mutex_enter(&sc->sc_lock);
 
@@ -376,7 +426,16 @@ exynos_uart_close(dev_t dev, int flag, i
 	ttyclose(tp);
 
 	/* Disable interrupts */
-	WR4(sc, SSCOM_UINTM, ~0u);
+	switch (sc->sc_conf->type) {
+	case EXYNOS_UART_SAMSUNG:
+		WR4(sc, SSCOM_UINTM, ~0u);
+		break;
+	case EXYNOS_UART_APPLE:
+		ucon = RD4(sc, SSCOM_UCON);
+		ucon &= ~(UCON_S5L_RXTHRESH | UCON_S5L_RX_TIMEOUT);
+		WR4(sc, SSCOM_UCON, ucon);
+		break;
+	}
 
 	mutex_exit(&sc->sc_lock);
 
@@ -460,11 +519,10 @@ exynos_uart_start(struct tty *tp)
 	for (brem = q_to_b(&tp->t_outq, sc->sc_buf, sizeof(sc->sc_buf));
 	     brem > 0;
 	     brem--, p++) {
-		while ((RD4(sc, SSCOM_UFSTAT) & UFSTAT_TXFULL) != 0)
+		while ((RD4(sc, SSCOM_UFSTAT) & sc->sc_conf->txfull) != 0)
 			;
 
-		bus_space_write_1(sc->sc_bst, sc->sc_bsh,
-		    SSCOM_UTXH, *p);
+		WR4(sc, SSCOM_UTXH, *p);
 	}
 
 	tp->t_state &= ~TS_BUSY;
@@ -533,11 +591,15 @@ exynos_uart_intr(void *priv)
 {
 	struct exynos_uart_softc *sc = priv;
 	struct tty *tp = sc->sc_tty;
-	uint32_t uintp, uerstat, ufstat, c;
+	uint32_t ack, uerstat, ufstat, c;
 
 	mutex_enter(&sc->sc_lock);
 
-	uintp = RD4(sc, SSCOM_UINTP);
+	if (sc->sc_conf->type == EXYNOS_UART_APPLE) {
+		ack = RD4(sc, SSCOM_UTRSTAT);
+	} else {
+		ack = RD4(sc, SSCOM_UINTP);
+	}
 
 	for (;;) {
 		int cn_trapped = 0;
@@ -551,18 +613,22 @@ exynos_uart_intr(void *priv)
 		}
 
 		ufstat = RD4(sc, SSCOM_UFSTAT);
-		if (__SHIFTOUT(ufstat, UFSTAT_RXCOUNT) == 0) {
+		if (__SHIFTOUT(ufstat, sc->sc_conf->rxcount) == 0) {
 			break;
 		}
 
-		c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, SSCOM_URXH);
+		c = RD4(sc, SSCOM_URXH);
 		cn_check_magic(tp->t_dev, c & 0xff, exynos_uart_cnm_state);
 		if (cn_trapped)
 			continue;
 		tp->t_linesw->l_rint(c & 0xff, tp);
 	}
 
-	WR4(sc, SSCOM_UINTP, uintp);
+	if (sc->sc_conf->type == EXYNOS_UART_APPLE) {
+		WR4(sc, SSCOM_UTRSTAT, ack);
+	} else {
+		WR4(sc, SSCOM_UINTP, ack);
+	}
 
 	mutex_exit(&sc->sc_lock);
 
@@ -589,11 +655,13 @@ exynos_uart_console_consinit(struct fdt_
 	bus_size_t size;
 	tcflag_t flags;
 	int speed;
+	const struct exynos_uart_config *conf;
 
 	speed = fdtbus_get_stdout_speed();
 	if (speed < 0)
 		speed = 115200; /* default */
 	flags = fdtbus_get_stdout_flags();
+	conf = of_compatible_lookup(phandle, compat_data)->data;
 
 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0)
 		panic("exynos_uart: couldn't get registers");
@@ -602,7 +670,7 @@ exynos_uart_console_consinit(struct fdt_
 
 	exynos_uart_consaddr = addr;
 
-	exynos_uart_cnattach(bst, bsh, speed, flags);
+	exynos_uart_cnattach(bst, bsh, speed, flags, conf);
 }
 
 static const struct fdt_console exynos_uart_console = {

Index: src/sys/arch/arm/samsung/sscom_reg.h
diff -u src/sys/arch/arm/samsung/sscom_reg.h:1.3 src/sys/arch/arm/samsung/sscom_reg.h:1.4
--- src/sys/arch/arm/samsung/sscom_reg.h:1.3	Thu Jul  5 13:11:58 2018
+++ src/sys/arch/arm/samsung/sscom_reg.h	Mon Sep 13 23:31:23 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: sscom_reg.h,v 1.3 2018/07/05 13:11:58 jmcneill Exp $ */
+/* $NetBSD: sscom_reg.h,v 1.4 2021/09/13 23:31:23 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2002, 2003 Fujitsu Component Limited
@@ -66,11 +66,14 @@
 #define  UCON_RXDMA_BRST_8	__SHIFTIN(2, UCON_RXDMA)
 #define  UCON_RXDMA_BRST_16	__SHIFTIN(3, UCON_RXDMA)
 #define  UCON_RXTO		__BITS(15,12)
+#define	 UCON_S5L_TXTHRESH	__BIT(13)	/* Apple specific */
+#define	 UCON_S5L_RXTHRESH	__BIT(12)	/* Apple specific */
 #define  UCON_RXTO_FIFO_EMPTY   __BIT(11)
 #define  UCON_RXTO_DMA_FSM_STOP __BIT(10)
 #define	 UCON_TXINT_TYPE	__BIT(9)	/* Tx interrupt. 0=pulse,1=level */
 #define	 UCON_TXINT_TYPE_LEVEL  UCON_TXINT_TYPE	/* 4412 mandatory */
 #define	 UCON_TXINT_TYPE_PULSE  0
+#define  UCON_S5L_RX_TIMEOUT	__BIT(9)	/* Apple specific */
 #define	 UCON_RXINT_TYPE	__BIT(8)	/* Rx interrupt */
 #define	 UCON_RXINT_TYPE_LEVEL  UCON_RXINT_TYPE	/* 4412 mandatory */
 #define	 UCON_RXINT_TYPE_PULSE  __SHIFTIN(0,UCON_RXINT_TYPE)
@@ -103,6 +106,9 @@
 #define  UTRSTAT_RXFIFOCNT	__BITS(23,16)
 #define  UTRSTAT_TXDMA_FSM	__BITS(15,12)
 #define  UTRSTAT_RXDMA_FSM	__BITS(11,8)
+#define	 UTRSTAT_S5L_RX_TIMEOUT	__BIT(9)	/* Apple specific */
+#define	 UTRSTAT_S5L_TXTHRESH	__BIT(5)	/* Apple specific */
+#define	 UTRSTAT_S5L_RXTHRESH	__BIT(4)	/* Apple specific */
 #define  UTRSTAT_RXTIMEOUT	__BIT(3)
 #define	 UTRSTAT_TXSHIFTER_EMPTY __BIT(2)
 #define	 UTRSTAT_TXEMPTY	__BIT(1) /* TX fifo or buffer empty */
@@ -117,8 +123,11 @@
 #define	 UFSTAT_TXFULL		__BIT(24) /* Tx fifo full */
 #define	 UFSTAT_TXCOUNT	  	__BITS(23,16)	/* TX FIFO count */
 #define  UFSTAT_RXERROR		__BIT(9)
+#define	 UFSTAT_S5L_TXFULL	__BIT(9) /* Tx fifo full (Apple) */
 #define	 UFSTAT_RXFULL		__BIT(8) /* Rx fifo full */
+#define	 UFSTAT_S5L_RXFULL	__BIT(8) /* Rx fifo full (Apple) */
 #define	 UFSTAT_RXCOUNT		__BITS(7,0)	/* RX FIFO count */
+#define	 UFSTAT_S5L_RXCOUNT	__BITS(3,0)	/* RX FIFO count (Apple) */
 #define	SSCOM_UMSTAT		0x1c	/* Modem status register */
 #define  UMSTAT_DCTS		__BIT(4)
 #define	 UMSTAT_CTS		__BIT(0) /* Clear to send */

Index: src/sys/arch/evbarm/conf/GENERIC64
diff -u src/sys/arch/evbarm/conf/GENERIC64:1.184 src/sys/arch/evbarm/conf/GENERIC64:1.185
--- src/sys/arch/evbarm/conf/GENERIC64:1.184	Tue Sep  7 10:09:34 2021
+++ src/sys/arch/evbarm/conf/GENERIC64	Mon Sep 13 23:31:23 2021
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: GENERIC64,v 1.184 2021/09/07 10:09:34 msaitoh Exp $
+#	$NetBSD: GENERIC64,v 1.185 2021/09/13 23:31:23 jmcneill Exp $
 #
 #	GENERIC ARM (aarch64) kernel
 #
@@ -307,6 +307,7 @@ ukphy*		at mii? phy ?		# generic unknown
 # UART
 com*		at fdt?	pass 4			# UART
 com*		at acpi?
+exuart*		at fdt? pass 4			# SSCOM UART
 imxuart*	at fdt? pass 4			# IMX UART
 options 	IMXUARTCONSOLE
 mesonuart*	at fdt? pass 4			# Amlogic Meson UART

Index: src/sys/arch/evbarm/conf/files.generic64
diff -u src/sys/arch/evbarm/conf/files.generic64:1.18 src/sys/arch/evbarm/conf/files.generic64:1.19
--- src/sys/arch/evbarm/conf/files.generic64:1.18	Mon Aug 30 23:26:26 2021
+++ src/sys/arch/evbarm/conf/files.generic64	Mon Sep 13 23:31:23 2021
@@ -1,4 +1,4 @@
-#	$NetBSD: files.generic64,v 1.18 2021/08/30 23:26:26 jmcneill Exp $
+#	$NetBSD: files.generic64,v 1.19 2021/09/13 23:31:23 jmcneill Exp $
 #
 # A generic (aarch64) kernel configuration info
 #
@@ -17,6 +17,7 @@ include "arch/arm/broadcom/files.bcm2835
 include "arch/arm/nvidia/files.tegra"
 include "arch/arm/nxp/files.imx"
 include "arch/arm/rockchip/files.rockchip"
+include "arch/arm/samsung/files.exynos"
 include "arch/arm/sunxi/files.sunxi"
 include "arch/arm/virt/files.virt"
 include "arch/arm/sociox/files.sociox"

Reply via email to