====本文系本站原创,欢迎转载! 转载请注明出处: 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()之后,串口设备即可和相应的驱动关联起来了,这样就完成了串口设备与串口驱动的注册过程。
下一篇讲进一步结合源码分析。