Module Name:    src
Committed By:   mlelstv
Date:           Tue Jan 24 06:56:40 UTC 2023

Modified Files:
        src/sys/arch/arm/acpi: acpi_platform.c plcom_acpi.c
        src/sys/arch/arm/fdt: plcom_fdt.c
        src/sys/arch/evbarm/dev: plcom.c plcomreg.h plcomvar.h

Log Message:
Add support for FIFOs and hardware flow-control to plcom driver.
Add a PLCOM_TYPE_GENERIC_UART variant to match SBSA requirements.


To generate a diff of this commit:
cvs rdiff -u -r1.34 -r1.35 src/sys/arch/arm/acpi/acpi_platform.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/acpi/plcom_acpi.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/fdt/plcom_fdt.c
cvs rdiff -u -r1.66 -r1.67 src/sys/arch/evbarm/dev/plcom.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/evbarm/dev/plcomreg.h
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/evbarm/dev/plcomvar.h

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/acpi/acpi_platform.c
diff -u src/sys/arch/arm/acpi/acpi_platform.c:1.34 src/sys/arch/arm/acpi/acpi_platform.c:1.35
--- src/sys/arch/arm/acpi/acpi_platform.c:1.34	Wed Nov 16 11:54:26 2022
+++ src/sys/arch/arm/acpi/acpi_platform.c	Tue Jan 24 06:56:40 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_platform.c,v 1.34 2022/11/16 11:54:26 skrll Exp $ */
+/* $NetBSD: acpi_platform.c,v 1.35 2023/01/24 06:56:40 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
 #include "opt_multiprocessor.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_platform.c,v 1.34 2022/11/16 11:54:26 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_platform.c,v 1.35 2023/01/24 06:56:40 mlelstv Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -188,7 +188,10 @@ acpi_platform_attach_uart(ACPI_TABLE_SPC
 	case ACPI_DBG2_ARM_PL011:
 	case ACPI_DBG2_ARM_SBSA_32BIT:
 	case ACPI_DBG2_ARM_SBSA_GENERIC:
-		plcom_console.pi_type = PLCOM_TYPE_PL011;
+		if (spcr->InterfaceType == ACPI_DBG2_ARM_PL011)
+			plcom_console.pi_type = PLCOM_TYPE_PL011;
+		else
+			plcom_console.pi_type = PLCOM_TYPE_GENERIC_UART;
 		plcom_console.pi_iot = &arm_generic_bs_tag;
 		plcom_console.pi_iobase = le64toh(spcr->SerialPort.Address);
 		plcom_console.pi_size = PL011COM_UART_SIZE;

Index: src/sys/arch/arm/acpi/plcom_acpi.c
diff -u src/sys/arch/arm/acpi/plcom_acpi.c:1.3 src/sys/arch/arm/acpi/plcom_acpi.c:1.4
--- src/sys/arch/arm/acpi/plcom_acpi.c:1.3	Sat Apr 25 21:34:26 2020
+++ src/sys/arch/arm/acpi/plcom_acpi.c	Tue Jan 24 06:56:40 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: plcom_acpi.c,v 1.3 2020/04/25 21:34:26 jmcneill Exp $ */
+/* $NetBSD: plcom_acpi.c,v 1.4 2023/01/24 06:56:40 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: plcom_acpi.c,v 1.3 2020/04/25 21:34:26 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: plcom_acpi.c,v 1.4 2023/01/24 06:56:40 mlelstv Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -50,9 +50,17 @@ static void	plcom_acpi_attach(device_t, 
 
 CFATTACH_DECL_NEW(plcom_acpi, sizeof(struct plcom_softc), plcom_acpi_match, plcom_acpi_attach, NULL, NULL);
 
-static const char * const compatible[] = {
-	"ARMH0011",
-	NULL
+enum plcom_acpi_variant {
+	PLCOM_ACPI_GENERIC,
+	PLCOM_ACPI_PL011,
+	PLCOM_ACPI_BCM2837
+};
+
+static const struct device_compatible_entry compat_data[] = {
+	{ .compat = "BCM2837",		.value = PLCOM_ACPI_BCM2837 },
+	{ .compat = "ARMH0011",		.value = PLCOM_ACPI_PL011 },
+	{ .compat = "ARMHB000",		.value = PLCOM_ACPI_GENERIC },
+	DEVICE_COMPAT_EOL
 };
 
 static int
@@ -63,7 +71,7 @@ plcom_acpi_match(device_t parent, cfdata
 	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
 		return 0;
 
-	return acpi_match_hid(aa->aa_node->ad_devinfo, compatible);
+	return acpi_compatible_match(aa, compat_data);
 }
 
 static void
@@ -98,9 +106,19 @@ plcom_acpi_attach(device_t parent, devic
 
 	sc->sc_hwflags = 0;
 	sc->sc_swflags = 0;
-
+	sc->sc_fifolen = 0;
 	sc->sc_pi.pi_type = PLCOM_TYPE_PL011;
 	sc->sc_pi.pi_flags = PLC_FLAG_32BIT_ACCESS;
+
+	switch (acpi_compatible_lookup(aa, compat_data)->value) {
+	case PLCOM_ACPI_BCM2837:
+		sc->sc_fifolen = 16;
+		break;
+	case PLCOM_ACPI_GENERIC:
+		sc->sc_pi.pi_type = PLCOM_TYPE_GENERIC_UART;
+		break;
+	}
+
 	sc->sc_pi.pi_iot = aa->aa_memt;
 	sc->sc_pi.pi_iobase = mem->ar_base;
 	if (bus_space_map(aa->aa_memt, mem->ar_base, mem->ar_length, 0, &sc->sc_pi.pi_ioh) != 0) {

Index: src/sys/arch/arm/fdt/plcom_fdt.c
diff -u src/sys/arch/arm/fdt/plcom_fdt.c:1.5 src/sys/arch/arm/fdt/plcom_fdt.c:1.6
--- src/sys/arch/arm/fdt/plcom_fdt.c:1.5	Wed Jan 27 03:10:19 2021
+++ src/sys/arch/arm/fdt/plcom_fdt.c	Tue Jan 24 06:56:40 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: plcom_fdt.c,v 1.5 2021/01/27 03:10:19 thorpej Exp $ */
+/* $NetBSD: plcom_fdt.c,v 1.6 2023/01/24 06:56:40 mlelstv Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: plcom_fdt.c,v 1.5 2021/01/27 03:10:19 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: plcom_fdt.c,v 1.6 2023/01/24 06:56:40 mlelstv Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -44,7 +44,8 @@ static int	plcom_fdt_match(device_t, cfd
 static void	plcom_fdt_attach(device_t, device_t, void *);
 
 static const struct device_compatible_entry compat_data[] = {
-	{ .compat = "arm,pl011" },
+	{ .compat = "arm,pl011", .value = PLCOM_TYPE_PL011 },
+	{ .compat = "arm,sbsa-uart", .value = PLCOM_TYPE_GENERIC_UART },
 	DEVICE_COMPAT_EOL
 };
 
@@ -70,6 +71,8 @@ plcom_fdt_attach(device_t parent, device
 	bus_addr_t addr;
 	bus_size_t size;
 	void *ih;
+	const u_int *data;
+	int len;
 
 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
 		aprint_error(": missing 'reg' property\n");
@@ -94,10 +97,13 @@ plcom_fdt_attach(device_t parent, device
 			sc->sc_frequency = clk_get_rate(clk);
 	}
 
-	sc->sc_hwflags = PLCOM_HW_TXFIFO_DISABLE;
+	sc->sc_hwflags = 0;
 	sc->sc_swflags = 0;
 
-	sc->sc_pi.pi_type = PLCOM_TYPE_PL011;
+	if ((data = fdtbus_get_prop(phandle, "arm,primecell-periphid", &len)) != NULL)
+                sc->sc_pi.pi_periphid = be32toh(data[0]);
+
+	sc->sc_pi.pi_type = of_compatible_lookup(faa->faa_phandle, compat_data)->value;
 	sc->sc_pi.pi_flags = PLC_FLAG_32BIT_ACCESS;
 	sc->sc_pi.pi_iot = faa->faa_bst;
 	sc->sc_pi.pi_iobase = addr;

Index: src/sys/arch/evbarm/dev/plcom.c
diff -u src/sys/arch/evbarm/dev/plcom.c:1.66 src/sys/arch/evbarm/dev/plcom.c:1.67
--- src/sys/arch/evbarm/dev/plcom.c:1.66	Wed Oct 26 23:38:07 2022
+++ src/sys/arch/evbarm/dev/plcom.c	Tue Jan 24 06:56:40 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: plcom.c,v 1.66 2022/10/26 23:38:07 riastradh Exp $	*/
+/*	$NetBSD: plcom.c,v 1.67 2023/01/24 06:56:40 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 2001 ARM Ltd
@@ -94,7 +94,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: plcom.c,v 1.66 2022/10/26 23:38:07 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: plcom.c,v 1.67 2023/01/24 06:56:40 mlelstv Exp $");
 
 #include "opt_plcom.h"
 #include "opt_kgdb.h"
@@ -149,7 +149,7 @@ void	plcom_config	(struct plcom_softc *)
 void	plcom_shutdown	(struct plcom_softc *);
 int	pl010comspeed	(long, long);
 int	pl011comspeed	(long, long);
-static	u_char	cflag2lcr (tcflag_t);
+static	uint32_t	cflag2lcr (tcflag_t);
 int	plcomparam	(struct tty *, struct termios *);
 void	plcomstart	(struct tty *);
 int	plcomhwiflow	(struct tty *, int);
@@ -267,7 +267,17 @@ pread1(struct plcom_instance *pi, bus_si
 	return bus_space_read_4(pi->pi_iot, pi->pi_ioh, reg & -4) >>
 	    (8 * (reg & 3));
 }
-int nhcr;
+
+static uint16_t
+pread2(struct plcom_instance *pi, bus_size_t reg)
+{
+	if (!ISSET(pi->pi_flags, PLC_FLAG_32BIT_ACCESS))
+		return bus_space_read_2(pi->pi_iot, pi->pi_ioh, reg);
+
+	return bus_space_read_4(pi->pi_iot, pi->pi_ioh, reg & -4) >>
+	    (8 * (reg & 3));
+}
+
 static void
 pwrite1(struct plcom_instance *pi, bus_size_t o, uint8_t val)
 {
@@ -283,6 +293,20 @@ pwrite1(struct plcom_instance *pi, bus_s
 }
 
 static void
+pwrite2(struct plcom_instance *pi, bus_size_t o, uint16_t val)
+{
+	if (!ISSET(pi->pi_flags, PLC_FLAG_32BIT_ACCESS)) {
+		bus_space_write_2(pi->pi_iot, pi->pi_ioh, o, val);
+	} else {
+		const size_t shift = 8 * (o & 3);
+		o &= -4;
+		uint32_t tmp = bus_space_read_4(pi->pi_iot, pi->pi_ioh, o);
+		tmp = (val << shift) | (tmp & ~(0xffff << shift));
+		bus_space_write_4(pi->pi_iot, pi->pi_ioh, o, tmp);
+	}
+}
+
+static void
 pwritem1(struct plcom_instance *pi, bus_size_t o, const uint8_t *datap,
     bus_size_t count)
 {
@@ -297,11 +321,13 @@ pwritem1(struct plcom_instance *pi, bus_
 }
 
 #define	PREAD1(pi, reg)		pread1(pi, reg)
+#define	PREAD2(pi, reg)		pread2(pi, reg)
 #define	PREAD4(pi, reg)		\
 	bus_space_read_4((pi)->pi_iot, (pi)->pi_ioh, (reg))
 
 #define	PWRITE1(pi, reg, val)	pwrite1(pi, reg, val)
 #define	PWRITEM1(pi, reg, d, c)	pwritem1(pi, reg, d, c)
+#define	PWRITE2(pi, reg, val)	pwrite2(pi, reg, val)
 #define	PWRITE4(pi, reg, val)	\
 	bus_space_write_4((pi)->pi_iot, (pi)->pi_ioh, (reg), (val))
 
@@ -381,14 +407,14 @@ plcomprobe1(bus_space_tag_t iot, bus_spa
 	/* Disable the UART.  */
 	bus_space_write_1(iot, ioh, plcom_cr, 0);
 	/* Make sure the FIFO is off.  */
-	bus_space_write_1(iot, ioh, plcom_lcr, PL01X_LCR_8BITS);
+	bus_space_write_4(iot, ioh, plcom_lcr, PL01X_LCR_8BITS);
 	/* Disable interrupts.  */
 	bus_space_write_1(iot, ioh, plcom_iir, 0);
 
 	/* Make sure we swallow anything in the receiving register.  */
 	data = bus_space_read_1(iot, ioh, plcom_dr);
 
-	if (bus_space_read_1(iot, ioh, plcom_lcr) != PL01X_LCR_8BITS)
+	if (bus_space_read_4(iot, ioh, plcom_lcr) != PL01X_LCR_8BITS)
 		return 0;
 
 	data = bus_space_read_1(iot, ioh, plcom_fr) & (PL01X_FR_RXFF | PL01X_FR_RXFE);
@@ -424,10 +450,11 @@ plcom_enable_debugport(struct plcom_soft
 		}
 		break;
 	case PLCOM_TYPE_PL011:
+	case PLCOM_TYPE_GENERIC_UART:
 		sc->sc_imsc = PL011_INT_RX | PL011_INT_RT;
 		SET(sc->sc_cr, PL011_CR_RXE | PL011_CR_TXE);
 		SET(sc->sc_cr, PL011_MCR(sc->sc_mcr));
-		PWRITE4(pi, PL011COM_CR, sc->sc_cr);
+		PWRITE2(pi, PL011COM_CR, sc->sc_cr);
 		PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc);
 		break;
 	}
@@ -446,6 +473,7 @@ plcom_attach_subr(struct plcom_softc *sc
 	switch (pi->pi_type) {
 	case PLCOM_TYPE_PL010:
 	case PLCOM_TYPE_PL011:
+	case PLCOM_TYPE_GENERIC_UART:
 		break;
 	default:
 		aprint_error_dev(sc->sc_dev,
@@ -470,8 +498,24 @@ plcom_attach_subr(struct plcom_softc *sc
 		 * hang when trying to print.
 		 */
 		sc->sc_cr = PL01X_CR_UARTEN;
-		if (pi->pi_type == PLCOM_TYPE_PL011)
+		switch (pi->pi_type) {
+		case PLCOM_TYPE_PL011:
+		case PLCOM_TYPE_GENERIC_UART:
 			SET(sc->sc_cr, PL011_CR_RXE | PL011_CR_TXE);
+			break;
+		}
+	}
+
+	switch (pi->pi_type) {
+	case PLCOM_TYPE_PL011:
+		if (pi->pi_periphid == 0) {
+			pi->pi_periphid = PREAD1(pi, PL011COM_PID0) << 0
+				| PREAD1(pi, PL011COM_PID1) << 8
+				| PREAD1(pi, PL011COM_PID2) << 16
+				| PREAD1(pi, PL011COM_PID3) << 24;
+		}
+		aprint_debug_dev(sc->sc_dev, "PID %08x\n", pi->pi_periphid);
+		break;
 	}
 
 	switch (pi->pi_type) {
@@ -480,7 +524,8 @@ plcom_attach_subr(struct plcom_softc *sc
 		break;
 
 	case PLCOM_TYPE_PL011:
-		PWRITE4(pi, PL011COM_CR, sc->sc_cr);
+	case PLCOM_TYPE_GENERIC_UART:
+		PWRITE2(pi, PL011COM_CR, sc->sc_cr);
 		PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc);
 		break;
 	}
@@ -496,18 +541,36 @@ plcom_attach_subr(struct plcom_softc *sc
 			break;
 		case PLCOM_TYPE_PL011:
 			/* Some revisions have a 32 byte TX FIFO */
-			sc->sc_fifolen = 16;
+			switch (pi->pi_periphid & (PL011_DESIGNER_MASK | PL011_HWREV_MASK)) {
+			case PL011_DESIGNER_ARM | __SHIFTIN(0, PL011_HWREV_MASK):
+			case PL011_DESIGNER_ARM | __SHIFTIN(1, PL011_HWREV_MASK):
+			case PL011_DESIGNER_ARM | __SHIFTIN(2, PL011_HWREV_MASK):
+				sc->sc_fifolen = 16;
+				break;
+			default:
+				sc->sc_fifolen = 32;
+				break;
+			}
+			break;
+		case PLCOM_TYPE_GENERIC_UART:
+			/* At least 32 byte TX FIFO */
+			sc->sc_fifolen = 32;
 			break;
 		}
 	}
 
+	/* Safe amount of bytes to fill when TX FIFO signals empty */
+	sc->sc_burstlen = 1;
+
 	if (ISSET(sc->sc_hwflags, PLCOM_HW_TXFIFO_DISABLE)) {
 		sc->sc_fifolen = 1;
 		aprint_normal_dev(sc->sc_dev, "txfifo disabled\n");
 	}
 
-	if (sc->sc_fifolen > 1)
+	if (sc->sc_fifolen > 1) {
 		SET(sc->sc_hwflags, PLCOM_HW_FIFO);
+		aprint_normal_dev(sc->sc_dev, "txfifo %u bytes\n", sc->sc_fifolen);
+	}
 
 	tp = tty_alloc();
 	tp->t_oproc = plcomstart;
@@ -582,7 +645,8 @@ plcom_config(struct plcom_softc *sc)
 		break;
 
 	case PLCOM_TYPE_PL011:
-		PWRITE4(pi, PL011COM_CR, sc->sc_cr);
+	case PLCOM_TYPE_GENERIC_UART:
+		PWRITE2(pi, PL011COM_CR, sc->sc_cr);
 		PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc);
 		break;
 	}
@@ -704,6 +768,7 @@ plcom_shutdown(struct plcom_softc *sc)
 			SET(sc->sc_cr, PL010_CR_RIE | PL010_CR_RTIE);
 			break;
 		case PLCOM_TYPE_PL011:
+		case PLCOM_TYPE_GENERIC_UART:
 			SET(sc->sc_cr, PL011_CR_RXE);
 			SET(sc->sc_imsc, PL011_INT_RT | PL011_INT_RX);
 			break;
@@ -715,9 +780,10 @@ plcom_shutdown(struct plcom_softc *sc)
 		PWRITE1(pi, PL010COM_CR, sc->sc_cr);
 		break;
 	case PLCOM_TYPE_PL011:
+	case PLCOM_TYPE_GENERIC_UART:
 		SET(sc->sc_cr, PL011_CR_RXE | PL011_CR_TXE);
 		SET(sc->sc_imsc, PL011_INT_RT | PL011_INT_RX);
-		PWRITE4(pi, PL011COM_CR, sc->sc_cr);
+		PWRITE2(pi, PL011COM_CR, sc->sc_cr);
 		PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc);
 		break;
 	}
@@ -815,6 +881,7 @@ plcomopen(dev_t dev, int flag, int mode,
 			sc->sc_msr = PREAD1(pi, PL01XCOM_FR);
 			break;
 		case PLCOM_TYPE_PL011:
+		case PLCOM_TYPE_GENERIC_UART:
 			SET(sc->sc_cr, PL011_CR_RXE | PL011_CR_TXE);
 			SET(sc->sc_imsc, PL011_INT_RT | PL011_INT_RX |
 			    PL011_INT_MSMASK);
@@ -1297,10 +1364,10 @@ plcom_to_tiocm(struct plcom_softc *sc)
 	return ttybits;
 }
 
-static u_char
+static uint32_t
 cflag2lcr(tcflag_t cflag)
 {
-	u_char lcr = 0;
+	uint32_t lcr = 0;
 
 	switch (ISSET(cflag, CSIZE)) {
 	case CS5:
@@ -1333,8 +1400,8 @@ plcomparam(struct tty *tp, struct termio
 	struct plcom_softc *sc =
 		device_lookup_private(&plcom_cd, PLCOMUNIT(tp->t_dev));
 	struct plcom_instance *pi = &sc->sc_pi;
-	int ospeed = -1;
-	u_char lcr;
+	int ospeed = -1, lvl;
+	uint32_t lcr;
 
 	if (PLCOM_ISALIVE(sc) == 0)
 		return EIO;
@@ -1344,6 +1411,7 @@ plcomparam(struct tty *tp, struct termio
 		ospeed = pl010comspeed(t->c_ospeed, sc->sc_frequency);
 		break;
 	case PLCOM_TYPE_PL011:
+	case PLCOM_TYPE_GENERIC_UART:
 		ospeed = pl011comspeed(t->c_ospeed, sc->sc_frequency);
 		break;
 	}
@@ -1387,9 +1455,26 @@ plcomparam(struct tty *tp, struct termio
 	else
 		sc->sc_fifo = 0;
 
-	if (sc->sc_fifo)
+	if (sc->sc_fifo) {
 		SET(sc->sc_lcr, PL01X_LCR_FEN);
 
+		switch (pi->pi_type) {
+		case PLCOM_TYPE_PL010:
+			sc->sc_ifls = 0;
+			break;
+		case PLCOM_TYPE_PL011:
+		case PLCOM_TYPE_GENERIC_UART:
+			lvl = PL011_IFLS_3QUARTERS;
+			sc->sc_ifls = PL011_IFLS_RXIFLS(lvl);
+
+			lvl = PL011_IFLS_1QUARTER;
+			sc->sc_ifls |= PL011_IFLS_TXIFLS(lvl);
+			sc->sc_burstlen = uimin(sc->sc_fifolen * 3 / 4, 1);
+			break;
+		}
+	} else
+		sc->sc_ifls = 0;
+
 	/*
 	 * If we're not in a mode that assumes a connection is present, then
 	 * ignore carrier changes.
@@ -1404,8 +1489,19 @@ plcomparam(struct tty *tp, struct termio
 	 */
 	if (ISSET(t->c_cflag, CRTSCTS)) {
 		sc->sc_mcr_dtr = PL01X_MCR_DTR;
-		sc->sc_mcr_rts = PL01X_MCR_RTS;
-		sc->sc_msr_cts = PL01X_MSR_CTS;
+
+		switch (pi->pi_type) {
+		case PLCOM_TYPE_PL010:
+			sc->sc_mcr_rts = PL01X_MCR_RTS;
+			sc->sc_msr_cts = PL01X_MSR_CTS;
+			break;
+		case PLCOM_TYPE_PL011:
+		case PLCOM_TYPE_GENERIC_UART:
+			sc->sc_mcr_rts = 0;
+			sc->sc_msr_cts = 0;
+			SET(sc->sc_cr, PL011_CR_CTSEN | PL011_CR_RTSEN);
+			break;
+		}
 	} else if (ISSET(t->c_cflag, MDMBUF)) {
 		/*
 		 * For DTR/DCD flow control, make sure we don't toggle DTR for
@@ -1414,6 +1510,12 @@ plcomparam(struct tty *tp, struct termio
 		sc->sc_mcr_dtr = 0;
 		sc->sc_mcr_rts = PL01X_MCR_DTR;
 		sc->sc_msr_cts = PL01X_MSR_DCD;
+
+		switch (pi->pi_type) {
+		case PLCOM_TYPE_PL011:
+			CLR(sc->sc_cr, PL011_CR_CTSEN | PL011_CR_RTSEN);
+			break;
+		}
 	} else {
 		/*
 		 * If no flow control, then always set RTS.  This will make
@@ -1427,6 +1529,12 @@ plcomparam(struct tty *tp, struct termio
 			SET(sc->sc_mcr, PL01X_MCR_RTS);
 		else
 			CLR(sc->sc_mcr, PL01X_MCR_RTS);
+		switch (pi->pi_type) {
+		case PLCOM_TYPE_PL011:
+		case PLCOM_TYPE_GENERIC_UART:
+			CLR(sc->sc_cr, PL011_CR_CTSEN | PL011_CR_RTSEN);
+			break;
+		}
 	}
 	sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd;
 
@@ -1443,6 +1551,7 @@ plcomparam(struct tty *tp, struct termio
 		sc->sc_rateh = (ospeed >> 8) & 0xff;
 		break;
 	case PLCOM_TYPE_PL011:
+	case PLCOM_TYPE_GENERIC_UART:
 		sc->sc_ratel = ospeed & ((1 << 6) - 1);
 		sc->sc_rateh = ospeed >> 6;
 		break;
@@ -1536,6 +1645,7 @@ void
 plcom_loadchannelregs(struct plcom_softc *sc)
 {
 	struct plcom_instance *pi = &sc->sc_pi;
+	uint16_t ifls;
 
 	/* XXXXX necessary? */
 	plcom_iflush(sc);
@@ -1559,16 +1669,23 @@ plcom_loadchannelregs(struct plcom_softc
 		break;
 
 	case PLCOM_TYPE_PL011:
-		PWRITE4(pi, PL011COM_CR, 0);
+	case PLCOM_TYPE_GENERIC_UART:
+		PWRITE2(pi, PL011COM_CR, 0);
 		if (sc->sc_frequency != 0) {
 			PWRITE1(pi, PL011COM_FBRD, sc->sc_ratel);
 			PWRITE4(pi, PL011COM_IBRD, sc->sc_rateh);
 		}
+
+		/* Bits 6..15 are reserved, don't modify, read as zero */
+		ifls = PREAD2(pi, PL011COM_IFLS) & ~PL011_IFLS_MASK;
+		ifls |= sc->sc_ifls & PL011_IFLS_MASK;
+		PWRITE2(pi, PL011COM_IFLS, ifls);
+
 		PWRITE1(pi, PL011COM_LCRH, sc->sc_lcr);
 		sc->sc_mcr_active = sc->sc_mcr;
 		CLR(sc->sc_cr, PL011_MCR(PL01X_MCR_RTS | PL01X_MCR_DTR));
 		SET(sc->sc_cr, PL011_MCR(sc->sc_mcr_active));
-		PWRITE4(pi, PL011COM_CR, sc->sc_cr);
+		PWRITE2(pi, PL011COM_CR, sc->sc_cr);
 		break;
 	}
 }
@@ -1633,9 +1750,10 @@ plcom_hwiflow(struct plcom_softc *sc)
 			     device_unit(sc->sc_dev), sc->sc_mcr_active);
 		break;
 	case PLCOM_TYPE_PL011:
+	case PLCOM_TYPE_GENERIC_UART:
 		CLR(sc->sc_cr, PL011_MCR(PL01X_MCR_RTS | PL01X_MCR_DTR));
 		SET(sc->sc_cr, PL011_MCR(sc->sc_mcr_active));
-		PWRITE4(pi, PL011COM_CR, sc->sc_cr);
+		PWRITE2(pi, PL011COM_CR, sc->sc_cr);
 		break;
 	}
 }
@@ -1687,6 +1805,7 @@ plcomstart(struct tty *tp)
 		}
 		break;
 	case PLCOM_TYPE_PL011:
+	case PLCOM_TYPE_GENERIC_UART:
 		if (!ISSET(sc->sc_imsc, PL011_INT_TX)) {
 			SET(sc->sc_imsc, PL011_INT_TX);
 			PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc);
@@ -1699,8 +1818,8 @@ plcomstart(struct tty *tp)
 		int n;
 
 		n = sc->sc_tbc;
-		if (n > sc->sc_fifolen)
-			n = sc->sc_fifolen;
+		if (n > sc->sc_burstlen)
+			n = sc->sc_burstlen;
 		PWRITEM1(pi, PL01XCOM_DR, sc->sc_tba, n);
 		sc->sc_tbc -= n;
 		sc->sc_tba += n;
@@ -1820,7 +1939,6 @@ plcom_rxsoft(struct plcom_softc *sc, str
 			get = sc->sc_rbuf;
 		cc--;
 	}
-
 	if (cc != scc) {
 		sc->sc_rbget = get;
 		mutex_spin_enter(&sc->sc_lock);
@@ -1837,6 +1955,7 @@ plcom_rxsoft(struct plcom_softc *sc, str
 					PWRITE1(pi, PL010COM_CR, sc->sc_cr);
 					break;
 				case PLCOM_TYPE_PL011:
+				case PLCOM_TYPE_GENERIC_UART:
 					SET(sc->sc_imsc,
 					    PL011_INT_RX | PL011_INT_RT);
 					PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc);
@@ -1937,6 +2056,7 @@ plcom_intstatus(struct plcom_instance *p
 		ret = ISSET(stat, PL010_IIR_IMASK);
 		break;
 	case PLCOM_TYPE_PL011:
+	case PLCOM_TYPE_GENERIC_UART:
 		stat = PREAD4(pi, PL011COM_MIS);
 		ret = ISSET(stat, PL011_INT_ALLMASK);
 		break;
@@ -1989,6 +2109,7 @@ plcomintr(void *arg)
 				/* Clear any error status.  */
 				if (ISSET(rsr, PL01X_RSR_ERROR))
 					PWRITE1(pi, PL01XCOM_ECR, 0);
+
 				if (ISSET(rsr, PL01X_RSR_BE)) {
 					cn_trapped = 0;
 					cn_check_magic(sc->sc_tty->t_dev,
@@ -2060,6 +2181,7 @@ plcomintr(void *arg)
 					PWRITE1(pi, PL010COM_CR, sc->sc_cr);
 					break;
 				case PLCOM_TYPE_PL011:
+				case PLCOM_TYPE_GENERIC_UART:
 					CLR(sc->sc_imsc,
 					    PL011_INT_RT | PL011_INT_RX);
 					PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc);
@@ -2078,11 +2200,12 @@ plcomintr(void *arg)
 				}
 				break;
 			case PLCOM_TYPE_PL011:
+			case PLCOM_TYPE_GENERIC_UART:
 				rxintr = ISSET(istatus, PL011_INT_RX);
 				if (rxintr) {
-					PWRITE4(pi, PL011COM_CR, 0);
+					PWRITE2(pi, PL011COM_CR, 0);
 					delay(10);
-					PWRITE4(pi, PL011COM_CR, sc->sc_cr);
+					PWRITE2(pi, PL011COM_CR, sc->sc_cr);
 					continue;
 				}
 				break;
@@ -2094,6 +2217,7 @@ plcomintr(void *arg)
 			msr = PREAD1(pi, PL01XCOM_FR);
 			break;
 		case PLCOM_TYPE_PL011:
+		case PLCOM_TYPE_GENERIC_UART:
 			msr = PREAD4(pi, PL01XCOM_FR);
 			break;
 		}
@@ -2109,6 +2233,7 @@ plcomintr(void *arg)
 			}
 			break;
 		case PLCOM_TYPE_PL011:
+		case PLCOM_TYPE_GENERIC_UART:
 			msintr = ISSET(istatus, PL011_INT_MSMASK);
 			if (msintr) {
 				PWRITE4(pi, PL011COM_ICR, PL011_INT_MSMASK);
@@ -2218,8 +2343,8 @@ plcomintr(void *arg)
 				int n;
 
 				n = sc->sc_tbc;
-				if (n > sc->sc_fifolen)
-					n = sc->sc_fifolen;
+				if (n > sc->sc_burstlen)
+					n = sc->sc_burstlen;
 				PWRITEM1(pi, PL01XCOM_DR, sc->sc_tba, n);
 				sc->sc_tbc -= n;
 				sc->sc_tba += n;
@@ -2237,6 +2362,7 @@ plcomintr(void *arg)
 					}
 					break;
 				case PLCOM_TYPE_PL011:
+				case PLCOM_TYPE_GENERIC_UART:
 					if (ISSET(sc->sc_imsc, PL011_INT_TX)) {
 						CLR(sc->sc_imsc, PL011_INT_TX);
 						PWRITE4(pi, PL011COM_IMSC,
@@ -2256,7 +2382,8 @@ plcomintr(void *arg)
 	mutex_spin_exit(&sc->sc_lock);
 
 	/* Wake up the poller. */
-	softint_schedule(sc->sc_si);
+	if ((sc->sc_rx_ready | sc->sc_st_check | sc->sc_tx_done) != 0)
+		softint_schedule(sc->sc_si);
 
 #ifdef RND_COM
 	rnd_add_uint32(&sc->rnd_source, istatus | rsr);
@@ -2347,7 +2474,7 @@ plcom_common_putc(dev_t dev, struct plco
 int
 plcominit(struct plcom_instance *pi, int rate, int frequency, tcflag_t cflag)
 {
-	u_char lcr;
+	uint32_t lcr;
 
 	switch (pi->pi_type) {
 	case PLCOM_TYPE_PL010:
@@ -2355,6 +2482,7 @@ plcominit(struct plcom_instance *pi, int
 			pi->pi_size = PL010COM_UART_SIZE;
 		break;
 	case PLCOM_TYPE_PL011:
+	case PLCOM_TYPE_GENERIC_UART:
 		if (pi->pi_size == 0)
 			pi->pi_size = PL011COM_UART_SIZE;
 		break;
@@ -2380,7 +2508,8 @@ plcominit(struct plcom_instance *pi, int
 		PWRITE1(pi, PL010COM_CR, PL01X_CR_UARTEN);
 		break;
 	case PLCOM_TYPE_PL011:
-		PWRITE4(pi, PL011COM_CR, 0);
+	case PLCOM_TYPE_GENERIC_UART:
+		PWRITE2(pi, PL011COM_CR, 0);
 
 		if (rate && frequency) {
 			rate = pl011comspeed(rate, frequency);
@@ -2388,7 +2517,7 @@ plcominit(struct plcom_instance *pi, int
 			PWRITE4(pi, PL011COM_IBRD, rate >> 6);
 		}
 		PWRITE1(pi, PL011COM_LCRH, lcr);
-		PWRITE4(pi, PL011COM_CR,
+		PWRITE2(pi, PL011COM_CR,
 		    PL01X_CR_UARTEN | PL011_CR_RXE | PL011_CR_TXE);
 		break;
 	}
@@ -2478,7 +2607,8 @@ plcomcnhalt(dev_t dev)
 		PWRITE1(pi, PL010COM_CR, PL01X_CR_UARTEN);
 		break;
 	case PLCOM_TYPE_PL011:
-		PWRITE4(pi, PL011COM_CR,
+	case PLCOM_TYPE_GENERIC_UART:
+		PWRITE2(pi, PL011COM_CR,
 		    PL01X_CR_UARTEN | PL011_CR_RXE | PL011_CR_TXE);
 		PWRITE4(pi, PL011COM_IMSC, 0);
 		break;

Index: src/sys/arch/evbarm/dev/plcomreg.h
diff -u src/sys/arch/evbarm/dev/plcomreg.h:1.6 src/sys/arch/evbarm/dev/plcomreg.h:1.7
--- src/sys/arch/evbarm/dev/plcomreg.h:1.6	Fri Dec 27 08:22:50 2019
+++ src/sys/arch/evbarm/dev/plcomreg.h	Tue Jan 24 06:56:40 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: plcomreg.h,v 1.6 2019/12/27 08:22:50 msaitoh Exp $	*/
+/*	$NetBSD: plcomreg.h,v 1.7 2023/01/24 06:56:40 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 2001 ARM Ltd
@@ -107,6 +107,7 @@
 #define	PL011_MSR_RI		PL011_FR_RI
 
 /* ifls */
+#define PL011_IFLS_MASK		0x001f
 #define	PL011_IFLS_1EIGHTH	0
 #define	PL011_IFLS_1QUARTER	1
 #define	PL011_IFLS_1HALF	2
@@ -133,6 +134,10 @@
 #define	PL011_INT_ALLMASK \
     (PL011_INT_RT | PL011_INT_TX | PL011_INT_RX | PL011_INT_MSMASK)
 
+/* PL011 HW revision bits in PID (0..3 combined little endian) */
+#define PL011_HWREV_MASK	0x00f00000
+#define PL011_DESIGNER_MASK	0x000ff000
+#define PL011_DESIGNER_ARM	0x00041000
 
 /* DMA control registers */
 #define	PL011_DMA_ONERR	0x4
@@ -161,6 +166,10 @@
 #define	PL011COM_MIS	0x40	/* Masked interrupt status register */
 #define	PL011COM_ICR	0x44	/* Interrupt clear register register */
 #define	PL011COM_DMACR	0x48	/* DMA control register register */
+#define	PL011COM_PID0	0xfe0	/* Peripheral ID register 0 */
+#define	PL011COM_PID1	0xfe4	/* Peripheral ID register 1 */
+#define	PL011COM_PID2	0xfe8	/* Peripheral ID register 2 */
+#define	PL011COM_PID3	0xfec	/* Peripheral ID register 3 */
 
 #define	PL010COM_UART_SIZE	0x100
 #define	PL011COM_UART_SIZE	0x1000

Index: src/sys/arch/evbarm/dev/plcomvar.h
diff -u src/sys/arch/evbarm/dev/plcomvar.h:1.18 src/sys/arch/evbarm/dev/plcomvar.h:1.19
--- src/sys/arch/evbarm/dev/plcomvar.h:1.18	Sun Oct 17 22:34:17 2021
+++ src/sys/arch/evbarm/dev/plcomvar.h	Tue Jan 24 06:56:40 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: plcomvar.h,v 1.18 2021/10/17 22:34:17 jmcneill Exp $	*/
+/*	$NetBSD: plcomvar.h,v 1.19 2023/01/24 06:56:40 mlelstv Exp $	*/
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
@@ -70,10 +70,12 @@ struct plcom_instance {
 	u_int			pi_type;
 #define	PLCOM_TYPE_PL010 0
 #define	PLCOM_TYPE_PL011 1
+#define	PLCOM_TYPE_GENERIC_UART 2		/* SBSA generic uart */
 
 	uint32_t		pi_flags;	/* flags for this PLCOM */
 #define	PLC_FLAG_USE_DMA		0x0001
 #define	PLC_FLAG_32BIT_ACCESS		0x0002
+	uint32_t		pi_periphid;
 
 	void 			*pi_cookie;
 
@@ -103,6 +105,7 @@ struct plcom_softc {
 	int sc_hwflags,
 	    sc_swflags;
 	u_int sc_fifolen;
+	u_int sc_burstlen;
 
 	struct timeval sc_hup_pending;
 
@@ -131,9 +134,10 @@ struct plcom_softc {
 			sc_rx_ready;
 
 	volatile u_char sc_heldchange;
-	volatile u_int sc_cr, sc_ratel, sc_rateh, sc_imsc;
-	volatile u_int sc_msr, sc_msr_delta, sc_msr_mask;
-	volatile u_char sc_mcr, sc_mcr_active, sc_lcr;
+	volatile uint32_t sc_cr, sc_ratel, sc_rateh, sc_imsc;
+	volatile uint32_t sc_msr, sc_msr_delta, sc_msr_mask;
+	volatile uint32_t sc_lcr, sc_ifls;
+	volatile u_char sc_mcr, sc_mcr_active;
 	u_char sc_mcr_dtr, sc_mcr_rts, sc_msr_cts, sc_msr_dcd;
 	u_int sc_fifo;
 

Reply via email to