|
|
포토로그
카테고리
An I2C chip driver controls the process of talking to an individual I2C device that lives on an I2C bus. I2C chip devices usually monitor a number of different physical devices on a motherboard, such as the different fan speeds, temperature values and voltages. The struct i2c_driver structure describes a I2C chip driver. This structure is defined in the include/linux/i2c.h file. Only the following fields are necessary to create a working chip driver: * struct module *owner; --set to the value THIS_MODULE that allows the proper module reference counting. The following code is from an example I2C chip driver called tiny_i2c_chip.c., which is available from the Linux Journal FTP site [ftp.ssc.com/pub/lj/listings/issue118/7252.tgz]. It shows how the struct i2c_driver structure is set up: static struct i2c_driver chip_driver = {
To register this I2C chip driver, the function i2c_add_driver should be called with a pointer to the struct i2c_driver: static int __init tiny_init(void)
static void __exit tiny_exit(void)
static int
If you look closely at the source code, you cannot find the addr_data structure anywhere. The reason for this is it is created by the SENSORS_INSMOD_1 macro. This macro is defined in the include/linux/i2c-sensor.h file and is quite complicated. It sets up a static variable called addr_data based on the number of different types of chips that this driver supports and the addresses at which these chips typically are present. It then provides the ability to override these values by using module parameters. An I2C chip driver must provide the variables normal_i2c, normal_i2c_range, normal_isa and normal_isa_range. These variables define the i2c smbus and i2c isa addresses this chip driver supports. They are an array of addresses, all terminated by either the special value I2C_CLIENT_END or I2C_CLIENT_ISA_END. Usually a specific type of I2C chip shows up in only a limited range of addresses. The tiny_i2c_client.c driver defines these variables as: static unsigned short normal_i2c[] =
In the tiny_i2c_chip.c driver, when an I2C chip device is found, the function chip_detect is called by the I2C core. This function is declared with the following parameters: static int
This function is responsible for creating a struct i2c_client structure that then is registered with the I2C core. The I2C core uses that structure as an individual I2C chip device. To create this structure, the chip_detect function does the following: struct i2c_client *new_client = NULL; new_client = kmalloc(sizeof(*new_client), data = kmalloc(sizeof(*data), GFP_KERNEL); i2c_set_clientdata(new_client, data);
First, the struct i2c_client structure and a separate local data structure (called struct chip_data) are created and initialized to zero. It is important that the i2c_client structure is initialized to zero, as the lower levels of the kernel driver core require this in order to work properly. After the memory is allocated successfully, some fields in the struct i2c_client are set to point to this specific device and this specific driver. Notably, the addr, adapter and driver variables must be initialized. The name of the struct i2c_client also must be set if it is to show up properly in the sysfs tree for this I2C device. After the struct i2c_client structure is initialized, it must be registered with the I2C core. This is done with a call to the i2c_attach_client function: /* Tell the I2C layer a new client has arrived */
In the 2.0, 2.2 and 2.4 kernels, the I2C code would place the I2C chip devices in the /proc/bus/i2c directory. In the 2.6 kernel, all I2C chip devices and adapters show up in the sysfs filesystem. I2C chip devices can be found at /sys/bus/i2c/devices, listed by their adapter address and chip address. For example, the tiny_i2c_chip driver loaded on a machine might produce the following sysfs tree structure:
This shows four different I2C chip devices, all controlled by the same tiny_chip driver. The controlling driver can be located by looking at the devices in the /sys/bus/i2c/drivers directory or by looking in the directory of the chip device itself and reading the name file: $ cat /sys/devices/pci0000:00/0000:00:06.0/i2c-0/0-0009/name All I2C chip drivers export the different sensor values through sysfs files within the I2C chip device directory. These filenames are standardized, along with the units in which the values are expressed, and are documented within the kernel tree in the file Documentation/i2c/sysfs-interface (Table 1). Table 1. Sensor Values Exported through sysfs Files As the information in Table 1 shows, there is only one value per file. All files are readable and some can be written to by users with the proper privileges. The tiny_i2c_chip.c driver emulates an I2C chip device that can report temperature values. It creates the files, temp_max1, temp_min1 and temp_input1 in sysfs. The values it returns when these files are read from is incremented every time the file is read to show how to access different unique chip values. In order to create a file in sysfs, the DEVICE_ATTR macro is used: static DEVICE_ATTR(temp_max, S_IWUSR | S_IRUGO,
/* Register sysfs files */
/sys/devices/pci0000:00/0000:00:06.0/i2c-0/0-0009 The file name is created by the I2C core, and the files detach_state and power/state are created by the driver core. But, let's go back to the DEVICE_ATTR macro. That macro wants to know the name of the file to be created, the mode of the file to be created, the name of the function to be called when the file is read from and the name of the function to be called when the file is written to. For the file temp_max, this declaration was: static DEVICE_ATTR(temp_max, S_IWUSR | S_IRUGO,
#define show(value)
In this function, the struct device * is converted into a struct i2c_client *. Then the private struct chip_data * is obtained from the struct i2c_client *. After that the chip data is updated with a call to chip_update_client. From there, the variable that has been asked for is printed into a buffer and returned to the driver core, which then returns it to the user:
The chip_update_client increments all values by one every time it is called: static void down(&data->update_lock);
$ cat /sys/devices/pci0000:00/0000:00:06.0/i2c-0/0-0009/temp_input The set_temp_max function also is created from a macro to allow variables to be written to: #define set(value, reg)
$ cat /sys/devices/pci0000:00/0000:00:06.0/i2c-0/0-0009/temp_max Cleaning Up When the I2C chip device is removed from the system, either by the I2C bus driver being unloaded or by the I2C chip driver being unloaded, the I2C core calls the detatch_client function specified in the struct i2c_driver structure. This usually is a simple function, as can be seen in the example driver's implementation: static int chip_detach_client(struct i2c_client *client) err = i2c_detach_client(client);
This example driver does not specifically remove the sysfs files from the sysfs core. This step is done automatically in the driver core within the i2c_detach_client function. But if the author would like, the file can be removed manually by a call to device_remove_file
이글루 파인더
메모장
이글루 링크
최근 등록된 덧글
<a href=http://www.you..
by Buy Generi at 07/20 <a href=http://pipes.y.. by Porn Clip at 07/16 <a href=http://pipes.y.. by Gay porn v at 07/15 <a href=http://www.goo.. by Order cial at 06/04 good by yanghui at 05/24 hello by Naomi at 04/06 hello by Naomi at 04/06 hello by Naomi at 04/06 hello by Naomi at 04/06 hello by Naomi at 04/06 메뉴릿
|
|