Commit 88b283281f1c783a79af175c400b5d20f10af2aa

Authored by Jean Delvare
Committed by Jean Delvare
1 parent 1a31a88f4f

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>

Showing 1 changed file with 52 additions and 43 deletions Side-by-side Diff

Documentation/i2c/functionality
... ... @@ -51,26 +51,38 @@
51 51 the transparent emulation layer)
52 52  
53 53  
54   -ALGORITHM/ADAPTER IMPLEMENTATION
55   ---------------------------------
  54 +ADAPTER IMPLEMENTATION
  55 +----------------------
56 56  
57   -When you write a new algorithm driver, you will have to implement a
58   -function callback `functionality', that gets an i2c_adapter structure
59   -pointer as its only parameter:
  57 +When you write a new adapter driver, you will have to implement a
  58 +function callback `functionality'. Typical implementations are given
  59 +below.
60 60  
61   - struct i2c_algorithm {
62   - /* Many other things of course; check <linux/i2c.h>! */
63   - u32 (*functionality) (struct i2c_adapter *);
  61 +A typical SMBus-only adapter would list all the SMBus transactions it
  62 +supports. This example comes from the i2c-piix4 driver:
  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  
66   -A typically implementation is given below, from i2c-algo-bit.c:
  71 +A typical full-I2C adapter would use the following (from the i2c-pxa
  72 +driver):
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 |
71   - I2C_FUNC_PROTOCOL_MANGLING;
  76 + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
72 77 }
73 78  
  79 +I2C_FUNC_SMBUS_EMUL includes all the SMBus transactions (with the
  80 +addition of I2C block transactions) which i2c-core can emulate using
  81 +I2C_FUNC_I2C without any help from the adapter driver. The idea is
  82 +to let the client drivers check for the support of SMBus functions
  83 +without having to care whether the said functions are implemented in
  84 +hardware by the adapter, or emulated in software by i2c-core on top
  85 +of an I2C adapter.
74 86  
75 87  
76 88 CLIENT CHECKING
77 89  
78 90  
79 91  
80 92  
81 93  
82 94  
83 95  
84 96  
85 97  
... ... @@ -78,57 +90,54 @@
78 90  
79 91 Before a client tries to attach to an adapter, or even do tests to check
80 92 whether one of the devices it supports is present on an adapter, it should
81   -check whether the needed functionality is present. There are two functions
82   -defined which should be used instead of calling the functionality hook
83   -in the algorithm structure directly:
  93 +check whether the needed functionality is present. The typical way to do
  94 +this is (from the lm75 driver):
84 95  
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   -
91   -This is a typical way to use these functions (from the writing-clients
92   -document):
93   - int foo_detect_client(struct i2c_adapter *adapter, int address,
94   - unsigned short flags, int kind)
  96 + static int lm75_detect(...)
95 97 {
96   - /* Define needed variables */
97   -
98   - /* As the very first action, we check whether the adapter has the
99   - needed functionality: we need the SMBus read_word_data,
100   - write_word_data and write_byte functions in this example. */
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 */
  98 + (...)
  99 + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
  100 + I2C_FUNC_SMBUS_WORD_DATA))
  101 + goto exit;
  102 + (...)
109 103 }
110 104  
  105 +Here, the lm75 driver checks if the adapter can do both SMBus byte data
  106 +and SMBus word data transactions. If not, then the driver won't work on
  107 +this adapter and there's no point in going on. If the check above is
  108 +successful, then the driver knows that it can call the following
  109 +functions: i2c_smbus_read_byte_data(), i2c_smbus_write_byte_data(),
  110 +i2c_smbus_read_word_data() and i2c_smbus_write_word_data(). As a rule of
  111 +thumb, the functionality constants you test for with
  112 +i2c_check_functionality() should match exactly the i2c_smbus_* functions
  113 +which you driver is calling.
111 114  
  115 +Note that the check above doesn't tell whether the functionalities are
  116 +implemented in hardware by the underlying adapter or emulated in
  117 +software by i2c-core. Client drivers don't have to care about this, as
  118 +i2c-core will transparently implement SMBus transactions on top of I2C
  119 +adapters.
112 120  
  121 +
113 122 CHECKING THROUGH /DEV
114 123 ---------------------
115 124  
116 125 If you try to access an adapter from a userspace program, you will have
117 126 to use the /dev interface. You will still have to check whether the
118 127 functionality you need is supported, of course. This is done using
119   -the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect
120   -program, is below:
  128 +the I2C_FUNCS ioctl. An example, adapted from the i2cdetect program, is
  129 +below:
121 130  
122 131 int file;
123   - if (file = open("/dev/i2c-0",O_RDWR) < 0) {
  132 + if (file = open("/dev/i2c-0", O_RDWR) < 0) {
124 133 /* Some kind of error handling */
125 134 exit(1);
126 135 }
127   - if (ioctl(file,I2C_FUNCS,&funcs) < 0) {
  136 + if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
128 137 /* Some kind of error handling */
129 138 exit(1);
130 139 }
131   - if (! (funcs & I2C_FUNC_SMBUS_QUICK)) {
  140 + if (!(funcs & I2C_FUNC_SMBUS_QUICK)) {
132 141 /* Oops, the needed functionality (SMBus write_quick function) is
133 142 not available! */
134 143 exit(1);