diff options
| -rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c | 68 |
1 files changed, 36 insertions, 32 deletions
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 3cbf66e9d861..291d11fe93e7 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c | |||
| @@ -90,7 +90,8 @@ struct pmbus_data { | |||
| 90 | 90 | ||
| 91 | u32 flags; /* from platform data */ | 91 | u32 flags; /* from platform data */ |
| 92 | 92 | ||
| 93 | int exponent; /* linear mode: exponent for output voltages */ | 93 | int exponent[PMBUS_PAGES]; |
| 94 | /* linear mode: exponent for output voltages */ | ||
| 94 | 95 | ||
| 95 | const struct pmbus_driver_info *info; | 96 | const struct pmbus_driver_info *info; |
| 96 | 97 | ||
| @@ -410,7 +411,7 @@ static long pmbus_reg2data_linear(struct pmbus_data *data, | |||
| 410 | long val; | 411 | long val; |
| 411 | 412 | ||
| 412 | if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ | 413 | if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ |
| 413 | exponent = data->exponent; | 414 | exponent = data->exponent[sensor->page]; |
| 414 | mantissa = (u16) sensor->data; | 415 | mantissa = (u16) sensor->data; |
| 415 | } else { /* LINEAR11 */ | 416 | } else { /* LINEAR11 */ |
| 416 | exponent = ((s16)sensor->data) >> 11; | 417 | exponent = ((s16)sensor->data) >> 11; |
| @@ -516,7 +517,7 @@ static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) | |||
| 516 | #define MIN_MANTISSA (511 * 1000) | 517 | #define MIN_MANTISSA (511 * 1000) |
| 517 | 518 | ||
| 518 | static u16 pmbus_data2reg_linear(struct pmbus_data *data, | 519 | static u16 pmbus_data2reg_linear(struct pmbus_data *data, |
| 519 | enum pmbus_sensor_classes class, long val) | 520 | struct pmbus_sensor *sensor, long val) |
| 520 | { | 521 | { |
| 521 | s16 exponent = 0, mantissa; | 522 | s16 exponent = 0, mantissa; |
| 522 | bool negative = false; | 523 | bool negative = false; |
| @@ -525,7 +526,7 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, | |||
| 525 | if (val == 0) | 526 | if (val == 0) |
| 526 | return 0; | 527 | return 0; |
| 527 | 528 | ||
| 528 | if (class == PSC_VOLTAGE_OUT) { | 529 | if (sensor->class == PSC_VOLTAGE_OUT) { |
| 529 | /* LINEAR16 does not support negative voltages */ | 530 | /* LINEAR16 does not support negative voltages */ |
| 530 | if (val < 0) | 531 | if (val < 0) |
| 531 | return 0; | 532 | return 0; |
| @@ -534,10 +535,10 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, | |||
| 534 | * For a static exponents, we don't have a choice | 535 | * For a static exponents, we don't have a choice |
| 535 | * but to adjust the value to it. | 536 | * but to adjust the value to it. |
| 536 | */ | 537 | */ |
| 537 | if (data->exponent < 0) | 538 | if (data->exponent[sensor->page] < 0) |
| 538 | val <<= -data->exponent; | 539 | val <<= -data->exponent[sensor->page]; |
| 539 | else | 540 | else |
| 540 | val >>= data->exponent; | 541 | val >>= data->exponent[sensor->page]; |
| 541 | val = DIV_ROUND_CLOSEST(val, 1000); | 542 | val = DIV_ROUND_CLOSEST(val, 1000); |
| 542 | return val & 0xffff; | 543 | return val & 0xffff; |
| 543 | } | 544 | } |
| @@ -548,14 +549,14 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, | |||
| 548 | } | 549 | } |
| 549 | 550 | ||
| 550 | /* Power is in uW. Convert to mW before converting. */ | 551 | /* Power is in uW. Convert to mW before converting. */ |
| 551 | if (class == PSC_POWER) | 552 | if (sensor->class == PSC_POWER) |
| 552 | val = DIV_ROUND_CLOSEST(val, 1000L); | 553 | val = DIV_ROUND_CLOSEST(val, 1000L); |
| 553 | 554 | ||
| 554 | /* | 555 | /* |
| 555 | * For simplicity, convert fan data to milli-units | 556 | * For simplicity, convert fan data to milli-units |
| 556 | * before calculating the exponent. | 557 | * before calculating the exponent. |
| 557 | */ | 558 | */ |
| 558 | if (class == PSC_FAN) | 559 | if (sensor->class == PSC_FAN) |
| 559 | val = val * 1000; | 560 | val = val * 1000; |
| 560 | 561 | ||
| 561 | /* Reduce large mantissa until it fits into 10 bit */ | 562 | /* Reduce large mantissa until it fits into 10 bit */ |
| @@ -585,22 +586,22 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data, | |||
| 585 | } | 586 | } |
| 586 | 587 | ||
| 587 | static u16 pmbus_data2reg_direct(struct pmbus_data *data, | 588 | static u16 pmbus_data2reg_direct(struct pmbus_data *data, |
| 588 | enum pmbus_sensor_classes class, long val) | 589 | struct pmbus_sensor *sensor, long val) |
| 589 | { | 590 | { |
| 590 | long m, b, R; | 591 | long m, b, R; |
| 591 | 592 | ||
| 592 | m = data->info->m[class]; | 593 | m = data->info->m[sensor->class]; |
| 593 | b = data->info->b[class]; | 594 | b = data->info->b[sensor->class]; |
| 594 | R = data->info->R[class]; | 595 | R = data->info->R[sensor->class]; |
| 595 | 596 | ||
| 596 | /* Power is in uW. Adjust R and b. */ | 597 | /* Power is in uW. Adjust R and b. */ |
| 597 | if (class == PSC_POWER) { | 598 | if (sensor->class == PSC_POWER) { |
| 598 | R -= 3; | 599 | R -= 3; |
| 599 | b *= 1000; | 600 | b *= 1000; |
| 600 | } | 601 | } |
| 601 | 602 | ||
| 602 | /* Calculate Y = (m * X + b) * 10^R */ | 603 | /* Calculate Y = (m * X + b) * 10^R */ |
| 603 | if (class != PSC_FAN) { | 604 | if (sensor->class != PSC_FAN) { |
| 604 | R -= 3; /* Adjust R and b for data in milli-units */ | 605 | R -= 3; /* Adjust R and b for data in milli-units */ |
| 605 | b *= 1000; | 606 | b *= 1000; |
| 606 | } | 607 | } |
| @@ -619,7 +620,7 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data, | |||
| 619 | } | 620 | } |
| 620 | 621 | ||
| 621 | static u16 pmbus_data2reg_vid(struct pmbus_data *data, | 622 | static u16 pmbus_data2reg_vid(struct pmbus_data *data, |
| 622 | enum pmbus_sensor_classes class, long val) | 623 | struct pmbus_sensor *sensor, long val) |
| 623 | { | 624 | { |
| 624 | val = clamp_val(val, 500, 1600); | 625 | val = clamp_val(val, 500, 1600); |
| 625 | 626 | ||
| @@ -627,20 +628,20 @@ static u16 pmbus_data2reg_vid(struct pmbus_data *data, | |||
| 627 | } | 628 | } |
| 628 | 629 | ||
| 629 | static u16 pmbus_data2reg(struct pmbus_data *data, | 630 | static u16 pmbus_data2reg(struct pmbus_data *data, |
| 630 | enum pmbus_sensor_classes class, long val) | 631 | struct pmbus_sensor *sensor, long val) |
| 631 | { | 632 | { |
| 632 | u16 regval; | 633 | u16 regval; |
| 633 | 634 | ||
| 634 | switch (data->info->format[class]) { | 635 | switch (data->info->format[sensor->class]) { |
| 635 | case direct: | 636 | case direct: |
| 636 | regval = pmbus_data2reg_direct(data, class, val); | 637 | regval = pmbus_data2reg_direct(data, sensor, val); |
| 637 | break; | 638 | break; |
| 638 | case vid: | 639 | case vid: |
| 639 | regval = pmbus_data2reg_vid(data, class, val); | 640 | regval = pmbus_data2reg_vid(data, sensor, val); |
| 640 | break; | 641 | break; |
| 641 | case linear: | 642 | case linear: |
| 642 | default: | 643 | default: |
| 643 | regval = pmbus_data2reg_linear(data, class, val); | 644 | regval = pmbus_data2reg_linear(data, sensor, val); |
| 644 | break; | 645 | break; |
| 645 | } | 646 | } |
| 646 | return regval; | 647 | return regval; |
| @@ -746,7 +747,7 @@ static ssize_t pmbus_set_sensor(struct device *dev, | |||
| 746 | return -EINVAL; | 747 | return -EINVAL; |
| 747 | 748 | ||
| 748 | mutex_lock(&data->update_lock); | 749 | mutex_lock(&data->update_lock); |
| 749 | regval = pmbus_data2reg(data, sensor->class, val); | 750 | regval = pmbus_data2reg(data, sensor, val); |
| 750 | ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval); | 751 | ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval); |
| 751 | if (ret < 0) | 752 | if (ret < 0) |
| 752 | rv = ret; | 753 | rv = ret; |
| @@ -1643,12 +1644,13 @@ static int pmbus_find_attributes(struct i2c_client *client, | |||
| 1643 | * This function is called for all chips. | 1644 | * This function is called for all chips. |
| 1644 | */ | 1645 | */ |
| 1645 | static int pmbus_identify_common(struct i2c_client *client, | 1646 | static int pmbus_identify_common(struct i2c_client *client, |
| 1646 | struct pmbus_data *data) | 1647 | struct pmbus_data *data, int page) |
| 1647 | { | 1648 | { |
| 1648 | int vout_mode = -1; | 1649 | int vout_mode = -1; |
| 1649 | 1650 | ||
| 1650 | if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) | 1651 | if (pmbus_check_byte_register(client, page, PMBUS_VOUT_MODE)) |
| 1651 | vout_mode = _pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); | 1652 | vout_mode = _pmbus_read_byte_data(client, page, |
| 1653 | PMBUS_VOUT_MODE); | ||
| 1652 | if (vout_mode >= 0 && vout_mode != 0xff) { | 1654 | if (vout_mode >= 0 && vout_mode != 0xff) { |
| 1653 | /* | 1655 | /* |
| 1654 | * Not all chips support the VOUT_MODE command, | 1656 | * Not all chips support the VOUT_MODE command, |
| @@ -1659,7 +1661,7 @@ static int pmbus_identify_common(struct i2c_client *client, | |||
| 1659 | if (data->info->format[PSC_VOLTAGE_OUT] != linear) | 1661 | if (data->info->format[PSC_VOLTAGE_OUT] != linear) |
| 1660 | return -ENODEV; | 1662 | return -ENODEV; |
| 1661 | 1663 | ||
| 1662 | data->exponent = ((s8)(vout_mode << 3)) >> 3; | 1664 | data->exponent[page] = ((s8)(vout_mode << 3)) >> 3; |
| 1663 | break; | 1665 | break; |
| 1664 | case 1: /* VID mode */ | 1666 | case 1: /* VID mode */ |
| 1665 | if (data->info->format[PSC_VOLTAGE_OUT] != vid) | 1667 | if (data->info->format[PSC_VOLTAGE_OUT] != vid) |
| @@ -1674,7 +1676,7 @@ static int pmbus_identify_common(struct i2c_client *client, | |||
| 1674 | } | 1676 | } |
| 1675 | } | 1677 | } |
| 1676 | 1678 | ||
| 1677 | pmbus_clear_fault_page(client, 0); | 1679 | pmbus_clear_fault_page(client, page); |
| 1678 | return 0; | 1680 | return 0; |
| 1679 | } | 1681 | } |
| 1680 | 1682 | ||
| @@ -1682,7 +1684,7 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, | |||
| 1682 | struct pmbus_driver_info *info) | 1684 | struct pmbus_driver_info *info) |
| 1683 | { | 1685 | { |
| 1684 | struct device *dev = &client->dev; | 1686 | struct device *dev = &client->dev; |
| 1685 | int ret; | 1687 | int page, ret; |
| 1686 | 1688 | ||
| 1687 | /* | 1689 | /* |
| 1688 | * Some PMBus chips don't support PMBUS_STATUS_BYTE, so try | 1690 | * Some PMBus chips don't support PMBUS_STATUS_BYTE, so try |
| @@ -1715,10 +1717,12 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, | |||
| 1715 | return -ENODEV; | 1717 | return -ENODEV; |
| 1716 | } | 1718 | } |
| 1717 | 1719 | ||
| 1718 | ret = pmbus_identify_common(client, data); | 1720 | for (page = 0; page < info->pages; page++) { |
| 1719 | if (ret < 0) { | 1721 | ret = pmbus_identify_common(client, data, page); |
| 1720 | dev_err(dev, "Failed to identify chip capabilities\n"); | 1722 | if (ret < 0) { |
| 1721 | return ret; | 1723 | dev_err(dev, "Failed to identify chip capabilities\n"); |
| 1724 | return ret; | ||
| 1725 | } | ||
| 1722 | } | 1726 | } |
| 1723 | return 0; | 1727 | return 0; |
| 1724 | } | 1728 | } |
