如何实例化一个i2c设备(struct i2c_client)

之前写的i2c驱动程序对应的linux-2.6的内核,在移植到linux-3.4时,发现好多API不一样了。让我们打开/linux-3.4.2/Documentation/i2c/instantiating-devices,一探究竟。

不像PCI或USB设备,I2C设备不在硬件级枚举。相反,软件必须知道连接在每个I2C总线段的设备,以及这些设备正在使用什么地址。因为这个原因,内核代码必须显式地实例化I2C设备。有实现这一目标的几种方法,取决于上下文和要求。

方法1:通过总线号来声明I2C设备

当I2C总线是系统总线的情况下,对于许多嵌入式系统这种方法是适当的。在这样的系统中,每个I2C总线有一个数字这是事先知道的。因此,可以预先声明附加在这个总线上的I2C设备。这是通过一个调用i2c_register_board_info()注册的结构体数组i2c_board_info。

static struct i2c_board_info __initdata h4_i2c_board_info[] = {
        {
                I2C_BOARD_INFO("isp1301_omap", 0x2d),
                .irq            = OMAP_GPIO_IRQ(125),
        },
        {       /* EEPROM on mainboard */
                I2C_BOARD_INFO("24c01", 0x52),
                .platform_data  = &m24c01,
        },
        {       /* EEPROM on cpu card */
                I2C_BOARD_INFO("24c01", 0x57),
                .platform_data  = &m24c01,
        },
};


static void __init omap_h4_init(void)
{
        (...)
        i2c_register_board_info(1, h4_i2c_board_info,
                        ARRAY_SIZE(h4_i2c_board_info));
        (...)
}

上面的代码声明了I2C总线1上的3个设备,包括它们各自的驱动程序所需的地址和自定义数据。当I2C总线被注册,I2C设备将自动实例化由I2C核心。

当他们依附的I2C总线消失时,设备将自动绑定并销毁(如果有的话)。

方法2:明确实例化设备

当一个较大的设备使用I2C总线内部沟通,这种方法是适当的。一个典型的例子是电视适配器。这些可以有调谐器、视频解码器、音频解码器等通常连接到主芯片采用I2C总线的方式。你不能提前知道I2C的总线数量,因此上述方法1不能使用。相反,您可以明确实例化您的I2C设备。这时填充结构i2c_board_info并调用i2c_new_device()。

static struct i2c_board_info sfe4001_hwmon_info = {
        I2C_BOARD_INFO("max6647", 0x4e),
};


int sfe4001_init(struct efx_nic *efx)
{
        (...)
        efx->board_info.hwmon_client =
                i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);


        (...)
}

上面的代码中实例化1 个网络适配器I2C总线上的设备。

当你不知道如果一个I2C设备是否存在(例如在廉价的单板不存在的可选功能,但你没有办法告诉他们分开),或它可能有不同的地址在不同单板(制造商改变其设计,没有通知),您可以调用 i2c_new_probed_device()而不是i2c_new_device()。

static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };


static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev)
{
        (...)
        struct i2c_adapter *i2c_adap;
        struct i2c_board_info i2c_info;


        (...)
        i2c_adap = i2c_get_adapter(2);
        memset(&i2c_info, 0, sizeof(struct i2c_board_info));
        strlcpy(i2c_info.type, "isp1301_nxp", I2C_NAME_SIZE);
        isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
                                                   normal_i2c, NULL);
        i2c_put_adapter(i2c_adap);
        (...)
}

上面的代码中实例化了1 个OHCI适配器I2C总线的设备。它第一次尝试在地址0x2c,如果没有发现尝试0x2d,如果仍然没有找到,它干脆放弃。

清理时实例化I2C设备的驱动程序负责销毁它。这是通过调用i2c_unregister_device()使用i2c_new_device()或i2c_new_probed_device()返回的指针。

方法3:探测某些设备的I2C总线

有时你没有足够的信息的I2C设备,甚至调用i2c_new_probed_device()。典型案例是在PC主板芯片的硬件监控。有几十种型号,可以使用25个不同的地址。鉴于主板的大量存在,要建立一个详尽正在使用的监控芯片硬件清单是不可能的。幸运的是,这些芯片大多制造商和设备ID寄存器,所以他们可以识别探测。

方法4:从用户空间实例化

一般来说,内核应该知道哪些I2C设备连接和他们住在什么住址。然而,在某些情况下,它没有,所以sysfs接口的加入,让用户提供信息。这接口是由2个属性文件,这是创建在每个I2C总线目录:new_device和delete_device。这两个文件只写和你为了正确实例化,必须将正确的参数写入它们,分别删除,一个I2C设备。

# echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device

补充:支持设备树以后

        i2c1: i2c@400a0000 {
                /* ... master properties skipped ... */
                clock-frequency = <100000>;


                flash@50 {
                        compatible = "atmel,24c256";
                        reg = <0x50>;
                };


                pca9532: gpio@60 {
                        compatible = "nxp,pca9532";
                        gpio-controller;
                        #gpio-cells = <2>;
                        reg = <0x60>;
                };
        };

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值