diff options
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_eeprom.c | 426 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 7 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_sysfs.c | 73 |
3 files changed, 439 insertions, 67 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c index e28a42f53769..72f90e8d5f76 100644 --- a/drivers/infiniband/hw/ipath/ipath_eeprom.c +++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c | |||
@@ -62,6 +62,33 @@ | |||
62 | * accessing eeprom contents from within the kernel, only via sysfs. | 62 | * accessing eeprom contents from within the kernel, only via sysfs. |
63 | */ | 63 | */ |
64 | 64 | ||
65 | /* Added functionality for IBA7220-based cards */ | ||
66 | #define IPATH_EEPROM_DEV_V1 0xA0 | ||
67 | #define IPATH_EEPROM_DEV_V2 0xA2 | ||
68 | #define IPATH_TEMP_DEV 0x98 | ||
69 | #define IPATH_BAD_DEV (IPATH_EEPROM_DEV_V2+2) | ||
70 | #define IPATH_NO_DEV (0xFF) | ||
71 | |||
72 | /* | ||
73 | * The number of I2C chains is proliferating. Table below brings | ||
74 | * some order to the madness. The basic principle is that the | ||
75 | * table is scanned from the top, and a "probe" is made to the | ||
76 | * device probe_dev. If that succeeds, the chain is considered | ||
77 | * to be of that type, and dd->i2c_chain_type is set to the index+1 | ||
78 | * of the entry. | ||
79 | * The +1 is so static initialization can mean "unknown, do probe." | ||
80 | */ | ||
81 | static struct i2c_chain_desc { | ||
82 | u8 probe_dev; /* If seen at probe, chain is this type */ | ||
83 | u8 eeprom_dev; /* Dev addr (if any) for EEPROM */ | ||
84 | u8 temp_dev; /* Dev Addr (if any) for Temp-sense */ | ||
85 | } i2c_chains[] = { | ||
86 | { IPATH_BAD_DEV, IPATH_NO_DEV, IPATH_NO_DEV }, /* pre-iba7220 bds */ | ||
87 | { IPATH_EEPROM_DEV_V1, IPATH_EEPROM_DEV_V1, IPATH_TEMP_DEV}, /* V1 */ | ||
88 | { IPATH_EEPROM_DEV_V2, IPATH_EEPROM_DEV_V2, IPATH_TEMP_DEV}, /* V2 */ | ||
89 | { IPATH_NO_DEV } | ||
90 | }; | ||
91 | |||
65 | enum i2c_type { | 92 | enum i2c_type { |
66 | i2c_line_scl = 0, | 93 | i2c_line_scl = 0, |
67 | i2c_line_sda | 94 | i2c_line_sda |
@@ -75,13 +102,6 @@ enum i2c_state { | |||
75 | #define READ_CMD 1 | 102 | #define READ_CMD 1 |
76 | #define WRITE_CMD 0 | 103 | #define WRITE_CMD 0 |
77 | 104 | ||
78 | static int eeprom_init; | ||
79 | |||
80 | /* | ||
81 | * The gpioval manipulation really should be protected by spinlocks | ||
82 | * or be converted to use atomic operations. | ||
83 | */ | ||
84 | |||
85 | /** | 105 | /** |
86 | * i2c_gpio_set - set a GPIO line | 106 | * i2c_gpio_set - set a GPIO line |
87 | * @dd: the infinipath device | 107 | * @dd: the infinipath device |
@@ -241,6 +261,27 @@ static int i2c_ackrcv(struct ipath_devdata *dd) | |||
241 | } | 261 | } |
242 | 262 | ||
243 | /** | 263 | /** |
264 | * rd_byte - read a byte, leaving ACK, STOP, etc up to caller | ||
265 | * @dd: the infinipath device | ||
266 | * | ||
267 | * Returns byte shifted out of device | ||
268 | */ | ||
269 | static int rd_byte(struct ipath_devdata *dd) | ||
270 | { | ||
271 | int bit_cntr, data; | ||
272 | |||
273 | data = 0; | ||
274 | |||
275 | for (bit_cntr = 7; bit_cntr >= 0; --bit_cntr) { | ||
276 | data <<= 1; | ||
277 | scl_out(dd, i2c_line_high); | ||
278 | data |= sda_in(dd, 0); | ||
279 | scl_out(dd, i2c_line_low); | ||
280 | } | ||
281 | return data; | ||
282 | } | ||
283 | |||
284 | /** | ||
244 | * wr_byte - write a byte, one bit at a time | 285 | * wr_byte - write a byte, one bit at a time |
245 | * @dd: the infinipath device | 286 | * @dd: the infinipath device |
246 | * @data: the byte to write | 287 | * @data: the byte to write |
@@ -331,7 +372,6 @@ static int eeprom_reset(struct ipath_devdata *dd) | |||
331 | ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg " | 372 | ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg " |
332 | "is %llx\n", (unsigned long long) *gpioval); | 373 | "is %llx\n", (unsigned long long) *gpioval); |
333 | 374 | ||
334 | eeprom_init = 1; | ||
335 | /* | 375 | /* |
336 | * This is to get the i2c into a known state, by first going low, | 376 | * This is to get the i2c into a known state, by first going low, |
337 | * then tristate sda (and then tristate scl as first thing | 377 | * then tristate sda (and then tristate scl as first thing |
@@ -340,12 +380,17 @@ static int eeprom_reset(struct ipath_devdata *dd) | |||
340 | scl_out(dd, i2c_line_low); | 380 | scl_out(dd, i2c_line_low); |
341 | sda_out(dd, i2c_line_high); | 381 | sda_out(dd, i2c_line_high); |
342 | 382 | ||
383 | /* Clock up to 9 cycles looking for SDA hi, then issue START and STOP */ | ||
343 | while (clock_cycles_left--) { | 384 | while (clock_cycles_left--) { |
344 | scl_out(dd, i2c_line_high); | 385 | scl_out(dd, i2c_line_high); |
345 | 386 | ||
387 | /* SDA seen high, issue START by dropping it while SCL high */ | ||
346 | if (sda_in(dd, 0)) { | 388 | if (sda_in(dd, 0)) { |
347 | sda_out(dd, i2c_line_low); | 389 | sda_out(dd, i2c_line_low); |
348 | scl_out(dd, i2c_line_low); | 390 | scl_out(dd, i2c_line_low); |
391 | /* ATMEL spec says must be followed by STOP. */ | ||
392 | scl_out(dd, i2c_line_high); | ||
393 | sda_out(dd, i2c_line_high); | ||
349 | ret = 0; | 394 | ret = 0; |
350 | goto bail; | 395 | goto bail; |
351 | } | 396 | } |
@@ -359,29 +404,121 @@ bail: | |||
359 | return ret; | 404 | return ret; |
360 | } | 405 | } |
361 | 406 | ||
362 | /** | 407 | /* |
363 | * ipath_eeprom_read - receives bytes from the eeprom via I2C | 408 | * Probe for I2C device at specified address. Returns 0 for "success" |
364 | * @dd: the infinipath device | 409 | * to match rest of this file. |
365 | * @eeprom_offset: address to read from | 410 | * Leave bus in "reasonable" state for further commands. |
366 | * @buffer: where to store result | ||
367 | * @len: number of bytes to receive | ||
368 | */ | 411 | */ |
412 | static int i2c_probe(struct ipath_devdata *dd, int devaddr) | ||
413 | { | ||
414 | int ret = 0; | ||
415 | |||
416 | ret = eeprom_reset(dd); | ||
417 | if (ret) { | ||
418 | ipath_dev_err(dd, "Failed reset probing device 0x%02X\n", | ||
419 | devaddr); | ||
420 | return ret; | ||
421 | } | ||
422 | /* | ||
423 | * Reset no longer leaves bus in start condition, so normal | ||
424 | * i2c_startcmd() will do. | ||
425 | */ | ||
426 | ret = i2c_startcmd(dd, devaddr | READ_CMD); | ||
427 | if (ret) | ||
428 | ipath_cdbg(VERBOSE, "Failed startcmd for device 0x%02X\n", | ||
429 | devaddr); | ||
430 | else { | ||
431 | /* | ||
432 | * Device did respond. Complete a single-byte read, because some | ||
433 | * devices apparently cannot handle STOP immediately after they | ||
434 | * ACK the start-cmd. | ||
435 | */ | ||
436 | int data; | ||
437 | data = rd_byte(dd); | ||
438 | stop_cmd(dd); | ||
439 | ipath_cdbg(VERBOSE, "Response from device 0x%02X\n", devaddr); | ||
440 | } | ||
441 | return ret; | ||
442 | } | ||
443 | |||
444 | /* | ||
445 | * Returns the "i2c type". This is a pointer to a struct that describes | ||
446 | * the I2C chain on this board. To minimize impact on struct ipath_devdata, | ||
447 | * the (small integer) index into the table is actually memoized, rather | ||
448 | * then the pointer. | ||
449 | * Memoization is because the type is determined on the first call per chip. | ||
450 | * An alternative would be to move type determination to early | ||
451 | * init code. | ||
452 | */ | ||
453 | static struct i2c_chain_desc *ipath_i2c_type(struct ipath_devdata *dd) | ||
454 | { | ||
455 | int idx; | ||
456 | |||
457 | /* Get memoized index, from previous successful probes */ | ||
458 | idx = dd->ipath_i2c_chain_type - 1; | ||
459 | if (idx >= 0 && idx < (ARRAY_SIZE(i2c_chains) - 1)) | ||
460 | goto done; | ||
461 | |||
462 | idx = 0; | ||
463 | while (i2c_chains[idx].probe_dev != IPATH_NO_DEV) { | ||
464 | /* if probe succeeds, this is type */ | ||
465 | if (!i2c_probe(dd, i2c_chains[idx].probe_dev)) | ||
466 | break; | ||
467 | ++idx; | ||
468 | } | ||
469 | |||
470 | /* | ||
471 | * Old EEPROM (first entry) may require a reset after probe, | ||
472 | * rather than being able to "start" after "stop" | ||
473 | */ | ||
474 | if (idx == 0) | ||
475 | eeprom_reset(dd); | ||
476 | |||
477 | if (i2c_chains[idx].probe_dev == IPATH_NO_DEV) | ||
478 | idx = -1; | ||
479 | else | ||
480 | dd->ipath_i2c_chain_type = idx + 1; | ||
481 | done: | ||
482 | return (idx >= 0) ? i2c_chains + idx : NULL; | ||
483 | } | ||
369 | 484 | ||
370 | static int ipath_eeprom_internal_read(struct ipath_devdata *dd, | 485 | static int ipath_eeprom_internal_read(struct ipath_devdata *dd, |
371 | u8 eeprom_offset, void *buffer, int len) | 486 | u8 eeprom_offset, void *buffer, int len) |
372 | { | 487 | { |
373 | /* compiler complains unless initialized */ | ||
374 | u8 single_byte = 0; | ||
375 | int bit_cntr; | ||
376 | int ret; | 488 | int ret; |
489 | struct i2c_chain_desc *icd; | ||
490 | u8 *bp = buffer; | ||
377 | 491 | ||
378 | if (!eeprom_init) | 492 | ret = 1; |
379 | eeprom_reset(dd); | 493 | icd = ipath_i2c_type(dd); |
380 | 494 | if (!icd) | |
381 | eeprom_offset = (eeprom_offset << 1) | READ_CMD; | 495 | goto bail; |
382 | 496 | ||
383 | if (i2c_startcmd(dd, eeprom_offset)) { | 497 | if (icd->eeprom_dev == IPATH_NO_DEV) { |
384 | ipath_dbg("Failed startcmd\n"); | 498 | /* legacy not-really-I2C */ |
499 | ipath_cdbg(VERBOSE, "Start command only address\n"); | ||
500 | eeprom_offset = (eeprom_offset << 1) | READ_CMD; | ||
501 | ret = i2c_startcmd(dd, eeprom_offset); | ||
502 | } else { | ||
503 | /* Actual I2C */ | ||
504 | ipath_cdbg(VERBOSE, "Start command uses devaddr\n"); | ||
505 | if (i2c_startcmd(dd, icd->eeprom_dev | WRITE_CMD)) { | ||
506 | ipath_dbg("Failed EEPROM startcmd\n"); | ||
507 | stop_cmd(dd); | ||
508 | ret = 1; | ||
509 | goto bail; | ||
510 | } | ||
511 | ret = wr_byte(dd, eeprom_offset); | ||
512 | stop_cmd(dd); | ||
513 | if (ret) { | ||
514 | ipath_dev_err(dd, "Failed to write EEPROM address\n"); | ||
515 | ret = 1; | ||
516 | goto bail; | ||
517 | } | ||
518 | ret = i2c_startcmd(dd, icd->eeprom_dev | READ_CMD); | ||
519 | } | ||
520 | if (ret) { | ||
521 | ipath_dbg("Failed startcmd for dev %02X\n", icd->eeprom_dev); | ||
385 | stop_cmd(dd); | 522 | stop_cmd(dd); |
386 | ret = 1; | 523 | ret = 1; |
387 | goto bail; | 524 | goto bail; |
@@ -392,22 +529,11 @@ static int ipath_eeprom_internal_read(struct ipath_devdata *dd, | |||
392 | * incrementing the address. | 529 | * incrementing the address. |
393 | */ | 530 | */ |
394 | while (len-- > 0) { | 531 | while (len-- > 0) { |
395 | /* get data */ | 532 | /* get and store data */ |
396 | single_byte = 0; | 533 | *bp++ = rd_byte(dd); |
397 | for (bit_cntr = 8; bit_cntr; bit_cntr--) { | ||
398 | u8 bit; | ||
399 | scl_out(dd, i2c_line_high); | ||
400 | bit = sda_in(dd, 0); | ||
401 | single_byte |= bit << (bit_cntr - 1); | ||
402 | scl_out(dd, i2c_line_low); | ||
403 | } | ||
404 | |||
405 | /* send ack if not the last byte */ | 534 | /* send ack if not the last byte */ |
406 | if (len) | 535 | if (len) |
407 | send_ack(dd); | 536 | send_ack(dd); |
408 | |||
409 | *((u8 *) buffer) = single_byte; | ||
410 | buffer++; | ||
411 | } | 537 | } |
412 | 538 | ||
413 | stop_cmd(dd); | 539 | stop_cmd(dd); |
@@ -418,31 +544,40 @@ bail: | |||
418 | return ret; | 544 | return ret; |
419 | } | 545 | } |
420 | 546 | ||
421 | |||
422 | /** | ||
423 | * ipath_eeprom_write - writes data to the eeprom via I2C | ||
424 | * @dd: the infinipath device | ||
425 | * @eeprom_offset: where to place data | ||
426 | * @buffer: data to write | ||
427 | * @len: number of bytes to write | ||
428 | */ | ||
429 | static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offset, | 547 | static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offset, |
430 | const void *buffer, int len) | 548 | const void *buffer, int len) |
431 | { | 549 | { |
432 | u8 single_byte; | ||
433 | int sub_len; | 550 | int sub_len; |
434 | const u8 *bp = buffer; | 551 | const u8 *bp = buffer; |
435 | int max_wait_time, i; | 552 | int max_wait_time, i; |
436 | int ret; | 553 | int ret; |
554 | struct i2c_chain_desc *icd; | ||
437 | 555 | ||
438 | if (!eeprom_init) | 556 | ret = 1; |
439 | eeprom_reset(dd); | 557 | icd = ipath_i2c_type(dd); |
558 | if (!icd) | ||
559 | goto bail; | ||
440 | 560 | ||
441 | while (len > 0) { | 561 | while (len > 0) { |
442 | if (i2c_startcmd(dd, (eeprom_offset << 1) | WRITE_CMD)) { | 562 | if (icd->eeprom_dev == IPATH_NO_DEV) { |
443 | ipath_dbg("Failed to start cmd offset %u\n", | 563 | if (i2c_startcmd(dd, |
444 | eeprom_offset); | 564 | (eeprom_offset << 1) | WRITE_CMD)) { |
445 | goto failed_write; | 565 | ipath_dbg("Failed to start cmd offset %u\n", |
566 | eeprom_offset); | ||
567 | goto failed_write; | ||
568 | } | ||
569 | } else { | ||
570 | /* Real I2C */ | ||
571 | if (i2c_startcmd(dd, icd->eeprom_dev | WRITE_CMD)) { | ||
572 | ipath_dbg("Failed EEPROM startcmd\n"); | ||
573 | goto failed_write; | ||
574 | } | ||
575 | ret = wr_byte(dd, eeprom_offset); | ||
576 | if (ret) { | ||
577 | ipath_dev_err(dd, "Failed to write EEPROM " | ||
578 | "address\n"); | ||
579 | goto failed_write; | ||
580 | } | ||
446 | } | 581 | } |
447 | 582 | ||
448 | sub_len = min(len, 4); | 583 | sub_len = min(len, 4); |
@@ -468,9 +603,11 @@ static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offse | |||
468 | * the writes have completed. We do this inline to avoid | 603 | * the writes have completed. We do this inline to avoid |
469 | * the debug prints that are in the real read routine | 604 | * the debug prints that are in the real read routine |
470 | * if the startcmd fails. | 605 | * if the startcmd fails. |
606 | * We also use the proper device address, so it doesn't matter | ||
607 | * whether we have real eeprom_dev. legacy likes any address. | ||
471 | */ | 608 | */ |
472 | max_wait_time = 100; | 609 | max_wait_time = 100; |
473 | while (i2c_startcmd(dd, READ_CMD)) { | 610 | while (i2c_startcmd(dd, icd->eeprom_dev | READ_CMD)) { |
474 | stop_cmd(dd); | 611 | stop_cmd(dd); |
475 | if (!--max_wait_time) { | 612 | if (!--max_wait_time) { |
476 | ipath_dbg("Did not get successful read to " | 613 | ipath_dbg("Did not get successful read to " |
@@ -478,15 +615,8 @@ static int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offse | |||
478 | goto failed_write; | 615 | goto failed_write; |
479 | } | 616 | } |
480 | } | 617 | } |
481 | /* now read the zero byte */ | 618 | /* now read (and ignore) the resulting byte */ |
482 | for (i = single_byte = 0; i < 8; i++) { | 619 | rd_byte(dd); |
483 | u8 bit; | ||
484 | scl_out(dd, i2c_line_high); | ||
485 | bit = sda_in(dd, 0); | ||
486 | scl_out(dd, i2c_line_low); | ||
487 | single_byte <<= 1; | ||
488 | single_byte |= bit; | ||
489 | } | ||
490 | stop_cmd(dd); | 620 | stop_cmd(dd); |
491 | } | 621 | } |
492 | 622 | ||
@@ -501,9 +631,12 @@ bail: | |||
501 | return ret; | 631 | return ret; |
502 | } | 632 | } |
503 | 633 | ||
504 | /* | 634 | /** |
505 | * The public entry-points ipath_eeprom_read() and ipath_eeprom_write() | 635 | * ipath_eeprom_read - receives bytes from the eeprom via I2C |
506 | * are now just wrappers around the internal functions. | 636 | * @dd: the infinipath device |
637 | * @eeprom_offset: address to read from | ||
638 | * @buffer: where to store result | ||
639 | * @len: number of bytes to receive | ||
507 | */ | 640 | */ |
508 | int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset, | 641 | int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset, |
509 | void *buff, int len) | 642 | void *buff, int len) |
@@ -519,6 +652,13 @@ int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset, | |||
519 | return ret; | 652 | return ret; |
520 | } | 653 | } |
521 | 654 | ||
655 | /** | ||
656 | * ipath_eeprom_write - writes data to the eeprom via I2C | ||
657 | * @dd: the infinipath device | ||
658 | * @eeprom_offset: where to place data | ||
659 | * @buffer: data to write | ||
660 | * @len: number of bytes to write | ||
661 | */ | ||
522 | int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset, | 662 | int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset, |
523 | const void *buff, int len) | 663 | const void *buff, int len) |
524 | { | 664 | { |
@@ -820,7 +960,7 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd) | |||
820 | * if we log an hour at 31 minutes, then we would need to set | 960 | * if we log an hour at 31 minutes, then we would need to set |
821 | * active_time to -29 to accurately count the _next_ hour. | 961 | * active_time to -29 to accurately count the _next_ hour. |
822 | */ | 962 | */ |
823 | if (new_time > 3600) { | 963 | if (new_time >= 3600) { |
824 | new_hrs = new_time / 3600; | 964 | new_hrs = new_time / 3600; |
825 | atomic_sub((new_hrs * 3600), &dd->ipath_active_time); | 965 | atomic_sub((new_hrs * 3600), &dd->ipath_active_time); |
826 | new_hrs += dd->ipath_eep_hrs; | 966 | new_hrs += dd->ipath_eep_hrs; |
@@ -885,3 +1025,159 @@ void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr) | |||
885 | spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags); | 1025 | spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags); |
886 | return; | 1026 | return; |
887 | } | 1027 | } |
1028 | |||
1029 | static int ipath_tempsense_internal_read(struct ipath_devdata *dd, u8 regnum) | ||
1030 | { | ||
1031 | int ret; | ||
1032 | struct i2c_chain_desc *icd; | ||
1033 | |||
1034 | ret = -ENOENT; | ||
1035 | |||
1036 | icd = ipath_i2c_type(dd); | ||
1037 | if (!icd) | ||
1038 | goto bail; | ||
1039 | |||
1040 | if (icd->temp_dev == IPATH_NO_DEV) { | ||
1041 | /* tempsense only exists on new, real-I2C boards */ | ||
1042 | ret = -ENXIO; | ||
1043 | goto bail; | ||
1044 | } | ||
1045 | |||
1046 | if (i2c_startcmd(dd, icd->temp_dev | WRITE_CMD)) { | ||
1047 | ipath_dbg("Failed tempsense startcmd\n"); | ||
1048 | stop_cmd(dd); | ||
1049 | ret = -ENXIO; | ||
1050 | goto bail; | ||
1051 | } | ||
1052 | ret = wr_byte(dd, regnum); | ||
1053 | stop_cmd(dd); | ||
1054 | if (ret) { | ||
1055 | ipath_dev_err(dd, "Failed tempsense WR command %02X\n", | ||
1056 | regnum); | ||
1057 | ret = -ENXIO; | ||
1058 | goto bail; | ||
1059 | } | ||
1060 | if (i2c_startcmd(dd, icd->temp_dev | READ_CMD)) { | ||
1061 | ipath_dbg("Failed tempsense RD startcmd\n"); | ||
1062 | stop_cmd(dd); | ||
1063 | ret = -ENXIO; | ||
1064 | goto bail; | ||
1065 | } | ||
1066 | /* | ||
1067 | * We can only clock out one byte per command, sensibly | ||
1068 | */ | ||
1069 | ret = rd_byte(dd); | ||
1070 | stop_cmd(dd); | ||
1071 | |||
1072 | bail: | ||
1073 | return ret; | ||
1074 | } | ||
1075 | |||
1076 | #define VALID_TS_RD_REG_MASK 0xBF | ||
1077 | |||
1078 | /** | ||
1079 | * ipath_tempsense_read - read register of temp sensor via I2C | ||
1080 | * @dd: the infinipath device | ||
1081 | * @regnum: register to read from | ||
1082 | * | ||
1083 | * returns reg contents (0..255) or < 0 for error | ||
1084 | */ | ||
1085 | int ipath_tempsense_read(struct ipath_devdata *dd, u8 regnum) | ||
1086 | { | ||
1087 | int ret; | ||
1088 | |||
1089 | if (regnum > 7) | ||
1090 | return -EINVAL; | ||
1091 | |||
1092 | /* return a bogus value for (the one) register we do not have */ | ||
1093 | if (!((1 << regnum) & VALID_TS_RD_REG_MASK)) | ||
1094 | return 0; | ||
1095 | |||
1096 | ret = mutex_lock_interruptible(&dd->ipath_eep_lock); | ||
1097 | if (!ret) { | ||
1098 | ret = ipath_tempsense_internal_read(dd, regnum); | ||
1099 | mutex_unlock(&dd->ipath_eep_lock); | ||
1100 | } | ||
1101 | |||
1102 | /* | ||
1103 | * There are three possibilities here: | ||
1104 | * ret is actual value (0..255) | ||
1105 | * ret is -ENXIO or -EINVAL from code in this file | ||
1106 | * ret is -EINTR from mutex_lock_interruptible. | ||
1107 | */ | ||
1108 | return ret; | ||
1109 | } | ||
1110 | |||
1111 | static int ipath_tempsense_internal_write(struct ipath_devdata *dd, | ||
1112 | u8 regnum, u8 data) | ||
1113 | { | ||
1114 | int ret = -ENOENT; | ||
1115 | struct i2c_chain_desc *icd; | ||
1116 | |||
1117 | icd = ipath_i2c_type(dd); | ||
1118 | if (!icd) | ||
1119 | goto bail; | ||
1120 | |||
1121 | if (icd->temp_dev == IPATH_NO_DEV) { | ||
1122 | /* tempsense only exists on new, real-I2C boards */ | ||
1123 | ret = -ENXIO; | ||
1124 | goto bail; | ||
1125 | } | ||
1126 | if (i2c_startcmd(dd, icd->temp_dev | WRITE_CMD)) { | ||
1127 | ipath_dbg("Failed tempsense startcmd\n"); | ||
1128 | stop_cmd(dd); | ||
1129 | ret = -ENXIO; | ||
1130 | goto bail; | ||
1131 | } | ||
1132 | ret = wr_byte(dd, regnum); | ||
1133 | if (ret) { | ||
1134 | stop_cmd(dd); | ||
1135 | ipath_dev_err(dd, "Failed to write tempsense command %02X\n", | ||
1136 | regnum); | ||
1137 | ret = -ENXIO; | ||
1138 | goto bail; | ||
1139 | } | ||
1140 | ret = wr_byte(dd, data); | ||
1141 | stop_cmd(dd); | ||
1142 | ret = i2c_startcmd(dd, icd->temp_dev | READ_CMD); | ||
1143 | if (ret) { | ||
1144 | ipath_dev_err(dd, "Failed tempsense data wrt to %02X\n", | ||
1145 | regnum); | ||
1146 | ret = -ENXIO; | ||
1147 | } | ||
1148 | |||
1149 | bail: | ||
1150 | return ret; | ||
1151 | } | ||
1152 | |||
1153 | #define VALID_TS_WR_REG_MASK ((1 << 9) | (1 << 0xB) | (1 << 0xD)) | ||
1154 | |||
1155 | /** | ||
1156 | * ipath_tempsense_write - write register of temp sensor via I2C | ||
1157 | * @dd: the infinipath device | ||
1158 | * @regnum: register to write | ||
1159 | * @data: data to write | ||
1160 | * | ||
1161 | * returns 0 for success or < 0 for error | ||
1162 | */ | ||
1163 | int ipath_tempsense_write(struct ipath_devdata *dd, u8 regnum, u8 data) | ||
1164 | { | ||
1165 | int ret; | ||
1166 | |||
1167 | if (regnum > 15 || !((1 << regnum) & VALID_TS_WR_REG_MASK)) | ||
1168 | return -EINVAL; | ||
1169 | |||
1170 | ret = mutex_lock_interruptible(&dd->ipath_eep_lock); | ||
1171 | if (!ret) { | ||
1172 | ret = ipath_tempsense_internal_write(dd, regnum, data); | ||
1173 | mutex_unlock(&dd->ipath_eep_lock); | ||
1174 | } | ||
1175 | |||
1176 | /* | ||
1177 | * There are three possibilities here: | ||
1178 | * ret is 0 for success | ||
1179 | * ret is -ENXIO or -EINVAL from code in this file | ||
1180 | * ret is -EINTR from mutex_lock_interruptible. | ||
1181 | */ | ||
1182 | return ret; | ||
1183 | } | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 3a15af26b093..398de7f7e2e4 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -654,8 +654,9 @@ struct ipath_devdata { | |||
654 | * Register bits for selecting i2c direction and values, used for | 654 | * Register bits for selecting i2c direction and values, used for |
655 | * I2C serial flash. | 655 | * I2C serial flash. |
656 | */ | 656 | */ |
657 | u16 ipath_gpio_sda_num; | 657 | u8 ipath_gpio_sda_num; |
658 | u16 ipath_gpio_scl_num; | 658 | u8 ipath_gpio_scl_num; |
659 | u8 ipath_i2c_chain_type; | ||
659 | u64 ipath_gpio_sda; | 660 | u64 ipath_gpio_sda; |
660 | u64 ipath_gpio_scl; | 661 | u64 ipath_gpio_scl; |
661 | 662 | ||
@@ -906,6 +907,8 @@ void ipath_release_user_pages(struct page **, size_t); | |||
906 | void ipath_release_user_pages_on_close(struct page **, size_t); | 907 | void ipath_release_user_pages_on_close(struct page **, size_t); |
907 | int ipath_eeprom_read(struct ipath_devdata *, u8, void *, int); | 908 | int ipath_eeprom_read(struct ipath_devdata *, u8, void *, int); |
908 | int ipath_eeprom_write(struct ipath_devdata *, u8, const void *, int); | 909 | int ipath_eeprom_write(struct ipath_devdata *, u8, const void *, int); |
910 | int ipath_tempsense_read(struct ipath_devdata *, u8 regnum); | ||
911 | int ipath_tempsense_write(struct ipath_devdata *, u8 regnum, u8 data); | ||
909 | 912 | ||
910 | /* these are used for the registers that vary with port */ | 913 | /* these are used for the registers that vary with port */ |
911 | void ipath_write_kreg_port(const struct ipath_devdata *, ipath_kreg, | 914 | void ipath_write_kreg_port(const struct ipath_devdata *, ipath_kreg, |
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c index bb41c3f6aad3..7961d26404f1 100644 --- a/drivers/infiniband/hw/ipath/ipath_sysfs.c +++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c | |||
@@ -943,6 +943,7 @@ invalid: | |||
943 | bail: | 943 | bail: |
944 | return ret; | 944 | return ret; |
945 | } | 945 | } |
946 | |||
946 | /* | 947 | /* |
947 | * Get/Set RX lane-reversal enable. 0=no, 1=yes. | 948 | * Get/Set RX lane-reversal enable. 0=no, 1=yes. |
948 | */ | 949 | */ |
@@ -997,6 +998,75 @@ static struct attribute_group driver_attr_group = { | |||
997 | .attrs = driver_attributes | 998 | .attrs = driver_attributes |
998 | }; | 999 | }; |
999 | 1000 | ||
1001 | static ssize_t store_tempsense(struct device *dev, | ||
1002 | struct device_attribute *attr, | ||
1003 | const char *buf, | ||
1004 | size_t count) | ||
1005 | { | ||
1006 | struct ipath_devdata *dd = dev_get_drvdata(dev); | ||
1007 | int ret, stat; | ||
1008 | u16 val; | ||
1009 | |||
1010 | ret = ipath_parse_ushort(buf, &val); | ||
1011 | if (ret <= 0) { | ||
1012 | ipath_dev_err(dd, "attempt to set invalid tempsense config\n"); | ||
1013 | goto bail; | ||
1014 | } | ||
1015 | /* If anything but the highest limit, enable T_CRIT_A "interrupt" */ | ||
1016 | stat = ipath_tempsense_write(dd, 9, (val == 0x7f7f) ? 0x80 : 0); | ||
1017 | if (stat) { | ||
1018 | ipath_dev_err(dd, "Unable to set tempsense config\n"); | ||
1019 | ret = -1; | ||
1020 | goto bail; | ||
1021 | } | ||
1022 | stat = ipath_tempsense_write(dd, 0xB, (u8) (val & 0xFF)); | ||
1023 | if (stat) { | ||
1024 | ipath_dev_err(dd, "Unable to set local Tcrit\n"); | ||
1025 | ret = -1; | ||
1026 | goto bail; | ||
1027 | } | ||
1028 | stat = ipath_tempsense_write(dd, 0xD, (u8) (val >> 8)); | ||
1029 | if (stat) { | ||
1030 | ipath_dev_err(dd, "Unable to set remote Tcrit\n"); | ||
1031 | ret = -1; | ||
1032 | goto bail; | ||
1033 | } | ||
1034 | |||
1035 | bail: | ||
1036 | return ret; | ||
1037 | } | ||
1038 | |||
1039 | /* | ||
1040 | * dump tempsense regs. in decimal, to ease shell-scripts. | ||
1041 | */ | ||
1042 | static ssize_t show_tempsense(struct device *dev, | ||
1043 | struct device_attribute *attr, | ||
1044 | char *buf) | ||
1045 | { | ||
1046 | struct ipath_devdata *dd = dev_get_drvdata(dev); | ||
1047 | int ret; | ||
1048 | int idx; | ||
1049 | u8 regvals[8]; | ||
1050 | |||
1051 | ret = -ENXIO; | ||
1052 | for (idx = 0; idx < 8; ++idx) { | ||
1053 | if (idx == 6) | ||
1054 | continue; | ||
1055 | ret = ipath_tempsense_read(dd, idx); | ||
1056 | if (ret < 0) | ||
1057 | break; | ||
1058 | regvals[idx] = ret; | ||
1059 | } | ||
1060 | if (idx == 8) | ||
1061 | ret = scnprintf(buf, PAGE_SIZE, "%d %d %02X %02X %d %d\n", | ||
1062 | *(signed char *)(regvals), | ||
1063 | *(signed char *)(regvals + 1), | ||
1064 | regvals[2], regvals[3], | ||
1065 | *(signed char *)(regvals + 5), | ||
1066 | *(signed char *)(regvals + 7)); | ||
1067 | return ret; | ||
1068 | } | ||
1069 | |||
1000 | struct attribute_group *ipath_driver_attr_groups[] = { | 1070 | struct attribute_group *ipath_driver_attr_groups[] = { |
1001 | &driver_attr_group, | 1071 | &driver_attr_group, |
1002 | NULL, | 1072 | NULL, |
@@ -1025,6 +1095,8 @@ static DEVICE_ATTR(jint_max_packets, S_IWUSR | S_IRUGO, | |||
1025 | show_jint_max_packets, store_jint_max_packets); | 1095 | show_jint_max_packets, store_jint_max_packets); |
1026 | static DEVICE_ATTR(jint_idle_ticks, S_IWUSR | S_IRUGO, | 1096 | static DEVICE_ATTR(jint_idle_ticks, S_IWUSR | S_IRUGO, |
1027 | show_jint_idle_ticks, store_jint_idle_ticks); | 1097 | show_jint_idle_ticks, store_jint_idle_ticks); |
1098 | static DEVICE_ATTR(tempsense, S_IWUSR | S_IRUGO, | ||
1099 | show_tempsense, store_tempsense); | ||
1028 | 1100 | ||
1029 | static struct attribute *dev_attributes[] = { | 1101 | static struct attribute *dev_attributes[] = { |
1030 | &dev_attr_guid.attr, | 1102 | &dev_attr_guid.attr, |
@@ -1044,6 +1116,7 @@ static struct attribute *dev_attributes[] = { | |||
1044 | &dev_attr_rx_pol_inv.attr, | 1116 | &dev_attr_rx_pol_inv.attr, |
1045 | &dev_attr_led_override.attr, | 1117 | &dev_attr_led_override.attr, |
1046 | &dev_attr_logged_errors.attr, | 1118 | &dev_attr_logged_errors.attr, |
1119 | &dev_attr_tempsense.attr, | ||
1047 | &dev_attr_localbus_info.attr, | 1120 | &dev_attr_localbus_info.attr, |
1048 | NULL | 1121 | NULL |
1049 | }; | 1122 | }; |