1. Abstract
抱歉这篇报告是我当初用英文写的,有兴趣的朋友可以参考。
2. Introduction
Document [1].chapter8 is a good tip for readers to understanding I2C basic ideas.
3. Adapter Codes
Codes exist in drivers/i2c/busses/i2c-pxa.c.
3.1 Data Structure
The device structure in arch/arm/mach-pxa/generic.c
static struct platform_device i2c_device = {
.name = "pxa2xx-i2c",
.id = 0,
.resource = i2c_resources,
.num_resources = ARRAY_SIZE(i2c_resources),
};
static struct resource i2c_resources[] = {
{
.start = 0x40301680,
.end = 0x403016a3,
.flags = IORESOURCE_MEM,
}, {
.start = IRQ_I2C,
.end = IRQ_I2C,
.flags = IORESOURCE_IRQ,
},
};
The driver data structure in drivers/i2c/busses/i2c-pxa.c:
static struct platform_driver i2c_pxa_driver = {
.probe = i2c_pxa_probe,
.remove = i2c_pxa_remove,
.driver = {
.name = "pxa2xx-i2c",
},
};
The driver private data data structure in drivers/i2c/busses/i2c-pxa.c:
struct pxa_i2c {
spinlock_t lock;
wait_queue_head_t wait;
struct i2c_msg *msg;
unsigned int msg_num;
unsigned int msg_idx;
unsigned int msg_ptr;
unsigned int slave_addr;
struct i2c_adapter adap;
#ifdef CONFIG_I2C_PXA_SLAVE
struct i2c_slave_client *slave;
#endif
unsigned int irqlogidx;
u32 isrlog[32];
u32 icrlog[32];
void __iomem *reg_base;
unsigned long iobase;
unsigned long iosize;
int irq;
};
And its global variable instance:
static struct pxa_i2c i2c_pxa = {
.lock = SPIN_LOCK_UNLOCKED,
.adap = {
.owner = THIS_MODULE,
.algo = &i2c_pxa_algorithm,
.name = "pxa2xx-i2c.0",
.retries = 5,
},
};
static const struct i2c_algorithm i2c_pxa_algorithm = {
.master_xfer = i2c_pxa_xfer,
.functionality = i2c_pxa_functionality,
};
3.2 Initialize Codes
3.2.1 Probe Function
Codes exist in drivers/i2c/busses/i2c-pxa.c.
static int i2c_pxa_probe(struct platform_device *dev)
{
struct pxa_i2c *i2c = &i2c_pxa;
struct resource *res;
#ifdef CONFIG_I2C_PXA_SLAVE
struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
#endif
int ret;
int irq;
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
irq = platform_get_irq(dev, 0);
……
if (!request_mem_region(res->start, res_len(res), res->name))
return -ENOMEM;
i2c = kmalloc(sizeof(struct pxa_i2c), GFP_KERNEL);
……
memcpy(i2c, &i2c_pxa, sizeof(struct pxa_i2c));
init_waitqueue_head(&i2c->wait);
i2c->adap.name[strlen(i2c->adap.name) - 1] = '0' + dev->id % 10;
i2c->reg_base = ioremap(res->start, res_len(res));
……
i2c->iobase = res->start;
i2c->iosize = res_len(res);
i2c->irq = irq;
i2c->slave_addr = I2C_PXA_SLAVE_ADDR; // I2C_PXA_SLAVE_ADDR equals to 1.
#ifdef CONFIG_I2C_PXA_SLAVE
if (plat) {
i2c->slave_addr = plat->slave_addr;
i2c->slave = plat->slave;
}
#endif
switch (dev->id) { //In our case it is 0, please refer to section 3.1, this part is used to set the clock.
case 0: