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

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

The new-style max6875 driver implements the optional detect() callback
to cover the use cases of the legacy driver. I'm curious if anyone
really needs this though, so it might be removed in the feature.

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

authored by

Jean Delvare and committed by
Jean Delvare
bd8d421f 3d63430a

+50 -72
+1 -1
Documentation/i2c/chips/max6875
··· 49 49 50 50 The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple 51 51 addresses. For example, for address 0x50, it also reserves 0x51. 52 - The even-address instance is called 'max6875', the odd one is 'max6875 subclient'. 52 + The even-address instance is called 'max6875', the odd one is 'dummy'. 53 53 54 54 55 55 Programming the chip using i2c-dev
+49 -71
drivers/i2c/chips/max6875.c
··· 53 53 54 54 /* Each client has this additional data */ 55 55 struct max6875_data { 56 - struct i2c_client client; 56 + struct i2c_client *fake_client; 57 57 struct mutex update_lock; 58 58 59 59 u32 valid; 60 60 u8 data[USER_EEPROM_SIZE]; 61 61 unsigned long last_updated[USER_EEPROM_SLICES]; 62 - }; 63 - 64 - static int max6875_attach_adapter(struct i2c_adapter *adapter); 65 - static int max6875_detect(struct i2c_adapter *adapter, int address, int kind); 66 - static int max6875_detach_client(struct i2c_client *client); 67 - 68 - /* This is the driver that will be inserted */ 69 - static struct i2c_driver max6875_driver = { 70 - .driver = { 71 - .name = "max6875", 72 - }, 73 - .attach_adapter = max6875_attach_adapter, 74 - .detach_client = max6875_detach_client, 75 62 }; 76 63 77 64 static void max6875_update_slice(struct i2c_client *client, int slice) ··· 146 159 .read = max6875_read, 147 160 }; 148 161 149 - static int max6875_attach_adapter(struct i2c_adapter *adapter) 162 + /* Return 0 if detection is successful, -ENODEV otherwise */ 163 + static int max6875_detect(struct i2c_client *client, int kind, 164 + struct i2c_board_info *info) 150 165 { 151 - return i2c_probe(adapter, &addr_data, max6875_detect); 152 - } 153 - 154 - /* This function is called by i2c_probe */ 155 - static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) 156 - { 157 - struct i2c_client *real_client; 158 - struct i2c_client *fake_client; 159 - struct max6875_data *data; 160 - int err; 166 + struct i2c_adapter *adapter = client->adapter; 161 167 162 168 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA 163 169 | I2C_FUNC_SMBUS_READ_BYTE)) 164 - return 0; 170 + return -ENODEV; 165 171 166 172 /* Only check even addresses */ 167 - if (address & 1) 168 - return 0; 173 + if (client->addr & 1) 174 + return -ENODEV; 175 + 176 + strlcpy(info->type, "max6875", I2C_NAME_SIZE); 177 + 178 + return 0; 179 + } 180 + 181 + static int max6875_probe(struct i2c_client *client, 182 + const struct i2c_device_id *id) 183 + { 184 + struct max6875_data *data; 185 + int err; 169 186 170 187 if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL))) 171 188 return -ENOMEM; 172 189 173 190 /* A fake client is created on the odd address */ 174 - if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { 191 + data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); 192 + if (!data->fake_client) { 175 193 err = -ENOMEM; 176 - goto exit_kfree1; 194 + goto exit_kfree; 177 195 } 178 196 179 197 /* Init real i2c_client */ 180 - real_client = &data->client; 181 - i2c_set_clientdata(real_client, data); 182 - real_client->addr = address; 183 - real_client->adapter = adapter; 184 - real_client->driver = &max6875_driver; 185 - strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); 198 + i2c_set_clientdata(client, data); 186 199 mutex_init(&data->update_lock); 187 200 188 - /* Init fake client data */ 189 - i2c_set_clientdata(fake_client, NULL); 190 - fake_client->addr = address | 1; 191 - fake_client->adapter = adapter; 192 - fake_client->driver = &max6875_driver; 193 - strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE); 194 - 195 - if ((err = i2c_attach_client(real_client)) != 0) 196 - goto exit_kfree2; 197 - 198 - if ((err = i2c_attach_client(fake_client)) != 0) 199 - goto exit_detach1; 200 - 201 - err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr); 201 + err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr); 202 202 if (err) 203 - goto exit_detach2; 203 + goto exit_remove_fake; 204 204 205 205 return 0; 206 206 207 - exit_detach2: 208 - i2c_detach_client(fake_client); 209 - exit_detach1: 210 - i2c_detach_client(real_client); 211 - exit_kfree2: 212 - kfree(fake_client); 213 - exit_kfree1: 207 + exit_remove_fake: 208 + i2c_unregister_device(data->fake_client); 209 + exit_kfree: 214 210 kfree(data); 215 211 return err; 216 212 } 217 213 218 - /* Will be called for both the real client and the fake client */ 219 - static int max6875_detach_client(struct i2c_client *client) 214 + static int max6875_remove(struct i2c_client *client) 220 215 { 221 - int err; 222 216 struct max6875_data *data = i2c_get_clientdata(client); 223 217 224 - /* data is NULL for the fake client */ 225 - if (data) 226 - sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); 218 + i2c_unregister_device(data->fake_client); 227 219 228 - err = i2c_detach_client(client); 229 - if (err) 230 - return err; 220 + sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); 221 + kfree(data); 231 222 232 - if (data) /* real client */ 233 - kfree(data); 234 - else /* fake client */ 235 - kfree(client); 236 223 return 0; 237 224 } 225 + 226 + static const struct i2c_device_id max6875_id[] = { 227 + { "max6875", 0 }, 228 + { } 229 + }; 230 + 231 + static struct i2c_driver max6875_driver = { 232 + .driver = { 233 + .name = "max6875", 234 + }, 235 + .probe = max6875_probe, 236 + .remove = max6875_remove, 237 + .id_table = max6875_id, 238 + 239 + .detect = max6875_detect, 240 + .address_data = &addr_data, 241 + }; 238 242 239 243 static int __init max6875_init(void) 240 244 {