aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/Kconfig9
-rw-r--r--drivers/serial/s3c2410.c143
-rw-r--r--drivers/serial/sunhv.c35
-rw-r--r--drivers/serial/sunsab.c12
-rw-r--r--drivers/serial/sunsu.c4
-rw-r--r--drivers/serial/sunzilog.c2
6 files changed, 175 insertions, 30 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index bef4a9622ed7..5b48ac22c9c5 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -354,21 +354,24 @@ config SERIAL_CLPS711X_CONSOLE
354 kernel at boot time.) 354 kernel at boot time.)
355 355
356config SERIAL_S3C2410 356config SERIAL_S3C2410
357 tristate "Samsung S3C2410 Serial port support" 357 tristate "Samsung S3C2410/S3C2440/S3C2442/S3C2412 Serial port support"
358 depends on ARM && ARCH_S3C2410 358 depends on ARM && ARCH_S3C2410
359 select SERIAL_CORE 359 select SERIAL_CORE
360 help 360 help
361 Support for the on-chip UARTs on the Samsung S3C2410X CPU, 361 Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
362 providing /dev/ttySAC0, 1 and 2 (note, some machines may not 362 providing /dev/ttySAC0, 1 and 2 (note, some machines may not
363 provide all of these ports, depending on how the serial port 363 provide all of these ports, depending on how the serial port
364 pins are configured. 364 pins are configured.
365 365
366 Currently this driver supports the UARTS on the S3C2410, S3C2440,
367 S3C2442, S3C2412 and S3C2413 CPUs.
368
366config SERIAL_S3C2410_CONSOLE 369config SERIAL_S3C2410_CONSOLE
367 bool "Support for console on S3C2410 serial port" 370 bool "Support for console on S3C2410 serial port"
368 depends on SERIAL_S3C2410=y 371 depends on SERIAL_S3C2410=y
369 select SERIAL_CORE_CONSOLE 372 select SERIAL_CORE_CONSOLE
370 help 373 help
371 Allow selection of the S3C2410 on-board serial ports for use as 374 Allow selection of the S3C24XX on-board serial ports for use as
372 an virtual console. 375 an virtual console.
373 376
374 Even if you say Y here, the currently visible virtual console 377 Even if you say Y here, the currently visible virtual console
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 53c2465bad2d..837b6da520b3 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -872,6 +872,8 @@ static const char *s3c24xx_serial_type(struct uart_port *port)
872 return "S3C2410"; 872 return "S3C2410";
873 case PORT_S3C2440: 873 case PORT_S3C2440:
874 return "S3C2440"; 874 return "S3C2440";
875 case PORT_S3C2412:
876 return "S3C2412";
875 default: 877 default:
876 return NULL; 878 return NULL;
877 } 879 }
@@ -1528,6 +1530,141 @@ static inline void s3c2440_serial_exit(void)
1528#define s3c2440_uart_inf_at NULL 1530#define s3c2440_uart_inf_at NULL
1529#endif /* CONFIG_CPU_S3C2440 */ 1531#endif /* CONFIG_CPU_S3C2440 */
1530 1532
1533#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
1534
1535static int s3c2412_serial_setsource(struct uart_port *port,
1536 struct s3c24xx_uart_clksrc *clk)
1537{
1538 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1539
1540 ucon &= ~S3C2412_UCON_CLKMASK;
1541
1542 if (strcmp(clk->name, "uclk") == 0)
1543 ucon |= S3C2440_UCON_UCLK;
1544 else if (strcmp(clk->name, "pclk") == 0)
1545 ucon |= S3C2440_UCON_PCLK;
1546 else if (strcmp(clk->name, "usysclk") == 0)
1547 ucon |= S3C2412_UCON_USYSCLK;
1548 else {
1549 printk(KERN_ERR "unknown clock source %s\n", clk->name);
1550 return -EINVAL;
1551 }
1552
1553 wr_regl(port, S3C2410_UCON, ucon);
1554 return 0;
1555}
1556
1557
1558static int s3c2412_serial_getsource(struct uart_port *port,
1559 struct s3c24xx_uart_clksrc *clk)
1560{
1561 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1562
1563 switch (ucon & S3C2412_UCON_CLKMASK) {
1564 case S3C2412_UCON_UCLK:
1565 clk->divisor = 1;
1566 clk->name = "uclk";
1567 break;
1568
1569 case S3C2412_UCON_PCLK:
1570 case S3C2412_UCON_PCLK2:
1571 clk->divisor = 1;
1572 clk->name = "pclk";
1573 break;
1574
1575 case S3C2412_UCON_USYSCLK:
1576 clk->divisor = 1;
1577 clk->name = "usysclk";
1578 break;
1579 }
1580
1581 return 0;
1582}
1583
1584static int s3c2412_serial_resetport(struct uart_port *port,
1585 struct s3c2410_uartcfg *cfg)
1586{
1587 unsigned long ucon = rd_regl(port, S3C2410_UCON);
1588
1589 dbg("%s: port=%p (%08lx), cfg=%p\n",
1590 __FUNCTION__, port, port->mapbase, cfg);
1591
1592 /* ensure we don't change the clock settings... */
1593
1594 ucon &= S3C2412_UCON_CLKMASK;
1595
1596 wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
1597 wr_regl(port, S3C2410_ULCON, cfg->ulcon);
1598
1599 /* reset both fifos */
1600
1601 wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
1602 wr_regl(port, S3C2410_UFCON, cfg->ufcon);
1603
1604 return 0;
1605}
1606
1607static struct s3c24xx_uart_info s3c2412_uart_inf = {
1608 .name = "Samsung S3C2412 UART",
1609 .type = PORT_S3C2412,
1610 .fifosize = 64,
1611 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
1612 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
1613 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
1614 .tx_fifofull = S3C2440_UFSTAT_TXFULL,
1615 .tx_fifomask = S3C2440_UFSTAT_TXMASK,
1616 .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
1617 .get_clksrc = s3c2412_serial_getsource,
1618 .set_clksrc = s3c2412_serial_setsource,
1619 .reset_port = s3c2412_serial_resetport,
1620};
1621
1622/* device management */
1623
1624static int s3c2412_serial_probe(struct platform_device *dev)
1625{
1626 dbg("s3c2440_serial_probe: dev=%p\n", dev);
1627 return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
1628}
1629
1630static struct platform_driver s3c2412_serial_drv = {
1631 .probe = s3c2412_serial_probe,
1632 .remove = s3c24xx_serial_remove,
1633 .suspend = s3c24xx_serial_suspend,
1634 .resume = s3c24xx_serial_resume,
1635 .driver = {
1636 .name = "s3c2412-uart",
1637 .owner = THIS_MODULE,
1638 },
1639};
1640
1641
1642static inline int s3c2412_serial_init(void)
1643{
1644 return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf);
1645}
1646
1647static inline void s3c2412_serial_exit(void)
1648{
1649 platform_driver_unregister(&s3c2412_serial_drv);
1650}
1651
1652#define s3c2412_uart_inf_at &s3c2412_uart_inf
1653#else
1654
1655static inline int s3c2412_serial_init(void)
1656{
1657 return 0;
1658}
1659
1660static inline void s3c2412_serial_exit(void)
1661{
1662}
1663
1664#define s3c2412_uart_inf_at NULL
1665#endif /* CONFIG_CPU_S3C2440 */
1666
1667
1531/* module initialisation code */ 1668/* module initialisation code */
1532 1669
1533static int __init s3c24xx_serial_modinit(void) 1670static int __init s3c24xx_serial_modinit(void)
@@ -1542,6 +1679,7 @@ static int __init s3c24xx_serial_modinit(void)
1542 1679
1543 s3c2400_serial_init(); 1680 s3c2400_serial_init();
1544 s3c2410_serial_init(); 1681 s3c2410_serial_init();
1682 s3c2412_serial_init();
1545 s3c2440_serial_init(); 1683 s3c2440_serial_init();
1546 1684
1547 return 0; 1685 return 0;
@@ -1551,6 +1689,7 @@ static void __exit s3c24xx_serial_modexit(void)
1551{ 1689{
1552 s3c2400_serial_exit(); 1690 s3c2400_serial_exit();
1553 s3c2410_serial_exit(); 1691 s3c2410_serial_exit();
1692 s3c2412_serial_exit();
1554 s3c2440_serial_exit(); 1693 s3c2440_serial_exit();
1555 1694
1556 uart_unregister_driver(&s3c24xx_uart_drv); 1695 uart_unregister_driver(&s3c24xx_uart_drv);
@@ -1773,6 +1912,8 @@ static int s3c24xx_serial_initconsole(void)
1773 info = s3c2410_uart_inf_at; 1912 info = s3c2410_uart_inf_at;
1774 } else if (strcmp(dev->name, "s3c2440-uart") == 0) { 1913 } else if (strcmp(dev->name, "s3c2440-uart") == 0) {
1775 info = s3c2440_uart_inf_at; 1914 info = s3c2440_uart_inf_at;
1915 } else if (strcmp(dev->name, "s3c2412-uart") == 0) {
1916 info = s3c2412_uart_inf_at;
1776 } else { 1917 } else {
1777 printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name); 1918 printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
1778 return 0; 1919 return 0;
@@ -1796,4 +1937,4 @@ console_initcall(s3c24xx_serial_initconsole);
1796 1937
1797MODULE_LICENSE("GPL"); 1938MODULE_LICENSE("GPL");
1798MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 1939MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1799MODULE_DESCRIPTION("Samsung S3C2410/S3C2440 Serial port driver"); 1940MODULE_DESCRIPTION("Samsung S3C2410/S3C2440/S3C2412 Serial port driver");
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index f137804b3133..ba22e256c6f7 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -427,31 +427,32 @@ static int __init hv_console_compatible(char *buf, int len)
427 427
428static unsigned int __init get_interrupt(void) 428static unsigned int __init get_interrupt(void)
429{ 429{
430 const char *cons_str = "console"; 430 struct device_node *dev_node;
431 const char *compat_str = "compatible";
432 int node = prom_getchild(sun4v_vdev_root);
433 char buf[64];
434 int err, len;
435
436 node = prom_searchsiblings(node, cons_str);
437 if (!node)
438 return 0;
439 431
440 len = prom_getproplen(node, compat_str); 432 dev_node = sun4v_vdev_root->child;
441 if (len == 0 || len == -1) 433 while (dev_node != NULL) {
442 return 0; 434 struct property *prop;
443 435
444 err = prom_getproperty(node, compat_str, buf, 64); 436 if (strcmp(dev_node->name, "console"))
445 if (err == -1) 437 goto next_sibling;
446 return 0; 438
439 prop = of_find_property(dev_node, "compatible", NULL);
440 if (!prop)
441 goto next_sibling;
447 442
448 if (!hv_console_compatible(buf, len)) 443 if (hv_console_compatible(prop->value, prop->length))
444 break;
445
446 next_sibling:
447 dev_node = dev_node->sibling;
448 }
449 if (!dev_node)
449 return 0; 450 return 0;
450 451
451 /* Ok, the this is the OBP node for the sun4v hypervisor 452 /* Ok, the this is the OBP node for the sun4v hypervisor
452 * console device. Decode the interrupt. 453 * console device. Decode the interrupt.
453 */ 454 */
454 return sun4v_vdev_device_interrupt(node); 455 return sun4v_vdev_device_interrupt(dev_node);
455} 456}
456 457
457static int __init sunhv_init(void) 458static int __init sunhv_init(void)
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index bfbe9dc90cca..e4c0fd2d6a9d 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -984,19 +984,19 @@ static void __init for_each_sab_edev(void (*callback)(struct linux_ebus_device *
984 984
985 for_each_ebus(ebus) { 985 for_each_ebus(ebus) {
986 for_each_ebusdev(edev, ebus) { 986 for_each_ebusdev(edev, ebus) {
987 if (!strcmp(edev->prom_name, "se")) { 987 if (!strcmp(edev->prom_node->name, "se")) {
988 callback(edev, arg); 988 callback(edev, arg);
989 continue; 989 continue;
990 } else if (!strcmp(edev->prom_name, "serial")) { 990 } else if (!strcmp(edev->prom_node->name, "serial")) {
991 char compat[32]; 991 char *compat;
992 int clen; 992 int clen;
993 993
994 /* On RIO this can be an SE, check it. We could 994 /* On RIO this can be an SE, check it. We could
995 * just check ebus->is_rio, but this is more portable. 995 * just check ebus->is_rio, but this is more portable.
996 */ 996 */
997 clen = prom_getproperty(edev->prom_node, "compatible", 997 compat = of_get_property(edev->prom_node,
998 compat, sizeof(compat)); 998 "compatible", &clen);
999 if (clen > 0) { 999 if (compat && clen > 0) {
1000 if (strncmp(compat, "sab82532", 8) == 0) { 1000 if (strncmp(compat, "sab82532", 8) == 0) {
1001 callback(edev, arg); 1001 callback(edev, arg);
1002 continue; 1002 continue;
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 4cdb610cdd37..0268b307c01e 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1053,7 +1053,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
1053 */ 1053 */
1054 for_each_ebus(ebus) { 1054 for_each_ebus(ebus) {
1055 for_each_ebusdev(dev, ebus) { 1055 for_each_ebusdev(dev, ebus) {
1056 if (dev->prom_node == up->port_node) { 1056 if (dev->prom_node->node == up->port_node) {
1057 /* 1057 /*
1058 * The EBus is broken on sparc; it delivers 1058 * The EBus is broken on sparc; it delivers
1059 * virtual addresses in resources. Oh well... 1059 * virtual addresses in resources. Oh well...
@@ -1073,7 +1073,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up)
1073#ifdef CONFIG_SPARC64 1073#ifdef CONFIG_SPARC64
1074 for_each_isa(isa_br) { 1074 for_each_isa(isa_br) {
1075 for_each_isadev(isa_dev, isa_br) { 1075 for_each_isadev(isa_dev, isa_br) {
1076 if (isa_dev->prom_node == up->port_node) { 1076 if (isa_dev->prom_node->node == up->port_node) {
1077 /* Same on sparc64. Cool architecure... */ 1077 /* Same on sparc64. Cool architecure... */
1078 up->port.membase = (char *) isa_dev->resource.start; 1078 up->port.membase = (char *) isa_dev->resource.start;
1079 up->port.mapbase = isa_dev->resource.start; 1079 up->port.mapbase = isa_dev->resource.start;
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 5b6569728a9c..76c9bac9271f 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1106,7 +1106,7 @@ static struct zilog_layout __iomem * __init get_zs_sun4u(int chip, int zsnode)
1106 + FHC_UREGS_ICLR; 1106 + FHC_UREGS_ICLR;
1107 imap = central_bus->child->fhc_regs.uregs 1107 imap = central_bus->child->fhc_regs.uregs
1108 + FHC_UREGS_IMAP; 1108 + FHC_UREGS_IMAP;
1109 zilog_irq = build_irq(12, 0, iclr, imap); 1109 zilog_irq = build_irq(0, iclr, imap);
1110 } else { 1110 } else {
1111 err = prom_getproperty(zsnode, "interrupts", 1111 err = prom_getproperty(zsnode, "interrupts",
1112 (char *) &sun4u_ino, 1112 (char *) &sun4u_ino,