diff options
Diffstat (limited to 'roms/skiboot/hw/ipmi/ipmi-sensor.c')
-rw-r--r-- | roms/skiboot/hw/ipmi/ipmi-sensor.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/roms/skiboot/hw/ipmi/ipmi-sensor.c b/roms/skiboot/hw/ipmi/ipmi-sensor.c new file mode 100644 index 000000000..857b789e4 --- /dev/null +++ b/roms/skiboot/hw/ipmi/ipmi-sensor.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* Copyright 2013-2017 IBM Corp. */ + +#include <device.h> +#include <ipmi.h> +#include <opal.h> +#include <skiboot.h> +#include <string.h> +#include <stdbool.h> + +#define IPMI_WRITE_SENSOR (1 << 0) + +#define FW_PROGRESS_SENSOR_TYPE 0x0F +#define BOOT_COUNT_SENSOR_TYPE 0xC3 + +static int16_t sensors[MAX_IPMI_SENSORS]; + +static bool sensors_present = false; + +struct set_sensor_req { + u8 sensor_number; + u8 operation; + u8 sensor_reading; + u8 assertion_mask[2]; + u8 deassertion_mask[2]; + u8 event_data[3]; +}; + +static bool ipmi_sensor_type_present(uint8_t sensor_type) +{ + const struct dt_property *type_prop; + uint8_t type; + struct dt_node *node; + + dt_for_each_compatible(dt_root, node, "ibm,ipmi-sensor") { + type_prop = dt_find_property(node, "ipmi-sensor-type"); + if (!type_prop) { + prlog(PR_ERR, "IPMI: sensor doesn't have ipmi-sensor-type\n"); + continue; + } + + type = (uint8_t)dt_property_get_cell(type_prop, 0); + if (type == sensor_type) + return true; + } + return false; +} + +uint8_t ipmi_get_sensor_number(uint8_t sensor_type) +{ + assert(sensor_type < MAX_IPMI_SENSORS); + return sensors[sensor_type]; +} + +int ipmi_set_boot_count(void) +{ + struct set_sensor_req req; + struct ipmi_msg *msg; + int boot_count_sensor; + + if (!sensors_present) + return OPAL_UNSUPPORTED; + + if (!ipmi_present()) + return OPAL_CLOSED; + + if (!ipmi_sensor_type_present(BOOT_COUNT_SENSOR_TYPE)) + return OPAL_HARDWARE; + + boot_count_sensor = sensors[BOOT_COUNT_SENSOR_TYPE]; + + if (boot_count_sensor < 0) { + prlog(PR_DEBUG, "IPMI: boot count set but not present\n"); + return OPAL_HARDWARE; + } + + memset(&req, 0, sizeof(req)); + + req.sensor_number = boot_count_sensor; + req.operation = IPMI_WRITE_SENSOR; + req.sensor_reading = 0x00; + req.assertion_mask[0] = 0x02; + + msg = ipmi_mkmsg_simple(IPMI_SET_SENSOR_READING, &req, sizeof(req)); + if (!msg) + return OPAL_HARDWARE; + + printf("IPMI: Resetting boot count on successful boot\n"); + + return ipmi_queue_msg(msg); +} + +int ipmi_set_fw_progress_sensor(uint8_t state) +{ + struct ipmi_msg *msg; + struct set_sensor_req request; + int fw_sensor_num; + + if (!sensors_present) + return OPAL_UNSUPPORTED; + + if (!ipmi_present()) + return OPAL_CLOSED; + + if (!ipmi_sensor_type_present(FW_PROGRESS_SENSOR_TYPE)) + return OPAL_HARDWARE; + + fw_sensor_num = sensors[FW_PROGRESS_SENSOR_TYPE]; + + if (fw_sensor_num < 0) { + prlog(PR_DEBUG, "IPMI: fw progress set but not present\n"); + return OPAL_HARDWARE; + } + + memset(&request, 0, sizeof(request)); + + request.sensor_number = fw_sensor_num; + request.operation = 0xa0; /* Set event data bytes, assertion bits */ + request.assertion_mask[0] = 0x04; /* Firmware progress offset */ + request.event_data[0] = 0xc2; + request.event_data[1] = state; + + prlog(PR_INFO, "IPMI: setting fw progress sensor %02x to %02x\n", + request.sensor_number, request.event_data[1]); + + msg = ipmi_mkmsg_simple(IPMI_SET_SENSOR_READING, &request, + sizeof(request)); + if (!msg) + return OPAL_HARDWARE; + + return ipmi_queue_msg(msg); +} + +void ipmi_sensor_init(void) +{ + const struct dt_property *type_prop, *num_prop; + uint8_t num, type; + struct dt_node *n; + + memset(sensors, -1, sizeof(sensors)); + + dt_for_each_compatible(dt_root, n, "ibm,ipmi-sensor") { + type_prop = dt_find_property(n, "ipmi-sensor-type"); + if (!type_prop) { + prerror("IPMI: sensor doesn't have ipmi-sensor-type\n"); + continue; + } + + num_prop = dt_find_property(n, "reg"); + if (!num_prop) { + prerror("IPMI: sensor doesn't have reg property\n"); + continue; + } + num = (uint8_t)dt_property_get_cell(num_prop, 0); + type = (uint8_t)dt_property_get_cell(type_prop, 0); + assert(type < MAX_IPMI_SENSORS); + sensors[type] = num; + } + sensors_present = true; +} |