diff options
| author | Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com> | 2018-07-21 07:49:05 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-08-02 04:08:43 -0400 |
| commit | 14288befeb572b4d2155f3435dca5cdec799152c (patch) | |
| tree | 8b38b1d382573f3c69b7183f8a5c55b1acf1f69a | |
| parent | da7bf20e7758042eb3931ff68fc96bdfaf94d881 (diff) | |
tty: serial: uartlite: Add clock adaptation
Add support of Common Clock Framework for Uartlite driver.
Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | drivers/tty/serial/uartlite.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 0f798f7837ad..b3a12be45801 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/of_address.h> | 21 | #include <linux/of_address.h> |
| 22 | #include <linux/of_device.h> | 22 | #include <linux/of_device.h> |
| 23 | #include <linux/of_platform.h> | 23 | #include <linux/of_platform.h> |
| 24 | #include <linux/clk.h> | ||
| 24 | 25 | ||
| 25 | #define ULITE_NAME "ttyUL" | 26 | #define ULITE_NAME "ttyUL" |
| 26 | #define ULITE_MAJOR 204 | 27 | #define ULITE_MAJOR 204 |
| @@ -56,6 +57,7 @@ | |||
| 56 | 57 | ||
| 57 | struct uartlite_data { | 58 | struct uartlite_data { |
| 58 | const struct uartlite_reg_ops *reg_ops; | 59 | const struct uartlite_reg_ops *reg_ops; |
| 60 | struct clk *clk; | ||
| 59 | }; | 61 | }; |
| 60 | 62 | ||
| 61 | struct uartlite_reg_ops { | 63 | struct uartlite_reg_ops { |
| @@ -261,8 +263,15 @@ static void ulite_break_ctl(struct uart_port *port, int ctl) | |||
| 261 | 263 | ||
| 262 | static int ulite_startup(struct uart_port *port) | 264 | static int ulite_startup(struct uart_port *port) |
| 263 | { | 265 | { |
| 266 | struct uartlite_data *pdata = port->private_data; | ||
| 264 | int ret; | 267 | int ret; |
| 265 | 268 | ||
| 269 | ret = clk_enable(pdata->clk); | ||
| 270 | if (ret) { | ||
| 271 | dev_err(port->dev, "Failed to enable clock\n"); | ||
| 272 | return ret; | ||
| 273 | } | ||
| 274 | |||
| 266 | ret = request_irq(port->irq, ulite_isr, IRQF_SHARED | IRQF_TRIGGER_RISING, | 275 | ret = request_irq(port->irq, ulite_isr, IRQF_SHARED | IRQF_TRIGGER_RISING, |
| 267 | "uartlite", port); | 276 | "uartlite", port); |
| 268 | if (ret) | 277 | if (ret) |
| @@ -277,9 +286,12 @@ static int ulite_startup(struct uart_port *port) | |||
| 277 | 286 | ||
| 278 | static void ulite_shutdown(struct uart_port *port) | 287 | static void ulite_shutdown(struct uart_port *port) |
| 279 | { | 288 | { |
| 289 | struct uartlite_data *pdata = port->private_data; | ||
| 290 | |||
| 280 | uart_out32(0, ULITE_CONTROL, port); | 291 | uart_out32(0, ULITE_CONTROL, port); |
| 281 | uart_in32(ULITE_CONTROL, port); /* dummy */ | 292 | uart_in32(ULITE_CONTROL, port); /* dummy */ |
| 282 | free_irq(port->irq, port); | 293 | free_irq(port->irq, port); |
| 294 | clk_disable(pdata->clk); | ||
| 283 | } | 295 | } |
| 284 | 296 | ||
| 285 | static void ulite_set_termios(struct uart_port *port, struct ktermios *termios, | 297 | static void ulite_set_termios(struct uart_port *port, struct ktermios *termios, |
| @@ -370,6 +382,17 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
| 370 | return -EINVAL; | 382 | return -EINVAL; |
| 371 | } | 383 | } |
| 372 | 384 | ||
| 385 | static void ulite_pm(struct uart_port *port, unsigned int state, | ||
| 386 | unsigned int oldstate) | ||
| 387 | { | ||
| 388 | struct uartlite_data *pdata = port->private_data; | ||
| 389 | |||
| 390 | if (!state) | ||
| 391 | clk_enable(pdata->clk); | ||
| 392 | else | ||
| 393 | clk_disable(pdata->clk); | ||
| 394 | } | ||
| 395 | |||
| 373 | #ifdef CONFIG_CONSOLE_POLL | 396 | #ifdef CONFIG_CONSOLE_POLL |
| 374 | static int ulite_get_poll_char(struct uart_port *port) | 397 | static int ulite_get_poll_char(struct uart_port *port) |
| 375 | { | 398 | { |
| @@ -405,6 +428,7 @@ static const struct uart_ops ulite_ops = { | |||
| 405 | .request_port = ulite_request_port, | 428 | .request_port = ulite_request_port, |
| 406 | .config_port = ulite_config_port, | 429 | .config_port = ulite_config_port, |
| 407 | .verify_port = ulite_verify_port, | 430 | .verify_port = ulite_verify_port, |
| 431 | .pm = ulite_pm, | ||
| 408 | #ifdef CONFIG_CONSOLE_POLL | 432 | #ifdef CONFIG_CONSOLE_POLL |
| 409 | .poll_get_char = ulite_get_poll_char, | 433 | .poll_get_char = ulite_get_poll_char, |
| 410 | .poll_put_char = ulite_put_poll_char, | 434 | .poll_put_char = ulite_put_poll_char, |
| @@ -669,7 +693,6 @@ static int ulite_release(struct device *dev) | |||
| 669 | /* --------------------------------------------------------------------- | 693 | /* --------------------------------------------------------------------- |
| 670 | * Platform bus binding | 694 | * Platform bus binding |
| 671 | */ | 695 | */ |
| 672 | |||
| 673 | #if defined(CONFIG_OF) | 696 | #if defined(CONFIG_OF) |
| 674 | /* Match table for of_platform binding */ | 697 | /* Match table for of_platform binding */ |
| 675 | static const struct of_device_id ulite_of_match[] = { | 698 | static const struct of_device_id ulite_of_match[] = { |
| @@ -684,7 +707,7 @@ static int ulite_probe(struct platform_device *pdev) | |||
| 684 | { | 707 | { |
| 685 | struct resource *res; | 708 | struct resource *res; |
| 686 | struct uartlite_data *pdata; | 709 | struct uartlite_data *pdata; |
| 687 | int irq; | 710 | int irq, ret; |
| 688 | int id = pdev->id; | 711 | int id = pdev->id; |
| 689 | #ifdef CONFIG_OF | 712 | #ifdef CONFIG_OF |
| 690 | const __be32 *prop; | 713 | const __be32 *prop; |
| @@ -706,11 +729,33 @@ static int ulite_probe(struct platform_device *pdev) | |||
| 706 | if (irq <= 0) | 729 | if (irq <= 0) |
| 707 | return -ENXIO; | 730 | return -ENXIO; |
| 708 | 731 | ||
| 732 | pdata->clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); | ||
| 733 | if (IS_ERR(pdata->clk)) { | ||
| 734 | if (PTR_ERR(pdata->clk) != -ENOENT) | ||
| 735 | return PTR_ERR(pdata->clk); | ||
| 736 | |||
| 737 | /* | ||
| 738 | * Clock framework support is optional, continue on | ||
| 739 | * anyways if we don't find a matching clock. | ||
| 740 | */ | ||
| 741 | pdata->clk = NULL; | ||
| 742 | } | ||
| 743 | |||
| 744 | ret = clk_prepare(pdata->clk); | ||
| 745 | if (ret) { | ||
| 746 | dev_err(&pdev->dev, "Failed to prepare clock\n"); | ||
| 747 | return ret; | ||
| 748 | } | ||
| 749 | |||
| 709 | return ulite_assign(&pdev->dev, id, res->start, irq, pdata); | 750 | return ulite_assign(&pdev->dev, id, res->start, irq, pdata); |
| 710 | } | 751 | } |
| 711 | 752 | ||
| 712 | static int ulite_remove(struct platform_device *pdev) | 753 | static int ulite_remove(struct platform_device *pdev) |
| 713 | { | 754 | { |
| 755 | struct uart_port *port = dev_get_drvdata(&pdev->dev); | ||
| 756 | struct uartlite_data *pdata = port->private_data; | ||
| 757 | |||
| 758 | clk_disable_unprepare(pdata->clk); | ||
| 714 | return ulite_release(&pdev->dev); | 759 | return ulite_release(&pdev->dev); |
| 715 | } | 760 | } |
| 716 | 761 | ||
