aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/hw/ipmi/ipmi-sensor.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/hw/ipmi/ipmi-sensor.c')
-rw-r--r--roms/skiboot/hw/ipmi/ipmi-sensor.c160
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;
+}