aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2011-03-05 10:55:10 -0500
committerGuenter Roeck <guenter.roeck@ericsson.com>2011-03-15 01:39:09 -0400
commit954df6763cd84551a565a0c341d3401cf30b9d2d (patch)
treec52ecb7b6255c8c1c06993d5d7dc6414da581e75 /drivers/hwmon
parent83274c68a34094bbb465589e61f91a3714f8d026 (diff)
hwmon: (pmbus) Improve support for paged fans
So far, it seemed like fans would either all be in page 0, or that there would be one page per fan. Turns out this was a wrong assumption. There is at least one PMBus fan controller which supports three pages with four fans each. Update code to handle this situation. Reported-by: Greg Schnorr <gschnorr@cisco.com> Tested-by: Greg Schnorr <gschnorr@cisco.com> Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Acked-by: Greg Schnorr <gschnorr@cisco.com>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/pmbus_core.c70
1 files changed, 40 insertions, 30 deletions
diff --git a/drivers/hwmon/pmbus_core.c b/drivers/hwmon/pmbus_core.c
index b7c64ba31f4c..d025a118bf92 100644
--- a/drivers/hwmon/pmbus_core.c
+++ b/drivers/hwmon/pmbus_core.c
@@ -58,12 +58,10 @@
58#define PMBUS_MAX_INPUT_LABELS 4 /* vin, vcap, iin, pin */ 58#define PMBUS_MAX_INPUT_LABELS 4 /* vin, vcap, iin, pin */
59 59
60/* 60/*
61 * status, status_vout, status_iout, status_fans, and status_temp 61 * status, status_vout, status_iout, status_fans, status_fan34, and status_temp
62 * are paged. status_input and status_fan34 are unpaged. 62 * are paged. status_input is unpaged.
63 * status_fan34 is a special case to handle a second set of fans
64 * on page 0.
65 */ 63 */
66#define PB_NUM_STATUS_REG (PMBUS_PAGES * 5 + 2) 64#define PB_NUM_STATUS_REG (PMBUS_PAGES * 6 + 1)
67 65
68/* 66/*
69 * Index into status register array, per status register group 67 * Index into status register array, per status register group
@@ -73,7 +71,7 @@
73#define PB_STATUS_IOUT_BASE (PB_STATUS_VOUT_BASE + PMBUS_PAGES) 71#define PB_STATUS_IOUT_BASE (PB_STATUS_VOUT_BASE + PMBUS_PAGES)
74#define PB_STATUS_FAN_BASE (PB_STATUS_IOUT_BASE + PMBUS_PAGES) 72#define PB_STATUS_FAN_BASE (PB_STATUS_IOUT_BASE + PMBUS_PAGES)
75#define PB_STATUS_FAN34_BASE (PB_STATUS_FAN_BASE + PMBUS_PAGES) 73#define PB_STATUS_FAN34_BASE (PB_STATUS_FAN_BASE + PMBUS_PAGES)
76#define PB_STATUS_INPUT_BASE (PB_STATUS_FAN34_BASE + 1) 74#define PB_STATUS_INPUT_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES)
77#define PB_STATUS_TEMP_BASE (PB_STATUS_INPUT_BASE + 1) 75#define PB_STATUS_TEMP_BASE (PB_STATUS_INPUT_BASE + 1)
78 76
79struct pmbus_sensor { 77struct pmbus_sensor {
@@ -327,14 +325,17 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
327 = pmbus_get_status(client, i, PMBUS_STATUS_FAN_12); 325 = pmbus_get_status(client, i, PMBUS_STATUS_FAN_12);
328 } 326 }
329 327
328 for (i = 0; i < info->pages; i++) {
329 if (!(info->func[i] & PMBUS_HAVE_STATUS_FAN34))
330 continue;
331 data->status[PB_STATUS_FAN34_BASE + i]
332 = pmbus_get_status(client, i, PMBUS_STATUS_FAN_34);
333 }
334
330 if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) 335 if (info->func[0] & PMBUS_HAVE_STATUS_INPUT)
331 data->status[PB_STATUS_INPUT_BASE] 336 data->status[PB_STATUS_INPUT_BASE]
332 = pmbus_get_status(client, 0, PMBUS_STATUS_INPUT); 337 = pmbus_get_status(client, 0, PMBUS_STATUS_INPUT);
333 338
334 if (info->func[0] & PMBUS_HAVE_STATUS_FAN34)
335 data->status[PB_STATUS_FAN34_BASE]
336 = pmbus_get_status(client, 0, PMBUS_STATUS_FAN_34);
337
338 for (i = 0; i < data->num_sensors; i++) { 339 for (i = 0; i < data->num_sensors; i++) {
339 struct pmbus_sensor *sensor = &data->sensors[i]; 340 struct pmbus_sensor *sensor = &data->sensors[i];
340 341
@@ -817,6 +818,20 @@ static const int pmbus_fan_status_registers[] = {
817 PMBUS_STATUS_FAN_34 818 PMBUS_STATUS_FAN_34
818}; 819};
819 820
821static const u32 pmbus_fan_flags[] = {
822 PMBUS_HAVE_FAN12,
823 PMBUS_HAVE_FAN12,
824 PMBUS_HAVE_FAN34,
825 PMBUS_HAVE_FAN34
826};
827
828static const u32 pmbus_fan_status_flags[] = {
829 PMBUS_HAVE_STATUS_FAN12,
830 PMBUS_HAVE_STATUS_FAN12,
831 PMBUS_HAVE_STATUS_FAN34,
832 PMBUS_HAVE_STATUS_FAN34
833};
834
820/* 835/*
821 * Determine maximum number of sensors, booleans, and labels. 836 * Determine maximum number of sensors, booleans, and labels.
822 * To keep things simple, only make a rough high estimate. 837 * To keep things simple, only make a rough high estimate.
@@ -848,17 +863,12 @@ static void pmbus_find_max_attr(struct i2c_client *client,
848 max_labels++; 863 max_labels++;
849 } 864 }
850 if (info->func[page] & PMBUS_HAVE_FAN12) { 865 if (info->func[page] & PMBUS_HAVE_FAN12) {
851 if (page == 0) { 866 max_sensors += 2 * PMBUS_MAX_SENSORS_PER_FAN;
852 max_sensors += 867 max_booleans += 2 * PMBUS_MAX_BOOLEANS_PER_FAN;
853 ARRAY_SIZE(pmbus_fan_registers) * 868 }
854 PMBUS_MAX_SENSORS_PER_FAN; 869 if (info->func[page] & PMBUS_HAVE_FAN34) {
855 max_booleans += 870 max_sensors += 2 * PMBUS_MAX_SENSORS_PER_FAN;
856 ARRAY_SIZE(pmbus_fan_registers) * 871 max_booleans += 2 * PMBUS_MAX_BOOLEANS_PER_FAN;
857 PMBUS_MAX_BOOLEANS_PER_FAN;
858 } else {
859 max_sensors += PMBUS_MAX_SENSORS_PER_FAN;
860 max_booleans += PMBUS_MAX_BOOLEANS_PER_FAN;
861 }
862 } 872 }
863 if (info->func[page] & PMBUS_HAVE_TEMP) { 873 if (info->func[page] & PMBUS_HAVE_TEMP) {
864 if (page == 0) { 874 if (page == 0) {
@@ -1365,15 +1375,14 @@ static void pmbus_find_attributes(struct i2c_client *client,
1365 */ 1375 */
1366 in_index = 1; 1376 in_index = 1;
1367 for (page = 0; page < info->pages; page++) { 1377 for (page = 0; page < info->pages; page++) {
1368 int fans, f; 1378 int f;
1369 1379
1370 if (!(info->func[page] & PMBUS_HAVE_FAN12)) 1380 for (f = 0; f < ARRAY_SIZE(pmbus_fan_registers); f++) {
1371 continue;
1372
1373 fans = page ? 1 : ARRAY_SIZE(pmbus_fan_registers);
1374 for (f = 0; f < fans; f++) {
1375 int regval; 1381 int regval;
1376 1382
1383 if (!(info->func[page] & pmbus_fan_flags[f]))
1384 break;
1385
1377 if (!pmbus_check_word_register(client, page, 1386 if (!pmbus_check_word_register(client, page,
1378 pmbus_fan_registers[f]) 1387 pmbus_fan_registers[f])
1379 || !pmbus_check_byte_register(client, page, 1388 || !pmbus_check_byte_register(client, page,
@@ -1399,12 +1408,13 @@ static void pmbus_find_attributes(struct i2c_client *client,
1399 * Each fan status register covers multiple fans, 1408 * Each fan status register covers multiple fans,
1400 * so we have to do some magic. 1409 * so we have to do some magic.
1401 */ 1410 */
1402 if (pmbus_check_byte_register 1411 if ((info->func[page] & pmbus_fan_status_flags[f]) &&
1403 (client, page, pmbus_fan_status_registers[f])) { 1412 pmbus_check_byte_register(client,
1413 page, pmbus_fan_status_registers[f])) {
1404 int base; 1414 int base;
1405 1415
1406 if (f > 1) /* fan 3, 4 */ 1416 if (f > 1) /* fan 3, 4 */
1407 base = PB_STATUS_FAN34_BASE; 1417 base = PB_STATUS_FAN34_BASE + page;
1408 else 1418 else
1409 base = PB_STATUS_FAN_BASE + page; 1419 base = PB_STATUS_FAN_BASE + page;
1410 pmbus_add_boolean_reg(data, "fan", "alarm", 1420 pmbus_add_boolean_reg(data, "fan", "alarm",