您的位置:首页 > 其它

s3c6410的UART设备驱动(4)

2015-01-13 17:29 309 查看
上两篇说了在模块初始化是调用uart_register_driver和uart_add_one_port注册UART驱动并添加端口,在模块卸载时调用uart_unregister_driver和uart_remove_one_port以注销UART驱动并移除端口,主要讲述的是这些函数的具体代码,但没说这些函数在何处被调用,这一篇讲述这些函数的调用。

1、在Samsung.c (linux2.6.28\drivers\serial)文件中,有如下代码:

module_init(s3c24xx_serial_modinit);

module_exit(s3c24xx_serial_modexit);

看到这两个,应该知道了此模块调用的函数,和卸载时的函数。列出其源码:

/* module initialisation code */

static int __init s3c24xx_serial_modinit(void)

{
int ret;
ret = uart_register_driver(&s3c24xx_uart_drv);在上一篇中讲的有,可以去查看。
其中它的参数为
static struct uart_driver s3c24xx_uart_drv = {
.owner
 = THIS_MODULE,
.dev_name
 = "s3c2410_serial",
.nr = CONFIG_SERIAL_SAMSUNG_UARTS,
.cons = S3C24XX_SERIAL_CONSOLE,
.driver_name
 = S3C24XX_SERIAL_NAME,
.major
 = S3C24XX_SERIAL_MAJOR,
.minor
 = S3C24XX_SERIAL_MINOR,

};
if (ret < 0) {
printk(KERN_ERR "failed to register UART driver\n");
return -1;
}
return 0;
}

static void __exit s3c24xx_serial_modexit(void)
{
uart_unregister_driver(&s3c24xx_uart_drv);
}

/**
 *
uart_unregister_driver - remove a driver from the uart core layer
 *
@drv: low level driver structure
 */
void uart_unregister_driver(struct uart_driver *drv)
{
struct tty_driver *p = drv->tty_driver;
tty_unregister_driver(p);
put_tty_driver(p);//减小引用数,为0是释放p
kfree(drv->state);
drv->tty_driver = NULL;
}

2、板级相关在S3c6400.c (linux2.6.28\drivers\serial)文件中有如下:

module_init(s3c6400_serial_init);

module_exit(s3c6400_serial_exit);

和上面一样列出其源码:

static int __init s3c6400_serial_init(void)

{
return s3c24xx_serial_init(&s3c6400_serial_drv, &s3c6400_uart_inf);

}

调用s3c24xx_serial_init函数,传入的参数为

static struct platform_driver s3c6400_serial_drv = {
.probe
 = s3c6400_serial_probe,
.remove
 = s3c24xx_serial_remove,
.driver
 = {
.name = "s3c6400-uart",
.owner
 = THIS_MODULE,
},

};

static struct s3c24xx_uart_info s3c6400_uart_inf = {
.name
= "Samsung S3C6400 UART",
.type
= PORT_S3C6400,
.fifosize
 = 64,
.rx_fifomask
 = S3C2440_UFSTAT_RXMASK,
.rx_fifoshift
 = S3C2440_UFSTAT_RXSHIFT,
.rx_fifofull
 = S3C2440_UFSTAT_RXFULL,
.tx_fifofull
 = S3C2440_UFSTAT_TXFULL,
.tx_fifomask
 = S3C2440_UFSTAT_TXMASK,
.tx_fifoshift
 = S3C2440_UFSTAT_TXSHIFT,
.get_clksrc
 = s3c6400_serial_getsource,
.set_clksrc
 = s3c6400_serial_setsource,
.reset_port
 = s3c6400_serial_resetport,
};这个结构体的原型在Samsung.h (linux2.6.28\drivers\serial)文件中,如下所示:

struct s3c24xx_uart_info {
char *name;
unsigned int
 type;
unsigned int
 fifosize;
unsigned long
 rx_fifomask;
unsigned long
 rx_fifoshift;
unsigned long
 rx_fifofull;
unsigned long
 tx_fifomask;
unsigned long
 tx_fifoshift;
unsigned long
 tx_fifofull;

/* clock source control */

int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);

/* uart controls */
int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *);

};

ints3c24xx_serial_init(struct platform_driver *drv,struct s3c24xx_uart_info *info)

{
dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);

#ifdef CONFIG_PM
drv->suspend = s3c24xx_serial_suspend;
drv->resume = s3c24xx_serial_resume;

#endif

return platform_driver_register(drv);

}

platform_driver_register这个函数才是重点,因为uart是作为一种平台设备存在的。大家都知道,会调用其

static struct platform_driver s3c6400_serial_drv = {
.probe= s3c6400_serial_probe

结构体中的probe函数,源码如下:
static int s3c6400_serial_probe(struct platform_device *dev)
{
dbg("s3c6400_serial_probe: dev=%p\n", dev);
return s3c24xx_serial_probe(dev, &s3c6400_uart_inf);//该函数里调用uart_add_one_port
}

因为这个函数实在太长,所以放在下一篇中在说。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: