From 64c79dfbc45863821e172a606f453b39c8a8be6b Mon Sep 17 00:00:00 2001 From: Guanbing Huang Date: Tue, 16 Apr 2024 11:16:59 +0800 Subject: 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: Guanbing Huang Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Reviewed-by: Bing Fan Tested-by: Linheng Du Link: https://lore.kernel.org/r/4726ecea8f7bfbfe42501b4f6ad9fe5b38994574.1713234515.git.albanhuang@tencent.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pnp.c | 40 ++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 1974bbadc975..8f72a7de1d1d 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -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)) -- cgit v1.2.3