aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-sis630.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-sis630.c')
-rw-r--r--drivers/i2c/busses/i2c-sis630.c59
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. */
315static s32 sis630_access(struct i2c_adapter *adap, u16 addr, 317static 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 = {
458static struct i2c_adapter sis630_adapter = { 465static 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