aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/s3c2410.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-06-24 20:48:14 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-24 20:48:14 -0400
commitdfd8317d3340f03bc06eba6b58f0ec0861da4a13 (patch)
tree43bd5c93ad045355687c26beb0983fcf6ca18a6b /drivers/serial/s3c2410.c
parent83626b01275d0228516b4d97da008328fc37c934 (diff)
parentc0897856553d45aee1780bed455b7c2e888dd64b (diff)
Merge master.kernel.org:/home/rmk/linux-2.6-arm
* master.kernel.org:/home/rmk/linux-2.6-arm: (25 commits) [ARM] 3648/1: Update struct ucontext layout for coprocessor registers [ARM] Add identifying number for non-rt sigframe [ARM] Gather common sigframe saving code into setup_sigframe() [ARM] Gather common sigframe restoration code into restore_sigframe() [ARM] Re-use sigframe within rt_sigframe [ARM] Merge sigcontext and sigmask members of sigframe [ARM] Replace extramask with a full copy of the sigmask [ARM] Remove rt_sigframe puc and pinfo pointers [ARM] 3647/1: S3C24XX: add Osiris to the list of simtec pm machines [ARM] 3645/1: S3C2412: irq support for external interrupts [ARM] 3643/1: S3C2410: Add new usb clocks [ARM] 3642/1: S3C24XX: Add machine SMDK2413 [ARM] 3641/1: S3C2412: Fixup gpio register naming [ARM] 3640/1: S3C2412: Use S3C24XX_DCLKCON instead of S3C2410_DCLKCON [ARM] 3639/1: S3C2412: serial port support [ARM] 3638/1: S3C2412: core clocks [ARM] 3637/1: S3C24XX: Add mpll clock, and set as fclk parent [ARM] 3636/1: S3C2412: Add selection of CPU_ARM926 [ARM] 3635/1: S3C24XX: Add S3C2412 core cpu support [ARM] 3633/1: S3C24XX: s3c2410 gpio bugfix - wrong pin nos ...
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");