I2C Drivers, Part I
The detach_state file and power directory is created by the kernel driver core and is used for power management. It is not created by the lm75 driver. The functions of the other files in this directory are described below.
If we ask the lm75 driver for the current value of temp_max, we receive the following:
$ cat /sys/devices/legacy/i2c-0/0-0048/temp_max 1000
To get that value, the lm75 driver asked the tiny_i2c_adap driver to read some addresses on the I2C bus. This request is shown in the syslog:
$ dmesg i2c_adapter i2c-0: tiny_access was called with the following parameters: i2c_adapter i2c-0: addr = 0048 i2c_adapter i2c-0: flags = 0000 i2c_adapter i2c-0: read_write = read i2c_adapter i2c-0: command = 0 i2c_adapter i2c-0: size = I2C_SMBUS_WORD_DATA i2c_adapter i2c-0: tiny_access was called with the following parameters: i2c_adapter i2c-0: addr = 0048 i2c_adapter i2c-0: flags = 0000 i2c_adapter i2c-0: read_write = read i2c_adapter i2c-0: command = 3 i2c_adapter i2c-0: size = I2C_SMBUS_WORD_DATA i2c_adapter i2c-0: tiny_access was called with the following parameters: i2c_adapter i2c-0: addr = 0048 i2c_adapter i2c-0: flags = 0000 i2c_adapter i2c-0: read_write = read i2c_adapter i2c-0: command = 2 i2c_adapter i2c-0: size = I2C_SMBUS_WORD_DATA
The log file shows that the tiny_access function was called three times. The first command wanted to read a word of data from register 0 out of the device with the address 0048. The second and third reads asked for register 3 and register 2 from the same device. The commands match up with the following code from the drivers/i2c/chips/lm75.c file in the lm75_update_client function:
data->temp_input = lm75_read_value(client,
LM75_REG_TEMP);
data->temp_max = lm75_read_value(client,
LM75_REG_TEMP_OS);
data->temp_hyst = lm75_read_value(client,
LM75_REG_TEMP_HYST);
The lm75_read_value function in that same file contains the following code:
/* All registers are word-sized, except for the
configuration register. LM75 uses a high-byte
first convention, which is exactly opposite to
the usual practice. */
static int lm75_read_value(struct i2c_client
*client, u8 reg)
{
if (reg == LM75_REG_CONF)
return i2c_smbus_read_byte_data(client,
reg);
else
return swap_bytes(
i2c_smbus_read_word_data(client,
reg));
}
Therefore, when the lm75 driver wants to read the value of the max temperature, it calls the lm75_read_value function with the register number, which then calls the I2C core function i2c_smbus_read_word_data. That I2C core function looks up on which I2C bus the client device is, and then it calls the I2C algorithm associated with that specific I2C bus to do the data transfer. This is the method, then, by which our tiny_i2c_adap driver is asked to complete the transfer.
If this same sysfs file is written to, the lm75 driver asks the tiny_i2c_adap driver to write some data to a specific address on the I2C bus in the same way the read was requested. This request also is shown in the syslog:
$ echo 300 > /sys/devices/legacy/i2c-0/0-0048/temp_max $ dmesg i2c_adapter i2c-0: tiny_access was called with the following parameters: i2c_adapter i2c-0: addr = 0048 i2c_adapter i2c-0: flags = 0000 i2c_adapter i2c-0: read_write = write i2c_adapter i2c-0: command = 3 i2c_adapter i2c-0: size = I2C_SMBUS_WORD_DATA i2c_adapter i2c-0: data = 8000
This month we covered the basics of the I2C driver subsystem and explained how to write a simple I2C bus and I2C algorithm driver that work with any existing I2C client driver. The complete driver, dmn-09-i2c-adap.c, is available from the Linux Journal FTP site at ftp.linuxjournal.com/pub/lj/listings/issue116/7136.tgz. In Part II, we will cover how to write an I2C chip driver.
Greg Kroah-Hartman currently is the Linux kernel maintainer for a variety of different driver subsystems. He works for IBM, doing Linux kernel-related things and can be reached at greg@kroah.com.
- « first
- ‹ previous
- 1
- 2
- 3
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
- Dynamic DNS—an Object Lesson in Problem Solving
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- New Products
- RSS Feeds
- A Topic for Discussion - Open Source Feature-Richness?
- Validate an E-Mail Address with PHP, the Right Way
- Drupal Is a Framework: Why Everyone Needs to Understand This
- Readers' Choice Awards
- The Secret Password Is...
- All the articles you talked
1 hour 41 min ago - All the articles you talked
1 hour 44 min ago - All the articles you talked
1 hour 45 min ago - myip
6 hours 10 min ago - Keeping track of IP address
8 hours 1 min ago - Roll your own dynamic dns
13 hours 14 min ago - Please correct the URL for Salt Stack's web site
16 hours 26 min ago - Android is Linux -- why no better inter-operation
18 hours 41 min ago - Connecting Android device to desktop Linux via USB
19 hours 10 min ago - Find new cell phone and tablet pc
20 hours 8 min ago




Comments
2.6
Hello,
I am tried building the examples from parts 1 and 2, and got errors. I am running version 2.6.21. The example from part 1 tried to include linux/config.h, which does not seem to exist in 2.6. I removed the include, but I still get errors. They start with the spinlock header
include/linux/spinlock.h: At top level:
include/linux/spinlock.h:290: error: expected declaration specifiers or '...' before 'bool'
include/linux/spinlock.h: In function 'double_spin_lock':
include/linux/spinlock.h:294: error: 'l1_first' undeclared (first use in this function)
include/linux/spinlock.h:294: error: (Each undeclared identifier is reported only once
include/linux/spinlock.h:294: error: for each function it appears in.)
include/linux/spinlock.h:295: warning: implicit declaration of function 'current_thread_info'
include/linux/spinlock.h:295: error: invalid type argument of '->' (have 'int')
include/linux/spinlock.h:295: warning: implicit declaration of function 'barrier'
include/linux/spinlock.h:296: error: invalid type argument of '->' (have 'int')
include/linux/spinlock.h:298: error: invalid type argument of '->' (have 'int')
include/linux/spinlock.h:299: error: invalid type argument of '->' (have 'int')
include/linux/spinlock.h: At top level:
include/linux/spinlock.h:309: error: expected declaration specifiers or '...' before 'bool'
include/linux/spinlock.h: In function 'double_spin_unlock':
include/linux/spinlock.h:313: error: 'l1_taken_first' undeclared (first use in this function)
include/linux/spinlock.h:314: error: invalid type argument of '->' (have 'int')
include/linux/spinlock.h:314: warning: implicit declaration of function 'unlikely'
include/linux/spinlock.h:314: warning: implicit declaration of function 'test_thread_flag'
include/linux/spinlock.h:314: error: 'TIF_NEED_RESCHED' undeclared (first use in this function
Is there something I need to change to make this example compatible with 2.6?
Thanks,
Chris
trying to write a driver for an audio chip
hello !
I'm trying to write a driver for an audio chip, this chip can be controlled via i2c bus (i2c-0)
the problem is that I don't understand how I can "open" the i2c-0 in kernel space...
I tried to do as le lm75 sensor driver...but it's not better..
I know that I have to register my driver as an i2c driver with the i2c_add_driver function
does this:
static intchip_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_detect(adapter, &addr_data,
chip_detect);
}
probes every i2c bus on my board ?
and I don't understand what addr_data is or what it does,
I know it is in the SENSORS_INSMOD_1 macro
but I'm not writing a driver for a sensor, but for an audio chip...
can anyone help me understand better all this ?