ARM-Linux s3c2440 之UART分析(三)

====本文系本站原创,欢迎转载! 转载请注明出处: http://blog.csdn.net/yyplc ====

回顾一下上文,s3c2440串口底层驱动围绕三个数据结构展开:

UART特定的驱动程序结构定义:struct uart_driver s3c24xx_uart_drv;

UART端口结构定义: struct uart_port s3c24xx_serial_ops;

UART相关操作函数结构定义: struct uart_ops s3c24xx_serial_ops;

 

实现了这三个数据结构体,基本完成了驱动操作函数的实现,紧接着需要对串口设备及设备驱动进行初始化,首先是模块初始化module_init(s3c24xx_serial_modinit):

static int __inits3c24xx_serial_modinit(void)
{
       intret;
       ret= uart_register_driver(&s3c24xx_uart_drv);  //注册uart驱动,在serial_core.c中实现
       if(ret < 0) {
              printk(KERN_ERR"failed to register UART driver\n");
              return-1;
       }
 
       return0;
}

uart_register_driver在串口核心及TTY层间进行相关注册:

int uart_register_driver(struct uart_driver*drv)
{
	struct tty_driver *normal = NULL;
	…
       drv->tty_driver= normal;
       normal->owner             = drv->owner;
       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->driver_state    = drv;
       tty_set_operations(normal,&uart_ops);
       ….
       retval= tty_register_driver(normal);   // tty 驱动注册
 out:
       if(retval < 0) {
              put_tty_driver(normal);
              kfree(drv->state);
       }
       returnretval;
}

接着进行总线驱动platform_driver_register:

int s3c24xx_serial_init(structplatform_driver *drv,
                     structs3c24xx_uart_info *info)
{
#ifdef CONFIG_PM
       drv->suspend= s3c24xx_serial_suspend;
       drv->resume= s3c24xx_serial_resume;
#endif
 
       returnplatform_driver_register(drv);  //
}

其中s3c24xx_serial_init为__init段,模块加载时初始化:

static int __init s3c2440_serial_init(void)
{
       returns3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf); //
}

platfrom_driver_register()中调用driver_register()

int platform_driver_register(structplatform_driver *drv)
{
       drv->driver.bus= &platform_bus_type;   //
       if(drv->probe)
              drv->driver.probe= platform_drv_probe;
       if(drv->remove)
              drv->driver.remove= platform_drv_remove;
       if(drv->shutdown)
              drv->driver.shutdown= platform_drv_shutdown;
       if(drv->suspend)
              drv->driver.suspend= platform_drv_suspend;
       if(drv->resume)
              drv->driver.resume= platform_drv_resume;
       returndriver_register(&drv->driver);  //
}

因为串口设备在系统是一种platform_device所以是一种总线驱动类型,总线设备驱动注册platform_driver_register()之后,串口设备即可和相应的驱动关联起来了,这样就完成了串口设备与串口驱动的注册过程。

下一篇讲进一步结合源码分析。

你可能感兴趣的:(数据结构,c,struct,Module,null)