📄 s3c2410.c.txt
字号:
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 + -