/*下面是设备提供给驱动的平台数据和资源,结构体在iic.h文件中定义*/
static struct s3c2410_platform_i2c default_i2c_data0 __initdata = {
.flags = 0,
.slave_addr = 0x10,
.frequency = 100*1000,
.sda_delay = 100,
};
static struct resource s3c_i2c_resource[] = {
[0] = {
.start = S3C_PA_IIC,
.end = S3C_PA_IIC + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IIC,
.end = IRQ_IIC,
.flags = IORESOURCE_IRQ,
},
};
/*在驱动和设备加载到总线上,并完成匹配的时候会调用驱动下面的probe函数驱动该硬件工作*/
在probe中初始化了三个结构体
struct s3c24xx_i2c *i2c;//在驱动文件中定义的“大”结构体
struct s3c2410_platform_i2c *pdata;//这两项是有设备提供的。
struct resource *res;
下面是对“大”结构体中的适配器(控制器)结构体(在iic.h中定义的)进行初始化
strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
i2c->adap.owner = THIS_MODULE;
i2c->adap.algo = &s3c24xx_i2c_algorithm;
i2c->adap.retries = 2;
i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
i2c->tx_setup = 50;
/* find the clock and enable it */
i2c->dev = &pdev->dev;
i2c->clk = clk_get(&pdev->dev, "i2c");
clk_enable(i2c->clk);
/* map the registers */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);//获得设备的IORESOURCE_MEM
i2c->ioarea = request_mem_region(res->start, resource_size(res),
pdev->name);//接着对“大”结构体初始化,这里是申请IO资源
i2c->regs = ioremap(res->start, resource_size(res));//对IO映射
/* setup info block for the i2c core */
i2c->adap.algo_data = i2c;
i2c->adap.dev.parent = &pdev->dev;
/* initialise the i2c controller */
ret = s3c24xx_i2c_init(i2c);//初始化IO控制器
/*s3c24xx_i2c_init()函数的作用就是initialise the controller,set the IO lines and frequency*/
下面是对中断的配置
i2c->irq = ret = platform_get_irq(pdev, 0);
ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
dev_name(&pdev->dev), i2c);
ret = s3c24xx_i2c_register_cpufreq(i2c);
platform_set_drvdata(pdev, i2c);//将i2c大结构体的数据放在dev->p->driver_data = data;
clk_disable(i2c->clk);
至此,probe完成,其工作主要是对适配器的初始化包含一些时钟IO和中断资源的申请。
操作系统就是这样,把资源都封装起来,驱动写起来更规范。
注意:这里并没有实现sysfs上的文件的操作函数,就是open write等操作方法,自己可以加上,作为函数调用,提供给应用程序是用,写个小的API玩一下。参考博文:
http://blog.chinaunix.net/uid-22030783-id-1710998.html
阅读(2649) | 评论(0) | 转发(1) |