以I2c-s3c2410.c驱动为例:
……
/* map the registers */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "cannot find IO resource\n");
ret = -ENOENT;
goto err_clk;
}
i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1,
pdev->name);
if (i2c->ioarea == NULL) {
dev_err(&pdev->dev, "cannot request IO\n");
ret = -ENXIO;
goto err_clk;
}
i2c->regs = ioremap(res->start, (res->end-res->start)+1);
……
最终得到了IIC的基地址:i2c->regs
以后只需要在基地址的基础上加上偏移量即可得到相应的寄存器,偏移量和寄存器操作宏 定义在regs-iic.h中:
寄存器:
#define S3C2410_IICREG(x) (x)
#define S3C2410_IICCON S3C2410_IICREG(0x00)
#define S3C2410_IICSTAT S3C2410_IICREG(0x04)
#define S3C2410_IICADD S3C2410_IICREG(0x08)
#define S3C2410_IICDS S3C2410_IICREG(0x0C)
#define S3C2440_IICLC S3C2410_IICREG(0x10)
操作宏:
#define S3C2410_IICCON_ACKEN (1<<7)
#define S3C2410_IICCON_TXDIV_16 (0<<6)
#define S3C2410_IICCON_TXDIV_512 (1<<6)
#define S3C2410_IICCON_IRQEN (1<<5)
#define S3C2410_IICCON_IRQPEND (1<<4)
#define S3C2410_IICCON_SCALE(x) ((x)&15)
#define S3C2410_IICCON_SCALEMASK (0xf)
……
现在遇到的问题是:为什么通过platform_get_resource、ioremap等一系列函数就能得到I2C寄存器的基地址呢?
解答:
因为通过platform_get_resource,返回一个resource结构指针,我们来看一下这个结构指针:
struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};
再来看一下arch\arm\plat-s3c24xx目录下的devs.c文件是如何定义I2C资源的:
static struct resource s3c_i2c_resource[] = {
[0] = {
.start = S3C24XX_PA_IIC,
.end = S3C24XX_PA_IIC + S3C24XX_SZ_IIC - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IIC,
.end = IRQ_IIC,
.flags = IORESOURCE_IRQ,
}
};
其中,S3C24XX_PA_IIC就是S3C24XX系列芯片的I2c基地址,它的定义在arch\arm\mach-s3c2410\include\mach目录下的map.h文件中,具体如下
……
#define S3C2410_PA_IIC (0x54000000)
……
#define S3C24XX_PA_IIC S3C2410_PA_IIC
……
基地址为0x54000000,这样就与芯片手册对应了起来。