Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: octeon: Improve error status checking

Introduce a function that checks for valid status codes depending
on the phase of a transmit or receive. Also add all existing status
codes and improve error handling for various states.

The Octeon TWSI has an "assert acknowledge" bit (TWSI_CTL_AAK) that
is required to be set in master receive mode until the last byte is
requested. The state check needs to consider if this bit was set.

Signed-off-by: Jan Glauber <jglauber@cavium.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>

authored by

Jan Glauber and committed by
Wolfram Sang
b4c715d0 f6903783

+107 -24
+107 -24
drivers/i2c/busses/i2c-octeon.c
··· 55 55 #define TWSI_CTL_IFLG 0x08 /* HW event, SW writes 0 to ACK */ 56 56 #define TWSI_CTL_AAK 0x04 /* Assert ACK */ 57 57 58 - /* Some status values */ 58 + /* Status values */ 59 + #define STAT_ERROR 0x00 59 60 #define STAT_START 0x08 60 - #define STAT_RSTART 0x10 61 + #define STAT_REP_START 0x10 61 62 #define STAT_TXADDR_ACK 0x18 63 + #define STAT_TXADDR_NAK 0x20 62 64 #define STAT_TXDATA_ACK 0x28 65 + #define STAT_TXDATA_NAK 0x30 66 + #define STAT_LOST_ARB_38 0x38 63 67 #define STAT_RXADDR_ACK 0x40 68 + #define STAT_RXADDR_NAK 0x48 64 69 #define STAT_RXDATA_ACK 0x50 70 + #define STAT_RXDATA_NAK 0x58 71 + #define STAT_SLAVE_60 0x60 72 + #define STAT_LOST_ARB_68 0x68 73 + #define STAT_SLAVE_70 0x70 74 + #define STAT_LOST_ARB_78 0x78 75 + #define STAT_SLAVE_80 0x80 76 + #define STAT_SLAVE_88 0x88 77 + #define STAT_GENDATA_ACK 0x90 78 + #define STAT_GENDATA_NAK 0x98 79 + #define STAT_SLAVE_A0 0xA0 80 + #define STAT_SLAVE_A8 0xA8 81 + #define STAT_LOST_ARB_B0 0xB0 82 + #define STAT_SLAVE_LOST 0xB8 83 + #define STAT_SLAVE_NAK 0xC0 84 + #define STAT_SLAVE_ACK 0xC8 85 + #define STAT_AD2W_ACK 0xD0 86 + #define STAT_AD2W_NAK 0xD8 65 87 #define STAT_IDLE 0xF8 66 88 67 89 /* TWSI_INT values */ ··· 247 225 return 0; 248 226 } 249 227 228 + static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read) 229 + { 230 + u8 stat = octeon_i2c_stat_read(i2c); 231 + 232 + switch (stat) { 233 + /* Everything is fine */ 234 + case STAT_IDLE: 235 + case STAT_AD2W_ACK: 236 + case STAT_RXADDR_ACK: 237 + case STAT_TXADDR_ACK: 238 + case STAT_TXDATA_ACK: 239 + return 0; 240 + 241 + /* ACK allowed on pre-terminal bytes only */ 242 + case STAT_RXDATA_ACK: 243 + if (!final_read) 244 + return 0; 245 + return -EIO; 246 + 247 + /* NAK allowed on terminal byte only */ 248 + case STAT_RXDATA_NAK: 249 + if (final_read) 250 + return 0; 251 + return -EIO; 252 + 253 + /* Arbitration lost */ 254 + case STAT_LOST_ARB_38: 255 + case STAT_LOST_ARB_68: 256 + case STAT_LOST_ARB_78: 257 + case STAT_LOST_ARB_B0: 258 + return -EAGAIN; 259 + 260 + /* Being addressed as slave, should back off & listen */ 261 + case STAT_SLAVE_60: 262 + case STAT_SLAVE_70: 263 + case STAT_GENDATA_ACK: 264 + case STAT_GENDATA_NAK: 265 + return -EOPNOTSUPP; 266 + 267 + /* Core busy as slave */ 268 + case STAT_SLAVE_80: 269 + case STAT_SLAVE_88: 270 + case STAT_SLAVE_A0: 271 + case STAT_SLAVE_A8: 272 + case STAT_SLAVE_LOST: 273 + case STAT_SLAVE_NAK: 274 + case STAT_SLAVE_ACK: 275 + return -EOPNOTSUPP; 276 + 277 + case STAT_TXDATA_NAK: 278 + return -EIO; 279 + case STAT_TXADDR_NAK: 280 + case STAT_RXADDR_NAK: 281 + case STAT_AD2W_NAK: 282 + return -ENXIO; 283 + default: 284 + dev_err(i2c->dev, "unhandled state: %d\n", stat); 285 + return -EIO; 286 + } 287 + } 288 + 250 289 /* calculate and set clock divisors */ 251 290 static void octeon_i2c_set_clock(struct octeon_i2c *i2c) 252 291 { ··· 401 318 } 402 319 403 320 data = octeon_i2c_stat_read(i2c); 404 - if ((data != STAT_START) && (data != STAT_RSTART)) { 321 + if ((data != STAT_START) && (data != STAT_REP_START)) { 405 322 dev_err(i2c->dev, "%s: bad status (0x%x)\n", __func__, data); 406 323 return -EIO; 407 324 } ··· 430 347 const u8 *data, int length) 431 348 { 432 349 int i, result; 433 - u8 tmp; 434 350 435 351 result = octeon_i2c_start(i2c); 436 352 if (result) ··· 443 361 return result; 444 362 445 363 for (i = 0; i < length; i++) { 446 - tmp = octeon_i2c_stat_read(i2c); 447 - 448 - if ((tmp != STAT_TXADDR_ACK) && (tmp != STAT_TXDATA_ACK)) { 449 - dev_err(i2c->dev, 450 - "%s: bad status before write (0x%x)\n", 451 - __func__, tmp); 452 - return -EIO; 453 - } 364 + result = octeon_i2c_check_status(i2c, false); 365 + if (result) 366 + return result; 454 367 455 368 octeon_i2c_data_write(i2c, data[i]); 456 369 octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); ··· 474 397 u8 *data, u16 *rlength, bool recv_len) 475 398 { 476 399 int i, result, length = *rlength; 477 - u8 tmp; 400 + bool final_read = false; 478 401 479 402 if (length < 1) 480 403 return -EINVAL; ··· 490 413 if (result) 491 414 return result; 492 415 493 - for (i = 0; i < length; i++) { 494 - tmp = octeon_i2c_stat_read(i2c); 495 - if ((tmp != STAT_RXDATA_ACK) && (tmp != STAT_RXADDR_ACK)) { 496 - dev_err(i2c->dev, 497 - "%s: bad status before read (0x%x)\n", 498 - __func__, tmp); 499 - return -EIO; 500 - } 416 + /* address OK ? */ 417 + result = octeon_i2c_check_status(i2c, false); 418 + if (result) 419 + return result; 501 420 502 - if (i + 1 < length) 503 - octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_AAK); 504 - else 421 + for (i = 0; i < length; i++) { 422 + /* for the last byte TWSI_CTL_AAK must not be set */ 423 + if (i + 1 == length) 424 + final_read = true; 425 + 426 + /* clear iflg to allow next event */ 427 + if (final_read) 505 428 octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB); 429 + else 430 + octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_AAK); 506 431 507 432 result = octeon_i2c_wait(i2c); 508 433 if (result) ··· 520 441 } 521 442 length += data[i]; 522 443 } 444 + 445 + result = octeon_i2c_check_status(i2c, final_read); 446 + if (result) 447 + return result; 523 448 } 524 449 *rlength = length; 525 450 return 0;