一、UART初始化
1. kernel-3.18/drivers/misc/mediatek/uart/uart.c
static int __init mtk_uart_init(void)
{
int ret = ;
tx_history.buffer = kzalloc(UART_HISTORY_DATA_SIZE, GFP_KERNEL);
rx_history.buffer = kzalloc(UART_HISTORY_DATA_SIZE, GFP_KERNEL);
tx_history.index = -;
rx_history.index = -;
if (!tx_history.buffer || !rx_history.buffer)
return -ENOMEM;
#ifndef CONFIG_MTK_SERIAL_CONSOLE
mtk_uart_init_ports();
#endif
#if defined(ENABLE_SYSFS)
mtk_uart_sysfs();
#endif
ret = uart_register_driver(&mtk_uart_drv);
if (ret)
return ret;
ret = platform_driver_register(&mtk_uart_dev_drv);
if (ret) {
uart_unregister_driver(&mtk_uart_drv);
return ret;
}
#ifdef CONFIG_PM
mtk_uart_init_ops();
#endif
#ifdef ENABLE_RAW_DATA_DUMP
mtk_uart_init_debug_spinlock();
#endif
spin_lock_init(&mtk_uart_bt_lock);
return ret;
}
第 21 行调用 uart_register_driver 函数注册 mtk_uart_drv。
mtk_uart_drv 结构如下:
static struct uart_driver mtk_uart_drv = {
.owner = THIS_MODULE,
.driver_name = DRV_NAME,
.dev_name = "ttyMT",
.major = UART_MAJOR,
.minor = UART_MINOR,
.nr = UART_NR,
#if defined(CONFIG_MTK_SERIAL_CONSOLE) && !defined(CONFIG_MTK_SERIAL_MODEM_TEST)
.cons = &mtk_uart_console,
#endif
};
static struct console mtk_uart_console = {
.name = "ttyMT",
#if !defined(CONFIG_MTK_SERIAL_MODEM_TEST)
/*don't configure UART4 as console */
.write = mtk_uart_console_write,
.setup = mtk_uart_console_setup,
#endif
.device = uart_console_device,
.flags = CON_PRINTBUFFER,
.index = -,
.data = &mtk_uart_drv,
};
uart_register_driver 函数定义在 kernel-3.18/drivers/tty/serial/serial_core.c 文件中,
/**
* uart_register_driver - register a driver with the uart core layer
* @drv: low level driver structure
*
* Register a uart driver with the core driver. We in turn register
* with the tty layer, and initialise the core driver per-port state.
*
* We have a proc file in /proc/tty/driver which is named after the
* normal driver.
*
* drv->port should be NULL, and the per-port structures should be
* registered using uart_add_one_port after this call has succeeded.
*/
int uart_register_driver(struct uart_driver *drv)
{
struct tty_driver *normal;
int i, retval;
BUG_ON(drv->state);
/*
* Maybe we should be using a slab cache for this, especially if
* we have a large number of ports to handle.
*/
drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
if (!drv->state)
goto out;
normal = alloc_tty_driver(drv->nr);
if (!normal)
goto out_kfree;
drv->tty_driver = normal;
normal->driver_name = drv->driver_name;
normal->name = drv->dev_name;
normal->major = drv->major;
normal->minor_start = drv->minor;
normal->type = TTY_DRIVER_TYPE_SERIAL;
normal->subtype = SERIAL_TYPE_NORMAL;
normal->init_termios = tty_std_termios;
normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
normal-