aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/amba-pl010.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2006-03-26 17:13:39 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-03-26 17:13:39 -0500
commitfbb18a277a6f192404aa20ece49529acb1e1e76d (patch)
tree2ae2b039d05ce15ad6e0f7209877aaf918f8f24a /drivers/serial/amba-pl010.c
parent335bd9dff31d042b773591933d3ee5bd62d5ea27 (diff)
[SERIAL] amba-pl010: allow platforms to specify modem control method
The amba-pl010 hardware does not provide RTS and DTR control lines; it is expected that these will be implemented using GPIO. Allow platforms to supply a function to implement manipulation of modem control lines. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/serial/amba-pl010.c')
-rw-r--r--drivers/serial/amba-pl010.c160
1 files changed, 67 insertions, 93 deletions
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 127d6cd5de7f..1631414000a2 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -51,8 +51,6 @@
51#include <linux/amba/serial.h> 51#include <linux/amba/serial.h>
52 52
53#include <asm/io.h> 53#include <asm/io.h>
54#include <asm/irq.h>
55#include <asm/hardware.h>
56 54
57#define UART_NR 2 55#define UART_NR 2
58 56
@@ -65,26 +63,16 @@
65#define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0) 63#define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0)
66#define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0) 64#define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0)
67 65
68#define UART_DUMMY_RSR_RX /*256*/0 66#define UART_DUMMY_RSR_RX 256
69#define UART_PORT_SIZE 64 67#define UART_PORT_SIZE 64
70 68
71/* 69/*
72 * On the Integrator platform, the port RTS and DTR are provided by
73 * bits in the following SC_CTRLS register bits:
74 * RTS DTR
75 * UART0 7 6
76 * UART1 5 4
77 */
78#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
79#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
80
81/*
82 * We wrap our port structure around the generic uart_port. 70 * We wrap our port structure around the generic uart_port.
83 */ 71 */
84struct uart_amba_port { 72struct uart_amba_port {
85 struct uart_port port; 73 struct uart_port port;
86 unsigned int dtr_mask; 74 struct amba_device *dev;
87 unsigned int rts_mask; 75 struct amba_pl010_data *data;
88 unsigned int old_status; 76 unsigned int old_status;
89}; 77};
90 78
@@ -300,20 +288,9 @@ static unsigned int pl010_get_mctrl(struct uart_port *port)
300static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl) 288static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
301{ 289{
302 struct uart_amba_port *uap = (struct uart_amba_port *)port; 290 struct uart_amba_port *uap = (struct uart_amba_port *)port;
303 unsigned int ctrls = 0, ctrlc = 0;
304
305 if (mctrl & TIOCM_RTS)
306 ctrlc |= uap->rts_mask;
307 else
308 ctrls |= uap->rts_mask;
309 291
310 if (mctrl & TIOCM_DTR) 292 if (uap->data)
311 ctrlc |= uap->dtr_mask; 293 uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl);
312 else
313 ctrls |= uap->dtr_mask;
314
315 __raw_writel(ctrls, SC_CTRLS);
316 __raw_writel(ctrlc, SC_CTRLC);
317} 294}
318 295
319static void pl010_break_ctl(struct uart_port *port, int break_state) 296static void pl010_break_ctl(struct uart_port *port, int break_state)
@@ -539,38 +516,7 @@ static struct uart_ops amba_pl010_pops = {
539 .verify_port = pl010_verify_port, 516 .verify_port = pl010_verify_port,
540}; 517};
541 518
542static struct uart_amba_port amba_ports[UART_NR] = { 519static struct uart_amba_port *amba_ports[UART_NR];
543 {
544 .port = {
545 .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
546 .mapbase = INTEGRATOR_UART0_BASE,
547 .iotype = UPIO_MEM,
548 .irq = IRQ_UARTINT0,
549 .uartclk = 14745600,
550 .fifosize = 16,
551 .ops = &amba_pl010_pops,
552 .flags = UPF_BOOT_AUTOCONF,
553 .line = 0,
554 },
555 .dtr_mask = 1 << 5,
556 .rts_mask = 1 << 4,
557 },
558 {
559 .port = {
560 .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
561 .mapbase = INTEGRATOR_UART1_BASE,
562 .iotype = UPIO_MEM,
563 .irq = IRQ_UARTINT1,
564 .uartclk = 14745600,
565 .fifosize = 16,
566 .ops = &amba_pl010_pops,
567 .flags = UPF_BOOT_AUTOCONF,
568 .line = 1,
569 },
570 .dtr_mask = 1 << 7,
571 .rts_mask = 1 << 6,
572 }
573};
574 520
575#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE 521#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
576 522
@@ -588,7 +534,7 @@ static void pl010_console_putchar(struct uart_port *port, int ch)
588static void 534static void
589pl010_console_write(struct console *co, const char *s, unsigned int count) 535pl010_console_write(struct console *co, const char *s, unsigned int count)
590{ 536{
591 struct uart_port *port = &amba_ports[co->index].port; 537 struct uart_port *port = &amba_ports[co->index]->port;
592 unsigned int status, old_cr; 538 unsigned int status, old_cr;
593 539
594 /* 540 /*
@@ -651,7 +597,7 @@ static int __init pl010_console_setup(struct console *co, char *options)
651 */ 597 */
652 if (co->index >= UART_NR) 598 if (co->index >= UART_NR)
653 co->index = 0; 599 co->index = 0;
654 port = &amba_ports[co->index].port; 600 port = &amba_ports[co->index]->port;
655 601
656 if (options) 602 if (options)
657 uart_parse_options(options, &baud, &parity, &bits, &flow); 603 uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -672,24 +618,6 @@ static struct console amba_console = {
672 .data = &amba_reg, 618 .data = &amba_reg,
673}; 619};
674 620
675static int __init amba_console_init(void)
676{
677 /*
678 * All port initializations are done statically
679 */
680 register_console(&amba_console);
681 return 0;
682}
683console_initcall(amba_console_init);
684
685static int __init amba_late_console_init(void)
686{
687 if (!(amba_console.flags & CON_ENABLED))
688 register_console(&amba_console);
689 return 0;
690}
691late_initcall(amba_late_console_init);
692
693#define AMBA_CONSOLE &amba_console 621#define AMBA_CONSOLE &amba_console
694#else 622#else
695#define AMBA_CONSOLE NULL 623#define AMBA_CONSOLE NULL
@@ -707,30 +635,76 @@ static struct uart_driver amba_reg = {
707 635
708static int pl010_probe(struct amba_device *dev, void *id) 636static int pl010_probe(struct amba_device *dev, void *id)
709{ 637{
710 int i; 638 struct uart_amba_port *port;
639 void __iomem *base;
640 int i, ret;
711 641
712 for (i = 0; i < UART_NR; i++) { 642 for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
713 if (amba_ports[i].port.mapbase != dev->res.start) 643 if (amba_ports[i] == NULL)
714 continue; 644 break;
715 645
716 amba_ports[i].port.dev = &dev->dev; 646 if (i == ARRAY_SIZE(amba_ports)) {
717 uart_add_one_port(&amba_reg, &amba_ports[i].port); 647 ret = -EBUSY;
718 amba_set_drvdata(dev, &amba_ports[i]); 648 goto out;
719 break;
720 } 649 }
721 650
722 return 0; 651 port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL);
652 if (!port) {
653 ret = -ENOMEM;
654 goto out;
655 }
656
657 base = ioremap(dev->res.start, PAGE_SIZE);
658 if (!base) {
659 ret = -ENOMEM;
660 goto free;
661 }
662
663 port->port.dev = &dev->dev;
664 port->port.mapbase = dev->res.start;
665 port->port.membase = base;
666 port->port.iotype = UPIO_MEM;
667 port->port.irq = dev->irq[0];
668 port->port.uartclk = 14745600;
669 port->port.fifosize = 16;
670 port->port.ops = &amba_pl010_pops;
671 port->port.flags = UPF_BOOT_AUTOCONF;
672 port->port.line = i;
673 port->dev = dev;
674 port->data = dev->dev.platform_data;
675
676 amba_ports[i] = port;
677
678 amba_set_drvdata(dev, port);
679 ret = uart_add_one_port(&amba_reg, &port->port);
680 if (ret) {
681 amba_set_drvdata(dev, NULL);
682 amba_ports[i] = NULL;
683 iounmap(base);
684 free:
685 kfree(port);
686 }
687
688 out:
689 return ret;
723} 690}
724 691
725static int pl010_remove(struct amba_device *dev) 692static int pl010_remove(struct amba_device *dev)
726{ 693{
727 struct uart_amba_port *uap = amba_get_drvdata(dev); 694 struct uart_amba_port *port = amba_get_drvdata(dev);
728 695 int i;
729 if (uap)
730 uart_remove_one_port(&amba_reg, &uap->port);
731 696
732 amba_set_drvdata(dev, NULL); 697 amba_set_drvdata(dev, NULL);
733 698
699 uart_remove_one_port(&amba_reg, &port->port);
700
701 for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
702 if (amba_ports[i] == port)
703 amba_ports[i] = NULL;
704
705 iounmap(port->port.membase);
706 kfree(port);
707
734 return 0; 708 return 0;
735} 709}
736 710