diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-amd8111.c')
-rw-r--r-- | drivers/i2c/busses/i2c-amd8111.c | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index 0fbc7186c91a..14ad9912f204 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c | |||
@@ -76,7 +76,8 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) | |||
76 | udelay(1); | 76 | udelay(1); |
77 | 77 | ||
78 | if (!timeout) { | 78 | if (!timeout) { |
79 | dev_warn(&smbus->dev->dev, "Timeout while waiting for IBF to clear\n"); | 79 | dev_warn(&smbus->dev->dev, |
80 | "Timeout while waiting for IBF to clear\n"); | ||
80 | return -1; | 81 | return -1; |
81 | } | 82 | } |
82 | 83 | ||
@@ -91,14 +92,16 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) | |||
91 | udelay(1); | 92 | udelay(1); |
92 | 93 | ||
93 | if (!timeout) { | 94 | if (!timeout) { |
94 | dev_warn(&smbus->dev->dev, "Timeout while waiting for OBF to set\n"); | 95 | dev_warn(&smbus->dev->dev, |
96 | "Timeout while waiting for OBF to set\n"); | ||
95 | return -1; | 97 | return -1; |
96 | } | 98 | } |
97 | 99 | ||
98 | return 0; | 100 | return 0; |
99 | } | 101 | } |
100 | 102 | ||
101 | static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data) | 103 | static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, |
104 | unsigned char *data) | ||
102 | { | 105 | { |
103 | if (amd_ec_wait_write(smbus)) | 106 | if (amd_ec_wait_write(smbus)) |
104 | return -1; | 107 | return -1; |
@@ -115,7 +118,8 @@ static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, | |||
115 | return 0; | 118 | return 0; |
116 | } | 119 | } |
117 | 120 | ||
118 | static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data) | 121 | static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, |
122 | unsigned char data) | ||
119 | { | 123 | { |
120 | if (amd_ec_wait_write(smbus)) | 124 | if (amd_ec_wait_write(smbus)) |
121 | return -1; | 125 | return -1; |
@@ -175,18 +179,19 @@ static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, | |||
175 | #define AMD_SMB_PRTCL_PEC 0x80 | 179 | #define AMD_SMB_PRTCL_PEC 0x80 |
176 | 180 | ||
177 | 181 | ||
178 | static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, | 182 | static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, |
179 | char read_write, u8 command, int size, union i2c_smbus_data * data) | 183 | unsigned short flags, char read_write, u8 command, int size, |
184 | union i2c_smbus_data * data) | ||
180 | { | 185 | { |
181 | struct amd_smbus *smbus = adap->algo_data; | 186 | struct amd_smbus *smbus = adap->algo_data; |
182 | unsigned char protocol, len, pec, temp[2]; | 187 | unsigned char protocol, len, pec, temp[2]; |
183 | int i; | 188 | int i; |
184 | 189 | ||
185 | protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ : AMD_SMB_PRTCL_WRITE; | 190 | protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ |
191 | : AMD_SMB_PRTCL_WRITE; | ||
186 | pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0; | 192 | pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0; |
187 | 193 | ||
188 | switch (size) { | 194 | switch (size) { |
189 | |||
190 | case I2C_SMBUS_QUICK: | 195 | case I2C_SMBUS_QUICK: |
191 | protocol |= AMD_SMB_PRTCL_QUICK; | 196 | protocol |= AMD_SMB_PRTCL_QUICK; |
192 | read_write = I2C_SMBUS_WRITE; | 197 | read_write = I2C_SMBUS_WRITE; |
@@ -208,8 +213,10 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl | |||
208 | case I2C_SMBUS_WORD_DATA: | 213 | case I2C_SMBUS_WORD_DATA: |
209 | amd_ec_write(smbus, AMD_SMB_CMD, command); | 214 | amd_ec_write(smbus, AMD_SMB_CMD, command); |
210 | if (read_write == I2C_SMBUS_WRITE) { | 215 | if (read_write == I2C_SMBUS_WRITE) { |
211 | amd_ec_write(smbus, AMD_SMB_DATA, data->word); | 216 | amd_ec_write(smbus, AMD_SMB_DATA, |
212 | amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8); | 217 | data->word & 0xff); |
218 | amd_ec_write(smbus, AMD_SMB_DATA + 1, | ||
219 | data->word >> 8); | ||
213 | } | 220 | } |
214 | protocol |= AMD_SMB_PRTCL_WORD_DATA | pec; | 221 | protocol |= AMD_SMB_PRTCL_WORD_DATA | pec; |
215 | break; | 222 | break; |
@@ -217,27 +224,31 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl | |||
217 | case I2C_SMBUS_BLOCK_DATA: | 224 | case I2C_SMBUS_BLOCK_DATA: |
218 | amd_ec_write(smbus, AMD_SMB_CMD, command); | 225 | amd_ec_write(smbus, AMD_SMB_CMD, command); |
219 | if (read_write == I2C_SMBUS_WRITE) { | 226 | if (read_write == I2C_SMBUS_WRITE) { |
220 | len = min_t(u8, data->block[0], 32); | 227 | len = min_t(u8, data->block[0], |
228 | I2C_SMBUS_BLOCK_MAX); | ||
221 | amd_ec_write(smbus, AMD_SMB_BCNT, len); | 229 | amd_ec_write(smbus, AMD_SMB_BCNT, len); |
222 | for (i = 0; i < len; i++) | 230 | for (i = 0; i < len; i++) |
223 | amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]); | 231 | amd_ec_write(smbus, AMD_SMB_DATA + i, |
232 | data->block[i + 1]); | ||
224 | } | 233 | } |
225 | protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec; | 234 | protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec; |
226 | break; | 235 | break; |
227 | 236 | ||
228 | case I2C_SMBUS_I2C_BLOCK_DATA: | 237 | case I2C_SMBUS_I2C_BLOCK_DATA: |
229 | len = min_t(u8, data->block[0], 32); | 238 | len = min_t(u8, data->block[0], |
239 | I2C_SMBUS_BLOCK_MAX); | ||
230 | amd_ec_write(smbus, AMD_SMB_CMD, command); | 240 | amd_ec_write(smbus, AMD_SMB_CMD, command); |
231 | amd_ec_write(smbus, AMD_SMB_BCNT, len); | 241 | amd_ec_write(smbus, AMD_SMB_BCNT, len); |
232 | if (read_write == I2C_SMBUS_WRITE) | 242 | if (read_write == I2C_SMBUS_WRITE) |
233 | for (i = 0; i < len; i++) | 243 | for (i = 0; i < len; i++) |
234 | amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]); | 244 | amd_ec_write(smbus, AMD_SMB_DATA + i, |
245 | data->block[i + 1]); | ||
235 | protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA; | 246 | protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA; |
236 | break; | 247 | break; |
237 | 248 | ||
238 | case I2C_SMBUS_PROC_CALL: | 249 | case I2C_SMBUS_PROC_CALL: |
239 | amd_ec_write(smbus, AMD_SMB_CMD, command); | 250 | amd_ec_write(smbus, AMD_SMB_CMD, command); |
240 | amd_ec_write(smbus, AMD_SMB_DATA, data->word); | 251 | amd_ec_write(smbus, AMD_SMB_DATA, data->word & 0xff); |
241 | amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8); | 252 | amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8); |
242 | protocol = AMD_SMB_PRTCL_PROC_CALL | pec; | 253 | protocol = AMD_SMB_PRTCL_PROC_CALL | pec; |
243 | read_write = I2C_SMBUS_READ; | 254 | read_write = I2C_SMBUS_READ; |
@@ -248,7 +259,8 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl | |||
248 | amd_ec_write(smbus, AMD_SMB_CMD, command); | 259 | amd_ec_write(smbus, AMD_SMB_CMD, command); |
249 | amd_ec_write(smbus, AMD_SMB_BCNT, len); | 260 | amd_ec_write(smbus, AMD_SMB_BCNT, len); |
250 | for (i = 0; i < len; i++) | 261 | for (i = 0; i < len; i++) |
251 | amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]); | 262 | amd_ec_write(smbus, AMD_SMB_DATA + i, |
263 | data->block[i + 1]); | ||
252 | protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec; | 264 | protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec; |
253 | read_write = I2C_SMBUS_READ; | 265 | read_write = I2C_SMBUS_READ; |
254 | break; | 266 | break; |
@@ -280,7 +292,6 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl | |||
280 | return 0; | 292 | return 0; |
281 | 293 | ||
282 | switch (size) { | 294 | switch (size) { |
283 | |||
284 | case I2C_SMBUS_BYTE: | 295 | case I2C_SMBUS_BYTE: |
285 | case I2C_SMBUS_BYTE_DATA: | 296 | case I2C_SMBUS_BYTE_DATA: |
286 | amd_ec_read(smbus, AMD_SMB_DATA, &data->byte); | 297 | amd_ec_read(smbus, AMD_SMB_DATA, &data->byte); |
@@ -296,10 +307,11 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl | |||
296 | case I2C_SMBUS_BLOCK_DATA: | 307 | case I2C_SMBUS_BLOCK_DATA: |
297 | case I2C_SMBUS_BLOCK_PROC_CALL: | 308 | case I2C_SMBUS_BLOCK_PROC_CALL: |
298 | amd_ec_read(smbus, AMD_SMB_BCNT, &len); | 309 | amd_ec_read(smbus, AMD_SMB_BCNT, &len); |
299 | len = min_t(u8, len, 32); | 310 | len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX); |
300 | case I2C_SMBUS_I2C_BLOCK_DATA: | 311 | case I2C_SMBUS_I2C_BLOCK_DATA: |
301 | for (i = 0; i < len; i++) | 312 | for (i = 0; i < len; i++) |
302 | amd_ec_read(smbus, AMD_SMB_DATA + i, data->block + i + 1); | 313 | amd_ec_read(smbus, AMD_SMB_DATA + i, |
314 | data->block + i + 1); | ||
303 | data->block[0] = len; | 315 | data->block[0] = len; |
304 | break; | 316 | break; |
305 | } | 317 | } |
@@ -310,7 +322,8 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl | |||
310 | 322 | ||
311 | static u32 amd8111_func(struct i2c_adapter *adapter) | 323 | static u32 amd8111_func(struct i2c_adapter *adapter) |
312 | { | 324 | { |
313 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | | 325 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | |
326 | I2C_FUNC_SMBUS_BYTE_DATA | | ||
314 | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA | | 327 | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA | |
315 | I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | | 328 | I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | |
316 | I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC; | 329 | I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC; |
@@ -329,12 +342,13 @@ static struct pci_device_id amd8111_ids[] = { | |||
329 | 342 | ||
330 | MODULE_DEVICE_TABLE (pci, amd8111_ids); | 343 | MODULE_DEVICE_TABLE (pci, amd8111_ids); |
331 | 344 | ||
332 | static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id) | 345 | static int __devinit amd8111_probe(struct pci_dev *dev, |
346 | const struct pci_device_id *id) | ||
333 | { | 347 | { |
334 | struct amd_smbus *smbus; | 348 | struct amd_smbus *smbus; |
335 | int error = -ENODEV; | 349 | int error; |
336 | 350 | ||
337 | if (~pci_resource_flags(dev, 0) & IORESOURCE_IO) | 351 | if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO)) |
338 | return -ENODEV; | 352 | return -ENODEV; |
339 | 353 | ||
340 | smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL); | 354 | smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL); |
@@ -345,12 +359,15 @@ static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_ | |||
345 | smbus->base = pci_resource_start(dev, 0); | 359 | smbus->base = pci_resource_start(dev, 0); |
346 | smbus->size = pci_resource_len(dev, 0); | 360 | smbus->size = pci_resource_len(dev, 0); |
347 | 361 | ||
348 | if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) | 362 | if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) { |
363 | error = -EBUSY; | ||
349 | goto out_kfree; | 364 | goto out_kfree; |
365 | } | ||
350 | 366 | ||
351 | smbus->adapter.owner = THIS_MODULE; | 367 | smbus->adapter.owner = THIS_MODULE; |
352 | snprintf(smbus->adapter.name, I2C_NAME_SIZE, | 368 | snprintf(smbus->adapter.name, I2C_NAME_SIZE, |
353 | "SMBus2 AMD8111 adapter at %04x", smbus->base); | 369 | "SMBus2 AMD8111 adapter at %04x", smbus->base); |
370 | smbus->adapter.id = I2C_HW_SMBUS_AMD8111; | ||
354 | smbus->adapter.class = I2C_CLASS_HWMON; | 371 | smbus->adapter.class = I2C_CLASS_HWMON; |
355 | smbus->adapter.algo = &smbus_algorithm; | 372 | smbus->adapter.algo = &smbus_algorithm; |
356 | smbus->adapter.algo_data = smbus; | 373 | smbus->adapter.algo_data = smbus; |
@@ -358,11 +375,11 @@ static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_ | |||
358 | /* set up the driverfs linkage to our parent device */ | 375 | /* set up the driverfs linkage to our parent device */ |
359 | smbus->adapter.dev.parent = &dev->dev; | 376 | smbus->adapter.dev.parent = &dev->dev; |
360 | 377 | ||
378 | pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0); | ||
361 | error = i2c_add_adapter(&smbus->adapter); | 379 | error = i2c_add_adapter(&smbus->adapter); |
362 | if (error) | 380 | if (error) |
363 | goto out_release_region; | 381 | goto out_release_region; |
364 | 382 | ||
365 | pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0); | ||
366 | pci_set_drvdata(dev, smbus); | 383 | pci_set_drvdata(dev, smbus); |
367 | return 0; | 384 | return 0; |
368 | 385 | ||
@@ -370,10 +387,9 @@ static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_ | |||
370 | release_region(smbus->base, smbus->size); | 387 | release_region(smbus->base, smbus->size); |
371 | out_kfree: | 388 | out_kfree: |
372 | kfree(smbus); | 389 | kfree(smbus); |
373 | return -1; | 390 | return error; |
374 | } | 391 | } |
375 | 392 | ||
376 | |||
377 | static void __devexit amd8111_remove(struct pci_dev *dev) | 393 | static void __devexit amd8111_remove(struct pci_dev *dev) |
378 | { | 394 | { |
379 | struct amd_smbus *smbus = pci_get_drvdata(dev); | 395 | struct amd_smbus *smbus = pci_get_drvdata(dev); |
@@ -395,7 +411,6 @@ static int __init i2c_amd8111_init(void) | |||
395 | return pci_register_driver(&amd8111_driver); | 411 | return pci_register_driver(&amd8111_driver); |
396 | } | 412 | } |
397 | 413 | ||
398 | |||
399 | static void __exit i2c_amd8111_exit(void) | 414 | static void __exit i2c_amd8111_exit(void) |
400 | { | 415 | { |
401 | pci_unregister_driver(&amd8111_driver); | 416 | pci_unregister_driver(&amd8111_driver); |