Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: Convert the pcf8574 driver to a new-style i2c driver

The new-style pcf8574 driver implements the optional detect() callback
to cover the use cases of the legacy driver.

Warning: users will now have to use the force module parameter to get
the driver to attach to their device. That's not a bad thing as these
devices can't be detected anyway.

Note that this doesn't change the fact that this driver is deprecated
in favor of gpio/pcf857x.

Signed-off-by: Jean Delvare <khali@linux-fr.org>

authored by

Jean Delvare and committed by
Jean Delvare
833bedb8 8b77e6ac

+51 -69
+5 -7
Documentation/i2c/chips/pcf8574
··· 4 4 Supported chips: 5 5 * Philips PCF8574 6 6 Prefix: 'pcf8574' 7 - Addresses scanned: I2C 0x20 - 0x27 7 + Addresses scanned: none 8 8 Datasheet: Publicly available at the Philips Semiconductors website 9 9 http://www.semiconductors.philips.com/pip/PCF8574P.html 10 10 11 11 * Philips PCF8574A 12 12 Prefix: 'pcf8574a' 13 - Addresses scanned: I2C 0x38 - 0x3f 13 + Addresses scanned: none 14 14 Datasheet: Publicly available at the Philips Semiconductors website 15 15 http://www.semiconductors.philips.com/pip/PCF8574P.html 16 16 ··· 38 38 Accessing PCF8574(A) via /sys interface 39 39 ------------------------------------- 40 40 41 - ! Be careful ! 42 41 The PCF8574(A) is plainly impossible to detect ! Stupid chip. 43 - So every chip with address in the interval [20..27] and [38..3f] are 44 - detected as PCF8574(A). If you have other chips in this address 45 - range, the workaround is to load this module after the one 46 - for your others chips. 42 + So, you have to pass the I2C bus and address of the installed PCF857A 43 + and PCF8574A devices explicitly to the driver at load time via the 44 + force=... parameter. 47 45 48 46 On detection (i.e. insmod, modprobe et al.), directories are being 49 47 created for each detected PCF8574(A):
+46 -62
drivers/i2c/chips/pcf8574.c
··· 38 38 #include <linux/slab.h> 39 39 #include <linux/i2c.h> 40 40 41 - /* Addresses to scan */ 42 - static const unsigned short normal_i2c[] = { 43 - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 44 - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 45 - I2C_CLIENT_END 46 - }; 41 + /* Addresses to scan: none, device can't be detected */ 42 + static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; 47 43 48 44 /* Insmod parameters */ 49 45 I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a); 50 46 51 47 /* Each client has this additional data */ 52 48 struct pcf8574_data { 53 - struct i2c_client client; 54 - 55 49 int write; /* Remember last written value */ 56 50 }; 57 51 58 - static int pcf8574_attach_adapter(struct i2c_adapter *adapter); 59 - static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind); 60 - static int pcf8574_detach_client(struct i2c_client *client); 61 52 static void pcf8574_init_client(struct i2c_client *client); 62 - 63 - /* This is the driver that will be inserted */ 64 - static struct i2c_driver pcf8574_driver = { 65 - .driver = { 66 - .name = "pcf8574", 67 - }, 68 - .attach_adapter = pcf8574_attach_adapter, 69 - .detach_client = pcf8574_detach_client, 70 - }; 71 53 72 54 /* following are the sysfs callback functions */ 73 55 static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf) ··· 101 119 * Real code 102 120 */ 103 121 104 - static int pcf8574_attach_adapter(struct i2c_adapter *adapter) 122 + /* Return 0 if detection is successful, -ENODEV otherwise */ 123 + static int pcf8574_detect(struct i2c_client *client, int kind, 124 + struct i2c_board_info *info) 105 125 { 106 - return i2c_probe(adapter, &addr_data, pcf8574_detect); 107 - } 108 - 109 - /* This function is called by i2c_probe */ 110 - static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind) 111 - { 112 - struct i2c_client *client; 113 - struct pcf8574_data *data; 114 - int err = 0; 115 - const char *client_name = ""; 126 + struct i2c_adapter *adapter = client->adapter; 127 + const char *client_name; 116 128 117 129 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) 118 - goto exit; 119 - 120 - /* OK. For now, we presume we have a valid client. We now create the 121 - client structure, even though we cannot fill it completely yet. */ 122 - if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) { 123 - err = -ENOMEM; 124 - goto exit; 125 - } 126 - 127 - client = &data->client; 128 - i2c_set_clientdata(client, data); 129 - client->addr = address; 130 - client->adapter = adapter; 131 - client->driver = &pcf8574_driver; 130 + return -ENODEV; 132 131 133 132 /* Now, we would do the remaining detection. But the PCF8574 is plainly 134 133 impossible to detect! Stupid chip. */ 135 134 136 135 /* Determine the chip type */ 137 136 if (kind <= 0) { 138 - if (address >= 0x38 && address <= 0x3f) 137 + if (client->addr >= 0x38 && client->addr <= 0x3f) 139 138 kind = pcf8574a; 140 139 else 141 140 kind = pcf8574; ··· 126 163 client_name = "pcf8574a"; 127 164 else 128 165 client_name = "pcf8574"; 166 + strlcpy(info->type, client_name, I2C_NAME_SIZE); 129 167 130 - /* Fill in the remaining client fields and put it into the global list */ 131 - strlcpy(client->name, client_name, I2C_NAME_SIZE); 168 + return 0; 169 + } 132 170 133 - /* Tell the I2C layer a new client has arrived */ 134 - if ((err = i2c_attach_client(client))) 135 - goto exit_free; 136 - 171 + static int pcf8574_probe(struct i2c_client *client, 172 + const struct i2c_device_id *id) 173 + { 174 + struct pcf8574_data *data; 175 + int err; 176 + 177 + data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL); 178 + if (!data) { 179 + err = -ENOMEM; 180 + goto exit; 181 + } 182 + 183 + i2c_set_clientdata(client, data); 184 + 137 185 /* Initialize the PCF8574 chip */ 138 186 pcf8574_init_client(client); 139 187 140 188 /* Register sysfs hooks */ 141 189 err = sysfs_create_group(&client->dev.kobj, &pcf8574_attr_group); 142 190 if (err) 143 - goto exit_detach; 191 + goto exit_free; 144 192 return 0; 145 193 146 - exit_detach: 147 - i2c_detach_client(client); 148 194 exit_free: 149 195 kfree(data); 150 196 exit: 151 197 return err; 152 198 } 153 199 154 - static int pcf8574_detach_client(struct i2c_client *client) 200 + static int pcf8574_remove(struct i2c_client *client) 155 201 { 156 - int err; 157 - 158 202 sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group); 159 - 160 - if ((err = i2c_detach_client(client))) 161 - return err; 162 - 163 203 kfree(i2c_get_clientdata(client)); 164 204 return 0; 165 205 } ··· 173 207 struct pcf8574_data *data = i2c_get_clientdata(client); 174 208 data->write = -EAGAIN; 175 209 } 210 + 211 + static const struct i2c_device_id pcf8574_id[] = { 212 + { "pcf8574", 0 }, 213 + { "pcf8574a", 0 }, 214 + { } 215 + }; 216 + 217 + static struct i2c_driver pcf8574_driver = { 218 + .driver = { 219 + .name = "pcf8574", 220 + }, 221 + .probe = pcf8574_probe, 222 + .remove = pcf8574_remove, 223 + .id_table = pcf8574_id, 224 + 225 + .detect = pcf8574_detect, 226 + .address_data = &addr_data, 227 + }; 176 228 177 229 static int __init pcf8574_init(void) 178 230 {