Commit 3873e2d7 authored by Andre Przywara's avatar Andre Przywara Committed by Greg Kroah-Hartman

drivers: PL011: refactor pl011_probe()

Currently the pl011_probe() function is relying on some AMBA IDs
and a device tree node to initialize the driver and a port.
Both features are not necessarily required for the driver:
- we lack AMBA IDs in the ARM SBSA generic UART and
- we lack a DT node in ACPI systems.
So lets refactor the function to ease later reuse.
Signed-off-by: default avatarAndre Przywara <andre.przywara@arm.com>
Tested-by: default avatarMark Langsdorf <mlangsdo@redhat.com>
Tested-by: default avatarNaresh Bhat <nbhat@cavium.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent ef5a9358
...@@ -2173,65 +2173,54 @@ static void pl011_unregister_port(struct uart_amba_port *uap) ...@@ -2173,65 +2173,54 @@ static void pl011_unregister_port(struct uart_amba_port *uap)
uart_unregister_driver(&amba_reg); uart_unregister_driver(&amba_reg);
} }
static int pl011_probe(struct amba_device *dev, const struct amba_id *id) static int pl011_find_free_port(void)
{ {
struct uart_amba_port *uap; int i;
struct vendor_data *vendor = id->data;
void __iomem *base;
int i, ret;
for (i = 0; i < ARRAY_SIZE(amba_ports); i++) for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
if (amba_ports[i] == NULL) if (amba_ports[i] == NULL)
break; return i;
if (i == ARRAY_SIZE(amba_ports))
return -EBUSY;
uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port), return -EBUSY;
GFP_KERNEL); }
if (uap == NULL)
return -ENOMEM;
i = pl011_probe_dt_alias(i, &dev->dev); static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
struct resource *mmiobase, int index)
{
void __iomem *base;
base = devm_ioremap(&dev->dev, dev->res.start, base = devm_ioremap_resource(dev, mmiobase);
resource_size(&dev->res));
if (!base) if (!base)
return -ENOMEM; return -ENOMEM;
uap->clk = devm_clk_get(&dev->dev, NULL); index = pl011_probe_dt_alias(index, dev);
if (IS_ERR(uap->clk))
return PTR_ERR(uap->clk);
uap->vendor = vendor;
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
uap->old_cr = 0; uap->old_cr = 0;
uap->fifosize = vendor->get_fifosize(dev); uap->port.dev = dev;
uap->port.dev = &dev->dev; uap->port.mapbase = mmiobase->start;
uap->port.mapbase = dev->res.start;
uap->port.membase = base; uap->port.membase = base;
uap->port.iotype = UPIO_MEM; uap->port.iotype = UPIO_MEM;
uap->port.irq = dev->irq[0];
uap->port.fifosize = uap->fifosize; uap->port.fifosize = uap->fifosize;
uap->port.ops = &amba_pl011_pops;
uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = i; uap->port.line = index;
/* Ensure interrupts from this UART are masked and cleared */ amba_ports[index] = uap;
writew(0, uap->port.membase + UART011_IMSC);
writew(0xffff, uap->port.membase + UART011_ICR);
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev)); return 0;
}
amba_ports[i] = uap; static int pl011_register_port(struct uart_amba_port *uap)
{
int ret;
amba_set_drvdata(dev, uap); /* Ensure interrupts from this UART are masked and cleared */
writew(0, uap->port.membase + UART011_IMSC);
writew(0xffff, uap->port.membase + UART011_ICR);
if (!amba_reg.state) { if (!amba_reg.state) {
ret = uart_register_driver(&amba_reg); ret = uart_register_driver(&amba_reg);
if (ret < 0) { if (ret < 0) {
dev_err(&dev->dev, dev_err(uap->port.dev,
"Failed to register AMBA-PL011 driver\n"); "Failed to register AMBA-PL011 driver\n");
return ret; return ret;
} }
...@@ -2244,6 +2233,43 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -2244,6 +2233,43 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
return ret; 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;
int portnr, ret;
portnr = pl011_find_free_port();
if (portnr < 0)
return portnr;
uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
GFP_KERNEL);
if (!uap)
return -ENOMEM;
uap->clk = devm_clk_get(&dev->dev, NULL);
if (IS_ERR(uap->clk))
return PTR_ERR(uap->clk);
uap->vendor = vendor;
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
uap->fifosize = vendor->get_fifosize(dev);
uap->port.irq = dev->irq[0];
uap->port.ops = &amba_pl011_pops;
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr);
if (ret)
return ret;
amba_set_drvdata(dev, uap);
return pl011_register_port(uap);
}
static int pl011_remove(struct amba_device *dev) static int pl011_remove(struct amba_device *dev)
{ {
struct uart_amba_port *uap = amba_get_drvdata(dev); struct uart_amba_port *uap = amba_get_drvdata(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment