/************************************************************
* 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. C# ASCII码排序

    将字典变成post参数 public static string GetSignContent(IDictionary<string, string> parameters) { // 第 ...

  2. 常用IP核

    前言 记录自己用到的模块,随时补充. 主要分类: 一.常用模块 1-FIFO FIFO分为两种,一是输入输出时钟相同(Common clock)的 fifo ;二是输入输出时钟不相同(Independ ...

  3. Android开发8——利用pull解析器读写XML文件

    一.基本介绍 对XML解析有SAX和DOM等多种方式,Android中极力推荐xmlpull方式解析xml.xmlpull不仅可用在Android上同样也适用于javase,但在javase环境中需自 ...

  4. AngularJS 使用 UI Router 实现表单向导

    Today we will be using AngularJS and the great UI Router and the Angular ngAnimate module to create ...

  5. mysqldump 备份某张表 Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions,

    [root@NB ok]# mysqldump -uemove -h xx.xx.xx.xx -P9906 DBname t_name -p >2t_tname.sqlWarning: A pa ...

  6. Angular External js library calling Document.Ready

    https://stackoverflow.com/questions/51094841/angular-external-js-library-calling-document-ready Step ...

  7. angular学习笔记(五)-阶乘计算实例(2)

    <!DOCTYPE html> <html ng-app> <head> <title>2.3.3计算阶乘实例2</title> <m ...

  8. 08、通过自定义依赖属性,用 StateTrigger 修改全局主题样式

    在 Win 10 的 UWP 中,需要在 xaml 中,通过使用 StateTrigger 修改全局的文本大小.Background.画刷等依赖属性等主题样式.下面只针对字体大小进行描述,其它依赖属性 ...

  9. git 命令删除远程分支

    删除 服务器上的分支: git push origin :sxz 分支名 注意 origin 后面的空格:

  10. poj1564-Sum It Up(经典DFS)

    给出一个n,k,再给出的n个数中,输出所有的可能使几个数的和等于k Sample Input 4 6 4 3 2 2 1 15 3 2 1 1400 12 50 50 50 50 50 50 25 2 ...