diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-sis630.c')
-rw-r--r-- | drivers/i2c/busses/i2c-sis630.c | 59 |
1 files changed, 33 insertions, 26 deletions
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 3765dd7f450f..e7c4b790da54 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c | |||
@@ -1,7 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | |||
5 | Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de> | 2 | Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de> |
6 | 3 | ||
7 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
@@ -55,6 +52,7 @@ | |||
55 | #include <linux/ioport.h> | 52 | #include <linux/ioport.h> |
56 | #include <linux/init.h> | 53 | #include <linux/init.h> |
57 | #include <linux/i2c.h> | 54 | #include <linux/i2c.h> |
55 | #include <linux/acpi.h> | ||
58 | #include <asm/io.h> | 56 | #include <asm/io.h> |
59 | 57 | ||
60 | /* SIS630 SMBus registers */ | 58 | /* SIS630 SMBus registers */ |
@@ -134,7 +132,7 @@ static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldc | |||
134 | 132 | ||
135 | if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { | 133 | if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { |
136 | dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); | 134 | dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); |
137 | return -1; | 135 | return -EBUSY; |
138 | } else { | 136 | } else { |
139 | dev_dbg(&adap->dev, "Successful!\n"); | 137 | dev_dbg(&adap->dev, "Successful!\n"); |
140 | } | 138 | } |
@@ -177,17 +175,17 @@ static int sis630_transaction_wait(struct i2c_adapter *adap, int size) | |||
177 | /* If the SMBus is still busy, we give up */ | 175 | /* If the SMBus is still busy, we give up */ |
178 | if (timeout >= MAX_TIMEOUT) { | 176 | if (timeout >= MAX_TIMEOUT) { |
179 | dev_dbg(&adap->dev, "SMBus Timeout!\n"); | 177 | dev_dbg(&adap->dev, "SMBus Timeout!\n"); |
180 | result = -1; | 178 | result = -ETIMEDOUT; |
181 | } | 179 | } |
182 | 180 | ||
183 | if (temp & 0x02) { | 181 | if (temp & 0x02) { |
184 | dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); | 182 | dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); |
185 | result = -1; | 183 | result = -ENXIO; |
186 | } | 184 | } |
187 | 185 | ||
188 | if (temp & 0x04) { | 186 | if (temp & 0x04) { |
189 | dev_err(&adap->dev, "Bus collision!\n"); | 187 | dev_err(&adap->dev, "Bus collision!\n"); |
190 | result = -1; | 188 | result = -EIO; |
191 | /* | 189 | /* |
192 | TBD: Datasheet say: | 190 | TBD: Datasheet say: |
193 | the software should clear this bit and restart SMBUS operation. | 191 | the software should clear this bit and restart SMBUS operation. |
@@ -250,8 +248,10 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat | |||
250 | if (i==8 || (len<8 && i==len)) { | 248 | if (i==8 || (len<8 && i==len)) { |
251 | dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i); | 249 | dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i); |
252 | /* first transaction */ | 250 | /* first transaction */ |
253 | if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) | 251 | rc = sis630_transaction_start(adap, |
254 | return -1; | 252 | SIS630_BLOCK_DATA, &oldclock); |
253 | if (rc) | ||
254 | return rc; | ||
255 | } | 255 | } |
256 | else if ((i-1)%8 == 7 || i==len) { | 256 | else if ((i-1)%8 == 7 || i==len) { |
257 | dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i); | 257 | dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i); |
@@ -264,9 +264,10 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat | |||
264 | */ | 264 | */ |
265 | sis630_write(SMB_STS,0x10); | 265 | sis630_write(SMB_STS,0x10); |
266 | } | 266 | } |
267 | if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { | 267 | rc = sis630_transaction_wait(adap, |
268 | SIS630_BLOCK_DATA); | ||
269 | if (rc) { | ||
268 | dev_dbg(&adap->dev, "trans_wait failed\n"); | 270 | dev_dbg(&adap->dev, "trans_wait failed\n"); |
269 | rc = -1; | ||
270 | break; | 271 | break; |
271 | } | 272 | } |
272 | } | 273 | } |
@@ -275,13 +276,14 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat | |||
275 | else { | 276 | else { |
276 | /* read request */ | 277 | /* read request */ |
277 | data->block[0] = len = 0; | 278 | data->block[0] = len = 0; |
278 | if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) { | 279 | rc = sis630_transaction_start(adap, |
279 | return -1; | 280 | SIS630_BLOCK_DATA, &oldclock); |
280 | } | 281 | if (rc) |
282 | return rc; | ||
281 | do { | 283 | do { |
282 | if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { | 284 | rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA); |
285 | if (rc) { | ||
283 | dev_dbg(&adap->dev, "trans_wait failed\n"); | 286 | dev_dbg(&adap->dev, "trans_wait failed\n"); |
284 | rc = -1; | ||
285 | break; | 287 | break; |
286 | } | 288 | } |
287 | /* if this first transaction then read byte count */ | 289 | /* if this first transaction then read byte count */ |
@@ -311,11 +313,13 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat | |||
311 | return rc; | 313 | return rc; |
312 | } | 314 | } |
313 | 315 | ||
314 | /* Return -1 on error. */ | 316 | /* Return negative errno on error. */ |
315 | static s32 sis630_access(struct i2c_adapter *adap, u16 addr, | 317 | static s32 sis630_access(struct i2c_adapter *adap, u16 addr, |
316 | unsigned short flags, char read_write, | 318 | unsigned short flags, char read_write, |
317 | u8 command, int size, union i2c_smbus_data *data) | 319 | u8 command, int size, union i2c_smbus_data *data) |
318 | { | 320 | { |
321 | int status; | ||
322 | |||
319 | switch (size) { | 323 | switch (size) { |
320 | case I2C_SMBUS_QUICK: | 324 | case I2C_SMBUS_QUICK: |
321 | sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | 325 | sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); |
@@ -350,13 +354,14 @@ static s32 sis630_access(struct i2c_adapter *adap, u16 addr, | |||
350 | size = SIS630_BLOCK_DATA; | 354 | size = SIS630_BLOCK_DATA; |
351 | return sis630_block_data(adap, data, read_write); | 355 | return sis630_block_data(adap, data, read_write); |
352 | default: | 356 | default: |
353 | printk("Unsupported I2C size\n"); | 357 | dev_warn(&adap->dev, "Unsupported transaction %d\n", |
354 | return -1; | 358 | size); |
355 | break; | 359 | return -EOPNOTSUPP; |
356 | } | 360 | } |
357 | 361 | ||
358 | if (sis630_transaction(adap, size)) | 362 | status = sis630_transaction(adap, size); |
359 | return -1; | 363 | if (status) |
364 | return status; | ||
360 | 365 | ||
361 | if ((size != SIS630_PCALL) && | 366 | if ((size != SIS630_PCALL) && |
362 | ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) { | 367 | ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) { |
@@ -372,9 +377,6 @@ static s32 sis630_access(struct i2c_adapter *adap, u16 addr, | |||
372 | case SIS630_WORD_DATA: | 377 | case SIS630_WORD_DATA: |
373 | data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8); | 378 | data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8); |
374 | break; | 379 | break; |
375 | default: | ||
376 | return -1; | ||
377 | break; | ||
378 | } | 380 | } |
379 | 381 | ||
380 | return 0; | 382 | return 0; |
@@ -433,6 +435,11 @@ static int sis630_setup(struct pci_dev *sis630_dev) | |||
433 | 435 | ||
434 | dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base); | 436 | dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base); |
435 | 437 | ||
438 | retval = acpi_check_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, | ||
439 | sis630_driver.name); | ||
440 | if (retval) | ||
441 | goto exit; | ||
442 | |||
436 | /* Everything is happy, let's grab the memory and set things up. */ | 443 | /* Everything is happy, let's grab the memory and set things up. */ |
437 | if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, | 444 | if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, |
438 | sis630_driver.name)) { | 445 | sis630_driver.name)) { |
@@ -458,7 +465,7 @@ static const struct i2c_algorithm smbus_algorithm = { | |||
458 | static struct i2c_adapter sis630_adapter = { | 465 | static struct i2c_adapter sis630_adapter = { |
459 | .owner = THIS_MODULE, | 466 | .owner = THIS_MODULE, |
460 | .id = I2C_HW_SMBUS_SIS630, | 467 | .id = I2C_HW_SMBUS_SIS630, |
461 | .class = I2C_CLASS_HWMON, | 468 | .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, |
462 | .algo = &smbus_algorithm, | 469 | .algo = &smbus_algorithm, |
463 | }; | 470 | }; |
464 | 471 | ||