aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/chips/eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/chips/eeprom.c')
-rw-r--r--drivers/i2c/chips/eeprom.c92
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 */
49struct eeprom_data { 49struct 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
59static int eeprom_attach_adapter(struct i2c_adapter *adapter);
60static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind);
61static int eeprom_detach_client(struct i2c_client *client);
62
63/* This is the driver that will be inserted */
64static 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
72static void eeprom_update_client(struct i2c_client *client, u8 slice) 58static 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
151static int eeprom_attach_adapter(struct i2c_adapter *adapter) 137/* Return 0 if detection is successful, -ENODEV otherwise */
152{ 138static 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 */
159static 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
165static 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
228exit_detach:
229 i2c_detach_client(client);
230exit_kfree: 207exit_kfree:
231 kfree(data); 208 kfree(data);
232exit: 209exit:
233 return err; 210 return err;
234} 211}
235 212
236static int eeprom_detach_client(struct i2c_client *client) 213static 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
221static const struct i2c_device_id eeprom_id[] = {
222 { "eeprom", 0 },
223 { }
224};
225
226static 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
251static int __init eeprom_init(void) 239static int __init eeprom_init(void)
252{ 240{
253 return i2c_add_driver(&eeprom_driver); 241 return i2c_add_driver(&eeprom_driver);