summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/8250/8250_platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/8250/8250_platform.c')
-rw-r--r--drivers/tty/serial/8250/8250_platform.c122
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.