aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2015-05-21 12:26:18 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-05-24 16:08:51 -0400
commit3873e2d7f63a9da3098b28c405d13f15667a01b0 (patch)
tree0f052abe653726b0124a3799a794676140b8f788
parentef5a9358844a2e6f466facaca3247b64c72ef417 (diff)
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>
-rw-r--r--drivers/tty/serial/amba-pl011.c96
1 files changed, 61 insertions, 35 deletions
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 686951a19716..38d2245d7485 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2173,65 +2173,54 @@ static void pl011_unregister_port(struct uart_amba_port *uap)
2173 uart_unregister_driver(&amba_reg); 2173 uart_unregister_driver(&amba_reg);
2174} 2174}
2175 2175
2176static int pl011_probe(struct amba_device *dev, const struct amba_id *id) 2176static int pl011_find_free_port(void)
2177{ 2177{
2178 struct uart_amba_port *uap; 2178 int i;
2179 struct vendor_data *vendor = id->data;
2180 void __iomem *base;
2181 int i, ret;
2182 2179
2183 for (i = 0; i < ARRAY_SIZE(amba_ports); i++) 2180 for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
2184 if (amba_ports[i] == NULL) 2181 if (amba_ports[i] == NULL)
2185 break; 2182 return i;
2186
2187 if (i == ARRAY_SIZE(amba_ports))
2188 return -EBUSY;
2189 2183
2190 uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port), 2184 return -EBUSY;
2191 GFP_KERNEL); 2185}
2192 if (uap == NULL)
2193 return -ENOMEM;
2194 2186
2195 i = pl011_probe_dt_alias(i, &dev->dev); 2187static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
2188 struct resource *mmiobase, int index)
2189{
2190 void __iomem *base;
2196 2191
2197 base = devm_ioremap(&dev->dev, dev->res.start, 2192 base = devm_ioremap_resource(dev, mmiobase);
2198 resource_size(&dev->res));
2199 if (!base) 2193 if (!base)
2200 return -ENOMEM; 2194 return -ENOMEM;
2201 2195
2202 uap->clk = devm_clk_get(&dev->dev, NULL); 2196 index = pl011_probe_dt_alias(index, dev);
2203 if (IS_ERR(uap->clk))
2204 return PTR_ERR(uap->clk);
2205 2197
2206 uap->vendor = vendor;
2207 uap->lcrh_rx = vendor->lcrh_rx;
2208 uap->lcrh_tx = vendor->lcrh_tx;
2209 uap->old_cr = 0; 2198 uap->old_cr = 0;
2210 uap->fifosize = vendor->get_fifosize(dev); 2199 uap->port.dev = dev;
2211 uap->port.dev = &dev->dev; 2200 uap->port.mapbase = mmiobase->start;
2212 uap->port.mapbase = dev->res.start;
2213 uap->port.membase = base; 2201 uap->port.membase = base;
2214 uap->port.iotype = UPIO_MEM; 2202 uap->port.iotype = UPIO_MEM;
2215 uap->port.irq = dev->irq[0];
2216 uap->port.fifosize = uap->fifosize; 2203 uap->port.fifosize = uap->fifosize;
2217 uap->port.ops = &amba_pl011_pops;
2218 uap->port.flags = UPF_BOOT_AUTOCONF; 2204 uap->port.flags = UPF_BOOT_AUTOCONF;
2219 uap->port.line = i; 2205 uap->port.line = index;
2220 2206
2221 /* Ensure interrupts from this UART are masked and cleared */ 2207 amba_ports[index] = uap;
2222 writew(0, uap->port.membase + UART011_IMSC);
2223 writew(0xffff, uap->port.membase + UART011_ICR);
2224 2208
2225 snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev)); 2209 return 0;
2210}
2226 2211
2227 amba_ports[i] = uap; 2212static int pl011_register_port(struct uart_amba_port *uap)
2213{
2214 int ret;
2228 2215
2229 amba_set_drvdata(dev, uap); 2216 /* Ensure interrupts from this UART are masked and cleared */
2217 writew(0, uap->port.membase + UART011_IMSC);
2218 writew(0xffff, uap->port.membase + UART011_ICR);
2230 2219
2231 if (!amba_reg.state) { 2220 if (!amba_reg.state) {
2232 ret = uart_register_driver(&amba_reg); 2221 ret = uart_register_driver(&amba_reg);
2233 if (ret < 0) { 2222 if (ret < 0) {
2234 dev_err(&dev->dev, 2223 dev_err(uap->port.dev,
2235 "Failed to register AMBA-PL011 driver\n"); 2224 "Failed to register AMBA-PL011 driver\n");
2236 return ret; 2225 return ret;
2237 } 2226 }
@@ -2244,6 +2233,43 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
2244 return ret; 2233 return ret;
2245} 2234}
2246 2235
2236static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
2237{
2238 struct uart_amba_port *uap;
2239 struct vendor_data *vendor = id->data;
2240 int portnr, ret;
2241
2242 portnr = pl011_find_free_port();
2243 if (portnr < 0)
2244 return portnr;
2245
2246 uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
2247 GFP_KERNEL);
2248 if (!uap)
2249 return -ENOMEM;
2250
2251 uap->clk = devm_clk_get(&dev->dev, NULL);
2252 if (IS_ERR(uap->clk))
2253 return PTR_ERR(uap->clk);
2254
2255 uap->vendor = vendor;
2256 uap->lcrh_rx = vendor->lcrh_rx;
2257 uap->lcrh_tx = vendor->lcrh_tx;
2258 uap->fifosize = vendor->get_fifosize(dev);
2259 uap->port.irq = dev->irq[0];
2260 uap->port.ops = &amba_pl011_pops;
2261
2262 snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
2263
2264 ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr);
2265 if (ret)
2266 return ret;
2267
2268 amba_set_drvdata(dev, uap);
2269
2270 return pl011_register_port(uap);
2271}
2272
2247static int pl011_remove(struct amba_device *dev) 2273static int pl011_remove(struct amba_device *dev)
2248{ 2274{
2249 struct uart_amba_port *uap = amba_get_drvdata(dev); 2275 struct uart_amba_port *uap = amba_get_drvdata(dev);