Skip to contentSkip to conversation

tty: pl011: Work around stuck BUSY bit on QDF2400

RFC In review Christopher Covington 3 participants 3 messages Jan 30, 2017 – Jan 31, 2017

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

RFC 1/1 tty: pl011: Work around stuck BUSY bit on QDF2400

N.B. I'm not confident that this patch is ready to be included as-is. Rather I'm hoping for guidance from reviewers and maintainers on broad implementation choices--whether A) the bitmask of flags to invert makes sense or B) vendor-specific is_busy() function pointers or C) hot-patching using the alternatives framework or D) some other approach would be best.

The Qualcomm Datacenter Technologies QDF2400 family of SoCs contains a custom (non-PrimeCell) implementation of the SBSA UART. Occasionally the BUSY bit in the Flag Register gets stuck as 1, erratum 44 for both 2432v1 and 2400v1 SoCs. Checking that the Transmit FIFO Empty (TXFE) bit is 0, instead of checking that the BUSY bit is 1, works around the issue. To facilitate this substitution, introduce vendor-specific inversion of Feature Register bits.

---
Based on https://git.kernel.org/cgit/linux/kernel/git/arm64/linux.git/log/?h=for-next/core

---
 Documentation/arm64/silicon-errata.txt |  2 ++
 arch/arm64/Kconfig                     | 11 +++++++++
 arch/arm64/include/asm/cpucaps.h       |  3 ++-
 arch/arm64/include/asm/cputype.h       |  2 ++
 arch/arm64/kernel/cpu_errata.c         | 16 +++++++++++++
 drivers/tty/serial/amba-pl011.c        | 44 ++++++++++++++++++++++++++++++----
 6 files changed, 73 insertions(+), 5 deletions(-)
Documentation/arm64/silicon-errata.txt +2 -0
index 50da8391e9dd..0993ebb3e86b 100644
@@ -65,3 +65,5 @@ stable kernels.
 | Freescale/NXP  | LS2080A/LS1043A | A-008585        | FSL_ERRATUM_A008585     |
 | Qualcomm Tech. | Falkor v1       | E1003           | QCOM_FALKOR_ERRATUM_1003|
 | Qualcomm Tech. | Falkor v1       | E1009           | QCOM_FALKOR_ERRATUM_1009|
+| Qualcomm Tech. | QDF2432v1 UART  | SoC E44         | QCOM_QDF2400_ERRATUM_44 |
+| Qualcomm Tech. | QDF2400v1 UART  | SoC E44         | QCOM_QDF2400_ERRATUM_44 |
arch/arm64/Kconfig +11 -0
index b5284a79bada..f90d0670171d 100644
@@ -501,6 +501,17 @@ config QCOM_FALKOR_ERRATUM_1009
 
 	  If unsure, say Y.
 
+config QCOM_QDF2400_ERRATUM_44
+	bool "QDF2400 E44: UART BUSY bit sticks as 1"
+	default y
+	help
+	  The BUSY bit in the Flag Register of the UART on the QDF2432v1 and
+	  QDF2400v1 SoCs may get stuck as 1, resulting in a hung serial console.
+	  Say Y here to work around the issue by checking TXFE == 0 instead of
+	  BUSY == 1 on affected systems.
+
+	  If unsure, say Y.
+
 endmenu
 
 
arch/arm64/include/asm/cpucaps.h +2 -1
index 55bcd02e4a3f..b0f2402f41a2 100644
@@ -37,7 +37,8 @@
 #define ARM64_HAS_NO_FPSIMD			16
 #define ARM64_WORKAROUND_QCOM_FALKOR_E1003	17
 #define ARM64_WORKAROUND_REPEAT_TLBI		18
+#define ARM64_WORKAROUND_QCOM_QDF2400_E44	19
 
-#define ARM64_NCAPS				19
+#define ARM64_NCAPS				20
 
 #endif /* __ASM_CPUCAPS_H */
arch/arm64/include/asm/cputype.h +2 -0
index fc502713ab37..cb399c7fe6ec 100644
@@ -88,12 +88,14 @@
 
 #define BRCM_CPU_PART_VULCAN		0x516
 
+#define QCOM_CPU_PART_KRYO_V1		0x281
 #define QCOM_CPU_PART_FALKOR_V1		0x800
 
 #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
 #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
 #define MIDR_THUNDERX	MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
 #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
+#define MIDR_QCOM_KRYO_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_V1)
 #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
 
 #ifndef __ASSEMBLY__
arch/arm64/kernel/cpu_errata.c +16 -0
index f6cc67e7626e..1a8c2f2b9edf 100644
@@ -151,6 +151,22 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 			   MIDR_CPU_VAR_REV(0, 0)),
 	},
 #endif
+#ifdef CONFIG_QCOM_QDF2400_ERRATUM_44
+	{
+		.desc = "Qualcomm Technologies QDF2432 SoC erratum 44",
+		.capability = ARM64_WORKAROUND_QCOM_QDF2400_E44,
+		MIDR_RANGE(MIDR_QCOM_KRYO_V1,
+			   MIDR_CPU_VAR_REV(0, 1),
+			   MIDR_CPU_VAR_REV(0, 1)),
+	},
+	{
+		.desc = "Qualcomm Technologies QDF2400 SoC erratum 44",
+		.capability = ARM64_WORKAROUND_QCOM_QDF2400_E44,
+		MIDR_RANGE(MIDR_QCOM_FALKOR_V1,
+			   MIDR_CPU_VAR_REV(0, 0),
+			   MIDR_CPU_VAR_REV(0, 0)),
+	},
+#endif
 	{
 	}
 };
drivers/tty/serial/amba-pl011.c +40 -4

91 lines not on this page · raw message

Signature · 3 lines
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora
Forum, a Linux Foundation Collaborative Project.
#1 lore raw
Quoted 16 lines · Christopher Covington

N.B. I'm not confident that this patch is ready to be included as-is. Rather I'm hoping for guidance from reviewers and maintainers on broad implementation choices--whether A) the bitmask of flags to invert makes sense or B) vendor-specific is_busy() function pointers or C) hot-patching using the alternatives framework or D) some other approach would be best.

The Qualcomm Datacenter Technologies QDF2400 family of SoCs contains a custom (non-PrimeCell) implementation of the SBSA UART. Occasionally the BUSY bit in the Flag Register gets stuck as 1, erratum 44 for both 2432v1 and 2400v1 SoCs. Checking that the Transmit FIFO Empty (TXFE) bit is 0, instead of checking that the BUSY bit is 1, works around the issue. To facilitate this substitution, introduce vendor-specific inversion of Feature Register bits.

Quoted 8 lines

---
Based on https://git.kernel.org/cgit/linux/kernel/git/arm64/linux.git/log/?h=for-next/core

---
 Documentation/arm64/silicon-errata.txt |  2 ++
 arch/arm64/Kconfig                     | 11 +++++++++
 arch/arm64/include/asm/cpucaps.h       |  3 ++-
 arch/arm64/include/asm/cputype.h       |  2 ++
 arch/arm64/kernel/cpu_errata.c         | 16 +++++++++++++

This isn't a bug in the CPU, so please don't reuse the CPU errata code to workaround it. You can handle it all privately in the pl011 driver, but do keep the update to silicon-errata.txt.

Will

maintainer Acked-by Russell King on v1 1/1
#2 lore raw
In reply to Christopher Covington

drivers/tty/serial/amba-pl011.c static unsigned int pl011_tx_empty(struct uart_port *port) · line 1551

Quoted 8 lines · Christopher Covington

{

drivers/tty/serial/amba-pl011.c +1 -1
 	struct uart_amba_port *uap =
 	    container_of(port, struct uart_amba_port, port);
-	unsigned int status = pl011_read(uap, REG_FR);
+	unsigned int status = pl011_read(uap, REG_FR) ^ uap->vendor->inv_fr;
 	return status & (uap->vendor->fr_busy | UART01x_FR_TXFF) ?
 							0 : TIOCSER_TEMT;
 }

I'd much prefer the reg & mask == val approach, but the above makes that difficult.

So for the PL011 changes:

Thanks.

Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.