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