diff options
Diffstat (limited to 'drivers/tty/serial/lantiq.c')
-rw-r--r-- | drivers/tty/serial/lantiq.c | 89 |
1 files changed, 35 insertions, 54 deletions
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index 02da071fe1e..bc95f52cad8 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c | |||
@@ -31,19 +31,16 @@ | |||
31 | #include <linux/tty_flip.h> | 31 | #include <linux/tty_flip.h> |
32 | #include <linux/serial_core.h> | 32 | #include <linux/serial_core.h> |
33 | #include <linux/serial.h> | 33 | #include <linux/serial.h> |
34 | #include <linux/of_platform.h> | 34 | #include <linux/platform_device.h> |
35 | #include <linux/of_address.h> | ||
36 | #include <linux/of_irq.h> | ||
37 | #include <linux/io.h> | 35 | #include <linux/io.h> |
38 | #include <linux/clk.h> | 36 | #include <linux/clk.h> |
39 | #include <linux/gpio.h> | ||
40 | 37 | ||
41 | #include <lantiq_soc.h> | 38 | #include <lantiq_soc.h> |
42 | 39 | ||
43 | #define PORT_LTQ_ASC 111 | 40 | #define PORT_LTQ_ASC 111 |
44 | #define MAXPORTS 2 | 41 | #define MAXPORTS 2 |
45 | #define UART_DUMMY_UER_RX 1 | 42 | #define UART_DUMMY_UER_RX 1 |
46 | #define DRVNAME "lantiq,asc" | 43 | #define DRVNAME "ltq_asc" |
47 | #ifdef __BIG_ENDIAN | 44 | #ifdef __BIG_ENDIAN |
48 | #define LTQ_ASC_TBUF (0x0020 + 3) | 45 | #define LTQ_ASC_TBUF (0x0020 + 3) |
49 | #define LTQ_ASC_RBUF (0x0024 + 3) | 46 | #define LTQ_ASC_RBUF (0x0024 + 3) |
@@ -117,9 +114,6 @@ static DEFINE_SPINLOCK(ltq_asc_lock); | |||
117 | 114 | ||
118 | struct ltq_uart_port { | 115 | struct ltq_uart_port { |
119 | struct uart_port port; | 116 | struct uart_port port; |
120 | /* clock used to derive divider */ | ||
121 | struct clk *fpiclk; | ||
122 | /* clock gating of the ASC core */ | ||
123 | struct clk *clk; | 117 | struct clk *clk; |
124 | unsigned int tx_irq; | 118 | unsigned int tx_irq; |
125 | unsigned int rx_irq; | 119 | unsigned int rx_irq; |
@@ -322,9 +316,7 @@ lqasc_startup(struct uart_port *port) | |||
322 | struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); | 316 | struct ltq_uart_port *ltq_port = to_ltq_uart_port(port); |
323 | int retval; | 317 | int retval; |
324 | 318 | ||
325 | if (ltq_port->clk) | 319 | port->uartclk = clk_get_rate(ltq_port->clk); |
326 | clk_enable(ltq_port->clk); | ||
327 | port->uartclk = clk_get_rate(ltq_port->fpiclk); | ||
328 | 320 | ||
329 | ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET), | 321 | ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET), |
330 | port->membase + LTQ_ASC_CLC); | 322 | port->membase + LTQ_ASC_CLC); |
@@ -346,21 +338,21 @@ lqasc_startup(struct uart_port *port) | |||
346 | ASCCON_ROEN, port->membase + LTQ_ASC_CON); | 338 | ASCCON_ROEN, port->membase + LTQ_ASC_CON); |
347 | 339 | ||
348 | retval = request_irq(ltq_port->tx_irq, lqasc_tx_int, | 340 | retval = request_irq(ltq_port->tx_irq, lqasc_tx_int, |
349 | 0, "asc_tx", port); | 341 | IRQF_DISABLED, "asc_tx", port); |
350 | if (retval) { | 342 | if (retval) { |
351 | pr_err("failed to request lqasc_tx_int\n"); | 343 | pr_err("failed to request lqasc_tx_int\n"); |
352 | return retval; | 344 | return retval; |
353 | } | 345 | } |
354 | 346 | ||
355 | retval = request_irq(ltq_port->rx_irq, lqasc_rx_int, | 347 | retval = request_irq(ltq_port->rx_irq, lqasc_rx_int, |
356 | 0, "asc_rx", port); | 348 | IRQF_DISABLED, "asc_rx", port); |
357 | if (retval) { | 349 | if (retval) { |
358 | pr_err("failed to request lqasc_rx_int\n"); | 350 | pr_err("failed to request lqasc_rx_int\n"); |
359 | goto err1; | 351 | goto err1; |
360 | } | 352 | } |
361 | 353 | ||
362 | retval = request_irq(ltq_port->err_irq, lqasc_err_int, | 354 | retval = request_irq(ltq_port->err_irq, lqasc_err_int, |
363 | 0, "asc_err", port); | 355 | IRQF_DISABLED, "asc_err", port); |
364 | if (retval) { | 356 | if (retval) { |
365 | pr_err("failed to request lqasc_err_int\n"); | 357 | pr_err("failed to request lqasc_err_int\n"); |
366 | goto err2; | 358 | goto err2; |
@@ -390,8 +382,6 @@ lqasc_shutdown(struct uart_port *port) | |||
390 | port->membase + LTQ_ASC_RXFCON); | 382 | port->membase + LTQ_ASC_RXFCON); |
391 | ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU, | 383 | ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU, |
392 | port->membase + LTQ_ASC_TXFCON); | 384 | port->membase + LTQ_ASC_TXFCON); |
393 | if (ltq_port->clk) | ||
394 | clk_disable(ltq_port->clk); | ||
395 | } | 385 | } |
396 | 386 | ||
397 | static void | 387 | static void |
@@ -640,7 +630,7 @@ lqasc_console_setup(struct console *co, char *options) | |||
640 | 630 | ||
641 | port = <q_port->port; | 631 | port = <q_port->port; |
642 | 632 | ||
643 | port->uartclk = clk_get_rate(ltq_port->fpiclk); | 633 | port->uartclk = clk_get_rate(ltq_port->clk); |
644 | 634 | ||
645 | if (options) | 635 | if (options) |
646 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 636 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
@@ -678,32 +668,37 @@ static struct uart_driver lqasc_reg = { | |||
678 | static int __init | 668 | static int __init |
679 | lqasc_probe(struct platform_device *pdev) | 669 | lqasc_probe(struct platform_device *pdev) |
680 | { | 670 | { |
681 | struct device_node *node = pdev->dev.of_node; | ||
682 | struct ltq_uart_port *ltq_port; | 671 | struct ltq_uart_port *ltq_port; |
683 | struct uart_port *port; | 672 | struct uart_port *port; |
684 | struct resource *mmres, irqres[3]; | 673 | struct resource *mmres, *irqres; |
685 | int line = 0; | 674 | int tx_irq, rx_irq, err_irq; |
675 | struct clk *clk; | ||
686 | int ret; | 676 | int ret; |
687 | 677 | ||
688 | mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 678 | mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
689 | ret = of_irq_to_resource_table(node, irqres, 3); | 679 | irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
690 | if (!mmres || (ret != 3)) { | 680 | if (!mmres || !irqres) |
691 | dev_err(&pdev->dev, | ||
692 | "failed to get memory/irq for serial port\n"); | ||
693 | return -ENODEV; | 681 | return -ENODEV; |
694 | } | ||
695 | 682 | ||
696 | /* check if this is the console port */ | 683 | if (pdev->id >= MAXPORTS) |
697 | if (mmres->start != CPHYSADDR(LTQ_EARLY_ASC)) | 684 | return -EBUSY; |
698 | line = 1; | ||
699 | 685 | ||
700 | if (lqasc_port[line]) { | 686 | if (lqasc_port[pdev->id] != NULL) |
701 | dev_err(&pdev->dev, "port %d already allocated\n", line); | ||
702 | return -EBUSY; | 687 | return -EBUSY; |
688 | |||
689 | clk = clk_get(&pdev->dev, "fpi"); | ||
690 | if (IS_ERR(clk)) { | ||
691 | pr_err("failed to get fpi clk\n"); | ||
692 | return -ENOENT; | ||
703 | } | 693 | } |
704 | 694 | ||
705 | ltq_port = devm_kzalloc(&pdev->dev, sizeof(struct ltq_uart_port), | 695 | tx_irq = platform_get_irq_byname(pdev, "tx"); |
706 | GFP_KERNEL); | 696 | rx_irq = platform_get_irq_byname(pdev, "rx"); |
697 | err_irq = platform_get_irq_byname(pdev, "err"); | ||
698 | if ((tx_irq < 0) | (rx_irq < 0) | (err_irq < 0)) | ||
699 | return -ENODEV; | ||
700 | |||
701 | ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL); | ||
707 | if (!ltq_port) | 702 | if (!ltq_port) |
708 | return -ENOMEM; | 703 | return -ENOMEM; |
709 | 704 | ||
@@ -714,26 +709,19 @@ lqasc_probe(struct platform_device *pdev) | |||
714 | port->ops = &lqasc_pops; | 709 | port->ops = &lqasc_pops; |
715 | port->fifosize = 16; | 710 | port->fifosize = 16; |
716 | port->type = PORT_LTQ_ASC, | 711 | port->type = PORT_LTQ_ASC, |
717 | port->line = line; | 712 | port->line = pdev->id; |
718 | port->dev = &pdev->dev; | 713 | port->dev = &pdev->dev; |
719 | /* unused, just to be backward-compatible */ | ||
720 | port->irq = irqres[0].start; | ||
721 | port->mapbase = mmres->start; | ||
722 | 714 | ||
723 | ltq_port->fpiclk = clk_get_fpi(); | 715 | port->irq = tx_irq; /* unused, just to be backward-compatibe */ |
724 | if (IS_ERR(ltq_port->fpiclk)) { | 716 | port->mapbase = mmres->start; |
725 | pr_err("failed to get fpi clk\n"); | ||
726 | return -ENOENT; | ||
727 | } | ||
728 | 717 | ||
729 | /* not all asc ports have clock gates, lets ignore the return code */ | 718 | ltq_port->clk = clk; |
730 | ltq_port->clk = clk_get(&pdev->dev, NULL); | ||
731 | 719 | ||
732 | ltq_port->tx_irq = irqres[0].start; | 720 | ltq_port->tx_irq = tx_irq; |
733 | ltq_port->rx_irq = irqres[1].start; | 721 | ltq_port->rx_irq = rx_irq; |
734 | ltq_port->err_irq = irqres[2].start; | 722 | ltq_port->err_irq = err_irq; |
735 | 723 | ||
736 | lqasc_port[line] = ltq_port; | 724 | lqasc_port[pdev->id] = ltq_port; |
737 | platform_set_drvdata(pdev, ltq_port); | 725 | platform_set_drvdata(pdev, ltq_port); |
738 | 726 | ||
739 | ret = uart_add_one_port(&lqasc_reg, port); | 727 | ret = uart_add_one_port(&lqasc_reg, port); |
@@ -741,17 +729,10 @@ lqasc_probe(struct platform_device *pdev) | |||
741 | return ret; | 729 | return ret; |
742 | } | 730 | } |
743 | 731 | ||
744 | static const struct of_device_id ltq_asc_match[] = { | ||
745 | { .compatible = DRVNAME }, | ||
746 | {}, | ||
747 | }; | ||
748 | MODULE_DEVICE_TABLE(of, ltq_asc_match); | ||
749 | |||
750 | static struct platform_driver lqasc_driver = { | 732 | static struct platform_driver lqasc_driver = { |
751 | .driver = { | 733 | .driver = { |
752 | .name = DRVNAME, | 734 | .name = DRVNAME, |
753 | .owner = THIS_MODULE, | 735 | .owner = THIS_MODULE, |
754 | .of_match_table = ltq_asc_match, | ||
755 | }, | 736 | }, |
756 | }; | 737 | }; |
757 | 738 | ||