dw_apb_i2c驱动简析

 
源码:
drivers\i2c\busses\i2c-designware-platdrv.c
drivers\i2c\busses\i2c-designware-master.c
drivers\i2c\busses\i2c-designware-slave.c

 

DTS:
i2c2: i2c@f0d80000 {
    compatible = "snps,designware-i2c";
    status = "disabled";
    interrupt-parent = <&gic>;
    interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
    reg = <0x0 0xf0d80000 0x0 0x1000>;
    clock-frequency = <400000>;
    #address-cells = <1>;
    #size-cells = <0>;
};
 
I2C control实例化分析:
static const struct of_device_id dw_i2c_of_match[] = {
    { .compatible = "snps,designware-i2c", },
    {},
};
最终dw_i2c_plat_probe(drivers\i2c\busses\i2c-designware-platdrv.c)函数会调用
static int dw_i2c_plat_probe(struct platform_device *pdev)
{
... ...
        i2c_dw_configure(dev);    // 区分master和slave
... ...    
        ret = i2c_dw_probe(dev);
 
... ...
}

 static inline void i2c_dw_configure(struct dw_i2c_dev *dev)
 {
         if (i2c_detect_slave_mode(dev->dev))
                 i2c_dw_configure_slave(dev);
         else
                 i2c_dw_configure_master(dev);
 }

 static inline int i2c_dw_probe(struct dw_i2c_dev *dev)
 {
         switch (dev->mode) {
         case DW_IC_SLAVE:
                 return i2c_dw_probe_slave(dev);
         case DW_IC_MASTER:
                 return i2c_dw_probe_master(dev);
         default:
                 dev_err(dev->dev, "Wrong operation mode: %d\n", dev->mode);
                 return -EINVAL;
         }
 }
 根据该i2c控制器是主机还是从机,进行控制器配置并且调用响应的probe函数,这里分析主机模式,调用i2c_dw_probe_master函数
static const struct i2c_algorithm i2c_dw_algo = {
    .master_xfer = i2c_dw_xfer,
    .functionality = i2c_dw_func,
};
 
int i2c_dw_probe_master(struct dw_i2c_dev *dev)
{
    struct i2c_adapter *adap = &dev->adapter;
    unsigned long irq_flags;
    int ret;
    .......
    ret = dev->init(dev);
    if (ret)
        return ret;
 
    snprintf(adap->name, sizeof(adap->name),
         "Synopsys DesignWare I2C adapter");
    adap->retries = 3;
    adap->algo = &i2c_dw_algo;
    adap->dev.parent = dev->dev;
    i2c_set_adapdata(adap, dev);
 
    if (dev->pm_disabled) {
        dev_pm_syscore_device(dev->dev, true);
        irq_flags = IRQF_NO_SUSPEND;
    } else {
        irq_flags = IRQF_SHARED | IRQF_COND_SUSPEND;
    }
    .....
    i2c_dw_disable_int(dev);
    ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, irq_flags,
                   dev_name(dev->dev), dev);
    ......
    ret = i2c_add_numbered_adapter(adap);
}
解析dts,设置struct i2c_adapter结构体,主要是adap->algo = &i2c_dw_algo,注册中断,最终调用i2c_add_numbered_adapter注册adapter
 
 
 
 
posted @ 2024-03-31 01:34  lethe1203  阅读(296)  评论(0编辑  收藏  举报