⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c2410.c.txt

📁 本源码是对三星S3C24xx系列的UART的驱动程序.
💻 TXT
📖 第 1 页 / 共 5 页
字号:
1445         return 0;
1446 }
1447 
1448 static int s3c2440_serial_resetport(struct uart_port *port,
1449                                     struct s3c2410_uartcfg *cfg)
1450 {
1451         unsigned long ucon = rd_regl(port, S3C2410_UCON);
1452 
1453         dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n",
1454             port, port->mapbase, cfg);
1455 
1456         /* ensure we don't change the clock settings... */
1457 
1458         ucon &= (S3C2440_UCON0_DIVMASK | (3<<10));
1459 
1460         wr_regl(port, S3C2410_UCON,  ucon | cfg->ucon);
1461         wr_regl(port, S3C2410_ULCON, cfg->ulcon);
1462 
1463         /* reset both fifos */
1464 
1465         wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
1466         wr_regl(port, S3C2410_UFCON, cfg->ufcon);
1467 
1468         return 0;
1469 }
1470 
1471 static struct s3c24xx_uart_info s3c2440_uart_inf = {
1472         .name           = "Samsung S3C2440 UART",
1473         .type           = PORT_S3C2440,
1474         .fifosize       = 64,
1475         .rx_fifomask    = S3C2440_UFSTAT_RXMASK,
1476         .rx_fifoshift   = S3C2440_UFSTAT_RXSHIFT,
1477         .rx_fifofull    = S3C2440_UFSTAT_RXFULL,
1478         .tx_fifofull    = S3C2440_UFSTAT_TXFULL,
1479         .tx_fifomask    = S3C2440_UFSTAT_TXMASK,
1480         .tx_fifoshift   = S3C2440_UFSTAT_TXSHIFT,
1481         .get_clksrc     = s3c2440_serial_getsource,
1482         .set_clksrc     = s3c2440_serial_setsource,
1483         .reset_port     = s3c2440_serial_resetport,
1484 };
1485 
1486 /* device management */
1487 
1488 static int s3c2440_serial_probe(struct platform_device *dev)
1489 {
1490         dbg("s3c2440_serial_probe: dev=%p\n", dev);
1491         return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
1492 }
1493 
1494 static struct platform_driver s3c2440_serial_drv = {
1495         .probe          = s3c2440_serial_probe,
1496         .remove         = s3c24xx_serial_remove,
1497         .suspend        = s3c24xx_serial_suspend,
1498         .resume         = s3c24xx_serial_resume,
1499         .driver         = {
1500                 .name   = "s3c2440-uart",
1501                 .owner  = THIS_MODULE,
1502         },
1503 };
1504 
1505 
1506 static inline int s3c2440_serial_init(void)
1507 {
1508         return s3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf);
1509 }
1510 
1511 static inline void s3c2440_serial_exit(void)
1512 {
1513         platform_driver_unregister(&s3c2440_serial_drv);
1514 }
1515 
1516 #define s3c2440_uart_inf_at &s3c2440_uart_inf
1517 #else
1518 
1519 static inline int s3c2440_serial_init(void)
1520 {
1521         return 0;
1522 }
1523 
1524 static inline void s3c2440_serial_exit(void)
1525 {
1526 }
1527 
1528 #define s3c2440_uart_inf_at NULL
1529 #endif /* CONFIG_CPU_S3C2440 */
1530 
1531 /* module initialisation code */
1532 
1533 static int __init s3c24xx_serial_modinit(void)
1534 {
1535         int ret;
1536 
1537         ret = uart_register_driver(&s3c24xx_uart_drv);
1538         if (ret < 0) {
1539                 printk(KERN_ERR "failed to register UART driver\n");
1540                 return -1;
1541         }
1542 
1543         s3c2400_serial_init();
1544         s3c2410_serial_init();
1545         s3c2440_serial_init();
1546 
1547         return 0;
1548 }
1549 
1550 static void __exit s3c24xx_serial_modexit(void)
1551 {
1552         s3c2400_serial_exit();
1553         s3c2410_serial_exit();
1554         s3c2440_serial_exit();
1555 
1556         uart_unregister_driver(&s3c24xx_uart_drv);
1557 }
1558 
1559 
1560 module_init(s3c24xx_serial_modinit);
1561 module_exit(s3c24xx_serial_modexit);
1562 
1563 /* Console code */
1564 
1565 #ifdef CONFIG_SERIAL_S3C2410_CONSOLE
1566 
1567 static struct uart_port *cons_uart;
1568 
1569 static int
1570 s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
1571 {
1572         struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
1573         unsigned long ufstat, utrstat;
1574 
1575         if (ufcon & S3C2410_UFCON_FIFOMODE) {
1576                 /* fifo mode - check ammount of data in fifo registers... */
1577 
1578                 ufstat = rd_regl(port, S3C2410_UFSTAT);
1579                 return (ufstat & info->tx_fifofull) ? 0 : 1;
1580         }
1581 
1582         /* in non-fifo mode, we go and use the tx buffer empty */
1583 
1584         utrstat = rd_regl(port, S3C2410_UTRSTAT);
1585         return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
1586 }
1587 
1588 static void
1589 s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
1590 {
1591         unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
1592         while (!s3c24xx_serial_console_txrdy(port, ufcon))
1593                 barrier();
1594         wr_regb(cons_uart, S3C2410_UTXH, ch);
1595 }
1596 
1597 static void
1598 s3c24xx_serial_console_write(struct console *co, const char *s,
1599                              unsigned int count)
1600 {
1601         uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
1602 }
1603 
1604 static void __init
1605 s3c24xx_serial_get_options(struct uart_port *port, int *baud,
1606                            int *parity, int *bits)
1607 {
1608         struct s3c24xx_uart_clksrc clksrc;
1609         struct clk *clk;
1610         unsigned int ulcon;
1611         unsigned int ucon;
1612         unsigned int ubrdiv;
1613         unsigned long rate;
1614 
1615         ulcon  = rd_regl(port, S3C2410_ULCON);
1616         ucon   = rd_regl(port, S3C2410_UCON);
1617         ubrdiv = rd_regl(port, S3C2410_UBRDIV);
1618 
1619         dbg("s3c24xx_serial_get_options: port=%p\n"
1620             "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
1621             port, ulcon, ucon, ubrdiv);
1622 
1623         if ((ucon & 0xf) != 0) {
1624                 /* consider the serial port configured if the tx/rx mode set */
1625 
1626                 switch (ulcon & S3C2410_LCON_CSMASK) {
1627                 case S3C2410_LCON_CS5:
1628                         *bits = 5;
1629                         break;
1630                 case S3C2410_LCON_CS6:
1631                         *bits = 6;
1632                         break;
1633                 case S3C2410_LCON_CS7:
1634                         *bits = 7;
1635                         break;
1636                 default:
1637                 case S3C2410_LCON_CS8:
1638                         *bits = 8;
1639                         break;
1640                 }
1641 
1642                 switch (ulcon & S3C2410_LCON_PMASK) {
1643                 case S3C2410_LCON_PEVEN:
1644                         *parity = 'e';
1645                         break;
1646 
1647                 case S3C2410_LCON_PODD:
1648                         *parity = 'o';
1649                         break;
1650 
1651                 case S3C2410_LCON_PNONE:
1652                 default:
1653                         *parity = 'n';
1654                 }
1655 
1656                 /* now calculate the baud rate */
1657 
1658                 s3c24xx_serial_getsource(port, &clksrc);
1659 
1660                 clk = clk_get(port->dev, clksrc.name);
1661                 if (!IS_ERR(clk) && clk != NULL)
1662                         rate = clk_get_rate(clk) / clksrc.divisor;
1663                 else
1664                         rate = 1;
1665 
1666 
1667                 *baud = rate / ( 16 * (ubrdiv + 1));
1668                 dbg("calculated baud %d\n", *baud);
1669         }
1670 
1671 }
1672 
1673 /* s3c24xx_serial_init_ports
1674  *
1675  * initialise the serial ports from the machine provided initialisation
1676  * data.
1677 */
1678 
1679 static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info)
1680 {
1681         struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports;
1682         struct platform_device **platdev_ptr;
1683         int i;
1684 
1685         dbg("s3c24xx_serial_init_ports: initialising ports...\n");
1686 
1687         platdev_ptr = s3c24xx_uart_devs;
1688 
1689         for (i = 0; i < NR_PORTS; i++, ptr++, platdev_ptr++) {
1690                 s3c24xx_serial_init_port(ptr, info, *platdev_ptr);
1691         }
1692 
1693         return 0;
1694 }
1695 
1696 static int __init
1697 s3c24xx_serial_console_setup(struct console *co, char *options)
1698 {
1699         struct uart_port *port;
1700         int baud = 9600;
1701         int bits = 8;
1702         int parity = 'n';
1703         int flow = 'n';
1704 
1705         dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n",
1706             co, co->index, options);
1707 
1708         /* is this a valid port */
1709 
1710         if (co->index == -1 || co->index >= NR_PORTS)
1711                 co->index = 0;
1712 
1713         port = &s3c24xx_serial_ports[co->index].port;
1714 
1715         /* is the port configured? */
1716 
1717         if (port->mapbase == 0x0) {
1718                 co->index = 0;
1719                 port = &s3c24xx_serial_ports[co->index].port;
1720         }
1721 
1722         cons_uart = port;
1723 
1724         dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index);
1725 
1726         /*
1727          * Check whether an invalid uart number has been specified, and
1728          * if so, search for the first available port that does have
1729          * console support.
1730          */
1731         if (options)
1732                 uart_parse_options(options, &baud, &parity, &bits, &flow);
1733         else
1734                 s3c24xx_serial_get_options(port, &baud, &parity, &bits);
1735 
1736         dbg("s3c24xx_serial_console_setup: baud %d\n", baud);
1737 
1738         return uart_set_options(port, co, baud, parity, bits, flow);
1739 }
1740 
1741 /* s3c24xx_serial_initconsole
1742  *
1743  * initialise the console from one of the uart drivers
1744 */
1745 
1746 static struct console s3c24xx_serial_console =
1747 {
1748         .name           = S3C24XX_SERIAL_NAME,
1749         .device         = uart_console_device,
1750         .flags          = CON_PRINTBUFFER,
1751         .index          = -1,
1752         .write          = s3c24xx_serial_console_write,
1753         .setup          = s3c24xx_serial_console_setup
1754 };
1755 
1756 static int s3c24xx_serial_initconsole(void)
1757 {
1758         struct s3c24xx_uart_info *info;
1759         struct platform_device *dev = s3c24xx_uart_devs[0];
1760 
1761         dbg("s3c24xx_serial_initconsole\n");
1762 
1763         /* select driver based on the cpu */
1764 
1765         if (dev == NULL) {
1766                 printk(KERN_ERR "s3c24xx: no devices for console init\n");
1767                 return 0;
1768         }
1769 
1770         if (strcmp(dev->name, "s3c2400-uart") == 0) {
1771                 info = s3c2400_uart_inf_at;
1772         } else if (strcmp(dev->name, "s3c2410-uart") == 0) {
1773                 info = s3c2410_uart_inf_at;
1774         } else if (strcmp(dev->name, "s3c2440-uart") == 0) {
1775                 info = s3c2440_uart_inf_at;
1776         } else {
1777                 printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
1778                 return 0;
1779         }
1780 
1781         if (info == NULL) {
1782                 printk(KERN_ERR "s3c24xx: no driver for console\n");
1783                 return 0;
1784         }
1785 
1786         s3c24xx_serial_console.data = &s3c24xx_uart_drv;
1787         s3c24xx_serial_init_ports(info);
1788 
1789         register_console(&s3c24xx_serial_console);
1790         return 0;
1791 }
1792 
1793 console_initcall(s3c24xx_serial_initconsole);
1794 
1795 #endif /* CONFIG_SERIAL_S3C2410_CONSOLE */
1796 
1797 MODULE_LICENSE("GPL");
1798 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1799 MODULE_DESCRIPTION("Samsung S3C2410/S3C2440 Serial port driver");
1800 

--------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -