Linux I2C设备驱动编写 - 图文(6)

2019-04-15 23:11

偏移量 ACh B0h B4h B8h 寄存器名 I2C_SA I2C_PSC I2C_SCLL I2C_SCLH 概述 读写,10位,设置从地址7bit/10bit 读写,8位,分频器设置,使能I2C前可修改 读写,8位,使能I2C前可修改,占空比低电平时间 读写,8位,使能I2C前可修改,占空比高电平时间 适配器代码解读 在Linux内核驱动中,此适配器驱动存在于drivers/i2c/busses/i2c-omap.c。根据前几节对适配器i2c_adapter的理解,在写I2C适配器驱动时,主要集中在对传输、设备初始化、电源管理这几点。 平台设备注册 static struct platform_driver omap_i2c_driver = { .probe = omap_i2c_probe, .remove = omap_i2c_remove, .driver = { .name = \ .owner = THIS_MODULE, .pm = OMAP_I2C_PM_OPS, .of_match_table = of_match_ptr(omap_i2c_of_match), }, }; 可以看到,此适配器的匹配是通过dts(Device Tree)进行匹配的,omap_i2c_of_match为:

static const struct of_device_id omap_i2c_of_match[] = { { .compatible = \ .data = &omap4_pdata, }, { .compatible = \ .data = &omap3_pdata, }, { }, }; 通过在查阅相关dts,不难发现有这样的设备节点存在:

i2c0: i2c@44e0b000 { compatible = \ #address-cells = <1>; #size-cells = <0>; ti,hwmods = \ reg = <0x44e0b000 0x1000>; interrupts = <70>; status = \ }; i2c1: i2c@4802a000 { compatible = \ #address-cells = <1>; #size-cells = <0>; ti,hwmods = \ reg = <0x4802a000 0x1000>; interrupts = <71>; status = \ }; i2c2: i2c@4819c000 { compatible = \ #address-cells = <1>; #size-cells = <0>; ti,hwmods = \ reg = <0x4819c000 0x1000>; interrupts = <30>; status = \ }; 通过查阅AM3359手册168页的内存映射表可以发现,这个dts所描述的3个I2C总线节点是与AM3359完全对应的,而名称(即compatible)也与驱动中所指定的列表项能够匹配。至于中断号的确定可通过手册的212页TABLE 6-1. ARM Cortex-A8 Interrupts得到,这里不再贴图,关于DTS的相关知识也非本问涉及,不做介绍。

下面重点分析此驱动的probe及电源管理。

匹配动作probe

由于DTS的存在,一旦内核检测到匹配的Device Tree节点就会触发probe匹配动作(因为DTS节省了对原本platform_device在板级代码中的存在)。由于probe函数内容较多,此处部分节选:

static int omap_i2c_probe(struct platform_device *pdev) { struct omap_i2c_dev *dev; struct i2c_adapter *adap; struct resource *mem; const struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data; struct device_node *node = pdev->dev.of_node; const struct of_device_id *match; int irq; int r; u32 rev; u16 minor, major, scheme; struct pinctrl *pinctrl; /* NOTE: driver uses the static register mapping */ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); //对应DTS中reg if (!mem) { dev_err(&pdev->dev, \ return -ENODEV; } irq = platform_get_irq(pdev, 0); //对应DTS中interrupts if (irq < 0) { dev_err(&pdev->dev, \ return irq; } dev = devm_kzalloc(&pdev->dev, sizeof(struct omap_i2c_dev), GFP_KERNEL); if (!dev) { dev_err(&pdev->dev, \ return -ENOMEM; } dev->base = devm_request_and_ioremap(&pdev->dev, mem); //做内存和IO映射 if (!dev->base) { dev_err(&pdev->dev, \ return -ENOMEM; } match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev); //通过DTS进行匹配 if (match) { u32 freq = 100000; /* default to 100000 Hz */ pdata = match->data; dev->flags = pdata->flags; of_property_read_u32(node, \ /* convert DT freq value in Hz into kHz for speed */ dev->speed = freq / 1000; //若成功匹配则设置I2C总线适配器速度为clock-frequency的数值 } else if (pdata != NULL) { dev->speed = pdata->clkrate; //若没匹配成功,而又有pdata(即通过传统方式注册platform_device) dev->flags = pdata->flags; dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; } rev = __raw_readw(dev->base + 0x04); //读取I2C_REVNB_HI寄存器 /* * #define OMAP_I2C_SCHEME(rev) ((rev & 0xc000) >> 14) * 对应spec中描述:4244页,15-14位SCHEME,只读。 */ scheme = OMAP_I2C_SCHEME(rev); switch (scheme) { case OMAP_I2C_SCHEME_0: dev->regs = (u8 *)reg_map_ip_v1; dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG); minor = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev); major = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev); break; case OMAP_I2C_SCHEME_1: /* FALLTHROUGH */ default: dev->regs = (u8 *)reg_map_ip_v2; rev = (rev << 16) | omap_i2c_read_reg(dev, OMAP_I2C_IP_V2_REVNB_LO); minor = OMAP_I2C_REV_SCHEME_1_MINOR(rev); major = OMAP_I2C_REV_SCHEME_1_MAJOR(rev); dev->rev = rev; } 上述代码为版本判断,根据不同版本确定不同的寄存器地图。根据spec能够确定,实际AM3359的I2C总线适配器应该是OMAP_I2C_SCHEME_1类型,其寄存器地图为reg_map_ip_v2:

static const u8 reg_map_ip_v2[] = { [OMAP_I2C_REV_REG] = 0x04, [OMAP_I2C_IE_REG] = 0x2c, [OMAP_I2C_STAT_REG] = 0x28, [OMAP_I2C_IV_REG] = 0x34, [OMAP_I2C_WE_REG] = 0x34, [OMAP_I2C_SYSS_REG] = 0x90, [OMAP_I2C_BUF_REG] = 0x94,


Linux I2C设备驱动编写 - 图文(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:点焊

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: