dw_apb_i2c驅動簡析

lethe1203發表於2024-03-31
學習資料:https://blog.csdn.net/yangguoyu8023/article/details/122362946
原始碼:
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

相關文章