mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-04-06 22:35:18 +00:00
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: Andre Przywara <andre.przywara@arm.com> Tested-by: Mark Langsdorf <mlangsdo@redhat.com> Tested-by: Naresh Bhat <nbhat@cavium.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ef5a935884
commit
3873e2d7f6
1 changed files with 61 additions and 35 deletions
|
@ -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;
|
||||||
return -EBUSY;
|
}
|
||||||
|
|
||||||
uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
|
static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
|
||||||
GFP_KERNEL);
|
struct resource *mmiobase, int index)
|
||||||
if (uap == NULL)
|
{
|
||||||
return -ENOMEM;
|
void __iomem *base;
|
||||||
|
|
||||||
i = pl011_probe_dt_alias(i, &dev->dev);
|
base = devm_ioremap_resource(dev, mmiobase);
|
||||||
|
|
||||||
base = devm_ioremap(&dev->dev, dev->res.start,
|
|
||||||
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;
|
||||||
|
|
||||||
|
amba_ports[index] = uap;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pl011_register_port(struct uart_amba_port *uap)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Ensure interrupts from this UART are masked and cleared */
|
/* Ensure interrupts from this UART are masked and cleared */
|
||||||
writew(0, uap->port.membase + UART011_IMSC);
|
writew(0, uap->port.membase + UART011_IMSC);
|
||||||
writew(0xffff, uap->port.membase + UART011_ICR);
|
writew(0xffff, uap->port.membase + UART011_ICR);
|
||||||
|
|
||||||
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
|
|
||||||
|
|
||||||
amba_ports[i] = uap;
|
|
||||||
|
|
||||||
amba_set_drvdata(dev, uap);
|
|
||||||
|
|
||||||
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)
|
||||||
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue