diff options
| author | Oleg Ryjkov <olegr@google.com> | 2007-07-12 08:12:31 -0400 |
|---|---|---|
| committer | Jean Delvare <khali@hyperion.delvare> | 2007-07-12 08:12:31 -0400 |
| commit | ca8b9e32a11a7cbfecbef00c8451a79fe1af392e (patch) | |
| tree | ae5404a18928769a9d956a810c34239a4201749f /drivers | |
| parent | a92c344d8c640a812c7a9f5a5202d862cd052a0f (diff) | |
i2c-i801: Various cleanups
* Use defines instead of raw numbers for register bits
* Fix several wrong indentations and trailing whitespace
* Move hwpec timeout checking to a separate function
Signed-off-by: Oleg Ryjkov <olegr@google.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 116 |
1 files changed, 75 insertions, 41 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 611b57192c96..d5e12a4f01b0 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
| @@ -22,10 +22,10 @@ | |||
| 22 | 22 | ||
| 23 | /* | 23 | /* |
| 24 | SUPPORTED DEVICES PCI ID | 24 | SUPPORTED DEVICES PCI ID |
| 25 | 82801AA 2413 | 25 | 82801AA 2413 |
| 26 | 82801AB 2423 | 26 | 82801AB 2423 |
| 27 | 82801BA 2443 | 27 | 82801BA 2443 |
| 28 | 82801CA/CAM 2483 | 28 | 82801CA/CAM 2483 |
| 29 | 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported) | 29 | 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported) |
| 30 | 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported) | 30 | 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported) |
| 31 | 6300ESB 25A4 | 31 | 6300ESB 25A4 |
| @@ -74,6 +74,13 @@ | |||
| 74 | #define SMBHSTCFG_SMB_SMI_EN 2 | 74 | #define SMBHSTCFG_SMB_SMI_EN 2 |
| 75 | #define SMBHSTCFG_I2C_EN 4 | 75 | #define SMBHSTCFG_I2C_EN 4 |
| 76 | 76 | ||
| 77 | /* Auxillary control register bits, ICH4+ only */ | ||
| 78 | #define SMBAUXCTL_CRC 1 | ||
| 79 | #define SMBAUXCTL_E32B 2 | ||
| 80 | |||
| 81 | /* kill bit for SMBHSTCNT */ | ||
| 82 | #define SMBHSTCNT_KILL 2 | ||
| 83 | |||
| 77 | /* Other settings */ | 84 | /* Other settings */ |
| 78 | #define MAX_TIMEOUT 100 | 85 | #define MAX_TIMEOUT 100 |
| 79 | #define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ | 86 | #define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ |
| @@ -91,10 +98,15 @@ | |||
| 91 | #define I801_START 0x40 | 98 | #define I801_START 0x40 |
| 92 | #define I801_PEC_EN 0x80 /* ICH4 only */ | 99 | #define I801_PEC_EN 0x80 /* ICH4 only */ |
| 93 | 100 | ||
| 94 | 101 | /* I801 Hosts Status register bits */ | |
| 95 | static int i801_transaction(void); | 102 | #define SMBHSTSTS_BYTE_DONE 0x80 |
| 96 | static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | 103 | #define SMBHSTSTS_INUSE_STS 0x40 |
| 97 | int command, int hwpec); | 104 | #define SMBHSTSTS_SMBALERT_STS 0x20 |
| 105 | #define SMBHSTSTS_FAILED 0x10 | ||
| 106 | #define SMBHSTSTS_BUS_ERR 0x08 | ||
| 107 | #define SMBHSTSTS_DEV_ERR 0x04 | ||
| 108 | #define SMBHSTSTS_INTR 0x02 | ||
| 109 | #define SMBHSTSTS_HOST_BUSY 0x01 | ||
| 98 | 110 | ||
| 99 | static unsigned long i801_smba; | 111 | static unsigned long i801_smba; |
| 100 | static unsigned char i801_original_hstcfg; | 112 | static unsigned char i801_original_hstcfg; |
| @@ -133,27 +145,32 @@ static int i801_transaction(void) | |||
| 133 | do { | 145 | do { |
| 134 | msleep(1); | 146 | msleep(1); |
| 135 | temp = inb_p(SMBHSTSTS); | 147 | temp = inb_p(SMBHSTSTS); |
| 136 | } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); | 148 | } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT)); |
| 137 | 149 | ||
| 138 | /* If the SMBus is still busy, we give up */ | 150 | /* If the SMBus is still busy, we give up */ |
| 139 | if (timeout >= MAX_TIMEOUT) { | 151 | if (timeout >= MAX_TIMEOUT) { |
| 140 | dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); | 152 | dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); |
| 141 | result = -1; | 153 | result = -1; |
| 154 | /* try to stop the current command */ | ||
| 155 | dev_dbg(&I801_dev->dev, "Terminating the current operation\n"); | ||
| 156 | outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); | ||
| 157 | msleep(1); | ||
| 158 | outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT); | ||
| 142 | } | 159 | } |
| 143 | 160 | ||
| 144 | if (temp & 0x10) { | 161 | if (temp & SMBHSTSTS_FAILED) { |
| 145 | result = -1; | 162 | result = -1; |
| 146 | dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); | 163 | dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); |
| 147 | } | 164 | } |
| 148 | 165 | ||
| 149 | if (temp & 0x08) { | 166 | if (temp & SMBHSTSTS_BUS_ERR) { |
| 150 | result = -1; | 167 | result = -1; |
| 151 | dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked " | 168 | dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked " |
| 152 | "until next hard reset. (sorry!)\n"); | 169 | "until next hard reset. (sorry!)\n"); |
| 153 | /* Clock stops and slave is stuck in mid-transmission */ | 170 | /* Clock stops and slave is stuck in mid-transmission */ |
| 154 | } | 171 | } |
| 155 | 172 | ||
| 156 | if (temp & 0x04) { | 173 | if (temp & SMBHSTSTS_DEV_ERR) { |
| 157 | result = -1; | 174 | result = -1; |
| 158 | dev_dbg(&I801_dev->dev, "Error: no response!\n"); | 175 | dev_dbg(&I801_dev->dev, "Error: no response!\n"); |
| 159 | } | 176 | } |
| @@ -172,6 +189,24 @@ static int i801_transaction(void) | |||
| 172 | return result; | 189 | return result; |
| 173 | } | 190 | } |
| 174 | 191 | ||
| 192 | /* wait for INTR bit as advised by Intel */ | ||
| 193 | static void i801_wait_hwpec(void) | ||
| 194 | { | ||
| 195 | int timeout = 0; | ||
| 196 | int temp; | ||
| 197 | |||
| 198 | do { | ||
| 199 | msleep(1); | ||
| 200 | temp = inb_p(SMBHSTSTS); | ||
| 201 | } while ((!(temp & SMBHSTSTS_INTR)) | ||
| 202 | && (timeout++ < MAX_TIMEOUT)); | ||
| 203 | |||
| 204 | if (timeout >= MAX_TIMEOUT) { | ||
| 205 | dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); | ||
| 206 | } | ||
| 207 | outb_p(temp, SMBHSTSTS); | ||
| 208 | } | ||
| 209 | |||
| 175 | /* All-inclusive block transaction function */ | 210 | /* All-inclusive block transaction function */ |
| 176 | static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | 211 | static int i801_block_transaction(union i2c_smbus_data *data, char read_write, |
| 177 | int command, int hwpec) | 212 | int command, int hwpec) |
| @@ -227,13 +262,13 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | |||
| 227 | /* Make sure the SMBus host is ready to start transmitting */ | 262 | /* Make sure the SMBus host is ready to start transmitting */ |
| 228 | temp = inb_p(SMBHSTSTS); | 263 | temp = inb_p(SMBHSTSTS); |
| 229 | if (i == 1) { | 264 | if (i == 1) { |
| 230 | /* Erronenous conditions before transaction: | 265 | /* Erronenous conditions before transaction: |
| 231 | * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ | 266 | * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ |
| 232 | errmask=0x9f; | 267 | errmask = 0x9f; |
| 233 | } else { | 268 | } else { |
| 234 | /* Erronenous conditions during transaction: | 269 | /* Erronenous conditions during transaction: |
| 235 | * Failed, Bus_Err, Dev_Err, Intr */ | 270 | * Failed, Bus_Err, Dev_Err, Intr */ |
| 236 | errmask=0x1e; | 271 | errmask = 0x1e; |
| 237 | } | 272 | } |
| 238 | if (temp & errmask) { | 273 | if (temp & errmask) { |
| 239 | dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " | 274 | dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " |
| @@ -243,7 +278,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | |||
| 243 | dev_err(&I801_dev->dev, | 278 | dev_err(&I801_dev->dev, |
| 244 | "Reset failed! (%02x)\n", temp); | 279 | "Reset failed! (%02x)\n", temp); |
| 245 | result = -1; | 280 | result = -1; |
| 246 | goto END; | 281 | goto END; |
| 247 | } | 282 | } |
| 248 | if (i != 1) { | 283 | if (i != 1) { |
| 249 | /* if die in middle of block transaction, fail */ | 284 | /* if die in middle of block transaction, fail */ |
| @@ -261,33 +296,40 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | |||
| 261 | msleep(1); | 296 | msleep(1); |
| 262 | temp = inb_p(SMBHSTSTS); | 297 | temp = inb_p(SMBHSTSTS); |
| 263 | } | 298 | } |
| 264 | while ((!(temp & 0x80)) | 299 | while ((!(temp & SMBHSTSTS_BYTE_DONE)) |
| 265 | && (timeout++ < MAX_TIMEOUT)); | 300 | && (timeout++ < MAX_TIMEOUT)); |
| 266 | 301 | ||
| 267 | /* If the SMBus is still busy, we give up */ | 302 | /* If the SMBus is still busy, we give up */ |
| 268 | if (timeout >= MAX_TIMEOUT) { | 303 | if (timeout >= MAX_TIMEOUT) { |
| 304 | /* try to stop the current command */ | ||
| 305 | dev_dbg(&I801_dev->dev, "Terminating the current " | ||
| 306 | "operation\n"); | ||
| 307 | outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); | ||
| 308 | msleep(1); | ||
| 309 | outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), | ||
| 310 | SMBHSTCNT); | ||
| 269 | result = -1; | 311 | result = -1; |
| 270 | dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); | 312 | dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); |
| 271 | } | 313 | } |
| 272 | 314 | ||
| 273 | if (temp & 0x10) { | 315 | if (temp & SMBHSTSTS_FAILED) { |
| 274 | result = -1; | 316 | result = -1; |
| 275 | dev_dbg(&I801_dev->dev, | 317 | dev_dbg(&I801_dev->dev, |
| 276 | "Error: Failed bus transaction\n"); | 318 | "Error: Failed bus transaction\n"); |
| 277 | } else if (temp & 0x08) { | 319 | } else if (temp & SMBHSTSTS_BUS_ERR) { |
| 278 | result = -1; | 320 | result = -1; |
| 279 | dev_err(&I801_dev->dev, "Bus collision!\n"); | 321 | dev_err(&I801_dev->dev, "Bus collision!\n"); |
| 280 | } else if (temp & 0x04) { | 322 | } else if (temp & SMBHSTSTS_DEV_ERR) { |
| 281 | result = -1; | 323 | result = -1; |
| 282 | dev_dbg(&I801_dev->dev, "Error: no response!\n"); | 324 | dev_dbg(&I801_dev->dev, "Error: no response!\n"); |
| 283 | } | 325 | } |
| 284 | 326 | ||
| 285 | if (i == 1 && read_write == I2C_SMBUS_READ) { | 327 | if (i == 1 && read_write == I2C_SMBUS_READ) { |
| 286 | len = inb_p(SMBHSTDAT0); | 328 | len = inb_p(SMBHSTDAT0); |
| 287 | if (len < 1) | 329 | if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { |
| 288 | len = 1; | 330 | result = -1; |
| 289 | if (len > 32) | 331 | goto END; |
| 290 | len = 32; | 332 | } |
| 291 | data->block[0] = len; | 333 | data->block[0] = len; |
| 292 | } | 334 | } |
| 293 | 335 | ||
| @@ -313,20 +355,9 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | |||
| 313 | goto END; | 355 | goto END; |
| 314 | } | 356 | } |
| 315 | 357 | ||
| 316 | if (hwpec) { | 358 | if (hwpec) |
| 317 | /* wait for INTR bit as advised by Intel */ | 359 | i801_wait_hwpec(); |
| 318 | timeout = 0; | ||
| 319 | do { | ||
| 320 | msleep(1); | ||
| 321 | temp = inb_p(SMBHSTSTS); | ||
| 322 | } while ((!(temp & 0x02)) | ||
| 323 | && (timeout++ < MAX_TIMEOUT)); | ||
| 324 | 360 | ||
| 325 | if (timeout >= MAX_TIMEOUT) { | ||
| 326 | dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); | ||
| 327 | } | ||
| 328 | outb_p(temp, SMBHSTSTS); | ||
| 329 | } | ||
| 330 | result = 0; | 361 | result = 0; |
| 331 | END: | 362 | END: |
| 332 | if (command == I2C_SMBUS_I2C_BLOCK_DATA) { | 363 | if (command == I2C_SMBUS_I2C_BLOCK_DATA) { |
| @@ -393,7 +424,10 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, | |||
| 393 | return -1; | 424 | return -1; |
| 394 | } | 425 | } |
| 395 | 426 | ||
| 396 | outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */ | 427 | if (hwpec) /* enable/disable hardware PEC */ |
| 428 | outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL); | ||
| 429 | else | ||
| 430 | outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL); | ||
| 397 | 431 | ||
| 398 | if(block) | 432 | if(block) |
| 399 | ret = i801_block_transaction(data, read_write, size, hwpec); | 433 | ret = i801_block_transaction(data, read_write, size, hwpec); |
| @@ -405,7 +439,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, | |||
| 405 | /* Some BIOSes don't like it when PEC is enabled at reboot or resume | 439 | /* Some BIOSes don't like it when PEC is enabled at reboot or resume |
| 406 | time, so we forcibly disable it after every transaction. */ | 440 | time, so we forcibly disable it after every transaction. */ |
| 407 | if (hwpec) | 441 | if (hwpec) |
| 408 | outb_p(0, SMBAUXCTL); | 442 | outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL); |
| 409 | 443 | ||
| 410 | if(block) | 444 | if(block) |
| 411 | return ret; | 445 | return ret; |
