diff options
author | Andre Przywara <andre.przywara@arm.com> | 2015-05-21 12:26:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-05-24 16:08:51 -0400 |
commit | 3873e2d7f63a9da3098b28c405d13f15667a01b0 (patch) | |
tree | 0f052abe653726b0124a3799a794676140b8f788 | |
parent | ef5a9358844a2e6f466facaca3247b64c72ef417 (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.c | 96 |
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 | ||
2176 | static int pl011_probe(struct amba_device *dev, const struct amba_id *id) | 2176 | static 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); | 2187 | static 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; | 2212 | static 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 | ||
2236 | static 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 | |||
2247 | static int pl011_remove(struct amba_device *dev) | 2273 | static 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); |