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
2 files changed, 148 insertions, 4 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");