Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 438630ef authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tty/serial fixes from Greg KH:
 "Here are two tty serial driver fixes for 4.13-rc5. One is a revert of
  a -rc1 patch that turned out to not be a good idea, and the other is a
  fix for the pl011 serial driver.

  Both have been in linux-next with no reported issues"

* tag 'tty-4.13-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  Revert "serial: Delete dead code for CIR serial ports"
  tty: pl011: fix initialization order of QDF2400 E44
parents dd95f186 9527b82a
Loading
Loading
Loading
Loading
+34 −2
Original line number Diff line number Diff line
@@ -16,6 +16,16 @@
#include <linux/kernel.h>
#include <linux/serial_core.h>

/*
 * Erratum 44 for QDF2432v1 and QDF2400v1 SoCs describes the BUSY bit as
 * occasionally getting stuck as 1. To avoid the potential for a hang, check
 * TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART
 * implementations, so only do so if an affected platform is detected in
 * parse_spcr().
 */
bool qdf2400_e44_present;
EXPORT_SYMBOL(qdf2400_e44_present);

/*
 * Some Qualcomm Datacenter Technologies SoCs have a defective UART BUSY bit.
 * Detect them by examining the OEM fields in the SPCR header, similiar to PCI
@@ -147,8 +157,30 @@ int __init parse_spcr(bool earlycon)
		goto done;
	}

	if (qdf2400_erratum_44_present(&table->header))
	/*
	 * If the E44 erratum is required, then we need to tell the pl011
	 * driver to implement the work-around.
	 *
	 * The global variable is used by the probe function when it
	 * creates the UARTs, whether or not they're used as a console.
	 *
	 * If the user specifies "traditional" earlycon, the qdf2400_e44
	 * console name matches the EARLYCON_DECLARE() statement, and
	 * SPCR is not used.  Parameter "earlycon" is false.
	 *
	 * If the user specifies "SPCR" earlycon, then we need to update
	 * the console name so that it also says "qdf2400_e44".  Parameter
	 * "earlycon" is true.
	 *
	 * For consistency, if we change the console name, then we do it
	 * for everyone, not just earlycon.
	 */
	if (qdf2400_erratum_44_present(&table->header)) {
		qdf2400_e44_present = true;
		if (earlycon)
			uart = "qdf2400_e44";
	}

	if (xgene_8250_erratum_present(table))
		iotype = "mmio32";

+17 −6
Original line number Diff line number Diff line
@@ -1043,13 +1043,24 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
		if (up->dl_write)
			uart->dl_write = up->dl_write;

		if (uart->port.type != PORT_8250_CIR) {
			if (serial8250_isa_config != NULL)
				serial8250_isa_config(0, &uart->port,
						&uart->capabilities);

		ret = uart_add_one_port(&serial8250_reg, &uart->port);
			ret = uart_add_one_port(&serial8250_reg,
						&uart->port);
			if (ret == 0)
				ret = uart->port.line;
		} else {
			dev_info(uart->port.dev,
				"skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n",
				uart->port.iobase,
				(unsigned long long)uart->port.mapbase,
				uart->port.irq);

			ret = 0;
		}
	}
	mutex_unlock(&serial_mutex);

+19 −18
Original line number Diff line number Diff line
@@ -142,15 +142,7 @@ static struct vendor_data vendor_sbsa = {
	.fixed_options		= true,
};

/*
 * Erratum 44 for QDF2432v1 and QDF2400v1 SoCs describes the BUSY bit as
 * occasionally getting stuck as 1. To avoid the potential for a hang, check
 * TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART
 * implementations, so only do so if an affected platform is detected in
 * parse_spcr().
 */
static bool qdf2400_e44_present = false;

#ifdef CONFIG_ACPI_SPCR_TABLE
static struct vendor_data vendor_qdt_qdf2400_e44 = {
	.reg_offset		= pl011_std_offsets,
	.fr_busy		= UART011_FR_TXFE,
@@ -165,6 +157,7 @@ static struct vendor_data vendor_qdt_qdf2400_e44 = {
	.always_enabled		= true,
	.fixed_options		= true,
};
#endif

static u16 pl011_st_offsets[REG_ARRAY_SIZE] = {
	[REG_DR] = UART01x_DR,
@@ -2375,12 +2368,14 @@ static int __init pl011_console_match(struct console *co, char *name, int idx,
	resource_size_t addr;
	int i;

	if (strcmp(name, "qdf2400_e44") == 0) {
		pr_info_once("UART: Working around QDF2400 SoC erratum 44");
		qdf2400_e44_present = true;
	} else if (strcmp(name, "pl011") != 0) {
	/*
	 * Systems affected by the Qualcomm Technologies QDF2400 E44 erratum
	 * have a distinct console name, so make sure we check for that.
	 * The actual implementation of the erratum occurs in the probe
	 * function.
	 */
	if ((strcmp(name, "qdf2400_e44") != 0) && (strcmp(name, "pl011") != 0))
		return -ENODEV;
	}

	if (uart_parse_earlycon(options, &iotype, &addr, &options))
		return -ENODEV;
@@ -2734,11 +2729,17 @@ static int sbsa_uart_probe(struct platform_device *pdev)
	}
	uap->port.irq	= ret;

	uap->reg_offset	= vendor_sbsa.reg_offset;
	uap->vendor	= qdf2400_e44_present ?
					&vendor_qdt_qdf2400_e44 : &vendor_sbsa;
#ifdef CONFIG_ACPI_SPCR_TABLE
	if (qdf2400_e44_present) {
		dev_info(&pdev->dev, "working around QDF2400 SoC erratum 44\n");
		uap->vendor = &vendor_qdt_qdf2400_e44;
	} else
#endif
		uap->vendor = &vendor_sbsa;

	uap->reg_offset	= uap->vendor->reg_offset;
	uap->fifosize	= 32;
	uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 : UPIO_MEM;
	uap->port.iotype = uap->vendor->access_32b ? UPIO_MEM32 : UPIO_MEM;
	uap->port.ops	= &sbsa_uart_pops;
	uap->fixed_baud = baudrate;

+1 −0
Original line number Diff line number Diff line
@@ -1209,6 +1209,7 @@ static inline bool acpi_has_watchdog(void) { return false; }
#endif

#ifdef CONFIG_ACPI_SPCR_TABLE
extern bool qdf2400_e44_present;
int parse_spcr(bool earlycon);
#else
static inline int parse_spcr(bool earlycon) { return 0; }