diff options
Diffstat (limited to 'drivers/i2c/chips/eeprom.c')
-rw-r--r-- | drivers/i2c/chips/eeprom.c | 92 |
1 files changed, 40 insertions, 52 deletions
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 373ea8d8fe8f..2c27193aeaa0 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c | |||
@@ -47,7 +47,6 @@ enum eeprom_nature { | |||
47 | 47 | ||
48 | /* Each client has this additional data */ | 48 | /* Each client has this additional data */ |
49 | struct eeprom_data { | 49 | struct eeprom_data { |
50 | struct i2c_client client; | ||
51 | struct mutex update_lock; | 50 | struct mutex update_lock; |
52 | u8 valid; /* bitfield, bit!=0 if slice is valid */ | 51 | u8 valid; /* bitfield, bit!=0 if slice is valid */ |
53 | unsigned long last_updated[8]; /* In jiffies, 8 slices */ | 52 | unsigned long last_updated[8]; /* In jiffies, 8 slices */ |
@@ -56,19 +55,6 @@ struct eeprom_data { | |||
56 | }; | 55 | }; |
57 | 56 | ||
58 | 57 | ||
59 | static int eeprom_attach_adapter(struct i2c_adapter *adapter); | ||
60 | static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind); | ||
61 | static int eeprom_detach_client(struct i2c_client *client); | ||
62 | |||
63 | /* This is the driver that will be inserted */ | ||
64 | static struct i2c_driver eeprom_driver = { | ||
65 | .driver = { | ||
66 | .name = "eeprom", | ||
67 | }, | ||
68 | .attach_adapter = eeprom_attach_adapter, | ||
69 | .detach_client = eeprom_detach_client, | ||
70 | }; | ||
71 | |||
72 | static void eeprom_update_client(struct i2c_client *client, u8 slice) | 58 | static void eeprom_update_client(struct i2c_client *client, u8 slice) |
73 | { | 59 | { |
74 | struct eeprom_data *data = i2c_get_clientdata(client); | 60 | struct eeprom_data *data = i2c_get_clientdata(client); |
@@ -148,25 +134,17 @@ static struct bin_attribute eeprom_attr = { | |||
148 | .read = eeprom_read, | 134 | .read = eeprom_read, |
149 | }; | 135 | }; |
150 | 136 | ||
151 | static int eeprom_attach_adapter(struct i2c_adapter *adapter) | 137 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
152 | { | 138 | static int eeprom_detect(struct i2c_client *client, int kind, |
153 | if (!(adapter->class & (I2C_CLASS_DDC | I2C_CLASS_SPD))) | 139 | struct i2c_board_info *info) |
154 | return 0; | ||
155 | return i2c_probe(adapter, &addr_data, eeprom_detect); | ||
156 | } | ||
157 | |||
158 | /* This function is called by i2c_probe */ | ||
159 | static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) | ||
160 | { | 140 | { |
161 | struct i2c_client *client; | 141 | struct i2c_adapter *adapter = client->adapter; |
162 | struct eeprom_data *data; | ||
163 | int err = 0; | ||
164 | 142 | ||
165 | /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all | 143 | /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all |
166 | addresses 0x50-0x57, but we only care about 0x50. So decline | 144 | addresses 0x50-0x57, but we only care about 0x50. So decline |
167 | attaching to addresses >= 0x51 on DDC buses */ | 145 | attaching to addresses >= 0x51 on DDC buses */ |
168 | if (!(adapter->class & I2C_CLASS_SPD) && address >= 0x51) | 146 | if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) |
169 | goto exit; | 147 | return -ENODEV; |
170 | 148 | ||
171 | /* There are four ways we can read the EEPROM data: | 149 | /* There are four ways we can read the EEPROM data: |
172 | (1) I2C block reads (faster, but unsupported by most adapters) | 150 | (1) I2C block reads (faster, but unsupported by most adapters) |
@@ -177,32 +155,33 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) | |||
177 | because all known adapters support one of the first two. */ | 155 | because all known adapters support one of the first two. */ |
178 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA) | 156 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA) |
179 | && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) | 157 | && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) |
180 | goto exit; | 158 | return -ENODEV; |
159 | |||
160 | strlcpy(info->type, "eeprom", I2C_NAME_SIZE); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int eeprom_probe(struct i2c_client *client, | ||
166 | const struct i2c_device_id *id) | ||
167 | { | ||
168 | struct i2c_adapter *adapter = client->adapter; | ||
169 | struct eeprom_data *data; | ||
170 | int err; | ||
181 | 171 | ||
182 | if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { | 172 | if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { |
183 | err = -ENOMEM; | 173 | err = -ENOMEM; |
184 | goto exit; | 174 | goto exit; |
185 | } | 175 | } |
186 | 176 | ||
187 | client = &data->client; | ||
188 | memset(data->data, 0xff, EEPROM_SIZE); | 177 | memset(data->data, 0xff, EEPROM_SIZE); |
189 | i2c_set_clientdata(client, data); | 178 | i2c_set_clientdata(client, data); |
190 | client->addr = address; | ||
191 | client->adapter = adapter; | ||
192 | client->driver = &eeprom_driver; | ||
193 | |||
194 | /* Fill in the remaining client fields */ | ||
195 | strlcpy(client->name, "eeprom", I2C_NAME_SIZE); | ||
196 | mutex_init(&data->update_lock); | 179 | mutex_init(&data->update_lock); |
197 | data->nature = UNKNOWN; | 180 | data->nature = UNKNOWN; |
198 | 181 | ||
199 | /* Tell the I2C layer a new client has arrived */ | ||
200 | if ((err = i2c_attach_client(client))) | ||
201 | goto exit_kfree; | ||
202 | |||
203 | /* Detect the Vaio nature of EEPROMs. | 182 | /* Detect the Vaio nature of EEPROMs. |
204 | We use the "PCG-" or "VGN-" prefix as the signature. */ | 183 | We use the "PCG-" or "VGN-" prefix as the signature. */ |
205 | if (address == 0x57 | 184 | if (client->addr == 0x57 |
206 | && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { | 185 | && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { |
207 | char name[4]; | 186 | char name[4]; |
208 | 187 | ||
@@ -221,33 +200,42 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) | |||
221 | /* create the sysfs eeprom file */ | 200 | /* create the sysfs eeprom file */ |
222 | err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr); | 201 | err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr); |
223 | if (err) | 202 | if (err) |
224 | goto exit_detach; | 203 | goto exit_kfree; |
225 | 204 | ||
226 | return 0; | 205 | return 0; |
227 | 206 | ||
228 | exit_detach: | ||
229 | i2c_detach_client(client); | ||
230 | exit_kfree: | 207 | exit_kfree: |
231 | kfree(data); | 208 | kfree(data); |
232 | exit: | 209 | exit: |
233 | return err; | 210 | return err; |
234 | } | 211 | } |
235 | 212 | ||
236 | static int eeprom_detach_client(struct i2c_client *client) | 213 | static int eeprom_remove(struct i2c_client *client) |
237 | { | 214 | { |
238 | int err; | ||
239 | |||
240 | sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); | 215 | sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); |
241 | |||
242 | err = i2c_detach_client(client); | ||
243 | if (err) | ||
244 | return err; | ||
245 | |||
246 | kfree(i2c_get_clientdata(client)); | 216 | kfree(i2c_get_clientdata(client)); |
247 | 217 | ||
248 | return 0; | 218 | return 0; |
249 | } | 219 | } |
250 | 220 | ||
221 | static const struct i2c_device_id eeprom_id[] = { | ||
222 | { "eeprom", 0 }, | ||
223 | { } | ||
224 | }; | ||
225 | |||
226 | static struct i2c_driver eeprom_driver = { | ||
227 | .driver = { | ||
228 | .name = "eeprom", | ||
229 | }, | ||
230 | .probe = eeprom_probe, | ||
231 | .remove = eeprom_remove, | ||
232 | .id_table = eeprom_id, | ||
233 | |||
234 | .class = I2C_CLASS_DDC | I2C_CLASS_SPD, | ||
235 | .detect = eeprom_detect, | ||
236 | .address_data = &addr_data, | ||
237 | }; | ||
238 | |||
251 | static int __init eeprom_init(void) | 239 | static int __init eeprom_init(void) |
252 | { | 240 | { |
253 | return i2c_add_driver(&eeprom_driver); | 241 | return i2c_add_driver(&eeprom_driver); |