aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/chips
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/chips')
-rw-r--r--drivers/i2c/chips/max6875.c120
1 files changed, 49 insertions, 71 deletions
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index 5a0285d8b6f9..033d9d81ec8a 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -53,7 +53,7 @@ I2C_CLIENT_INSMOD_1(max6875);
53 53
54/* Each client has this additional data */ 54/* Each client has this additional data */
55struct max6875_data { 55struct max6875_data {
56 struct i2c_client client; 56 struct i2c_client *fake_client;
57 struct mutex update_lock; 57 struct mutex update_lock;
58 58
59 u32 valid; 59 u32 valid;
@@ -61,19 +61,6 @@ struct max6875_data {
61 unsigned long last_updated[USER_EEPROM_SLICES]; 61 unsigned long last_updated[USER_EEPROM_SLICES];
62}; 62};
63 63
64static int max6875_attach_adapter(struct i2c_adapter *adapter);
65static int max6875_detect(struct i2c_adapter *adapter, int address, int kind);
66static int max6875_detach_client(struct i2c_client *client);
67
68/* This is the driver that will be inserted */
69static struct i2c_driver max6875_driver = {
70 .driver = {
71 .name = "max6875",
72 },
73 .attach_adapter = max6875_attach_adapter,
74 .detach_client = max6875_detach_client,
75};
76
77static void max6875_update_slice(struct i2c_client *client, int slice) 64static void max6875_update_slice(struct i2c_client *client, int slice)
78{ 65{
79 struct max6875_data *data = i2c_get_clientdata(client); 66 struct max6875_data *data = i2c_get_clientdata(client);
@@ -159,96 +146,87 @@ static struct bin_attribute user_eeprom_attr = {
159 .read = max6875_read, 146 .read = max6875_read,
160}; 147};
161 148
162static int max6875_attach_adapter(struct i2c_adapter *adapter) 149/* Return 0 if detection is successful, -ENODEV otherwise */
150static int max6875_detect(struct i2c_client *client, int kind,
151 struct i2c_board_info *info)
163{ 152{
164 return i2c_probe(adapter, &addr_data, max6875_detect); 153 struct i2c_adapter *adapter = client->adapter;
165}
166
167/* This function is called by i2c_probe */
168static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
169{
170 struct i2c_client *real_client;
171 struct i2c_client *fake_client;
172 struct max6875_data *data;
173 int err;
174 154
175 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA 155 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
176 | I2C_FUNC_SMBUS_READ_BYTE)) 156 | I2C_FUNC_SMBUS_READ_BYTE))
177 return 0; 157 return -ENODEV;
178 158
179 /* Only check even addresses */ 159 /* Only check even addresses */
180 if (address & 1) 160 if (client->addr & 1)
181 return 0; 161 return -ENODEV;
162
163 strlcpy(info->type, "max6875", I2C_NAME_SIZE);
164
165 return 0;
166}
167
168static int max6875_probe(struct i2c_client *client,
169 const struct i2c_device_id *id)
170{
171 struct max6875_data *data;
172 int err;
182 173
183 if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL))) 174 if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL)))
184 return -ENOMEM; 175 return -ENOMEM;
185 176
186 /* A fake client is created on the odd address */ 177 /* A fake client is created on the odd address */
187 if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { 178 data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1);
179 if (!data->fake_client) {
188 err = -ENOMEM; 180 err = -ENOMEM;
189 goto exit_kfree1; 181 goto exit_kfree;
190 } 182 }
191 183
192 /* Init real i2c_client */ 184 /* Init real i2c_client */
193 real_client = &data->client; 185 i2c_set_clientdata(client, data);
194 i2c_set_clientdata(real_client, data);
195 real_client->addr = address;
196 real_client->adapter = adapter;
197 real_client->driver = &max6875_driver;
198 strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
199 mutex_init(&data->update_lock); 186 mutex_init(&data->update_lock);
200 187
201 /* Init fake client data */ 188 err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr);
202 i2c_set_clientdata(fake_client, NULL);
203 fake_client->addr = address | 1;
204 fake_client->adapter = adapter;
205 fake_client->driver = &max6875_driver;
206 strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE);
207
208 if ((err = i2c_attach_client(real_client)) != 0)
209 goto exit_kfree2;
210
211 if ((err = i2c_attach_client(fake_client)) != 0)
212 goto exit_detach1;
213
214 err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
215 if (err) 189 if (err)
216 goto exit_detach2; 190 goto exit_remove_fake;
217 191
218 return 0; 192 return 0;
219 193
220exit_detach2: 194exit_remove_fake:
221 i2c_detach_client(fake_client); 195 i2c_unregister_device(data->fake_client);
222exit_detach1: 196exit_kfree:
223 i2c_detach_client(real_client);
224exit_kfree2:
225 kfree(fake_client);
226exit_kfree1:
227 kfree(data); 197 kfree(data);
228 return err; 198 return err;
229} 199}
230 200
231/* Will be called for both the real client and the fake client */ 201static int max6875_remove(struct i2c_client *client)
232static int max6875_detach_client(struct i2c_client *client)
233{ 202{
234 int err;
235 struct max6875_data *data = i2c_get_clientdata(client); 203 struct max6875_data *data = i2c_get_clientdata(client);
236 204
237 /* data is NULL for the fake client */ 205 i2c_unregister_device(data->fake_client);
238 if (data)
239 sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
240 206
241 err = i2c_detach_client(client); 207 sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
242 if (err) 208 kfree(data);
243 return err;
244 209
245 if (data) /* real client */
246 kfree(data);
247 else /* fake client */
248 kfree(client);
249 return 0; 210 return 0;
250} 211}
251 212
213static const struct i2c_device_id max6875_id[] = {
214 { "max6875", 0 },
215 { }
216};
217
218static struct i2c_driver max6875_driver = {
219 .driver = {
220 .name = "max6875",
221 },
222 .probe = max6875_probe,
223 .remove = max6875_remove,
224 .id_table = max6875_id,
225
226 .detect = max6875_detect,
227 .address_data = &addr_data,
228};
229
252static int __init max6875_init(void) 230static int __init max6875_init(void)
253{ 231{
254 return i2c_add_driver(&max6875_driver); 232 return i2c_add_driver(&max6875_driver);