第一个驱动程序之i2c驱动架构介绍

来源:互联网 发布:单片机管脚图 编辑:程序博客网 时间:2024/06/10 19:48

编写一个I2C设备驱动程序的工作可分为两部分,一是定义和注册I2C设备,即i2c_client;二是定义和注册I2C设备驱动,即i2c_driver。下面我们就以mini2440的I2C设备at24c08 EEPROM为例,介绍如何完成这两个工作。


一、定义和注册I2C设备

步骤1:用i2c_board_info保存I2C设备相关信息

在Linux中,struct i2c_client代表一个I2C设备,该结构体定义在include/linux/i2c.h文件中:

200/**201 * struct i2c_client - represent an I2Cslave device202 * @flags: I2C_CLIENT_TEN indicates thedevice uses a ten bit chip address;203 * I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking204 * @addr: Address used on the I2C busconnected to the parent adapter.205 * @name: Indicates the type of thedevice, usually a chip name that's206 * generic enough to hide second-sourcing and compatible revisions.207 * @adapter: manages the bus segmenthosting this I2C device208 * @driver: device's driver, hencepointer to access routines209 * @dev: Driver model device node forthe slave.210 * @irq: indicates the IRQ generated bythis device (if any)211 * @detected: member of ani2c_driver.clients list or i2c-core's212 * userspace_devices list213 *214 * An i2c_client identifies a singledevice (i.e. chip) connected to an215 * i2c bus. The behaviour exposed to Linuxis defined by the driver216 * managing the device.217 */218struct i2c_client {219   unsigned short flags;       /*div., see below      */220   unsigned short addr;        /*chip address - NOTE: 7bit    */221                    /* addresses are stored inthe  */222                    /* _LOWER_ 7 bits       */223   char name[I2C_NAME_SIZE];224   struct i2c_adapter *adapter;    /*the adapter we sit on    */225   struct i2c_driver *driver;  /* andour access routines  */226   struct device dev;      /* thedevice structure     */227   int irq;            /* irq issuedby device     */228   struct list_head detected;229};

我们不用直接定义一个i2c_client结构,Linux会根据I2C设备的相关信息自动创建i2c_client。所以,我们需要提供I2C设备的相关信息。对于Mini2440的I2C设备at24c08 EEPROM,其相关信息保存在arch/arm/mach-s3c24xx/mach-mini2440.c文件中:

485/*486 * I2C devices487 */488static struct at24_platform_data at24c08= {489   .byte_len   = SZ_8K / 8,490   .page_size  = 16,491};492493static struct i2c_board_infomini2440_i2c_devs[] __initdata = {494   {495       I2C_BOARD_INFO("24c08", 0x50),496       .platform_data = &at24c08,497   },498};

struct i2c_board_info是创建i2c设备的模板,该结构体定义在include/linux/i2c.h文件中:

251/**252 * struct i2c_board_info - template fordevice creation253 * @type: chip type, to initializei2c_client.name254 * @flags: to initializei2c_client.flags255 * @addr: stored in i2c_client.addr256 * @platform_data: stored ini2c_client.dev.platform_data257 * @archdata: copied intoi2c_client.dev.archdata258 * @of_node: pointer to OpenFirmwaredevice node259 * @acpi_node: ACPI device node260 * @irq: stored in i2c_client.irq261 *262 * I2C doesn't actually support hardwareprobing, although controllers and263 * devices may be able to useI2C_SMBUS_QUICK to tell whether or not there's264 * a device at a given address.  Drivers commonly need more information than265 * that, such as chip type,configuration, associated IRQ, and so on.266 *267 * i2c_board_info is used to buildtables of information listing I2C devices268 * that are present.  This information is used to grow the drivermodel tree.269 * For mainboards this is donestatically using i2c_register_board_info();270 * bus numbers identify adapters thataren't yet available.  For add-on boards,271 * i2c_new_device() does thisdynamically with the adapter already known.272 */273struct i2c_board_info {274   char        type[I2C_NAME_SIZE];275   unsigned short  flags;276   unsigned short  addr;277   void        *platform_data;278   struct dev_archdata *archdata;279   struct device_node *of_node;280   struct acpi_dev_node acpi_node;281   int     irq;282};

从注释可以看到,i2c_board_info结构体用来保存I2C设备的相关信息,Linux根据这些信息创建I2C设备相关的设备模型树。对于mainboards,通过调用i2c_register_board_info()静态完成。对于add-on boards,通过调用i2c_new_device()动态完成。

i2c_board_info结构体有两个成员必须初始化,一个是type,用来初始化i2c_client.name;另一个是addr,用来初始化i2c_client.addr。其它i2c_board_info结构体成员根据需要赋值或保持为空。

宏I2C_BOARD_INFO定义在include/linux/i2c.h文件中,其内容如下:

284/**285 * I2C_BOARD_INFO - macro used to listan i2c device and its address286 * @dev_type: identifies the device type287 * @dev_addr: the device's address onthe bus.288 *289 * This macro initializes essentialfields of a struct i2c_board_info,290 * declaring what has been provided on aparticular board.  Optional291 * fields (such as associated irq, ordevice-specific platform_data)292 * are provided using conventionalsyntax.293 */294#define I2C_BOARD_INFO(dev_type,dev_addr) \295   .type = dev_type, .addr = (dev_addr)


从注释可以看到,I2C_BOARD_INFO宏用来初始化i2c_board_info结构体的两个必须初始化的成员变量type和addr。i2c_board_info结构体的其它成员变量使用常规的初始化语法。

struct at24_platform_data定义在include/linux/i2c/at24.h文件中:

4/**15 * struct at24_platform_data - data toset up at24 (generic eeprom) driver16 * @byte_len: size of eeprom in byte17 * @page_size: number of byte which canbe written in one go18 * @flags: tunable options, checkAT24_FLAG_* defines19 * @setup: an optional callback invokedafter eeprom is probed; enables kernel20   code to access eeprom via memory_accessor, see example21 * @context: optional parameter passed tosetup()22 *23 * If you set up a custom eeprom type,please double-check the parameters.24 * Especially page_size needs extra care,as you risk data loss if your value25 * is bigger than what the chip actuallysupports!26 *27 * An example in pseudo code for asetup() callback:28 *29 * void get_mac_addr(structmemory_accessor *mem_acc, void *context)30 * {31 * u8 *mac_addr = ethernet_pdata->mac_addr;32 * off_t offset = context;33 *34 * // Read MAC addr from EEPROM35 * if (mem_acc->read(mem_acc, mac_addr, offset, ETH_ALEN) == ETH_ALEN)36 *     pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr);37 * }38 *39 * This function pointer and context cannow be set up in at24_platform_data.40 */4142struct at24_platform_data {43   u32     byte_len;       /* size (sum of all addr) */44   u16     page_size;      /* for writes */45   u8      flags;46#define AT24_FLAG_ADDR16    0x80   /* address pointer is 16 bit */47#define AT24_FLAG_READONLY  0x40   /* sysfs-entry will be read-only */48#define AT24_FLAG_IRUGO     0x20   /* sysfs-entry will be world-readable */49#define AT24_FLAG_TAKE8ADDR 0x10    /* take always 8 addresses (24c00) */5051   void        (*setup)(structmemory_accessor *, void *context);52   void        *context;53};

该结构体用来保存at24系列EEPROM的platform data。byte_len成员变量保存EEPROM的大小,以byte为单位。page_size成员变量用来指定一次最多能写多少个byte。对于Mini2440,定义at24_platform_data结构体变量at24c08:

488static struct at24_platform_data at24c08= {489   .byte_len   = SZ_8K / 8,490   .page_size  = 16,491};

SZ_8K宏即8K,定义在include/linux/sizes.h文件中:

25#define SZ_8K               0x00002000

步骤2:调用i2c_register_board_info注册i2c设备相关信息

对于Mini2440的I2C设备at24c08 EEPROM,由arch/arm/mach-s3c24xx/mach-mini2440.c文件中的mini2440_init函数调用i2c_register_board_info注册i2c设备相关信息,mini2440_init函数内容如下:

622static void __init mini2440_init(void)623{624   struct mini2440_features_t features = { 0 };625   int i;626627   printk(KERN_INFO "MINI2440: Option string mini2440=%s\n",628            mini2440_features_str);629630   /* Parse the feature string */631   mini2440_parse_features(&features, mini2440_features_str);632633   /* turn LCD on */634   s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);635636   /* Turn the backlight early on */637   WARN_ON(gpio_request_one(S3C2410_GPG(4), GPIOF_OUT_INIT_HIGH, NULL));638   gpio_free(S3C2410_GPG(4));639640   /* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s*/641   gpio_request_one(S3C2410_GPB(1), GPIOF_IN, NULL);642   s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP);643   gpio_free(S3C2410_GPB(1));644645   /* mark the key as input, without pullups (there is one on the board) */646   for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) {647       s3c_gpio_setpull(mini2440_buttons[i].gpio, S3C_GPIO_PULL_UP);648       s3c_gpio_cfgpin(mini2440_buttons[i].gpio, S3C2410_GPIO_INPUT);649   }650   if (features.lcd_index != -1) {651       int li;652653       mini2440_fb_info.displays =654           &mini2440_lcd_cfg[features.lcd_index];655656       printk(KERN_INFO "MINI2440: LCD");657       for (li = 0; li < ARRAY_SIZE(mini2440_lcd_cfg); li++)658            if (li == features.lcd_index)659                printk(" [%d:%dx%d]",li,660                   mini2440_lcd_cfg[li].width,661                   mini2440_lcd_cfg[li].height);662            else663                printk(" %d:%dx%d",li,664                    mini2440_lcd_cfg[li].width,665                    mini2440_lcd_cfg[li].height);666       printk("\n");667       s3c24xx_fb_set_platdata(&mini2440_fb_info);668   }669670   s3c24xx_udc_set_platdata(&mini2440_udc_cfg);671   s3c24xx_mci_set_platdata(&mini2440_mmc_cfg);672   s3c_nand_set_platdata(&mini2440_nand_info);673   s3c_i2c0_set_platdata(NULL);674675   i2c_register_board_info(0, mini2440_i2c_devs,676                ARRAY_SIZE(mini2440_i2c_devs));677678   platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));679680   if (features.count) /* the optional features */681       platform_add_devices(features.optional, features.count);682683}

这个函数我们这里只需要关注675行,调用i2c_register_board_info注册mini2440_i2c_devs。mini2440_i2c_devs就是上面定义的i2c_board_info结构体数组,其中定义了at24c08相关信息。

i2c_register_board_info函数定义在drivers/i2c/i2c-boardinfo.c文件中,其内容如下:

42/**43 * i2c_register_board_info - staticallydeclare I2C devices44 * @busnum: identifies the bus to whichthese devices belong45 * @info: vector of i2c devicedescriptors46 * @len: how many descriptors in the vector;may be zero to reserve47 * the specified bus number.48 *49 * Systems using the Linux I2C driverstack can declare tables of board info50 * while they initialize.  This should be done in board-specific initcode51 * near arch_initcall() time, orequivalent, before any I2C adapter driver is52 * registered.  For example, mainboard init code could defineseveral devices,53 * as could the init code for eachdaughtercard in a board stack.54 *55 * The I2C devices will be created later,after the adapter for the relevant56 * bus has been registered.  After that moment, standard driver modeltools57 * are used to bind "new style"I2C drivers to the devices.  The busnumber58 * for any device declared using thisroutine is not available for dynamic59 * allocation.60 *61 * The board info passed can safely be__initdata, but be careful of embedded62 * pointers (for platform_data,functions, etc) since that won't be copied.63 */64int __init65i2c_register_board_info(int busnum,66   struct i2c_board_info const *info, unsigned len)67{68   int status;6970   down_write(&__i2c_board_lock);7172   /* dynamic bus numbers will be assigned after the last static one */73   if (busnum >= __i2c_first_dynamic_bus_num)74       __i2c_first_dynamic_bus_num = busnum + 1;7576   for (status = 0; len; len--, info++) {77       struct i2c_devinfo  *devinfo;7879       devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);80       if (!devinfo) {81            pr_debug("i2c-core: can'tregister boardinfo!\n");82            status = -ENOMEM;83            break;84       }8586       devinfo->busnum = busnum;87       devinfo->board_info = *info;88       list_add_tail(&devinfo->list, &__i2c_board_list);89   }9091   up_write(&__i2c_board_lock);9293   return status;94}

第一个参数busnum表明I2C设备所依附的I2C总线的总线号。

72-74行,如果参数传递进来的busnum 大于等于__i2c_first_dynamic_bus_num,则将__i2c_first_dynamic_bus_num设置为busnum+1。__i2c_first_dynamic_bus_num代表第一个动态分配的I2C总线号,所以,动态分配的I2C总线号总是大于静态分配的I2C总线号。

__i2c_first_dynamic_bus_num定义在drivers/i2c/i2c-boardinfo.c文件中:

38int __i2c_first_dynamic_bus_num;

因为__i2c_first_dynamic_bus_num是一个全局变量,所以其值被自动初始化为0。所以73行的if判断是成立的。

76-89行,循环遍历info数组,用i2c_board_info变量初始化structi2c_devinfo指针变量devinfo,然后将devinfo放入__i2c_board_list链表中。

i2c_devinfo变量定义在drivers/i2c/i2c-core.h文件中:

22struct i2c_devinfo {23   struct list_head    list;24   int         busnum;25   struct i2c_board_info  board_info;26};

可以看到i2c_devinfo结构体只有三个成员变量,busnum用来保存I2C设备所依附的I2C总线号。board_info用来保存I2C设备相关信息。list用于链接到全局链表__i2c_board_list中。

__i2c_board_list 链表定义在drivers/i2c/i2c-boardinfo.c文件中:

35LIST_HEAD(__i2c_board_list);36EXPORT_SYMBOL_GPL(__i2c_board_list);

全局变量__i2c_board_list上挂载着所有的I2C设备的信息,包括I2C设备所在的I2C总线的总线号。

所以,i2c_register_board_info函数并没有创建i2c_client,只是将i2c_devinfo变量放入__i2c_board_list链表中。那么,什么时候才会创建i2c_client呢?这个就与创建I2C设备驱动程序无关了,而是跟I2C adapter驱动程序有关:

注册一个I2C adapter有两种方法,一是调用i2c_add_adapter函数,二是调用i2c_add_numbered_adapter函数。

先来看i2c_add_adapter函数,它定义在drivers/i2c/i2c-core.c文件中:

1099/**1100 * i2c_add_adapter - declare i2cadapter, use dynamic bus number1101 * @adapter: the adapter to add1102 * Context: can sleep1103 *1104 * This routine is used to declare anI2C adapter when its bus number1105 * doesn't matter or when its busnumber is specified by an dt alias.1106 * Examples of bases when the busnumber doesn't matter: I2C adapters1107 * dynamically added by USB links orPCI plugin cards.1108 *1109 * When this returns zero, a new busnumber was allocated and stored1110 * in adap->nr, and the specifiedadapter became available for clients.1111 * Otherwise, a negative errno value isreturned.1112 */1113int i2c_add_adapter(struct i2c_adapter*adapter)1114{1115   struct device *dev = &adapter->dev;1116   int id;11171118   if (dev->of_node) {1119       id = of_alias_get_id(dev->of_node, "i2c");1120       if (id >= 0) {1121            adapter->nr = id;1122            return__i2c_add_numbered_adapter(adapter);1123       }1124   }11251126   mutex_lock(&core_lock);1127   id = idr_alloc(&i2c_adapter_idr, adapter,1128               __i2c_first_dynamic_bus_num, 0,GFP_KERNEL);1129   mutex_unlock(&core_lock);1130   if (id < 0)1131       return id;11321133   adapter->nr = id;11341135   return i2c_register_adapter(adapter);1136}

该函数为参数指定的i2c_adapter动态分配的个I2C总线号,并注册该i2c_adapter。

1118-1124行,忽略。

1127-1133行,调用idr_alloc,动态分配一个id号,并将该id号做为i2c_adapter的I2C总线号。

关于idr机制,我们不详细分析,只需要知道它是一种快速索引机制,它将一个整数ID与一个需要被索引的指针建立联系,方便进行查找。例如,这里idr_alloc返回的id与i2c_adapter建立了索引。idr_alloc的第三个参数指定返回ID的最小值(闭区间),第四个参数指定返回ID的最大值(开区间),即idr_alloc返回的ID大于等于第三个参数,而且必须小于第四个参数。在这个函数中,第三个参数为__i2c_first_dynamic_bus_num,所以返回的id必然是大于等于__i2c_first_dynamic_bus_num的,即动态分配的I2C总线号必然大于__i2c_first_dynamic_bus_num。

1135行,调用i2c_register_adapter注册i2c_adapter。

下面我们来看i2c_add_numbered_adapter,该函数定义在drivers/i2c/i2c-core.c文件中:

1139/**1140 * i2c_add_numbered_adapter - declarei2c adapter, use static bus number1141 * @adap: the adapter to register (withadap->nr initialized)1142 * Context: can sleep1143 *1144 * This routine is used to declare anI2C adapter when its bus number1145 * matters.  For example, use it for I2C adapters fromsystem-on-chip CPUs,1146 * or otherwise built in to thesystem's mainboard, and where i2c_board_info1147 * is used to properly configure I2Cdevices.1148 *1149 * If the requested bus number is setto -1, then this function will behave1150 * identically to i2c_add_adapter, andwill dynamically assign a bus number.1151 *1152 * If no devices have pre-been declaredfor this bus, then be sure to1153 * register the adapter before anydynamically allocated ones.  Otherwise1154 * the required bus ID may not beavailable.1155 *1156 * When this returns zero, thespecified adapter became available for1157 * clients using the bus numberprovided in adap->nr.  Also, the table1158 * of I2C devices pre-declared usingi2c_register_board_info() is scanned,1159 * and the appropriate driver modeldevice nodes are created.  Otherwise, a1160 * negative errno value is returned.1161 */1162int i2c_add_numbered_adapter(structi2c_adapter *adap)1163{1164   if (adap->nr == -1) /* -1 means dynamically assign bus id */1165       return i2c_add_adapter(adap);11661167   return __i2c_add_numbered_adapter(adap);1168}

该函数用于注册参数指定的i2c_adapter,该i2c_adapter的I2C总线号即i2c_adapter.nr必须已经静态设置好了。如果adap->nr为-1,则调用i2c_add_adapter动态分配I2C总线号,再注册。否则,调用__i2c_add_numbered_adapter函数。

__i2c_add_numbered_adapter函数定义在drivers/i2c/i2c-core.c文件中:

1078/**1079 * __i2c_add_numbered_adapter -i2c_add_numbered_adapter where nr is never -11080 * @adap: the adapter to register (withadap->nr initialized)1081 * Context: can sleep1082 *1083 * See i2c_add_numbered_adapter() fordetails.1084 */1085static int__i2c_add_numbered_adapter(struct i2c_adapter *adap)1086{1087   int id;10881089   mutex_lock(&core_lock);1090   id = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1,1091               GFP_KERNEL);1092   mutex_unlock(&core_lock);1093   if (id < 0)1094       return id == -ENOSPC ? -EBUSY : id;10951096   return i2c_register_adapter(adap);1097}

1090-1091行,调用idr_alloc函数,建立idr索引关系。返回的id必须大于等于第三个参数adap->nr,同时必须小于第四个参数adap->nr+1,所以返回的id必然等于adap->nr,即静态指定的I2C总线号。

1096行,调用i2c_register_adapter注册i2c_adapter。

到这里,我们就知道了注册一个i2c_adapter可以调用i2c_add_numbered_adapter函数静态指定一个I2C总线号,也可以调用i2c_add_adapter函数动态分配一个I2C总线号。但是不论哪种方法,最后的注册工作都必须通过调用i2c_register_adapter函数完成。

i2c_register_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

 980staticint i2c_register_adapter(struct i2c_adapter *adap) 981{ 982   int res = 0; 983 984   /* Can't register until after driver model init */ 985   if (unlikely(WARN_ON(!i2c_bus_type.p))) { 986       res = -EAGAIN; 987       goto out_list; 988    } 989 990   /* Sanity checks */ 991   if (unlikely(adap->name[0] == '\0')) { 992       pr_err("i2c-core: Attempt to register an adapter with " 993               "no name!\n"); 994       return -EINVAL; 995    } 996   if (unlikely(!adap->algo)) { 997       pr_err("i2c-core: Attempt to register adapter '%s' with " 998               "no algo!\n",adap->name); 999       return -EINVAL;1000   }10011002   rt_mutex_init(&adap->bus_lock);1003   mutex_init(&adap->userspace_clients_lock);1004   INIT_LIST_HEAD(&adap->userspace_clients);10051006   /* Set default timeout to 1 second if not already set */1007   if (adap->timeout == 0)1008       adap->timeout = HZ;10091010   dev_set_name(&adap->dev, "i2c-%d", adap->nr);1011   adap->dev.bus = &i2c_bus_type;1012   adap->dev.type = &i2c_adapter_type;1013   res = device_register(&adap->dev);1014   if (res)1015       goto out_list;10161017   dev_dbg(&adap->dev, "adapter [%s] registered\n",adap->name);10181019#ifdef CONFIG_I2C_COMPAT1020   res = class_compat_create_link(i2c_adapter_compat_class,&adap->dev,1021                       adap->dev.parent);1022   if (res)1023       dev_warn(&adap->dev,1024             "Failed to createcompatibility class link\n");1025#endif10261027   /* bus recovery specific initialization */1028   if (adap->bus_recovery_info) {1029       struct i2c_bus_recovery_info*bri = adap->bus_recovery_info;10301031       if (!bri->recover_bus) {1032            dev_err(&adap->dev, "Norecover_bus() found, not using recovery\n");1033            adap->bus_recovery_info = NULL;1034            goto exit_recovery;1035       }10361037       /* Generic GPIO recovery */1038       if (bri->recover_bus == i2c_generic_gpio_recovery) {1039            if(!gpio_is_valid(bri->scl_gpio)) {1040                dev_err(&adap->dev,"Invalid SCL gpio, not using recovery\n");1041                adap->bus_recovery_info =NULL;1042                goto exit_recovery;1043            }10441045            if(gpio_is_valid(bri->sda_gpio))1046                bri->get_sda =get_sda_gpio_value;1047           else1048                bri->get_sda = NULL;10491050            bri->get_scl =get_scl_gpio_value;1051            bri->set_scl =set_scl_gpio_value;1052       } else if (!bri->set_scl || !bri->get_scl) {1053            /* Generic SCL recovery */1054            dev_err(&adap->dev, "No{get|set}_gpio() found, not using recovery\n");1055            adap->bus_recovery_info = NULL;1056       }1057   }10581059exit_recovery:1060   /* create pre-declared device nodes */1061   if (adap->nr < __i2c_first_dynamic_bus_num)1062       i2c_scan_static_board_info(adap);10631064   /* Notify drivers */1065   mutex_lock(&core_lock);1066   bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);1067   mutex_unlock(&core_lock);10681069   return 0;10701071out_list:1072   mutex_lock(&core_lock);1073   idr_remove(&i2c_adapter_idr, adap->nr);1074   mutex_unlock(&core_lock);1075   return res;1076}

984-1000行,做一些必要的检查工作。

1002-1008行,做一些简单的i2c_adapter成员变量初始化工作。

1010-1013行,初始化i2c_adapter.dev,并调用device_register注册i2c_adapter.dev。

1028-1057行,I2C总线恢复时相关的初始化工作。

1060-1062行,因为动态分析的I2C总线号必须大于或等于__i2c_first_dynamic_bus_num,所以,如果adap->nr< __i2c_first_dynamic_bus_num,说明是静态指定的I2C总线号,此时,要调用i2c_scan_static_board_info函数探测I2C总线上静态注册的I2C设备。

i2c_scan_static_board_info函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

 941staticvoid i2c_scan_static_board_info(struct i2c_adapter *adapter) 942{ 943   struct i2c_devinfo  *devinfo; 944 945   down_read(&__i2c_board_lock); 946   list_for_each_entry(devinfo, &__i2c_board_list, list) { 947       if (devinfo->busnum == adapter->nr 948                &&!i2c_new_device(adapter, 949                       &devinfo->board_info)) 950           dev_err(&adapter->dev, 951                "Can't create device at0x%02x\n", 952                devinfo->board_info.addr); 953    } 954   up_read(&__i2c_board_lock); 955}

946-953行,遍历__i2c_board_list链表,如果devinfo->busnum等于adapter->nr,即链表节点所代表的I2C设备的I2C总线号等于i2c_adapter的I2C总线号,则调用i2c_new_device创建并注册I2C设备对应的i2c_client结构体。

到这里,就和我们在本文开始部分介绍的静态注册的i2c_board_info信息联系起来了。回忆一下我们通过调用i2c_register_board_info函数将将包含所有I2C设备的i2c_board_info信息的i2c_devinfo变量加入到__i2c_board_list链表中。现在在注册i2c_adater时,又通过调用i2c_scan_static_board_info函数遍历__i2c_board_list链表,查找属于对应i2c_adapter的I2C设备,如果找到,调用i2c_new_device创建对应的i2c_client结构体。

i2c_new_device函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

 612/** 613* i2c_new_device - instantiate an i2c device 614* @adap: the adapter managing the device 615* @info: describes one I2C device; bus_num is ignored 616* Context: can sleep 617* 618* Create an i2c device. Binding is handled through driver model 619* probe()/remove() methods.  A driver maybe bound to this device when we 620* return from this function, or any later moment (e.g. maybe hotplugging will 621* load the driver module).  This call isnot appropriate for use by mainboard 622* initialization logic, which usually runs during an arch_initcall() long 623* before any i2c_adapter could exist. 624* 625* This returns the new i2c client, which may be saved for later use with 626* i2c_unregister_device(); or NULL to indicate an error. 627*/ 628struct i2c_client * 629i2c_new_device(struct i2c_adapter *adap,struct i2c_board_info const *info) 630{ 631   struct i2c_client   *client; 632   int         status; 633 634   client = kzalloc(sizeof *client, GFP_KERNEL); 635   if (!client) 636       return NULL; 637 638   client->adapter = adap; 639 640   client->dev.platform_data = info->platform_data; 641 642   if (info->archdata) 643       client->dev.archdata = *info->archdata; 644 645   client->flags = info->flags; 646   client->addr = info->addr; 647   client->irq = info->irq; 648 649   strlcpy(client->name, info->type, sizeof(client->name)); 650 651   /* Check for address validity */ 652   status = i2c_check_client_addr_validity(client); 653   if (status) { 654        dev_err(&adap->dev,"Invalid %d-bit I2C address 0x%02hx\n", 655            client->flags & I2C_CLIENT_TEN ?10 : 7, client->addr); 656       goto out_err_silent; 657    } 658 659   /* Check for address business */ 660   status = i2c_check_addr_busy(adap, client->addr); 661   if (status) 662       goto out_err; 663 664   client->dev.parent = &client->adapter->dev; 665   client->dev.bus = &i2c_bus_type; 666   client->dev.type = &i2c_client_type; 667   client->dev.of_node = info->of_node; 668   ACPI_HANDLE_SET(&client->dev, info->acpi_node.handle); 669 670   /* For 10-bit clients, add an arbitrary offset to avoid collisions */ 671   dev_set_name(&client->dev, "%d-%04x",i2c_adapter_id(adap), 672            client->addr | ((client->flags & I2C_CLIENT_TEN) 673                     ? 0xa000 : 0)); 674    status =device_register(&client->dev); 675   if (status) 676       goto out_err; 677 678   dev_dbg(&adap->dev, "client [%s] registered with bus id%s\n", 679       client->name, dev_name(&client->dev)); 680 681   return client; 682 683out_err: 684   dev_err(&adap->dev, "Failed to register i2c client %s at0x%02x " 685       "(%d)\n", client->name, client->addr, status); 686out_err_silent: 687   kfree(client); 688   return NULL; 689}

这个函数根据参数传递进来的信息,创建并注册i2c_client。

634行,为i2c_client变量分配内存空间。

638行,将i2c_client.adapter设置为参数传递进来的i2c_adapter。

640 行,将i2c_client.dev.platform_data设置为 info->platform_data;

645行,将i2c_client.flags设置为info->flags;

646行,将i2c_client.addr设置为info->addr;

647行,将i2c_client.irq设置为info->irq;

649行,将i2c_client.name设置为info->type;

651-657行,检查指定的I2C设备地址是否有效。

660-662行,检查指定的I2C设备地址是否忙。

664-674行,初始化i2c_client.dev,并调用device_register注册i2c_client.dev。

i2c_register_adapter函数我们还有一点内容没有分析完,回到i2c_register_adapter函数,上面我们分析到了1062行的i2c_scan_static_board_info(adap),只有在adap->nr小于__i2c_first_dynamic_bus_num即静态指定了i2c_adapter的I2C总线号的情况下,才会调用这个函数。对于动态分配I2C总线号的情况,直接跳过。这就说明,只有在静态指定i2c_adapter的I2C总线号的情况下,才会扫描静态注册的I2C设备,如果动态指定i2c_adapter的I2C总线号,不会扫描静态注册的I2C设备。对于I2C驱动程序,这种静态注册的方式,称为new-style driver;而动态探测的方式,称为legacy driver。

下面我们继续分析i2c_register_adapter函数,前面调用i2c_scan_static_board_info实例化了静态注册的I2C设备,下面要完成对I2C设备的动态探测和实例化:

不论是静态指定还是动态分配I2C总线号,都会调用到1066行的bus_for_each_drv函数。

1066行,调用bus_for_each_drv函数,该函数定义在drivers/base/bus.c文件中,其内容如下:

 417/** 418 * bus_for_each_drv - driver iterator 419 * @bus: bus we're dealing with. 420 * @start: driver to start iterating on. 421 * @data: data to pass to the callback. 422 * @fn: function to call for each driver. 423 * 424 * This is nearly identical to the device iterator above. 425 * We iterate over each driver that belongs to @bus, and call 426 * @fn for each. If @fn returns anything but 0, we break out 427 * and return it. If @start is not NULL, we use it as the head 428 * of the list. 429 * 430 * NOTE: we don't return the driver that returns a non-zero 431 * value, nor do we leave the reference count incremented for that 432 * driver. If the caller needs to know that info, it must set it 433 * in the callback. It must also be sure to increment the refcount 434 * so it doesn't disappear before returning to the caller. 435 */ 436int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, 437             void *data, int (*fn)(struct device_driver *, void *)) 438{ 439    struct klist_iter i; 440    struct device_driver *drv; 441    int error = 0; 442 443    if (!bus) 444        return -EINVAL; 445 446    klist_iter_init_node(&bus->p->klist_drivers, &i, 447                 start ? &start->p->knode_bus : NULL); 448    while ((drv = next_driver(&i)) && !error) 449        error = fn(drv, data); 450    klist_iter_exit(&i); 451    return error; 452}

这个函数我们在《Linux设备模型分析之device(基于3.10.1内核)》一文中已经分析过了。448-449行,这个while循环依次遍历bus->p->klist_drivers中的所有device_driver,对于每个device_driver,调用fn(drv,data)函数。这里,传递过来的fn参数是__process_new_adapter,data参数是adap。这个循环是一个关键点,注册一个新的i2c_adapter后,要为该i2c_adapter上的i2c设备匹配驱动程序,这个匹配过程就是通过这个循环调用__process_new_adapter函数完成的。
__process_new_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
 975static int __process_new_adapter(struct device_driver *d, void *data) 976{ 977    return i2c_do_add_adapter(to_i2c_driver(d), data); 978}

注意i2c_do_add_adapter函数的第一个参数,从device_driver转换为i2c_driver。
i2c_do_add_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
 957static int i2c_do_add_adapter(struct i2c_driver *driver, 958                  struct i2c_adapter *adap) 959{ 960    /* Detect supported devices on that bus, and instantiate them */ 961    i2c_detect(adap, driver); 962 963    /* Let legacy drivers scan this bus for matching devices */ 964    if (driver->attach_adapter) { 965        dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n", 966             driver->driver.name); 967        dev_warn(&adap->dev, "Please use another way to instantiate " 968             "your i2c_client\n"); 969        /* We ignore the return code; if it fails, too bad */ 970        driver->attach_adapter(adap); 971    } 972    return 0; 973}

961行,调用i2c_detect函数,探测并初始化该i2c总线上的i2c设备。该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
1730static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)1731{1732    const unsigned short *address_list;1733    struct i2c_client *temp_client;1734    int i, err = 0;1735    int adap_id = i2c_adapter_id(adapter);17361737    address_list = driver->address_list;1738    if (!driver->detect || !address_list)1739        return 0;17401741    /* Stop here if the classes do not match */1742    if (!(adapter->class & driver->class))1743        return 0;17441745    /* Set up a temporary client to help detect callback */1746    temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);1747    if (!temp_client)1748        return -ENOMEM;1749    temp_client->adapter = adapter;17501751    for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {1752        dev_dbg(&adapter->dev, "found normal entry for adapter %d, "1753            "addr 0x%02x\n", adap_id, address_list[i]);1754        temp_client->addr = address_list[i];1755        err = i2c_detect_address(temp_client, driver);1756        if (unlikely(err))1757            break;1758    }17591760    kfree(temp_client);1761    return err;1762}

1755行,调用i2c_detect_address,探测指定的地址上的I2C设备是否存在,如果存在,注册该i2c设备。i2c_detect_address函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
1675static int i2c_detect_address(struct i2c_client *temp_client,1676                  struct i2c_driver *driver)1677{1678    struct i2c_board_info info;1679    struct i2c_adapter *adapter = temp_client->adapter;1680    int addr = temp_client->addr;1681    int err;16821683    /* Make sure the address is valid */1684    err = i2c_check_addr_validity(addr);1685    if (err) {1686        dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",1687             addr);1688        return err;1689    }16901691    /* Skip if already in use */1692    if (i2c_check_addr_busy(adapter, addr))1693        return 0;16941695    /* Make sure there is something at this address */1696    if (!i2c_default_probe(adapter, addr))1697        return 0;16981699    /* Finally call the custom detection function */1700    memset(&info, 0, sizeof(struct i2c_board_info));1701    info.addr = addr;1702    err = driver->detect(temp_client, &info);1703    if (err) {1704        /* -ENODEV is returned if the detection fails. We catch it1705           here as this isn't an error. */1706        return err == -ENODEV ? 0 : err;1707    }17081709    /* Consistency check */1710    if (info.type[0] == '\0') {1711        dev_err(&adapter->dev, "%s detection function provided "1712            "no name for 0x%x\n", driver->driver.name,1713            addr);1714    } else {1715        struct i2c_client *client;17161717        /* Detection succeeded, instantiate the device */1718        dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n",1719            info.type, info.addr);1720        client = i2c_new_device(adapter, &info);1721        if (client)1722            list_add_tail(&client->detected, &driver->clients);1723        else1724            dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n",1725                info.type, info.addr);1726    }1727    return 0;1728}

1702行,调用driver->detect。
1720行,如果探测到i2c设备确实存在,调用i2c_new_device函数初始化对应的i2c_client结构体并注册。i2c_new_device函数我们在前面已经分析过。
至此,i2c_adapter的注册过程我们就清楚了。同时,我们对I2C设备的注册定义和注册也就完全清楚了。

 

二、定义和注册I2C设备驱动

步骤1:定义i2c_driver结构体变量。

Linux I2C设备驱动程序对应的结构体是structi2c_driver,定义在include/linux/i2c.h文件中:

124/**125 * struct i2c_driver - represent an I2Cdevice driver126 * @class: What kind of i2c device weinstantiate (for detect)127 * @attach_adapter: Callback for busaddition (deprecated)128 * @probe: Callback for device binding129 * @remove: Callback for deviceunbinding130 * @shutdown: Callback for deviceshutdown131 * @suspend: Callback for device suspend132 * @resume: Callback for device resume133 * @alert: Alert callback, for examplefor the SMBus alert protocol134 * @command: Callback for bus-wide signaling(optional)135 * @driver: Device driver model driver136 * @id_table: List of I2C devicessupported by this driver137 * @detect: Callback for devicedetection138 * @address_list: The I2C addresses toprobe (for detect)139 * @clients: List of detected clients wecreated (for i2c-core use only)140 *141 * The driver.owner field should be setto the module owner of this driver.142 * The driver.name field should be setto the name of this driver.143 *144 * For automatic device detection, both @detectand @address_list must145 * be defined. @class should also beset, otherwise only devices forced146 * with module parameters will becreated. The detect function must147 * fill at least the name field of thei2c_board_info structure it is148 * handed upon successful detection, andpossibly also the flags field.149 *150 * If @detect is missing, the driverwill still work fine for enumerated151 * devices. Detected devices simplywon't be supported. This is expected152 * for the many I2C/SMBus devices whichcan't be detected reliably, and153 * the ones which can always beenumerated in practice.154 *155 * The i2c_client structure which ishanded to the @detect callback is156 * not a real i2c_client. It isinitialized just enough so that you can157 * call i2c_smbus_read_byte_data andfriends on it. Don't do anything158 * else with it. In particular, callingdev_dbg and friends on it is159 * not allowed.160 */161struct i2c_driver {162   unsigned int class;163164   /* Notifies the driver that a new bus has appeared. You should avoid165    * using this, it will be removed in a near future.166    */167   int (*attach_adapter)(struct i2c_adapter *) __deprecated;168169   /* Standard driver model interfaces */170   int (*probe)(struct i2c_client *, const struct i2c_device_id *);171   int (*remove)(struct i2c_client *);172173   /* driver model interfaces that don't relate to enumeration  */174   void (*shutdown)(struct i2c_client *);175   int (*suspend)(struct i2c_client *, pm_message_t mesg);176   int (*resume)(struct i2c_client *);177178   /* Alert callback, for example for the SMBus alert protocol.179    * The format and meaning of the data value depends on the protocol.180    * For the SMBus alert protocol, there is a single bit of data passed181    * as the alert response's low bit ("event flag").182    */183   void (*alert)(struct i2c_client *, unsigned int data);184185   /* a ioctl like command that can be used to perform specific functions186    * with the device.187    */188   int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);189190   struct device_driver driver;191   const struct i2c_device_id *id_table;192193   /* Device detection callback for automatic device creation */194   int (*detect)(struct i2c_client *, struct i2c_board_info *);195   const unsigned short *address_list;196   struct list_head clients;197};

注意注释中的说明,driver.name和driver.owner必须初始化。

id_table成员变量是i2c_device_id结构体指针,它用来保存该i2c_driver支持的I2C设备列表。

struct i2c_device_id定义在include/linux/mod_devicetable.h文件中,其内容如下:

419struct i2c_device_id {420   char name[I2C_NAME_SIZE];421   kernel_ulong_t driver_data; /* Data private to the driver */422};

对于Mini2440的I2C设备at24c08 EEPROM,其对应的i2c_driver结构体变量实现在drivers/misc/eeprom/at24.c文件中:

677static struct i2c_driver at24_driver = {678   .driver = {679       .name = "at24",680       .owner = THIS_MODULE,681   },682   .probe = at24_probe,683   .remove = at24_remove,684   .id_table = at24_ids,685};

678-681行,初始化了要求必须初始化的i2c_driver.driver.name和i2c_driver.driver.owner。

682行,指定i2c_driver.probe函数为at24_probe。

683行,指定i2c_driver.remove函数为at24_remove。

684行,指定i2c_driver.id_table为at24_ids。

at24_ids定义在drivers/misc/eeprom/at24.c文件中,其内容如下:

99#define AT24_SIZE_BYTELEN 5100#define AT24_SIZE_FLAGS 8101102#define AT24_BITMASK(x) (BIT(x) - 1)103104/* create non-zero magic value for giveneeprom parameters */105#define AT24_DEVICE_MAGIC(_len,_flags)         \106   ((1 << AT24_SIZE_FLAGS | (_flags))      \107       << AT24_SIZE_BYTELEN | ilog2(_len))108109static const struct i2c_device_idat24_ids[] = {110   /* needs 8 addresses as A0-A2 are ignored */111   { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) },112   /* old variants can't be handled with this generic entry! */113   { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) },114   { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) },115   /* spd is a 24c02 in memory DIMMs */116   { "spd", AT24_DEVICE_MAGIC(2048 / 8,117       AT24_FLAG_READONLY | AT24_FLAG_IRUGO) },118   { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) },119   /* 24rf08 quirk is handled at i2c-core */120   { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) },121   { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) },122   { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) },123   { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) },124   { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) },125   { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) },126   { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) },127   { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16)},128   { "at24", 0 },129   { /* END OF LIST */ }130};

可以看到,at24_driver支持很多设备,其中包括Mini2440使用的24c08 EEPROM。

 

步骤2:调用i2c_add_driver注册i2c_driver结构体变量。

对于Mini2440的I2C设备at24c08 EEPROM,这一步工作是在drivers/misc/eeprom/at24.c文件中的at24_init函数中完成的:

687static int __init at24_init(void)688{689   if (!io_limit) {690       pr_err("at24: io_limit must not be 0!\n");691       return -EINVAL;692   }693694   io_limit = rounddown_pow_of_two(io_limit);695   return i2c_add_driver(&at24_driver);696}

695行,调用i2c_add_driver注册上面定义的at24_driver。

i2c_add_driver是一个宏,定义在include/linux/i2c.h文件中:
497/* use a define to avoid include chaining to get THIS_MODULE */498#define i2c_add_driver(driver) \499    i2c_register_driver(THIS_MODULE, driver)

i2c_register_driver函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
1307/*1308 * An i2c_driver is used with one or more i2c_client (device) nodes to access1309 * i2c slave chips, on a bus instance associated with some i2c_adapter.1310 */13111312int i2c_register_driver(struct module *owner, struct i2c_driver *driver)1313{1314    int res;13151316    /* Can't register until after driver model init */1317    if (unlikely(WARN_ON(!i2c_bus_type.p)))1318        return -EAGAIN;13191320    /* add the driver to the list of i2c drivers in the driver core */1321    driver->driver.owner = owner;1322    driver->driver.bus = &i2c_bus_type;13231324    /* When registration returns, the driver core1325     * will have called probe() for all matching-but-unbound devices.1326     */1327    res = driver_register(&driver->driver);1328    if (res)1329        return res;13301331    /* Drivers should switch to dev_pm_ops instead. */1332    if (driver->suspend)1333        pr_warn("i2c-core: driver [%s] using legacy suspend method\n",1334            driver->driver.name);1335    if (driver->resume)1336        pr_warn("i2c-core: driver [%s] using legacy resume method\n",1337            driver->driver.name);13381339    pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);13401341    INIT_LIST_HEAD(&driver->clients);1342    /* Walk the adapters that are already present */1343    i2c_for_each_dev(driver, __process_new_driver);13441345    return 0;1346}

1327行,调用driver_register注册i2c_driver.driver。参考《 Linux设备模型分析之device_driver(基于3.10.1内核)》对Linux设备模型的分析,在driver_register执行过程中,如果I2C总线上找到了与该驱动匹配的I2C设备,则i2c_driver.probe函数会被调用执行。

1343行,调用i2c_for_each_dev遍历所有已存在的i2c_adapter。该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
1288int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))1289{1290    int res;12911292    mutex_lock(&core_lock);1293    res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);1294    mutex_unlock(&core_lock);12951296    return res;1297}


1293行,调用bus_for_each_dev,这个函数定义在drivers/base/bus.c文件中,其内容如下:

286intbus_for_each_dev(struct bus_type *bus, struct device *start, 287            void *data, int (*fn)(struct device *, void *)) 288{ 289   struct klist_iter i; 290   struct device *dev; 291   int error = 0; 292 293   if (!bus || !bus->p) 294       return -EINVAL; 295 296   klist_iter_init_node(&bus->p->klist_devices, &i, 297                 (start ?&start->p->knode_bus : NULL)); 298   while ((dev = next_device(&i)) && !error) 299       error = fn(dev, data); 300   klist_iter_exit(&i); 301   return error; 302}

我们在《 Linux设备模型分析之device_driver(基于3.10.1内核)》一文中已经分析过这个函数。这里,传递过来的data参数是要注册的i2c_driver,fn参数是__process_new_driver函数,所以我们来看__process_new_driver函数,该函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:
1300static int __process_new_driver(structdevice *dev, void *data)1301{1302   if (dev->type != &i2c_adapter_type)1303       return 0;1304   return i2c_do_add_adapter(data, to_i2c_adapter(dev));1305}

i2c_do_add_adapter函数定义在drivers/i2c/i2c-core.c文件中,其内容如下:

957static int i2c_do_add_adapter(structi2c_driver *driver, 958                  struct i2c_adapter *adap) 959{ 960   /* Detect supported devices on that bus, and instantiate them */ 961   i2c_detect(adap, driver); 962 963   /* Let legacy drivers scan this bus for matching devices */ 964   if (driver->attach_adapter) { 965       dev_warn(&adap->dev, "%s: attach_adapter method isdeprecated\n", 966            driver->driver.name); 967       dev_warn(&adap->dev, "Please use another way to instantiate" 968            "your i2c_client\n"); 969       /* We ignore the return code; if it fails, too bad */ 970       driver->attach_adapter(adap); 971    } 972   return 0; 973}

这个函数我们在分析i2c_adapter的注册过程时已经分析过了,它主要完成i2c_driver与i2c_adapter上的i2c设备的匹配工作,如果匹配成功,初始化并注册对应的i2c_client。

至此,i2c_driver的注册过程我们就清楚了。


步骤3:实现i2c_driver中要示实现的函数

对于Mini2440的I2C设备at24c08 EEPROM,at24_driver要求实现的是i2c_driver.probe和i2c_driver.remove函数。


0 0
原创粉丝点击