/************************************************************
* am335x uart分析
* 本文记录am335x uart驱动的注册过程。
* 参考:
* http://www.cnblogs.com/helloworldtoyou/p/5385595.html
* 涉及文件:
* arch/arm/mach-omap2/board-am335xevm.c
* drivers/tty/serial/omap-serial.c
*
* Tony Liu, 2016-5-2, Shenzhen
***********************************************************/ MACHINE_START(AM335XEVM, "am335xevm")
/* Maintainer: Texas Instruments */
.atag_offset = 0x100,
.map_io = am335x_evm_map_io,
.init_early = am33xx_init_early,
.init_irq = ti81xx_init_irq,
.handle_irq = omap3_intc_handle_irq,
.timer = &omap3_am33xx_timer,
.init_machine = am335x_evm_init, ---+
MACHINE_END |
|
static void __init am335x_evm_init(void) <--+
{
am33xx_cpuidle_init();
am33xx_mux_init(board_mux);
omap_serial_init();
am335x_evm_i2c_init();
omap_sdrc_init(NULL, NULL);
usb_musb_init(&musb_board_data); omap_board_config = am335x_evm_config;
omap_board_config_size = ARRAY_SIZE(am335x_evm_config); daughter_brd_detected = false;
setup_xxx_xxxx(); --+
...... |
} |
|
V
static void setup_xxx_xxxx(void)
{
/*which doesn't have Write Protect pin LAN8710A_PHY_ID */
am335x_mmc[].gpio_wp = -EINVAL; int ret; //配置引脚复用
_configure_device(EVM_SK, xxx_xxxx_dev_cfg, PROFILE_NONE); -----+
| |
} | |
V |
static void _configure_device(int evm_id, struct evm_dev_cfg *dev_cfg, |
int profile) |
{ |
int i; |
|
am335x_evm_set_id(evm_id); |
|
if (profile == PROFILE_NONE) { |
for (i = ; dev_cfg->device_init != NULL; dev_cfg++) { |
if (dev_cfg->device_on == DEV_ON_BASEBOARD) |
dev_cfg->device_init(evm_id, profile); |
else if (daughter_brd_detected == true) |
dev_cfg->device_init(evm_id, profile); |
} |
} else { |
for (i = ; dev_cfg->device_init != NULL; dev_cfg++) { |
if (dev_cfg->profile & profile) { |
if (dev_cfg->device_on == DEV_ON_BASEBOARD) |
dev_cfg->device_init(evm_id, profile); |
else if (daughter_brd_detected == true) |
dev_cfg->device_init(evm_id, profile); |
} |
} |
} |
} |
|
static struct evm_dev_cfg xxx_xxxx_dev_cfg[] = { <--------+
......
{uart0_init, DEV_ON_BASEBOARD, PROFILE_ALL},//fixed ---+
{uart1_init, DEV_ON_BASEBOARD, PROFILE_ALL},//fixed |
{uart4_init, DEV_ON_BASEBOARD, PROFILE_ALL},//fixed |
...... |
{NULL, , }, |
}; |
|
static void uart0_init(int evm_id, int profile) <---+
{
setup_pin_mux(uart0_pin_mux); ------+
return; | |
} | |
V |
static void setup_pin_mux(struct pinmux_config *pin_mux) |
{ |
int i; |
|
for (i = ; pin_mux->string_name != NULL; pin_mux++) |
omap_mux_init_signal(pin_mux->string_name, pin_mux->val); |
} |
|
static struct pinmux_config uart0_pin_mux[] = { <-----+
{"uart0_rxd.uart0_rxd", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
{"uart0_txd.uart0_txd", OMAP_MUX_MODE0 | AM33XX_PULL_ENBL},
{"uart0_ctsn.uart0_ctsn", OMAP_MUX_MODE0 | AM33XX_PULL_ENBL},
{NULL, },
}; drivers/tty/serial/omap-serial.c
static int __init serial_omap_init(void)
{
int ret; ret = uart_register_driver(&serial_omap_reg); -------+
if (ret != ) |
return ret; |
ret = platform_driver_register(&serial_omap_driver); --+ |
if (ret != ) | |
uart_unregister_driver(&serial_omap_reg); | |
return ret; | |
} | |
| |
static struct uart_driver serial_omap_reg = { | |
.owner = THIS_MODULE, | |
.driver_name = "OMAP-SERIAL", | |
.dev_name = OMAP_SERIAL_NAME, | |
.nr = OMAP_MAX_HSUART_PORTS, | |
.cons = OMAP_CONSOLE, | |
}; | |
| |
#define OMAP_SERIAL_NAME "ttyO" | |
#define OMAP_MAX_HSUART_PORTS 6 | |
| |
#define OMAP_CONSOLE (&serial_omap_console) | |
| |
static struct console serial_omap_console = { | <------+
.name = OMAP_SERIAL_NAME, |
.write = serial_omap_console_write, |
.device = uart_console_device, |
.setup = serial_omap_console_setup, |
.flags = CON_PRINTBUFFER, |
.index = -, |
.data = &serial_omap_reg, |
}; |
|
static struct platform_driver serial_omap_driver = { <--+
.probe = serial_omap_probe,
.remove = serial_omap_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &serial_omap_dev_pm_ops,
.of_match_table = of_match_ptr(omap_serial_of_match),
},
}; static int serial_omap_probe(struct platform_device *pdev)
{
struct uart_omap_port *up;
struct resource *mem, *irq, *dma_tx, *dma_rx;
struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
int ret = -ENOSPC; if (pdev->dev.of_node)
omap_up_info = of_get_uart_port_info(&pdev->dev); ......
up->pdev = pdev;
up->port.dev = &pdev->dev;
up->port.type = PORT_OMAP;
up->port.iotype = UPIO_MEM;
up->port.irq = irq->start; up->port.regshift = ;
up->port.fifosize = ;
up->port.ops = &serial_omap_pops; --------+
|
if (pdev->dev.of_node) |
up->port.line = of_alias_get_id(pdev->dev.of_node, "serial"); |
else |
up->port.line = pdev->id; |
|
if (up->port.line < ) { |
dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", |
up->port.line); |
ret = -ENODEV; |
goto err; |
} |
|
sprintf(up->name, "OMAP UART%d", up->port.line); |
up->port.mapbase = mem->start; |
up->port.membase = ioremap(mem->start, resource_size(mem)); |
if (!up->port.membase) { |
dev_err(&pdev->dev, "can't ioremap UART\n"); |
ret = -ENOMEM; |
goto err; |
} |
|
up->port.flags = omap_up_info->flags; |
up->port.uartclk = omap_up_info->uartclk; |
if (!up->port.uartclk) { |
up->port.uartclk = DEFAULT_CLK_SPEED; |
dev_warn(&pdev->dev, "No clock speed specified: using default:" |
"%d\n", DEFAULT_CLK_SPEED); |
} |
up->uart_dma.uart_base = mem->start; |
up->errata = omap_up_info->errata; |
|
if (omap_up_info->dma_enabled) { |
up->uart_dma.uart_dma_tx = dma_tx->start; |
up->uart_dma.uart_dma_rx = dma_rx->start; |
up->use_dma = ; |
up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size; |
up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout; |
up->uart_dma.rx_poll_rate = omap_up_info->dma_rx_poll_rate; |
spin_lock_init(&(up->uart_dma.tx_lock)); |
spin_lock_init(&(up->uart_dma.rx_lock)); |
up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; |
up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; |
} |
|
up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; |
up->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; |
pm_qos_add_request(&up->pm_qos_request, |
PM_QOS_CPU_DMA_LATENCY, up->latency); |
serial_omap_uart_wq = create_singlethread_workqueue(up->name); |
INIT_WORK(&up->qos_work, serial_omap_uart_qos_work); |
|
pm_runtime_use_autosuspend(&pdev->dev); |
pm_runtime_set_autosuspend_delay(&pdev->dev, |
omap_up_info->autosuspend_timeout); |
|
pm_runtime_irq_safe(&pdev->dev); |
pm_runtime_enable(&pdev->dev); |
pm_runtime_get_sync(&pdev->dev); |
|
ui[up->port.line] = up; |
serial_omap_add_console_port(up); |
|
ret = uart_add_one_port(&serial_omap_reg, &up->port); --------------+ |
if (ret != ) | |
goto do_release_region; | |
| |
pm_runtime_put(&pdev->dev); | |
platform_set_drvdata(pdev, up); | |
return ; | |
err: | |
dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n", | |
pdev->id, __func__, ret); | |
do_release_region: | |
release_mem_region(mem->start, resource_size(mem)); | |
return ret; | |
} | |
| |
static struct uart_ops serial_omap_pops = { <--------|--+
.tx_empty = serial_omap_tx_empty, |
.set_mctrl = serial_omap_set_mctrl, |
.get_mctrl = serial_omap_get_mctrl, |
.stop_tx = serial_omap_stop_tx, |
.start_tx = serial_omap_start_tx, |
.stop_rx = serial_omap_stop_rx, |
.enable_ms = serial_omap_enable_ms, |
.break_ctl = serial_omap_break_ctl, |
.startup = serial_omap_startup, |
.shutdown = serial_omap_shutdown, |
.set_termios = serial_omap_set_termios, |
.pm = serial_omap_pm, |
.type = serial_omap_type, |
.release_port = serial_omap_release_port, |
.request_port = serial_omap_request_port, |
.config_port = serial_omap_config_port, |
.verify_port = serial_omap_verify_port, |
#ifdef CONFIG_CONSOLE_POLL |
.poll_put_char = serial_omap_poll_put_char, |
.poll_get_char = serial_omap_poll_get_char, |
#endif |
}; |
|
int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) <-+
{
struct uart_state *state;
struct tty_port *port;
int ret = ;
struct device *tty_dev; BUG_ON(in_interrupt()); if (uport->line >= drv->nr)
return -EINVAL; state = drv->state + uport->line;
port = &state->port; mutex_lock(&port_mutex);
mutex_lock(&port->mutex);
if (state->uart_port) {
ret = -EINVAL;
goto out;
} state->uart_port = uport;
state->pm_state = -; uport->cons = drv->cons;
uport->state = state; /*
* If this port is a console, then the spinlock is already
* initialised.
*/
if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) {
spin_lock_init(&uport->lock);
lockdep_set_class(&uport->lock, &port_lock_key);
} uart_configure_port(drv, state, uport); /*
* Register the port whether it's detected or not. This allows
* setserial to be used to alter this ports parameters.
*/
tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev); -----+
if (likely(!IS_ERR(tty_dev))) { |
device_init_wakeup(tty_dev, ); |
device_set_wakeup_enable(tty_dev, ); |
} else |
printk(KERN_ERR "Cannot register tty device on line %d\n", |
uport->line); |
|
/* |
* Ensure UPF_DEAD is not set. |
*/ |
uport->flags &= ~UPF_DEAD; |
|
out: |
mutex_unlock(&port->mutex); |
mutex_unlock(&port_mutex); |
|
return ret; |
} |
|
struct device *tty_register_device(struct tty_driver *driver, unsigned index, <---+
struct device *device)
{
char name[];
dev_t dev = MKDEV(driver->major, driver->minor_start) + index; if (index >= driver->num) {
printk(KERN_ERR "Attempt to register invalid tty line number "
" (%d).\n", index);
return ERR_PTR(-EINVAL);
} if (driver->type == TTY_DRIVER_TYPE_PTY)
pty_line_name(driver, index, name);
else
tty_line_name(driver, index, name); ---+
|
return device_create(tty_class, device, dev, NULL, name); |
} |
// 设备名 |
static void tty_line_name(struct tty_driver *driver, int index, char *p) <--+
{
sprintf(p, "%s%d", driver->name, index + driver->name_base);
}

am335x uart分析的更多相关文章

  1. am335x i2c分析

    /***************************************************************************** * am335x i2c分析 * i2c驱 ...

  2. z-stack协议uart分析(DMA)

    1.从ZMain里面的main函数开始分析 2.进入int main( void ); HalDriverInit();   //硬件相关初始化,有DMA初始化和UART初始化 3.进入HalDriv ...

  3. am335x gpio分析

    /************************************************************************ * am335x_gpio * 本文主要记录am33 ...

  4. imx6 uart分析

    本文主要记录: 1.uart设备注册 2.uart驱动注册 3.上层应用调用有些地方理解的还不是很透彻,希望指正. 1.uart设备注册过程 MACHINE_START(MX6Q_SABRESD, & ...

  5. AM335X UBOOT(以UART为例分析UBOOT主要流程)

    UBOOT2016.05 UART初始化及设置 SPL阶段 第一部分C函数 |- s_init //(arch/arm/cpu/armv7/am33xx/board.c) |- set_uart_mu ...

  6. am335x uboot启动流程分析

    基本指令含义 .globl _start .globl指示告诉汇编器,_start这个符号要被链接器用到,所以要在目标文件的符号表中标记它是一个全局符号 b,bl b是不带返回的跳转  bl带返回的跳 ...

  7. [tty与uart]3.tty驱动分析

    转自:http://www.wowotech.net/linux_kenrel/183.html 目录: 1 首先分析设备驱动的注册 1.1 uart_register_driver分析 1.2 tt ...

  8. [uart]3.tty驱动分析

    转自:http://www.wowotech.net/linux_kenrel/183.html 目录: 1 首先分析设备驱动的注册 1.1 uart_register_driver分析 1.2 tt ...

  9. am335x omap serial 驱动分析

    am335x 自身的 uart 驱动集成在 kernel 的 arch/arm/mach-omap2/ 里面. 文件是 arch/arm/mach-omap2/serial.c // 看到最底部 om ...

随机推荐

  1. 关于HTTP协议(未完)

    转 : https://www.cnblogs.com/ranyonsue/p/5984001.html

  2. Eclipse color theme jsp javascript显示问题

    Q: 在eclipse 中,设置为sublime格式时, 在编辑器中,jsp中嵌套的javascript底色非常难看. A:在如下位置进行设置,Window -> Preferences-> ...

  3. U3D-LookAt插值动画

    var qua = Quaternion.FromToRotation(Vector3.forward, target.transform.position - transform.position) ...

  4. C#匿名对象的使用

    单个对象 new { Inv = item.Inv, Count = item.Count } 数组 var testData = new[] { }, }, }, }, }, }, }, }, } ...

  5. AI、机器学习、深度学习、神经网络

    1.AI:人工智能(Artificial Intelligence) 2.机器学习:(Machine Learning, ML) 3.深度学习:Deep Learning 人工功能的实现是让机器自己学 ...

  6. [svc][op]ssh交互yes问题解决-expect

    Expect是Unix系统中用来进行自动化控制和测试的软件工具C67默认未安装:使用需要安装: yum install expect -ywhich expect #查看安装路径 核心命令: [roo ...

  7. 前端 JS,localStorage/sessionStorage、cookie 及 url 等实现前台数据共享、传输

    需求是这样的:需要统计用户公司某款产品用户的回馈情况,美工给的设计多个psd,每个页面里面都有一个选择题,让用户选择自己的答案,最后经过几次选择之后在最后一个页面统一提交到后台!所以这里引出的技术需求 ...

  8. 学习笔记之gethostbyname函数

    我们现在认知一台计算机主机通常采用直观可读的名字.例如博客园我们会记住 www.cnblogs.com 而不是记住42.121.252.58这个IP.对于大多数的应用程序来说应该是处理名字而不是处理地 ...

  9. 关于ajax上传文件的流程 和选择图片立即显示

    关键点: 1.制作一个表单..然后把上传字段附加到该表单中 2.制作一个框架..把表单的_target的属性指向该框架. 3.提交表单.. jQuery.extend({ createUploadIf ...

  10. Ajax的XMLHttpRequest对象的属性和方法总结

    1.redayState属性: 当一个XMLHttpRequest对象被创建后,readyState属性别哦是当前对象正处于什么状态:0:未初始化状态:已经建立:1:准备发送状态:此时XMLHttpR ...