diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-03 11:38:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-03 11:38:36 -0700 |
commit | 2f01ea908bcf838e815c0124b579513dbda3b8c8 (patch) | |
tree | f42db47c1695daaf369f08a21b2267d4a8ece756 /drivers/tty/serial/ar933x_uart.c | |
parent | 751144271f4b63d5de9005ea4e5e6e5c7c6fd629 (diff) | |
parent | 2d1d3f3ae985ec5676fb56ff2c7acad2e1c4e6eb (diff) |
Merge tag 'tty-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver patches from Greg KH:
"Here's the big tty/serial driver pull request for 3.12-rc1.
Lots of n_tty reworks to resolve some very long-standing issues,
removing the 3-4 different locks that were taken for every character.
This code has been beaten on for a long time in linux-next with no
reported regressions.
Other than that, a range of serial and tty driver updates and
revisions. Full details in the shortlog"
* tag 'tty-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (226 commits)
hvc_xen: Remove unnecessary __GFP_ZERO from kzalloc
serial: imx: initialize the local variable
tty: ar933x_uart: add device tree support and binding documentation
tty: ar933x_uart: allow to build the driver as a module
ARM: dts: msm: Update uartdm compatible strings
devicetree: serial: Document msm_serial bindings
serial: unify serial bindings into a single dir
serial: fsl-imx-uart: Cleanup duplicate device tree binding
tty: ar933x_uart: use config_enabled() macro to clean up ifdefs
tty: ar933x_uart: remove superfluous assignment of ar933x_uart_driver.nr
tty: ar933x_uart: use the clk API to get the uart clock
tty: serial: cpm_uart: Adding proper request of GPIO used by cpm_uart driver
serial: sirf: fix the amount of serial ports
serial: sirf: define macro for some magic numbers of USP
serial: icom: move array overflow checks earlier
TTY: amiserial, remove unnecessary platform_set_drvdata()
serial: st-asc: remove unnecessary platform_set_drvdata()
msm_serial: Send more than 1 character on the console w/ UARTDM
msm_serial: Add support for non-GSBI UARTDM devices
msm_serial: Switch clock consumer strings and simplify code
...
Diffstat (limited to 'drivers/tty/serial/ar933x_uart.c')
-rw-r--r-- | drivers/tty/serial/ar933x_uart.c | 111 |
1 files changed, 67 insertions, 44 deletions
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index 27f20c57abed..acd03af7cd52 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -17,6 +17,8 @@ #include <linux/sysrq.h> #include <linux/delay.h> #include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_platform.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/serial_core.h> @@ -24,11 +26,11 @@ #include <linux/slab.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/clk.h> #include <asm/div64.h> #include <asm/mach-ath79/ar933x_uart.h> -#include <asm/mach-ath79/ar933x_uart_platform.h> #define DRIVER_NAME "ar933x-uart" @@ -47,8 +49,14 @@ struct ar933x_uart_port { unsigned int ier; /* shadow Interrupt Enable Register */ unsigned int min_baud; unsigned int max_baud; + struct clk *clk; }; +static inline bool ar933x_uart_console_enabled(void) +{ + return config_enabled(CONFIG_SERIAL_AR933X_CONSOLE); +} + static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up, int offset) { @@ -322,7 +330,9 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up) tty_insert_flip_char(port, ch, TTY_NORMAL); } while (max_count-- > 0); + spin_unlock(&up->port.lock); tty_flip_buffer_push(port); + spin_lock(&up->port.lock); } static void ar933x_uart_tx_chars(struct ar933x_uart_port *up) @@ -497,8 +507,6 @@ static struct uart_ops ar933x_uart_ops = { .verify_port = ar933x_uart_verify_port, }; -#ifdef CONFIG_SERIAL_AR933X_CONSOLE - static struct ar933x_uart_port * ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS]; @@ -597,80 +605,88 @@ static struct console ar933x_uart_console = { static void ar933x_uart_add_console_port(struct ar933x_uart_port *up) { + if (!ar933x_uart_console_enabled()) + return; + ar933x_console_ports[up->port.line] = up; } -#define AR933X_SERIAL_CONSOLE (&ar933x_uart_console) - -#else - -static inline void ar933x_uart_add_console_port(struct ar933x_uart_port *up) {} - -#define AR933X_SERIAL_CONSOLE NULL - -#endif /* CONFIG_SERIAL_AR933X_CONSOLE */ - static struct uart_driver ar933x_uart_driver = { .owner = THIS_MODULE, .driver_name = DRIVER_NAME, .dev_name = "ttyATH", .nr = CONFIG_SERIAL_AR933X_NR_UARTS, - .cons = AR933X_SERIAL_CONSOLE, + .cons = NULL, /* filled in runtime */ }; static int ar933x_uart_probe(struct platform_device *pdev) { - struct ar933x_uart_platform_data *pdata; struct ar933x_uart_port *up; struct uart_port *port; struct resource *mem_res; struct resource *irq_res; + struct device_node *np; unsigned int baud; int id; int ret; - pdata = pdev->dev.platform_data; - if (!pdata) - return -EINVAL; - - id = pdev->id; - if (id == -1) - id = 0; + np = pdev->dev.of_node; + if (config_enabled(CONFIG_OF) && np) { + id = of_alias_get_id(np, "serial"); + if (id < 0) { + dev_err(&pdev->dev, "unable to get alias id, err=%d\n", + id); + return id; + } + } else { + id = pdev->id; + if (id == -1) + id = 0; + } if (id > CONFIG_SERIAL_AR933X_NR_UARTS) return -EINVAL; - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem_res) { - dev_err(&pdev->dev, "no MEM resource\n"); - return -EINVAL; - } - irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { dev_err(&pdev->dev, "no IRQ resource\n"); return -EINVAL; } - up = kzalloc(sizeof(struct ar933x_uart_port), GFP_KERNEL); + up = devm_kzalloc(&pdev->dev, sizeof(struct ar933x_uart_port), + GFP_KERNEL); if (!up) return -ENOMEM; + up->clk = devm_clk_get(&pdev->dev, "uart"); + if (IS_ERR(up->clk)) { + dev_err(&pdev->dev, "unable to get UART clock\n"); + return PTR_ERR(up->clk); + } + port = &up->port; - port->mapbase = mem_res->start; - port->membase = ioremap(mem_res->start, AR933X_UART_REGS_SIZE); - if (!port->membase) { - ret = -ENOMEM; - goto err_free_up; + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + port->membase = devm_ioremap_resource(&pdev->dev, mem_res); + if (IS_ERR(port->membase)) + return PTR_ERR(port->membase); + + ret = clk_prepare_enable(up->clk); + if (ret) + return ret; + + port->uartclk = clk_get_rate(up->clk); + if (!port->uartclk) { + ret = -EINVAL; + goto err_disable_clk; } + port->mapbase = mem_res->start; port->line = id; port->irq = irq_res->start; port->dev = &pdev->dev; port->type = PORT_AR933X; port->iotype = UPIO_MEM32; - port->uartclk = pdata->uartclk; port->regshift = 2; port->fifosize = AR933X_UART_FIFO_SIZE; @@ -686,15 +702,13 @@ static int ar933x_uart_probe(struct platform_device *pdev) ret = uart_add_one_port(&ar933x_uart_driver, &up->port); if (ret) - goto err_unmap; + goto err_disable_clk; platform_set_drvdata(pdev, up); return 0; -err_unmap: - iounmap(up->port.membase); -err_free_up: - kfree(up); +err_disable_clk: + clk_disable_unprepare(up->clk); return ret; } @@ -703,23 +717,30 @@ static int ar933x_uart_remove(struct platform_device *pdev) struct ar933x_uart_port *up; up = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); if (up) { uart_remove_one_port(&ar933x_uart_driver, &up->port); - iounmap(up->port.membase); - kfree(up); + clk_disable_unprepare(up->clk); } return 0; } +#ifdef CONFIG_OF +static const struct of_device_id ar933x_uart_of_ids[] = { + { .compatible = "qca,ar9330-uart" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ar933x_uart_of_ids); +#endif + static struct platform_driver ar933x_uart_platform_driver = { .probe = ar933x_uart_probe, .remove = ar933x_uart_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ar933x_uart_of_ids), }, }; @@ -727,7 +748,9 @@ static int __init ar933x_uart_init(void) { int ret; - ar933x_uart_driver.nr = CONFIG_SERIAL_AR933X_NR_UARTS; + if (ar933x_uart_console_enabled()) + ar933x_uart_driver.cons = &ar933x_uart_console; + ret = uart_register_driver(&ar933x_uart_driver); if (ret) goto err_out; |