aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/i2c/functionality
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2008-05-11 14:37:05 -0400
committerJean Delvare <khali@hyperion.delvare>2008-05-11 14:37:05 -0400
commit88b283281f1c783a79af175c400b5d20f10af2aa (patch)
tree28099d412d4e1a48ca7e77808304f647ca201e4a /Documentation/i2c/functionality
parent1a31a88f4f1a14f0b28ec3c5c179b93a10b24a18 (diff)
i2c: Improve the functionality documentation
Attempt to make the documentation about the I2C/SMBus functionality checking API clearer. Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'Documentation/i2c/functionality')
-rw-r--r--Documentation/i2c/functionality95
1 files changed, 52 insertions, 43 deletions
diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality
index 60cca249e452..42c17c1fb3cd 100644
--- a/Documentation/i2c/functionality
+++ b/Documentation/i2c/functionality
@@ -51,26 +51,38 @@ A few combinations of the above flags are also defined for your convenience:
51 the transparent emulation layer) 51 the transparent emulation layer)
52 52
53 53
54ALGORITHM/ADAPTER IMPLEMENTATION 54ADAPTER IMPLEMENTATION
55-------------------------------- 55----------------------
56 56
57When you write a new algorithm driver, you will have to implement a 57When you write a new adapter driver, you will have to implement a
58function callback `functionality', that gets an i2c_adapter structure 58function callback `functionality'. Typical implementations are given
59pointer as its only parameter: 59below.
60 60
61 struct i2c_algorithm { 61A typical SMBus-only adapter would list all the SMBus transactions it
62 /* Many other things of course; check <linux/i2c.h>! */ 62supports. This example comes from the i2c-piix4 driver:
63 u32 (*functionality) (struct i2c_adapter *); 63
64 static u32 piix4_func(struct i2c_adapter *adapter)
65 {
66 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
67 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
68 I2C_FUNC_SMBUS_BLOCK_DATA;
64 } 69 }
65 70
66A typically implementation is given below, from i2c-algo-bit.c: 71A typical full-I2C adapter would use the following (from the i2c-pxa
72driver):
67 73
68 static u32 bit_func(struct i2c_adapter *adap) 74 static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
69 { 75 {
70 return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | 76 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
71 I2C_FUNC_PROTOCOL_MANGLING;
72 } 77 }
73 78
79I2C_FUNC_SMBUS_EMUL includes all the SMBus transactions (with the
80addition of I2C block transactions) which i2c-core can emulate using
81I2C_FUNC_I2C without any help from the adapter driver. The idea is
82to let the client drivers check for the support of SMBus functions
83without having to care whether the said functions are implemented in
84hardware by the adapter, or emulated in software by i2c-core on top
85of an I2C adapter.
74 86
75 87
76CLIENT CHECKING 88CLIENT CHECKING
@@ -78,36 +90,33 @@ CLIENT CHECKING
78 90
79Before a client tries to attach to an adapter, or even do tests to check 91Before a client tries to attach to an adapter, or even do tests to check
80whether one of the devices it supports is present on an adapter, it should 92whether one of the devices it supports is present on an adapter, it should
81check whether the needed functionality is present. There are two functions 93check whether the needed functionality is present. The typical way to do
82defined which should be used instead of calling the functionality hook 94this is (from the lm75 driver):
83in the algorithm structure directly:
84
85 /* Return the functionality mask */
86 extern u32 i2c_get_functionality (struct i2c_adapter *adap);
87
88 /* Return 1 if adapter supports everything we need, 0 if not. */
89 extern int i2c_check_functionality (struct i2c_adapter *adap, u32 func);
90 95
91This is a typical way to use these functions (from the writing-clients 96 static int lm75_detect(...)
92document):
93 int foo_detect_client(struct i2c_adapter *adapter, int address,
94 unsigned short flags, int kind)
95 { 97 {
96 /* Define needed variables */ 98 (...)
97 99 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
98 /* As the very first action, we check whether the adapter has the 100 I2C_FUNC_SMBUS_WORD_DATA))
99 needed functionality: we need the SMBus read_word_data, 101 goto exit;
100 write_word_data and write_byte functions in this example. */ 102 (...)
101 if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
102 I2C_FUNC_SMBUS_WRITE_BYTE))
103 goto ERROR0;
104
105 /* Now we can do the real detection */
106
107 ERROR0:
108 /* Return an error */
109 } 103 }
110 104
105Here, the lm75 driver checks if the adapter can do both SMBus byte data
106and SMBus word data transactions. If not, then the driver won't work on
107this adapter and there's no point in going on. If the check above is
108successful, then the driver knows that it can call the following
109functions: i2c_smbus_read_byte_data(), i2c_smbus_write_byte_data(),
110i2c_smbus_read_word_data() and i2c_smbus_write_word_data(). As a rule of
111thumb, the functionality constants you test for with
112i2c_check_functionality() should match exactly the i2c_smbus_* functions
113which you driver is calling.
114
115Note that the check above doesn't tell whether the functionalities are
116implemented in hardware by the underlying adapter or emulated in
117software by i2c-core. Client drivers don't have to care about this, as
118i2c-core will transparently implement SMBus transactions on top of I2C
119adapters.
111 120
112 121
113CHECKING THROUGH /DEV 122CHECKING THROUGH /DEV
@@ -116,19 +125,19 @@ CHECKING THROUGH /DEV
116If you try to access an adapter from a userspace program, you will have 125If you try to access an adapter from a userspace program, you will have
117to use the /dev interface. You will still have to check whether the 126to use the /dev interface. You will still have to check whether the
118functionality you need is supported, of course. This is done using 127functionality you need is supported, of course. This is done using
119the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect 128the I2C_FUNCS ioctl. An example, adapted from the i2cdetect program, is
120program, is below: 129below:
121 130
122 int file; 131 int file;
123 if (file = open("/dev/i2c-0",O_RDWR) < 0) { 132 if (file = open("/dev/i2c-0", O_RDWR) < 0) {
124 /* Some kind of error handling */ 133 /* Some kind of error handling */
125 exit(1); 134 exit(1);
126 } 135 }
127 if (ioctl(file,I2C_FUNCS,&funcs) < 0) { 136 if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
128 /* Some kind of error handling */ 137 /* Some kind of error handling */
129 exit(1); 138 exit(1);
130 } 139 }
131 if (! (funcs & I2C_FUNC_SMBUS_QUICK)) { 140 if (!(funcs & I2C_FUNC_SMBUS_QUICK)) {
132 /* Oops, the needed functionality (SMBus write_quick function) is 141 /* Oops, the needed functionality (SMBus write_quick function) is
133 not available! */ 142 not available! */
134 exit(1); 143 exit(1);