Here's a completely untested patch to convert of_serial to be usable via ACPI properties too. The properties themselves were fairly straightforward; the interesting part is converting to platform_get_irq() and platform_get_resource() — in the latter case first trying IORESOURCE_MEM then IORESOURCE_IO if that fails. Does this look sane? We'll probably want to think about renaming the module and the config option too, but that can come after the basic functionality. diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 26cec64..be95a4c 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1094,14 +1094,14 @@ config SERIAL_NETX_CONSOLE you can make it the console by answering Y to this option. config SERIAL_OF_PLATFORM - tristate "Serial port on Open Firmware platform bus" - depends on OF + tristate "Serial port on firmware platform bus" + depends on OF || ACPI depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL help - If you have a PowerPC based system that has serial ports - on a platform specific bus, you should enable this option. - Currently, only 8250 compatible ports are supported, but - others can easily be added. + If you have a system which advertises its serial ports through + devicetree or ACPI, you should enable this option. Currently + only 8250 compatible and NWP ports and are supported, but others + can easily be added. config SERIAL_OMAP tristate "OMAP serial port support" diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 68d4455..73ee9af 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -57,13 +57,14 @@ static int of_platform_serial_setup(struct platform_device *ofdev, int type, struct uart_port *port, struct of_serial_info *info) { - struct resource resource; - struct device_node *np = ofdev->dev.of_node; + struct resource *resource; u32 clk, spd, prop; + unsigned char iotype = UPIO_MEM; + u32 res_start; int ret; memset(port, 0, sizeof *port); - if (of_property_read_u32(np, "clock-frequency", &clk)) { + if (device_property_read_u32(&ofdev->dev, "clock-frequency", &clk)) { /* Get clk rate through clk driver if present */ info->clk = clk_get(&ofdev->dev, NULL); @@ -77,40 +78,52 @@ static int of_platform_serial_setup(struct platform_device *ofdev, clk = clk_get_rate(info->clk); } /* If current-speed was set, then try not to change it. */ - if (of_property_read_u32(np, "current-speed", &spd) == 0) + if (device_property_read_u32(&ofdev->dev, "current-speed", &spd) == 0) port->custom_divisor = clk / (16 * spd); - ret = of_address_to_resource(np, 0, &resource); - if (ret) { + resource = platform_get_resource(ofdev, IORESOURCE_MEM, 0); + if (!resource) { + resource = platform_get_resource(ofdev, IORESOURCE_IO, 0); + iotype = UPIO_PORT; + } + if (!resource) { dev_warn(&ofdev->dev, "invalid address\n"); goto out; } spin_lock_init(&port->lock); - port->mapbase = resource.start; + res_start = resource->start; /* Check for shifted address mapping */ - if (of_property_read_u32(np, "reg-offset", &prop) == 0) - port->mapbase += prop; + if (device_property_read_u32(&ofdev->dev, "reg-offset", &prop) == 0) + res_start += prop; + + if (iotype == UPIO_PORT) + port->iobase = res_start; + else + port->mapbase = res_start; /* Check for registers offset within the devices address range */ - if (of_property_read_u32(np, "reg-shift", &prop) == 0) + if (device_property_read_u32(&ofdev->dev, "reg-shift", &prop) == 0) port->regshift = prop; /* Check for fifo size */ - if (of_property_read_u32(np, "fifo-size", &prop) == 0) + if (device_property_read_u32(&ofdev->dev, "fifo-size", &prop) == 0) port->fifosize = prop; - port->irq = irq_of_parse_and_map(np, 0); - port->iotype = UPIO_MEM; - if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { + port->irq = platform_get_irq(ofdev, 0); + port->iotype = iotype; + if (device_property_read_u32(&ofdev->dev, "reg-io-width", &prop) == 0) { switch (prop) { case 1: - port->iotype = UPIO_MEM; + port->iotype = iotype; break; case 4: - port->iotype = UPIO_MEM32; - break; + if (iotype == UPIO_MEM) { + port->iotype = UPIO_MEM32; + break; + } + /* Fall through for non-memory */ default: dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n", prop); @@ -124,7 +137,7 @@ static int of_platform_serial_setup(struct platform_device *ofdev, port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE; - if (of_find_property(np, "no-loopback-test", NULL)) + if (!device_get_property(&ofdev->dev, "no-loopback-test", NULL)) port->flags |= UPF_SKIP_TEST; port->dev = &ofdev->dev; @@ -155,7 +168,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev) if (!match) return -EINVAL; - if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL)) + if (!device_get_property(&ofdev->dev, "used-by-rtas", NULL)) return -EBUSY; info = kmalloc(sizeof(*info), GFP_KERNEL); @@ -179,12 +192,10 @@ static int of_platform_serial_probe(struct platform_device *ofdev) if (port.fifosize) port8250.capabilities = UART_CAP_FIFO; - if (of_property_read_bool(ofdev->dev.of_node, - "auto-flow-control")) + if (!device_get_property(&ofdev->dev, "auto-flow-control", NULL)) port8250.capabilities |= UART_CAP_AFE; - if (of_property_read_bool(ofdev->dev.of_node, - "has-hw-flow-control")) + if (!device_get_property(&ofdev->dev, "has-hw-flow-control", NULL)) port8250.port.flags |= UPF_HARD_FLOW; ret = serial8250_register_8250_port(&port8250); -- dwmw2