diff options
-rw-r--r-- | drivers/hwmon/pmbus_core.c | 70 |
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 | ||
79 | struct pmbus_sensor { | 77 | struct 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 | ||
821 | static const u32 pmbus_fan_flags[] = { | ||
822 | PMBUS_HAVE_FAN12, | ||
823 | PMBUS_HAVE_FAN12, | ||
824 | PMBUS_HAVE_FAN34, | ||
825 | PMBUS_HAVE_FAN34 | ||
826 | }; | ||
827 | |||
828 | static 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", |