aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Stanley <joel@jms.id.au>2014-08-12 17:59:41 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-08-13 16:15:42 +1000
commit50d2e37faf5bb2fd154d4a1eeac465f8016e1f65 (patch)
tree1a275d39c8b74e6f0ec397942763e68e9e29c8f0
parent7f43755ba160e160554c8eb537efc5f691e99bc6 (diff)
downloadskiboot-50d2e37faf5bb2fd154d4a1eeac465f8016e1f65.zip
skiboot-50d2e37faf5bb2fd154d4a1eeac465f8016e1f65.tar.gz
skiboot-50d2e37faf5bb2fd154d4a1eeac465f8016e1f65.tar.bz2
plat/palmetto: Add shutdown and reboot
Rebooting and power down for the Palmetto is done by the BMC, which we speak to over the BT interface using IPMI. Implement the IPMI chassis commands which are used for power control, and hook them up to the palmetto platform callbacks for shutdown and reboot. Signed-off-by: Joel Stanley <joel@jms.id.au> Signed-off-by: Alistair Popple <alistair@popple.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--core/ipmi.c26
-rw-r--r--include/ipmi.h9
-rw-r--r--platforms/bmc/palmetto.c19
3 files changed, 54 insertions, 0 deletions
diff --git a/core/ipmi.c b/core/ipmi.c
index b21a0f3..6cf435d 100644
--- a/core/ipmi.c
+++ b/core/ipmi.c
@@ -17,17 +17,43 @@
#include <stdio.h>
#include <bt.h>
#include <ipmi.h>
+#include <opal.h>
static void ipmi_cmd_done(struct ipmi_msg *msg)
{
if (msg->cc != IPMI_CC_NO_ERROR) {
prerror("IPMI: Got error response 0x%02x\n", msg->cc);
+ goto out;
}
switch (msg->netfn) {
+ case IPMI_NETFN_CHASSIS_RESPONSE:
+ break;
default:
prerror("IPMI: Invalid IPMI function code in response\n");
}
+
+out:
+ free(msg);
+}
+
+int64_t ipmi_opal_chassis_request(uint64_t request)
+{
+ struct ipmi_msg *msg = zalloc(sizeof(struct ipmi_msg));
+
+ if (!msg)
+ return OPAL_HARDWARE;
+
+ msg->cmd = request;
+ msg->netfn = IPMI_NETFN_CHASSIS_REQUEST;
+ msg->req_data = NULL;
+ msg->req_data_len = 0;
+ msg->resp_data = NULL;
+ msg->resp_data_len = 0;
+
+ prlog(PR_INFO, "IPMI: sending chassis request %llu\n", request);
+
+ return bt_add_ipmi_msg_wait(msg);
}
void ipmi_init(void)
diff --git a/include/ipmi.h b/include/ipmi.h
index 3e08cdb..8cc7e5a 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -37,6 +37,12 @@
#define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
#define IPMI_GET_CHANNEL_INFO_CMD 0x42
+#define IPMI_NETFN_CHASSIS_REQUEST 0x00
+#define IPMI_NETFN_CHASSIS_RESPONSE 0x01
+#define IPMI_SET_CHASSIS_PWR_DOWN_CMD 0x00
+#define IPMI_SET_CHASSIS_PWR_UP_CMD 0x01
+#define IPMI_SET_CHASSIS_PWR_CYCLE_CMD 0x02
+
#define IPMI_NETFN_STORAGE_REQUEST 0x0a
#define IPMI_NETFN_STORAGE_RESPONSE 0x0b
#define IPMI_GET_SEL_INFO_CMD 0x40
@@ -72,4 +78,7 @@ struct ipmi_msg {
/* Initialise the IPMI interface */
void ipmi_init(void);
+/* Change the power state of the P8 */
+int64_t ipmi_opal_chassis_request(uint64_t request);
+
#endif
diff --git a/platforms/bmc/palmetto.c b/platforms/bmc/palmetto.c
index 50e2050..f0a0c86 100644
--- a/platforms/bmc/palmetto.c
+++ b/platforms/bmc/palmetto.c
@@ -209,10 +209,29 @@ static bool palmetto_probe(void)
return true;
}
+static int64_t palmetto_ipmi_power_down(uint64_t request __unused)
+{
+ /* Request is:
+ * 0 = normal
+ * 1 = immediate
+ * When doing "shutdown -h now" from linux, we get a 0.
+ * However, I believe at that point we are ready to shut down,
+ * so unconditionally tell the BMC to immediately power us down.
+ */
+ return ipmi_opal_chassis_request(IPMI_SET_CHASSIS_PWR_DOWN_CMD);
+}
+
+static int64_t palmetto_ipmi_reboot(void)
+{
+ return ipmi_opal_chassis_request(IPMI_SET_CHASSIS_PWR_CYCLE_CMD);
+}
+
DECLARE_PLATFORM(palmetto) = {
.name = "Palmetto",
.probe = palmetto_probe,
.init = palmetto_init,
.external_irq = palmetto_ext_irq,
+ .cec_power_down = palmetto_ipmi_power_down,
+ .cec_reboot = palmetto_ipmi_reboot,
};