aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/lantiq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/lantiq.c')
-rw-r--r--drivers/tty/serial/lantiq.c89
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
118struct ltq_uart_port { 115struct 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
397static void 387static void
@@ -640,7 +630,7 @@ lqasc_console_setup(struct console *co, char *options)
640 630
641 port = &ltq_port->port; 631 port = &ltq_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 = {
678static int __init 668static int __init
679lqasc_probe(struct platform_device *pdev) 669lqasc_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
744static const struct of_device_id ltq_asc_match[] = {
745 { .compatible = DRVNAME },
746 {},
747};
748MODULE_DEVICE_TABLE(of, ltq_asc_match);
749
750static struct platform_driver lqasc_driver = { 732static 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