aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/s3c2410.c
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2006-06-24 16:21:32 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-24 16:21:32 -0400
commit73e55cb3b3549d0174d1dadb755200938232e8d0 (patch)
tree041dc51100fae9a8da403a69a7d966f99c578bc9 /drivers/serial/s3c2410.c
parent736855f0c748dacb624070b8d6ffffe4532cf4dc (diff)
[ARM] 3639/1: S3C2412: serial port support
Patch from Ben Dooks Serial port support for the on-board UART blocks on the Samsung S3C2412 and S3C2413 UARTs. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/serial/s3c2410.c')
-rw-r--r--drivers/serial/s3c2410.c143
1 files changed, 142 insertions, 1 deletions
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");