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