diff options
Diffstat (limited to 'drivers/tty/serial/8250/8250_platform.c')
-rw-r--r-- | drivers/tty/serial/8250/8250_platform.c | 122 |
1 files changed, 104 insertions, 18 deletions
diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c index d5c8d851348d..be7ff07cbdd0 100644 --- a/drivers/tty/serial/8250/8250_platform.c +++ b/drivers/tty/serial/8250/8250_platform.c @@ -2,11 +2,15 @@ /* * Universal/legacy platform driver for 8250/16550-type serial ports * - * Supports: ISA-compatible 8250/16550 ports + * Supports: + * ISA-compatible 8250/16550 ports + * ACPI 8250/16550 ports * PNP 8250/16550 ports * "serial8250" platform devices */ +#include <linux/acpi.h> #include <linux/array_size.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/once.h> @@ -22,9 +26,9 @@ /* * Configuration: - * share_irqs Whether we pass IRQF_SHARED to request_irq(). + * share_irqs: Whether we pass IRQF_SHARED to request_irq(). * This option is unsafe when used on edge-triggered interrupts. - * skip_txen_test Force skip of txen test at init time. + * skip_txen_test: Force skip of txen test at init time. */ unsigned int share_irqs = SERIAL8250_SHARE_IRQS; unsigned int skip_txen_test; @@ -61,9 +65,9 @@ static void __init __serial8250_isa_init_ports(void) nr_uarts = UART_NR; /* - * Set up initial isa ports based on nr_uart module param, or else + * Set up initial ISA ports based on nr_uart module param, or else * default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not - * need to increase nr_uarts when setting up the initial isa ports. + * need to increase nr_uarts when setting up the initial ISA ports. */ for (i = 0; i < nr_uarts; i++) serial8250_setup_port(i); @@ -101,13 +105,63 @@ void __init serial8250_isa_init_ports(void) } /* - * Register a set of serial devices attached to a platform device. The - * list is terminated with a zero flags entry, which means we expect - * all entries to have at least UPF_BOOT_AUTOCONF set. + * Generic 16550A platform devices */ -static int serial8250_probe(struct platform_device *dev) +static int serial8250_probe_acpi(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct uart_8250_port uart = { }; + struct resource *regs; + unsigned char iotype; + int ret, line; + + regs = platform_get_mem_or_io(pdev, 0); + if (!regs) + return dev_err_probe(dev, -EINVAL, "no registers defined\n"); + + switch (resource_type(regs)) { + case IORESOURCE_IO: + uart.port.iobase = regs->start; + iotype = UPIO_PORT; + break; + case IORESOURCE_MEM: + uart.port.mapbase = regs->start; + uart.port.mapsize = resource_size(regs); + uart.port.flags = UPF_IOREMAP; + iotype = UPIO_MEM; + break; + default: + return -EINVAL; + } + + /* default clock frequency */ + uart.port.uartclk = 1843200; + uart.port.type = PORT_16550A; + uart.port.dev = &pdev->dev; + uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + + ret = uart_read_and_validate_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; + + line = serial8250_register_8250_port(&uart); + if (line < 0) + return line; + + return 0; +} + +static int serial8250_probe_platform(struct platform_device *dev, struct plat_serial8250_port *p) { - struct plat_serial8250_port *p = dev_get_platdata(&dev->dev); struct uart_8250_port uart; int ret, i, irqflag = 0; @@ -156,6 +210,31 @@ static int serial8250_probe(struct platform_device *dev) } /* + * Register a set of serial devices attached to a platform device. + * The list is terminated with a zero flags entry, which means we expect + * all entries to have at least UPF_BOOT_AUTOCONF set. + */ +static int serial8250_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct plat_serial8250_port *p; + + p = dev_get_platdata(dev); + if (p) + return serial8250_probe_platform(pdev, p); + + /* + * Probe platform UART devices defined using standard hardware + * discovery mechanism like ACPI or DT. Support only ACPI based + * serial device for now. + */ + if (has_acpi_companion(dev)) + return serial8250_probe_acpi(pdev); + + return 0; +} + +/* * Remove serial ports registered against a platform device. */ static void serial8250_remove(struct platform_device *dev) @@ -198,6 +277,12 @@ static int serial8250_resume(struct platform_device *dev) return 0; } +static const struct acpi_device_id acpi_platform_serial_table[] = { + { "RSCV0003" }, /* RISC-V Generic 16550A UART */ + { } +}; +MODULE_DEVICE_TABLE(acpi, acpi_platform_serial_table); + static struct platform_driver serial8250_isa_driver = { .probe = serial8250_probe, .remove_new = serial8250_remove, @@ -205,12 +290,13 @@ static struct platform_driver serial8250_isa_driver = { .resume = serial8250_resume, .driver = { .name = "serial8250", + .acpi_match_table = acpi_platform_serial_table, }, }; /* * This "device" covers _all_ ISA 8250-compatible serial devices listed - * in the table in include/asm/serial.h + * in the table in include/asm/serial.h. */ struct platform_device *serial8250_isa_devs; @@ -239,8 +325,7 @@ static int __init serial8250_init(void) if (ret) goto unreg_uart_drv; - serial8250_isa_devs = platform_device_alloc("serial8250", - PLAT8250_DEV_LEGACY); + serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY); if (!serial8250_isa_devs) { ret = -ENOMEM; goto unreg_pnp; @@ -279,7 +364,7 @@ static void __exit serial8250_exit(void) /* * This tells serial8250_unregister_port() not to re-register * the ports (thereby making serial8250_isa_driver permanently - * in use.) + * in use). */ serial8250_isa_devs = NULL; @@ -312,12 +397,13 @@ MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); #ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS #ifndef MODULE -/* This module was renamed to 8250_core in 3.7. Keep the old "8250" name - * working as well for the module options so we don't break people. We +/* + * This module was renamed to 8250_core in 3.7. Keep the old "8250" name + * working as well for the module options so we don't break people. We * need to keep the names identical and the convenient macros will happily * refuse to let us do that by failing the build with redefinition errors - * of global variables. So we stick them inside a dummy function to avoid - * those conflicts. The options still get parsed, and the redefined + * of global variables. So we stick them inside a dummy function to avoid + * those conflicts. The options still get parsed, and the redefined * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive. * * This is hacky. I'm sorry. |