博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
am335x uart分析
阅读量:6243 次
发布时间:2019-06-22

本文共 20414 字,大约阅读时间需要 68 分钟。

/************************************************************ *                  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();  --+    ......               |}                        |                         |                         Vstatic void setup_xxx_xxxx(void){    /*which doesn't have Write Protect pin LAN8710A_PHY_ID */    am335x_mmc[0].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 = 0; 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 = 0; 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, 0, 0},                                              |};                                                             |                                                               |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 = 0; 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, 0},};drivers/tty/serial/omap-serial.cstatic int __init serial_omap_init(void){ int ret; ret = uart_register_driver(&serial_omap_reg); -------+ if (ret != 0) | return ret; | ret = platform_driver_register(&serial_omap_driver); --+ | if (ret != 0) | | 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 = -1, | .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 = 2; up->port.fifosize = 64; 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 < 0) { | 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 = 1; | 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 != 0) | | goto do_release_region; | | | | pm_runtime_put(&pdev->dev); | | platform_set_drvdata(pdev, up); | | return 0; | |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 = 0; 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 = -1; 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, 1); | device_set_wakeup_enable(tty_dev, 0); | } 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[64]; 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);}

 

你可能感兴趣的文章
一台电脑同时运行多个tomcat配置方法
查看>>
让文本框只能输入数字
查看>>
pwnable.kr 之 passcode write up
查看>>
多任务之协程浅谈
查看>>
Qt Creator快捷键
查看>>
idea中lombok的使用
查看>>
网站集成支付宝在线支付
查看>>
mac下安装appium
查看>>
js ---- 函数防抖
查看>>
js call 和 apply
查看>>
CentOS 6.5下Percona Xtrabackup的安装错误解决方案
查看>>
VCS双机+oracle 11gR2+ASM主机名修改
查看>>
转:// LINUX下为ORACLE数据库设置大页--hugepage
查看>>
Linux文件权限与属性详解 之 chattr & lsattr
查看>>
负载均衡集群之LVS配置命令
查看>>
PHP使用文件流下载文件方法(附:解决下载文件内容乱码问题)
查看>>
多线程编程
查看>>
再谈谈数学
查看>>
Scheme来实现八皇后问题(1)
查看>>
pip或者anacnda安装opencv以及opencv-contrib
查看>>