I2C的设备ID,包含一个设备名字,和私有数据结构(目前没用到),属于i2c_driver;
include/linux/mod_devicetable.h
#define I2C_NAME_SIZE 20
#define I2C_MODULE_PREFIX "i2c:"
struct i2c_device_id {
char name[I2C_NAME_SIZE];
kernel_ulong_t driver_data /* Data private to the driver */
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
内核关于I2C_driver是这样注释的。为了完成设备自动检测,需要实现detect、address_data、class(这三项在i2c_detect中需要,不过我这板子上没有I2C设备,通过调试信息可以发现没有设置,直接return 0),driver.owner, driver.name(i2c_register_driver中需要)的设置。否则,将只创建强制使用模块参数的设备。
在完成detect函数的时候,最少需要填充i2c_board_info的name域。i2c_board_info结构体在成功detect后将被移交,可能还有flag域。
就算没有实现detect函数,驱动依然可以枚举I2C设备,但是不会支持设备。//红色是文章中出现并设置的变量
i2c_client结构体,是交给detect的回调信息,并不是真的i2c_client.完成足够的初始化,这样就可以调用i2c_smbus_read_byte_data。
include/linux/i2c.h
struct i2c_driver {
unsigned int class; //I2C设备实例的种类(for detect)
/* 标准驱动模型接口 */
int (*probe)(struct i2c_client *, const struct i2c_device_id *);//设备和驱动match之后的回调函数
int (*remove)(struct i2c_client *);//设备和驱动解绑的回调函数
struct device_driver driver;//设备模型驱动,见设备驱动第十四章设备模型
const struct i2c_device_id *id_table;//I2C设备列表support
/* 设备检测回调,用于自动创建设备 */
int (*detect)(struct i2c_client *, struct i2c_board_info *);//设备探测回调函数
const unsigned short *address_list;//The I2C addresses to probe (for detect)
struct list_head clients;//List of detected clients we created (for i2c-core use only)
/* 与枚举设备无关的驱动模型接口 */
void (*shutdown)(struct i2c_client *);//设备关机回调函数
int (*suspend)(struct i2c_client *, pm_message_t mesg);//设备挂起回调
int (*resume)(struct i2c_client *);//设备恢复回调
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);//类似于ioctl
};
i2c_driver的实现,完成了标准模型接口函数probe、remove。配置了i2c_device_id、和device_driver的name配置。
arch/arm/mach-davinci/board-da850-sdi.c
typedef struct cdce_reg {
u8 addr;
u8 val;
} cdce_reg; //创建地址->数值键值对,服务probe
static int cdce_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
int i;
struct cdce_reg regData[] = {
{ 0x03, 0x09 },
{ 0x14, 0x6d },
{ 0x18, 0xc0 },
{ 0x19, 0x04 },
{ 0x1A, 0x82 },
{ 0x1B, 0x07 },
};
for (i=0; i < sizeof(regData) / (sizeof(cdce_reg)); i++) {
ret = i2c_smbus_write_byte_data(client,
regData[i].addr | 0x80, regData[i].val);
if (ret) {
printk (KERN_WARNING "Failed to write to CDCE13 register 0x%02x.", regData[i].addr);
return ret;
}
}
return ret;
}//match完成,配置cdce913
static int __devexit cdce_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id cdce_id[] = {
{ "cdce913", 0 },//设置i2c的名字,和私有结构数据
{ }
};
static struct i2c_driver cdce_driver = {
.driver = {
.name = "cdce913", //设置了注释需要的driver.name
},
.probe = cdce_probe,
.remove = cdce_remove,
.id_table = cdce_id,
};
static __init void da850_evm_init(void)
{
i2c_add_driver(&cdce_driver);
}
i2c_add_driver,这样就把I2C驱动注册进系统,完成I2C驱动的初始化。下面看深层次的i2c_add_drvier做了什么工作
include/linux/i2c.h
/* use a define to avoid include chaining to get THIS_MODULE */
#define i2c_add_driver(driver) \
i2c_register_driver(THIS_MODULE, driver)
drivers/i2c/i2c-core.c
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
drivers/i2c/i2c-core.c
int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
/*设备模型注册见设备驱动程序第十四章,设备模型*/
/*i2c_driver 与 1个或多个i2c_client节点用于访问i2c slave芯片*/
int res;
driver->driver.owner = owner; //在这里设置了i2c_driver 注释里面要求设置drvier的变量
driver->driver.bus = &i2c_bus_type;
res = driver_register(&driver->driver);
if (res)
return res;
INIT_LIST_HEAD(&driver->clients);
/* 遍历已存在的适配器 */
i2c_for_each_dev(driver, __process_new_driver);
return 0;
}
EXPORT_SYMBOL(i2c_register_driver);
drivers/i2c/i2c-core.c
int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
{
int res;
mutex_lock(&core_lock);
res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);
mutex_unlock(&core_lock);
return res;
}
EXPORT_SYMBOL_GPL(i2c_for_each_dev);
drivers/base/bus.c
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
struct klist_iter i;
struct device *dev;
int error = 0;
/*构建了一个以i为迭代器,klist_devices内核设备链表为头,插入start节点的klist*/
klist_iter_init_node(&bus->p->klist_devices, &i,
(start ? &start->p->knode_bus : NULL));
/*data是i2c_driver, fn是__process_new_driver
*遍历与总线关联的设备列表,关于klist_devices可见文章最后结构体*/
while ((dev = next_device(&i)) && !error)
error = fn(dev, data);
klist_iter_exit(&i);
return error;
}
EXPORT_SYMBOL_GPL(bus_for_each_dev);
drivers/i2c/i2c-core.c
static int __process_new_driver(struct device *dev, void *data)
{
/*i2c添加适配器, data是驱动,通过设备dev找到适配器adapter*/
return i2c_do_add_adapter(data, to_i2c_adapter(dev));
}
static int i2c_do_add_adapter(struct i2c_driver *driver,
struct i2c_adapter *adap)
{
/* Detect supported devices on that bus, and instantiate them */
i2c_detect(adap, driver);
return 0;
}
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
{
const unsigned short *address_list;
struct i2c_client *temp_client;
int i, err = 0;
int adap_id = i2c_adapter_id(adapter);
address_list = driver->address_list;
if (!driver->detect || !address_list)
return 0;
/* Stop here if the classes do not match */
if (!(adapter->class & driver->class))
return 0;
/* Set up a temporary client to help detect callback */
temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!temp_client)
return -ENOMEM;
temp_client->adapter = adapter;
for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
"addr 0x%02x\n", adap_id, address_list[i]);
temp_client->addr = address_list[i];
err = i2c_detect_address(temp_client, driver);
if (unlikely(err))
break;
}
kfree(temp_client);
return err;
}
static int i2c_detect_address(struct i2c_client *temp_client,
struct i2c_driver *driver)
{
struct i2c_board_info info;
struct i2c_adapter *adapter = temp_client->adapter;
int addr = temp_client->addr;
int err;
/* Finally call the custom detection function */
memset(&info, 0, sizeof(struct i2c_board_info));
info.addr = addr;
err = driver->detect(temp_client, &info);
if (err) {
/* -ENODEV is returned if the detection fails. We catch it
here as this isn't an error. */
return err == -ENODEV ? 0 : err;
}
/* Consistency check */
if (info.type[0] == '\0') {
dev_err(&adapter->dev, "%s detection function provided "
"no name for 0x%x\n", driver->driver.name,
addr);
} else {
struct i2c_client *client;
/* Detection succeeded, instantiate the device */
dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n",
info.type, info.addr);
client = i2c_new_device(adapter, &info);
if (client)
list_add_tail(&client->detected, &driver->clients);
else
dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n",
info.type, info.addr);
}
return 0
}
include/linux/device.h
/**
* struct bus_type - The bus type of the device
*
* @name: The name of the bus.
* @dev_name: Used for subsystems to enumerate devices like ("foo%u", dev->id).
* @dev_root: Default device to use as the parent.
* @bus_attrs: Default attributes of the bus.
* @dev_attrs: Default attributes of the devices on the bus.
* @drv_attrs: Default attributes of the device drivers on the bus.
* @match: Called, perhaps multiple times, whenever a new device or driver
* is added for this bus. It should return a nonzero value if the
* given device can be handled by the given driver.
* @uevent: Called when a device is added, removed, or a few other things
* that generate uevents to add the environment variables.
* @probe: Called when a new device or driver add to this bus, and callback
* the specific driver's probe to initial the matched device.
* @remove: Called when a device removed from this bus.
* @shutdown: Called at shut-down time to quiesce the device.
* @suspend: Called when a device on this bus wants to go to sleep mode.
* @resume: Called to bring a device on this bus out of sleep mode.
* @pm: Power management operations of this bus, callback the specific
* device driver's pm-ops.
* @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU
* driver implementations to a bus and allow the driver to do
* bus-specific setup
* @p: The private data of the driver core, only the driver core can
* touch this.
*
* A bus is a channel between the processor and one or more devices. For the
* purposes of the device model, all devices are connected via a bus, even if
* it is an internal, virtual, "platform" bus. Buses can plug into each other.
* A USB controller is usually a PCI device, for example. The device model
* represents the actual connections between buses and the devices they control.
* A bus is represented by the bus_type structure. It contains the name, the
* default attributes, the bus' methods, PM operations, and the driver core's
* private data.
*/
struct bus_type {
const char *name;
const char *dev_name;
struct device *dev_root;
struct bus_attribute *bus_attrs;
struct device_attribute *dev_attrs;
struct driver_attribute *drv_attrs;
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
const struct dev_pm_ops *pm;
struct iommu_ops *iommu_ops;
struct subsys_private *p;
};
drivers/base/base.h
/**
* struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
*
* @subsys - the struct kset that defines this subsystem
* @devices_kset - the subsystem's 'devices' directory
* @interfaces - list of subsystem interfaces associated
* @mutex - protect the devices, and interfaces lists.
*
* @drivers_kset - the list of drivers associated
* @klist_devices - the klist to iterate over the @devices_kset
* @klist_drivers - the klist to iterate over the @drivers_kset
* @bus_notifier - the bus notifier list for anything that cares about things
* on this bus.
* @bus - pointer back to the struct bus_type that this structure is associated
* with.
*
* @glue_dirs - "glue" directory to put in-between the parent device to
* avoid namespace conflicts
* @class - pointer back to the struct class that this structure is associated
* with.
*
* This structure is the one that is the actual kobject allowing struct
* bus_type/class to be statically allocated safely. Nothing outside of the
* driver core should ever touch these fields.
*/
struct subsys_private {
struct kset subsys;
struct kset *devices_kset;
struct list_head interfaces;
struct mutex mutex;
struct kset *drivers_kset;
struct klist klist_devices;
struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
unsigned int drivers_autoprobe:1;
struct bus_type *bus;
struct kset glue_dirs;
struct class *class;
};
201 include/linux/i2c.h
/**
202 * struct i2c_client - represent an I2C slave device
203 * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
204 * I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
205 * @addr: Address used on the I2C bus connected to the parent adapter.
206 * @name: Indicates the type of the device, usually a chip name that's
207 * generic enough to hide second-sourcing and compatible revisions.
208 * @adapter: manages the bus segment hosting this I2C device
209 * @driver: device's driver, hence pointer to access routines
210 * @dev: Driver model device node for the slave.
211 * @irq: indicates the IRQ generated by this device (if any)
212 * @detected: member of an i2c_driver.clients list or i2c-core's
213 * userspace_devices list
214 *
215 * An i2c_client identifies a single device (i.e. chip) connected to an
216 * i2c bus. The behaviour exposed to Linux is defined by the driver
217 * managing the device.
218 */
219 struct i2c_client {
220 unsigned short flags; /* div., see below */
221 unsigned short addr; /* chip address - NOTE: 7bit */
222 /* addresses are stored in the */
223 /* _LOWER_ 7 bits */
224 char name[I2C_NAME_SIZE];
225 struct i2c_adapter *adapter; /* the adapter we sit on */
226 struct i2c_driver *driver; /* and our access routines */
227 struct device dev; /* the device structure */
228 int irq; /* irq issued by device */
229 struct list_head detected;
230 };
/*
* i2c_adapter is the structure used to identify a physical i2c bus along
* with the access algorithms necessary to access it.
*/
struct i2c_adapter {
struct module *owner;
unsigned int class; /* classes to allow probing for */
const struct i2c_algorithm *algo; /* the algorithm to access the bus */
void *algo_data;
/* data fields that are valid for all devices */
struct rt_mutex bus_lock;
int timeout; /* in jiffies */
int retries;
struct device dev; /* the adapter device */
int nr;
char name[48];
struct completion dev_released;
struct mutex userspace_clients_lock;
struct list_head userspace_clients;
};
drivers/base/driver.c
214 /**
215 * driver_register - register driver with bus
216 * @drv: driver to register
217 *
218 * We pass off most of the work to the bus_add_driver() call,
219 * since most of the things we have to do deal with the bus
220 * structures.
221 */
222 int driver_register(struct device_driver *drv)
223 {
224 int ret;
225 struct device_driver *other;
226
235 other = driver_find(drv->name, drv->bus);
236 if (other) {
237 put_driver(other);
238 printk(KERN_ERR "Error: Driver '%s' is already registered, "
239 "aborting...\n", drv->name);
240 return -EBUSY;
241 }
242
243 ret = bus_add_driver(drv);
244 if (ret)
245 return ret;
246 ret = driver_add_groups(drv, drv->groups);
247 if (ret)
248 bus_remove_driver(drv);
249 return ret;
250 }
251 EXPORT_SYMBOL_GPL(driver_register);