Instead of making clock devices in ACPI which is non standard assume that the firmware is going to handle clock enable/disable for us and just read the clock rate from _PRP in ASL.
This is currently prototype as it needs a new amba bus driver for ACPI as trying to interleive ACPI support in old driver leaves a mess of nested ifs.
Signed-off-by: Graeme Gregory graeme.gregory@linaro.org --- drivers/tty/serial/amba-pl011.c | 74 +++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 17 deletions(-)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index dacf0a0..7ec29ea 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -58,6 +58,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/sizes.h> #include <linux/io.h> +#include <linux/acpi.h>
#define UART_NR 14
@@ -1482,11 +1483,13 @@ static int pl011_hwinit(struct uart_port *port) /* * Try to enable the clock producer. */ - retval = clk_prepare_enable(uap->clk); - if (retval) - goto out; + if (uap->clk) { + retval = clk_prepare_enable(uap->clk); + if (retval) + goto out;
- uap->port.uartclk = clk_get_rate(uap->clk); + uap->port.uartclk = clk_get_rate(uap->clk); + }
/* Clear pending error and receive interrupts */ writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS | @@ -1604,7 +1607,8 @@ static int pl011_startup(struct uart_port *port) return 0;
clk_dis: - clk_disable_unprepare(uap->clk); + if (uap->clk) + clk_disable_unprepare(uap->clk); return retval; }
@@ -2011,9 +2015,13 @@ static int __init pl011_console_setup(struct console *co, char *options) /* Allow pins to be muxed in and configured */ pinctrl_pm_select_default_state(uap->port.dev);
- ret = clk_prepare(uap->clk); - if (ret) - return ret; + if (uap->clk) { + ret = clk_prepare(uap->clk); + if (ret) + return ret; + + uap->port.uartclk = clk_get_rate(uap->clk); + }
if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; @@ -2023,8 +2031,6 @@ static int __init pl011_console_setup(struct console *co, char *options) plat->init(); }
- uap->port.uartclk = clk_get_rate(uap->clk); - if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else @@ -2091,10 +2097,47 @@ static int pl011_probe_dt_alias(int index, struct device *dev) return ret; }
+static int pl011_dt_probe(int index, struct uart_amba_port *uap, + struct device *dev) +{ + int ret; + + ret = pl011_probe_dt_alias(index, dev); + + uap->clk = devm_clk_get(dev, NULL); + if (IS_ERR(uap->clk)) + ret = PTR_ERR(uap->clk); + + return ret; +} + +static int pl011_acpi_probe(struct uart_amba_port *uap, acpi_handle handle, + struct device *dev) +{ + struct acpi_device *acpi_dev; + int ret; + u32 clkrate = 0; + + if (acpi_bus_get_device(handle, &acpi_dev)) { + dev_dbg(dev, "ACPI device not found in %s!\n", __func__); + return -ENODEV; + } + + ret = acpi_dev_get_property_u32(acpi_dev, "clock-rate", &clkrate); + + if (!ret) + uap->port.uartclk = clkrate; + + dev_info(dev, "clkrate %d from AML\n", clkrate); + + return ret; +} + static int pl011_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; struct vendor_data *vendor = id->data; + acpi_handle handle = ACPI_HANDLE(&dev->dev); void __iomem *base; int i, ret;
@@ -2114,7 +2157,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) goto out; }
- i = pl011_probe_dt_alias(i, &dev->dev); + if (handle) + pl011_acpi_probe(uap, handle, &dev->dev); + else + pl011_dt_probe(i, uap, &dev->dev);
base = devm_ioremap(&dev->dev, dev->res.start, resource_size(&dev->res)); @@ -2123,12 +2169,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) goto out; }
- uap->clk = devm_clk_get(&dev->dev, NULL); - if (IS_ERR(uap->clk)) { - ret = PTR_ERR(uap->clk); - goto out; - } - uap->vendor = vendor; uap->lcrh_rx = vendor->lcrh_rx; uap->lcrh_tx = vendor->lcrh_tx;