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 <[email protected]>
@@ -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;