Commit 64c79dfb authored by Guanbing Huang's avatar Guanbing Huang Committed by Greg Kroah-Hartman
Browse files

serial: 8250_pnp: Support configurable reg shift property



The 16550a serial port based on the ACPI table requires obtaining the
reg-shift attribute. In the ACPI scenario, If the reg-shift property
is not configured like in DTS, the 16550a serial driver cannot read or
write controller registers properly during initialization.

Signed-off-by: default avatarGuanbing Huang <albanhuang@tencent.com>
Suggested-by: default avatarAndy Shevchenko <andriy.shevchenko@intel.com>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: default avatarBing Fan <tombinfan@tencent.com>
Tested-by: default avatarLinheng Du <dylanlhdu@tencent.com>
Link: https://lore.kernel.org/r/4726ecea8f7bfbfe42501b4f6ad9fe5b38994574.1713234515.git.albanhuang@tencent.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 18ba7f2d
Loading
Loading
Loading
Loading
+25 −15
Original line number Diff line number Diff line
@@ -435,6 +435,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
	struct uart_8250_port uart, *port;
	int ret, line, flags = dev_id->driver_data;
	unsigned char iotype;

	if (flags & UNKNOWN_DEV) {
		ret = serial_pnp_guess_board(dev);
@@ -443,37 +444,46 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
	}

	memset(&uart, 0, sizeof(uart));
	if (pnp_irq_valid(dev, 0))
		uart.port.irq = pnp_irq(dev, 0);
	if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
		uart.port.iobase = pnp_port_start(dev, 2);
		uart.port.iotype = UPIO_PORT;
		iotype = UPIO_PORT;
	} else if (pnp_port_valid(dev, 0)) {
		uart.port.iobase = pnp_port_start(dev, 0);
		uart.port.iotype = UPIO_PORT;
		iotype = UPIO_PORT;
	} else if (pnp_mem_valid(dev, 0)) {
		uart.port.mapbase = pnp_mem_start(dev, 0);
		uart.port.iotype = UPIO_MEM;
		uart.port.mapsize = pnp_mem_len(dev, 0);
		iotype = UPIO_MEM;
		uart.port.flags = UPF_IOREMAP;
	} else
		return -ENODEV;

	dev_dbg(&dev->dev,
		 "Setup PNP port: port %#lx, mem %#llx, irq %u, type %u\n",
		 uart.port.iobase, (unsigned long long)uart.port.mapbase,
		 uart.port.irq, uart.port.iotype);
	uart.port.uartclk = 1843200;
	uart.port.dev = &dev->dev;
	uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;

	ret = uart_read_port_properties(&uart.port);
	/* no interrupt -> fall back to polling */
	if (ret == -ENXIO)
		ret = 0;
	if (ret)
		return ret;

	/*
	 * The previous call may not set iotype correctly when reg-io-width
	 * property is absent and it doesn't support IO port resource.
	 */
	uart.port.iotype = iotype;

	if (flags & CIR_PORT) {
		uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
		uart.port.type = PORT_8250_CIR;
	}

	uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
	if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
		uart.port.flags |= UPF_SHARE_IRQ;
	uart.port.uartclk = 1843200;
	device_property_read_u32(&dev->dev, "clock-frequency", &uart.port.uartclk);
	uart.port.dev = &dev->dev;
	dev_dbg(&dev->dev,
		 "Setup PNP port: port %#lx, mem %#llx, size %#llx, irq %u, type %u\n",
		 uart.port.iobase, (unsigned long long)uart.port.mapbase,
		 (unsigned long long)uart.port.mapsize, uart.port.irq, uart.port.iotype);

	line = serial8250_register_8250_port(&uart);
	if (line < 0 || (flags & CIR_PORT))