diff options
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/Kconfig | 9 | ||||
-rw-r--r-- | drivers/serial/s3c2410.c | 143 | ||||
-rw-r--r-- | drivers/serial/sunhv.c | 35 | ||||
-rw-r--r-- | drivers/serial/sunsab.c | 12 | ||||
-rw-r--r-- | drivers/serial/sunsu.c | 4 | ||||
-rw-r--r-- | drivers/serial/sunzilog.c | 2 |
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 | ||
356 | config SERIAL_S3C2410 | 356 | config 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 | |||
366 | config SERIAL_S3C2410_CONSOLE | 369 | config 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 | |||
1535 | static 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 | |||
1558 | static 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 | |||
1584 | static 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 | |||
1607 | static 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 | |||
1624 | static 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 | |||
1630 | static 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 | |||
1642 | static inline int s3c2412_serial_init(void) | ||
1643 | { | ||
1644 | return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf); | ||
1645 | } | ||
1646 | |||
1647 | static 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 | |||
1655 | static inline int s3c2412_serial_init(void) | ||
1656 | { | ||
1657 | return 0; | ||
1658 | } | ||
1659 | |||
1660 | static 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 | ||
1533 | static int __init s3c24xx_serial_modinit(void) | 1670 | static 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 | ||
1797 | MODULE_LICENSE("GPL"); | 1938 | MODULE_LICENSE("GPL"); |
1798 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | 1939 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); |
1799 | MODULE_DESCRIPTION("Samsung S3C2410/S3C2440 Serial port driver"); | 1940 | MODULE_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 | ||
428 | static unsigned int __init get_interrupt(void) | 428 | static 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 | ||
457 | static int __init sunhv_init(void) | 458 | static 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, |