From patchwork Mon Jan 30 23:44:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christopher Covington X-Patchwork-Id: 9546189 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C304D60417 for ; Mon, 30 Jan 2017 23:44:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B9D3A283ED for ; Mon, 30 Jan 2017 23:44:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ADDAD28406; Mon, 30 Jan 2017 23:44:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, T_DKIM_INVALID autolearn=no version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 313C2283ED for ; Mon, 30 Jan 2017 23:44:52 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cYLcw-0008Jk-GE; Mon, 30 Jan 2017 23:44:50 +0000 Received: from smtp.codeaurora.org ([198.145.29.96]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cYLcs-0008J0-CS for linux-arm-kernel@lists.infradead.org; Mon, 30 Jan 2017 23:44:48 +0000 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 774F160A82; Mon, 30 Jan 2017 23:44:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1485819864; bh=tN9vAU6fU84uhrsNlVZ6AIzo33DHscJbAS/L/86NSGU=; h=From:To:Cc:Subject:Date:From; b=NtqPuxbdzu3NTIhPDsCFjbznqAukfQxzXFt5cPCeXAwR1yjT2KWwLqBOp5T90USEk 2L0/HLAQOSfVXlzm51gdB2FxdgiRXLY6e3eRJQQqpjcTbYoXbTbviph5RDgKNRVTXc CtcawpmThuAF6ehHDVPEjdhmAzu9XowxWhJY8lqw= Received: from illium.qualcomm.com (global_nat1_iad_fw.qualcomm.com [129.46.232.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: cov@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id AA4F76041C; Mon, 30 Jan 2017 23:44:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1485819863; bh=tN9vAU6fU84uhrsNlVZ6AIzo33DHscJbAS/L/86NSGU=; h=From:To:Cc:Subject:Date:From; b=RjUY55eb/zea+zAPL+i5zVVR3SW8Z0qiBA9LFteQn76IzemyjsvT5S9Rg0r1nAdhT 0TkAuG3jpQUqB53Jrn8mpfW/Oub5aqZUYs8phz+VSe/YBKD8QySKfHWTvHbMlXmAkm SM9TCb+9a/2YJQAXh4qcscS0wW7DspXrzRhcI3l8= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org AA4F76041C Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=cov@codeaurora.org From: Christopher Covington To: Peter Hurley , timur@codeaurora.org, pelcan@codeaurora.org, nleeder@codeaurora.org, Catalin Marinas , Will Deacon , Jonathan Corbet , Russell King , Greg Kroah-Hartman , Jiri Slaby , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org Subject: [RFC] tty: pl011: Work around stuck BUSY bit on QDF2400 Date: Mon, 30 Jan 2017 18:44:17 -0500 Message-Id: <20170130234417.20855-1-cov@codeaurora.org> X-Mailer: git-send-email 2.9.3 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170130_154446_495180_946D4962 X-CRM114-Status: GOOD ( 18.23 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Christopher Covington MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP 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. Signed-off-by: Christopher Covington Acked-by: Russell King --- 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(-) diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt index 50da8391e9dd..0993ebb3e86b 100644 --- a/Documentation/arm64/silicon-errata.txt +++ b/Documentation/arm64/silicon-errata.txt @@ -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 | diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b5284a79bada..f90d0670171d 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -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 diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index 55bcd02e4a3f..b0f2402f41a2 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -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 */ diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index fc502713ab37..cb399c7fe6ec 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -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__ diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index f6cc67e7626e..1a8c2f2b9edf 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -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 { } }; diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index d4171d71a258..32ed6423a6ba 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -97,6 +97,7 @@ struct vendor_data { unsigned int fr_dsr; unsigned int fr_cts; unsigned int fr_ri; + unsigned int inv_fr; bool access_32b; bool oversampling; bool dma_threshold; @@ -168,6 +169,32 @@ static u16 pl011_st_offsets[REG_ARRAY_SIZE] = { [REG_ST_ABIMSC] = ST_UART011_ABIMSC, }; +#ifdef CONFIG_QCOM_QDF2400_ERRATUM_44 +#define QDF2400_E44_BUSY UART011_FR_TXFE +#define QDF2400_E44_INV UART011_FR_TXFE +#else +#define QDF2400_E44_BUSY UART01x_FR_BUSY +#define QDF2400_E44_INV 0 +#endif + +static struct vendor_data vendor_qdt = { + .reg_offset = pl011_std_offsets, + .fr_busy = QDF2400_E44_BUSY, + .fr_dsr = UART01x_FR_DSR, + .fr_cts = UART01x_FR_CTS, + .fr_ri = UART011_FR_RI, + .inv_fr = QDF2400_E44_INV, + .access_32b = true, + .oversampling = false, + .dma_threshold = false, + .cts_event_workaround = false, + .always_enabled = true, + .fixed_options = true, +}; + +#undef QDF2400_E44_BUSY +#undef QDF2400_E44_INV + static unsigned int get_fifosize_st(struct amba_device *dev) { return 64; @@ -1518,7 +1545,7 @@ static unsigned int pl011_tx_empty(struct uart_port *port) { 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; } @@ -2218,7 +2245,8 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * Finally, wait for transmitter to become empty * and restore the TCR */ - while (pl011_read(uap, REG_FR) & uap->vendor->fr_busy) + while ((pl011_read(uap, REG_FR) ^ uap->vendor->inv_fr) + & uap->vendor->fr_busy) cpu_relax(); if (!uap->vendor->always_enabled) pl011_write(old_cr, uap, REG_CR); @@ -2385,13 +2413,17 @@ static struct console amba_console = { static void pl011_putc(struct uart_port *port, int c) { + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) cpu_relax(); if (port->iotype == UPIO_MEM32) writel(c, port->membase + UART01x_DR); else writeb(c, port->membase + UART01x_DR); - while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) + while ((readl(port->membase + UART01x_FR) ^ uap->vendor->inv_fr) + & uap->vendor->fr_busy) cpu_relax(); } @@ -2645,12 +2677,16 @@ static int sbsa_uart_probe(struct platform_device *pdev) uap->port.irq = ret; uap->reg_offset = vendor_sbsa.reg_offset; - uap->vendor = &vendor_sbsa; uap->fifosize = 32; uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 : UPIO_MEM; uap->port.ops = &sbsa_uart_pops; uap->fixed_baud = baudrate; + if (cpus_have_const_cap(ARM64_WORKAROUND_QCOM_QDF2400_E44)) + uap->vendor = &vendor_qdt; + else + uap->vendor = &vendor_sbsa; + snprintf(uap->type, sizeof(uap->type), "SBSA"); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);