I2C-client-devices-drivers-writing

来源:互联网 发布:知天下资源吧进不去 编辑:程序博客网 时间:2024/04/30 12:57

<0>About L3G4200D digital output gyroscope sensor

            made by STMicroelectronics.

<1>i2c-client的驱动从板级枚举开始(对应的结构:struct platform_data{})
         >>> e.g: /arch/arm/mach-x/xxx.c    
    a:板级枚举时需要初始化的内容包括:platform_data结构和client特征信息。
    b:platform_data, e.g:
#if defined (CONFIG_SENSOR_L3G4200D)#define L3G4200D_IRQ_PIN PIN5_PA0static int l3g4200d_board_init(void){         if(gpio_request(L3G4200D_IRQ_PIN, "l3g4200d_irq") != 0){                 gpio_free(L3G4200D_IRQ_PIN);                 printk("> l3g4200d init platform_hw gpio_request error.\n");                 return -EIO;         }         gpio_direction_input(L3G4200D_IRQ_PIN);         return 0;} struct l3g4200d_platform_data l3g4200d_pdata = {         .poll_interval = 2,         .min_interval = 0,         .fs_range = 250,         .axis_map_x= 0,        .axis_map_y= 1,        .axis_map_z= 2,        .negate_x= 0,        .negate_y= 0,        .negate_z= 0,         .init = l3g4200d_board_init,};#endif  //end->CONFIG_SENSOR_L3D4200D
    c: 芯片特征信息,e.g:
static struct i2c_board_info __initdata board_i2c0_devices[] = {         {                 .type                   = "l3g4200d",                 .addr                   = 0x69,    /*slave addr*/                 .flags                  = 0,                 .irq                    = L3G4200D_IRQ_PIN,                 .platform_data          = &l3g4200d_pdata,         },........};

d:最终注册这个设备的board信息到指定的I2C总线:
i2c_register_board_info(default_i2c0_data.bus_num, board_i2c0_devices,       ARRAY_SIZE(board_i2c0_devices));
         把platform_data的数据保存起来,备总线方法使用.

e:枚举的其他方法可以参考/kenrel/Documentation/i2c/instantiating-devices

<2>device-driver:

a:初始化struct i2c_driver结构,e.g:
static struct i2c_driver l3g4200d_driver = {         .driver = {                         .owner = THIS_MODULE,                        .name = L3G4200D_GYR_DEV_NAME,                        .pm = &l3g4200d_pm, /* suspend(), resume() */        },          .probe = l3g4200d_probe,        .remove = __devexit_p(l3g4200d_remove),        .id_table = l3g4200d_id,};

b:实现probe方法:
static int  xxx_probe(struct i2c_client *client, const struct i2c_device_id *id);
        >>>l3g4200d_pdata会被bus方法存到client->dev.platform_data,
         如果有board级的方法,可以在通过这个接口调用.

        >>>检查platform_data(在板级注册)

        >>>检查adapter功能,e.g:

if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {err = -ENODEV;goto exit;}              p.s. more in kernel/Documentation/i2c/functionality
        >>>把dev.platform_data存到client->pdata.

        >>>调用板级初始化方法,本例中为dev.platform_data.init() <if there has>;

                e.g: 亦可直接完成:申请gpio, 注册中断等工作.

        >>>检查芯片,通常通过一个叫"WHO_AM_I"的寄存器检查其chip id.

        >>>注册字符设备,class,input设备,misc....

<3>i2c基础方法, read(), write():

/* read method*/i2c_read_reg();i2c_read();/* write method */i2c_write_reg();i2c_write();

<4>上层接口:
a: input
b: cdev
c: procfs
d: sysfs

/** * ____/|     * \ o.O| *  =(_)= -> to be continue... *    U */