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
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
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
| 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 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- RSS Feeds
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- New Products
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Home, My Backup Data Center
- Validate an E-Mail Address with PHP, the Right Way
- New Products
- Developer Poll
- Tech Tip: Really Simple HTTP Server with Python
- not living upto the mobile revolution
2 hours 31 min ago - Deceptive Advertising and
3 hours 7 min ago - Let\'s declare that you have
3 hours 8 min ago - Alterations in Contest Due
3 hours 9 min ago - At a numbers mindset, your
3 hours 10 min ago - Do not get Just Almost any
3 hours 14 min ago - A fantastic rule-of-thumb to
3 hours 15 min ago - Keren mastah..
Penting,
4 hours 13 min ago - mini tablet compare
5 hours 32 min ago - Looking Good
9 hours 5 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 ?