From f89f4898a39f02468a286da27f1dc9fb0b9d5c80 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Mon, 15 Apr 2019 13:41:53 +0000 Subject: [PATCH] Add quirk for ignoring SPCR AccessWidth values on the PL011 UART The SPCR table on the Lenovo HR330A Ampere eMAG server indicates 8-bit access, but 32-bit access is required for the PL011 to work. PL011 on SBSA platforms always supports 32-bit access (and that was hardcoded here before my EC2 fix), let's use 32-bit access for PL011 and 32BIT interface types. Tested by emaste on Ampere eMAG and Cavium/Marvell ThunderX2. Submitted by: Greg V Reviewed by: andrew, imp (earlier) Differential Revision: https://reviews.freebsd.org/D19507 --- sys/dev/uart/uart_bus.h | 3 ++- sys/dev/uart/uart_cpu_arm64.c | 5 +++++ sys/dev/uart/uart_dev_pl011.c | 5 +++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h index 2bc33734cfb5..d3b22256b915 100644 --- a/sys/dev/uart/uart_bus.h +++ b/sys/dev/uart/uart_bus.h @@ -57,7 +57,8 @@ #define UART_IOCTL_BAUD 4 /* UART quirk flags */ -#define UART_F_BUSY_DETECT 0x1 +#define UART_F_BUSY_DETECT 0x1 +#define UART_F_IGNORE_SPCR_REGSHFT 0x2 /* * UART class & instance (=softc) diff --git a/sys/dev/uart/uart_cpu_arm64.c b/sys/dev/uart/uart_cpu_arm64.c index ed4323ac7449..fd6cdea787a2 100644 --- a/sys/dev/uart/uart_cpu_arm64.c +++ b/sys/dev/uart/uart_cpu_arm64.c @@ -153,6 +153,11 @@ uart_cpu_acpi_probe(struct uart_class **classp, bus_space_tag_t *bst, *shiftp = spcr->SerialPort.AccessWidth - 1; *iowidthp = spcr->SerialPort.BitWidth / 8; + if ((cd->cd_quirks & UART_F_IGNORE_SPCR_REGSHFT) == + UART_F_IGNORE_SPCR_REGSHFT) { + *shiftp = cd->cd_regshft; + } + out: acpi_unmap_table(spcr); return (err); diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c index 08905d13c1e6..3b4f6ba57381 100644 --- a/sys/dev/uart/uart_dev_pl011.c +++ b/sys/dev/uart/uart_dev_pl011.c @@ -342,8 +342,9 @@ UART_FDT_CLASS_AND_DEVICE(fdt_compat_data); #ifdef DEV_ACPI static struct acpi_uart_compat_data acpi_compat_data[] = { - {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_PL011, 2, 0, 0, 0, "uart plo11"}, - {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_SBSA_GENERIC, 2, 0, 0, 0, "uart plo11"}, + {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_PL011, 2, 0, 0, UART_F_IGNORE_SPCR_REGSHFT, "uart pl011"}, + {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_SBSA_GENERIC, 2, 0, 0, UART_F_IGNORE_SPCR_REGSHFT, "uart pl011"}, + {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_SBSA_32BIT, 2, 0, 0, UART_F_IGNORE_SPCR_REGSHFT, "uart pl011"}, {NULL, NULL, 0, 0, 0, 0, 0, NULL}, }; UART_ACPI_CLASS_AND_DEVICE(acpi_compat_data);