aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/ipmi.c164
-rw-r--r--hw/Makefile.inc4
-rw-r--r--hw/bt.c48
-rw-r--r--hw/ipmi/Makefile.inc5
-rw-r--r--hw/ipmi/ipmi-power.c40
-rw-r--r--hw/ipmi/ipmi-rtc.c94
-rw-r--r--include/bt.h16
-rw-r--r--include/ipmi.h63
-rw-r--r--platforms/bmc/palmetto.c7
9 files changed, 272 insertions, 169 deletions
diff --git a/core/ipmi.c b/core/ipmi.c
index 1f9dd5f..90d8aaf 100644
--- a/core/ipmi.c
+++ b/core/ipmi.c
@@ -22,151 +22,79 @@
#include <time.h>
#include <time-utils.h>
-/* Sane default (2014/01/01) */
-static time_t time = 1388494800;
+static struct ipmi_backend *ipmi_backend = NULL;
-static void ipmi_process_storage_resp(struct ipmi_msg *msg)
+void ipmi_free_msg(struct ipmi_msg *msg)
{
- uint32_t new_time;
-
- switch (msg->cmd) {
- case IPMI_GET_SEL_TIME_CMD:
- /*
- * I couldn't find any mention of endianess in the IPMI spec,
- * but ipmitool seemed to assume little endian?
- */
- memcpy(&new_time, msg->data, 4);
- time = le32_to_cpu(new_time);
- break;
-
- case IPMI_SET_SEL_TIME_CMD:
- /* Nothing to do in this case */
- break;
-
- default:
- printf("Unsupported/invalid IPMI storage command\n");
- }
+ msg->backend->free_msg(msg);
}
-static int64_t ipmi_get_sel_time(void)
+struct ipmi_msg *ipmi_mkmsg_simple(uint32_t code, void *req_data, size_t req_size)
{
- struct ipmi_msg *msg;
- static uint32_t time_result;
-
- msg = bt_alloc_ipmi_msg(0, 4);
- if (!msg)
- return OPAL_HARDWARE;
-
- msg->cmd = IPMI_GET_SEL_TIME_CMD;
- msg->netfn = IPMI_NETFN_STORAGE_REQUEST;
-
- if (bt_add_ipmi_msg_wait(msg))
- return -1;
-
- memcpy(&time_result, msg->data, sizeof(time_result));
-
- return time_result;
+ return ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, code, ipmi_free_msg, NULL,
+ req_data, req_size, 0);
}
-static int64_t ipmi_set_sel_time(uint32_t tv)
+struct ipmi_msg *ipmi_mkmsg(int interface, uint32_t code,
+ void (*complete)(struct ipmi_msg *),
+ void *user_data, void *req_data, size_t req_size,
+ size_t resp_size)
{
struct ipmi_msg *msg;
- msg = bt_alloc_ipmi_msg(sizeof(tv), 0);
- if (!msg)
- return OPAL_HARDWARE;
-
- msg->cmd = IPMI_SET_SEL_TIME_CMD;
- msg->netfn = IPMI_NETFN_STORAGE_REQUEST;
- memcpy(msg->data, &tv, sizeof(tv));
+ /* We don't actually support multiple interfaces at the moment. */
+ assert(interface == IPMI_DEFAULT_INTERFACE);
- return bt_add_ipmi_msg_wait(msg);
-}
+ msg = ipmi_backend->alloc_msg(req_size, resp_size);
+ if (!msg)
+ return NULL;
-static int64_t ipmi_opal_rtc_read(uint32_t *y_m_d,
- uint64_t *h_m_s_m)
-{
- struct tm tm;
+ msg->backend = ipmi_backend;
+ msg->cmd = IPMI_CMD(code);
+ msg->netfn = IPMI_NETFN(code);
+ msg->req_size = req_size;
+ msg->resp_size = resp_size;
+ msg->complete = complete;
+ msg->user_data = user_data;
- if (ipmi_get_sel_time() < 0)
- return OPAL_HARDWARE;
+ if (req_data)
+ memcpy(msg->data, req_data, req_size);
- gmtime_r(&time, &tm);
- tm_to_datetime(&tm, y_m_d, h_m_s_m);
- return OPAL_SUCCESS;
+ return msg;
}
-static int64_t ipmi_opal_rtc_write(uint32_t year_month_day,
- uint64_t hour_minute_second_millisecond)
+int ipmi_sync_queue_msg(struct ipmi_msg *msg)
{
- time_t t;
- struct tm tm;
+ /* Here we could choose which interface to use if we want to support
+ multiple interfaces. */
- datetime_to_tm(year_month_day, hour_minute_second_millisecond, &tm);
- t = mktime(&tm);
- t = cpu_to_le32(t);
- if (ipmi_set_sel_time(t))
- return OPAL_HARDWARE;
+ /* We should also store the original message cmd/netfn here if we wish
+ to validate it when we get the response. */
- return OPAL_SUCCESS;
+ return msg->backend->queue_msg(msg);
}
-static void ipmi_rtc_init(void)
-{
- struct dt_node *np = dt_new(opal_node, "rtc");
- dt_add_property_strings(np, "compatible", "ibm,opal-rtc");
-
- opal_register(OPAL_RTC_READ, ipmi_opal_rtc_read, 2);
- opal_register(OPAL_RTC_WRITE, ipmi_opal_rtc_write, 2);
-}
-
-static void ipmi_cmd_done(struct ipmi_msg *msg)
+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_STORAGE_RESPONSE:
- ipmi_process_storage_resp(msg);
- break;
-
- case IPMI_NETFN_CHASSIS_RESPONSE:
- break;
- default:
- prerror("IPMI: Invalid IPMI function code in response\n");
- }
-
-out:
- bt_free_ipmi_msg(msg);
-}
-
-int64_t ipmi_opal_chassis_control(uint64_t request)
-{
- struct ipmi_msg *msg;
- uint8_t chassis_control = request;
-
- msg = bt_alloc_ipmi_msg(sizeof(chassis_control), 0);
- if (!msg)
- return OPAL_HARDWARE;
- if (request > IPMI_CHASSIS_SOFT_SHUTDOWN)
- return OPAL_PARAMETER;
+ if (msg->error)
+ msg->error(msg);
+ } else if (msg->complete)
+ msg->complete(msg);
- msg->cmd = IPMI_CHASSIS_CONTROL_CMD;
- msg->netfn = IPMI_NETFN_CHASSIS_REQUEST;
- msg->data[0] = chassis_control;
-
- prlog(PR_INFO, "IPMI: sending chassis control request %llu\n",
- request);
-
- return bt_add_ipmi_msg_wait(msg);
+ /* At this point the message has should have been freed by the
+ completion functions. */
+ msg = NULL;
}
-void ipmi_init(void)
+void ipmi_register_backend(struct ipmi_backend *backend)
{
- bt_init(ipmi_cmd_done);
-
- ipmi_rtc_init();
+ /* We only support one backend at the moment */
+ assert(backend->alloc_msg);
+ assert(backend->free_msg);
+ assert(backend->queue_msg);
+ assert(backend->dequeue_msg);
+ ipmi_backend = backend;
}
diff --git a/hw/Makefile.inc b/hw/Makefile.inc
index 320e33b..3f372b1 100644
--- a/hw/Makefile.inc
+++ b/hw/Makefile.inc
@@ -10,6 +10,6 @@ HW=hw/built-in.o
include $(SRC)/hw/fsp/Makefile.inc
include $(SRC)/hw/ec/Makefile.inc
include $(SRC)/hw/ast-bmc/Makefile.inc
+include $(SRC)/hw/ipmi/Makefile.inc
-$(HW): $(HW_OBJS:%=hw/%) $(FSP) $(EC) $(AST_BMC)
-
+$(HW): $(HW_OBJS:%=hw/%) $(FSP) $(EC) $(AST_BMC) $(IPMI)
diff --git a/hw/bt.c b/hw/bt.c
index da92597..882d72c 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -72,7 +72,6 @@ struct bt {
enum bt_states state;
struct lock lock;
struct list_head msgq;
- void (*ipmi_cmd_done)(struct ipmi_msg *);
};
static struct bt bt;
@@ -151,7 +150,7 @@ static bool bt_try_send_msg(void)
bt_setmask(BT_CTRL_CLR_WR_PTR, BT_CTRL);
/* Byte 1 - Length */
- bt_outb(ipmi_msg->req_data_len + BT_MIN_REQ_LEN, BT_HOST2BMC);
+ bt_outb(ipmi_msg->req_size + BT_MIN_REQ_LEN, BT_HOST2BMC);
/* Byte 2 - NetFn/LUN */
bt_outb((ipmi_msg->netfn << 2) | (bt_msg->lun & 0x3), BT_HOST2BMC);
@@ -163,7 +162,7 @@ static bool bt_try_send_msg(void)
bt_outb(ipmi_msg->cmd, BT_HOST2BMC);
/* Byte 5:N - Data */
- for (i = 0; i < ipmi_msg->req_data_len; i++)
+ for (i = 0; i < ipmi_msg->req_size; i++)
bt_outb(ipmi_msg->data[i], BT_HOST2BMC);
bt_setmask(BT_CTRL_H2B_ATN, BT_CTRL);
@@ -215,12 +214,12 @@ static bool bt_get_resp(void)
* are unsigned we will also trigger this error if
* bt_inb(BT_HOST2BMC) < BT_MIN_RESP_LEN (which should never occur).
*/
- if (resp_len > ipmi_msg->resp_data_len) {
+ if (resp_len > ipmi_msg->resp_size) {
prerror("BT: Invalid resp_len %d for ipmi_msg->cmd = 0x%02x\n", resp_len, ipmi_msg->cmd);
- resp_len = ipmi_msg->resp_data_len;
+ resp_len = ipmi_msg->resp_size;
cc = IPMI_ERR_MSG_TRUNCATED;
}
- ipmi_msg->resp_data_len = resp_len;
+ ipmi_msg->resp_size = resp_len;
/* Byte 2 - NetFn/LUN */
netfn = bt_inb(BT_HOST2BMC);
@@ -253,8 +252,7 @@ static bool bt_get_resp(void)
/*
* Call the IPMI layer to finish processing the message.
*/
- if (bt.ipmi_cmd_done)
- bt.ipmi_cmd_done(ipmi_msg);
+ ipmi_cmd_done(ipmi_msg);
/* Immediately send the next message */
return false;
@@ -307,28 +305,29 @@ static bool bt_wait_state(enum bt_states state)
}
/*
- * Allocate a BT-IPMI message and return the IPMI message struct. Allocates
- * enough space for the request and response data.
+ * Allocate an ipmi message and bt container and return the ipmi
+ * message struct. Allocates enough space for the request and response
+ * data.
*/
-struct ipmi_msg *bt_alloc_ipmi_msg(size_t request_size, size_t response_size)
+static struct ipmi_msg *bt_alloc_ipmi_msg(size_t request_size, size_t response_size)
{
struct bt_msg *bt_msg;
- bt_msg = malloc(sizeof(struct bt_msg) + MAX(request_size, response_size));
+ bt_msg = zalloc(sizeof(struct bt_msg) + MAX(request_size, response_size));
if (!bt_msg)
return NULL;
- bt_msg->ipmi_msg.req_data_len = request_size;
- bt_msg->ipmi_msg.resp_data_len = response_size;
+ bt_msg->ipmi_msg.req_size = request_size;
+ bt_msg->ipmi_msg.resp_size = response_size;
bt_msg->ipmi_msg.data = (uint8_t *) (bt_msg + 1);
return &bt_msg->ipmi_msg;
}
/*
- * Free a previously allocated BT-IPMI message.
+ * Free a previously allocated ipmi message.
*/
-void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg)
+static void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg)
{
struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
@@ -338,7 +337,7 @@ void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg)
/*
* Add an ipmi message to the queue and wait for a response.
*/
-int bt_add_ipmi_msg_wait(struct ipmi_msg *msg)
+static int bt_add_ipmi_msg_wait(struct ipmi_msg *msg)
{
int ret = 0;
@@ -375,16 +374,24 @@ out:
* will need to be freed by the caller with bt_free_ipmi_msg() as it will no
* longer be in the queue of messages.
*/
-void bt_del_ipmi_msg(struct ipmi_msg *ipmi_msg)
+static int bt_del_ipmi_msg(struct ipmi_msg *ipmi_msg)
{
struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg);
lock(&bt.lock);
list_del(&bt_msg->link);
unlock(&bt.lock);
+ return 0;
}
-void bt_init(void (*ipmi_cmd_done)(struct ipmi_msg *))
+struct ipmi_backend bt_backend = {
+ .alloc_msg = bt_alloc_ipmi_msg,
+ .free_msg = bt_free_ipmi_msg,
+ .queue_msg = bt_add_ipmi_msg_wait,
+ .dequeue_msg = bt_del_ipmi_msg,
+};
+
+void bt_init(void)
{
struct dt_node *n;
const struct dt_property *prop;
@@ -413,6 +420,7 @@ void bt_init(void (*ipmi_cmd_done)(struct ipmi_msg *))
* initialised it.
*/
bt_set_state(BT_STATE_B_BUSY);
- bt.ipmi_cmd_done = ipmi_cmd_done;
list_head_init(&bt.msgq);
+
+ ipmi_register_backend(&bt_backend);
}
diff --git a/hw/ipmi/Makefile.inc b/hw/ipmi/Makefile.inc
new file mode 100644
index 0000000..c939f6c
--- /dev/null
+++ b/hw/ipmi/Makefile.inc
@@ -0,0 +1,5 @@
+SUBDIRS += hw/ipmi
+
+IPMI_OBJS = ipmi-rtc.o ipmi-power.o
+IPMI = hw/ipmi/built-in.o
+$(IPMI): $(IPMI_OBJS:%=hw/ipmi/%)
diff --git a/hw/ipmi/ipmi-power.c b/hw/ipmi/ipmi-power.c
new file mode 100644
index 0000000..ac37d14
--- /dev/null
+++ b/hw/ipmi/ipmi-power.c
@@ -0,0 +1,40 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <ipmi.h>
+#include <opal.h>
+
+int64_t ipmi_opal_chassis_control(uint64_t request)
+{
+ struct ipmi_msg *msg;
+ uint8_t chassis_control = request;
+
+ if (chassis_control > IPMI_CHASSIS_SOFT_SHUTDOWN)
+ return OPAL_PARAMETER;
+
+
+ msg = ipmi_mkmsg_simple(IPMI_CHASSIS_CONTROL, &chassis_control,
+ sizeof(chassis_control));
+ if (!msg)
+ return OPAL_HARDWARE;
+
+
+ prlog(PR_INFO, "IPMI: sending chassis control request %llu\n",
+ request);
+
+ return ipmi_sync_queue_msg(msg);
+}
diff --git a/hw/ipmi/ipmi-rtc.c b/hw/ipmi/ipmi-rtc.c
new file mode 100644
index 0000000..5ddfced
--- /dev/null
+++ b/hw/ipmi/ipmi-rtc.c
@@ -0,0 +1,94 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <ipmi.h>
+#include <time.h>
+#include <time-utils.h>
+#include <device.h>
+#include <opal.h>
+
+/* Sane default (2014/01/01) */
+static time_t time = 1388494800;
+
+static void get_sel_time_complete(struct ipmi_msg *msg)
+{
+ uint32_t result;
+
+ memcpy(&result, msg->data, 4);
+ time = le32_to_cpu(result);
+}
+
+
+static int64_t ipmi_get_sel_time(void)
+{
+ struct ipmi_msg *msg;
+
+ msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_GET_SEL_TIME,
+ get_sel_time_complete, &time, NULL, 0, 4);
+ if (!msg)
+ return OPAL_HARDWARE;
+
+ return ipmi_sync_queue_msg(msg);
+}
+
+static int64_t ipmi_set_sel_time(uint32_t tv)
+{
+ struct ipmi_msg *msg;
+
+ tv = cpu_to_le32(tv);
+ msg = ipmi_mkmsg_simple(IPMI_SET_SEL_TIME, &tv, sizeof(tv));
+ if (!msg)
+ return OPAL_HARDWARE;
+
+ return ipmi_sync_queue_msg(msg);
+}
+
+static int64_t ipmi_opal_rtc_read(uint32_t *y_m_d,
+ uint64_t *h_m_s_m)
+{
+ struct tm tm;
+
+ if (ipmi_get_sel_time() < 0)
+ return OPAL_HARDWARE;
+
+ gmtime_r(&time, &tm);
+ tm_to_datetime(&tm, y_m_d, h_m_s_m);
+ return OPAL_SUCCESS;
+}
+
+static int64_t ipmi_opal_rtc_write(uint32_t year_month_day,
+ uint64_t hour_minute_second_millisecond)
+{
+ time_t t;
+ struct tm tm;
+
+ datetime_to_tm(year_month_day, hour_minute_second_millisecond, &tm);
+ t = mktime(&tm);
+ if (ipmi_set_sel_time(t))
+ return OPAL_HARDWARE;
+
+ return OPAL_SUCCESS;
+}
+
+void ipmi_rtc_init(void)
+{
+ struct dt_node *np = dt_new(opal_node, "rtc");
+ dt_add_property_strings(np, "compatible", "ibm,opal-rtc");
+
+ opal_register(OPAL_RTC_READ, ipmi_opal_rtc_read, 2);
+ opal_register(OPAL_RTC_WRITE, ipmi_opal_rtc_write, 2);
+}
diff --git a/include/bt.h b/include/bt.h
index 5f8a91e..1763d9f 100644
--- a/include/bt.h
+++ b/include/bt.h
@@ -17,21 +17,7 @@
#ifndef __BT_H
#define __BT_H
-#include <ipmi.h>
-
/* Initialise the BT interface */
-void bt_init(void (*ipmi_cmd_done)(struct ipmi_msg *));
-
-/* Allocate an BT-IPMI message */
-struct ipmi_msg *bt_alloc_ipmi_msg(size_t request_size, size_t response_size);
-
-/* Free a BT-IPMI message */
-void bt_free_ipmi_msg(struct ipmi_msg *ipmi_msg);
-
-/* Add an IPMI message to the BT queue and wait for a resposne */
-int bt_add_ipmi_msg_wait(struct ipmi_msg *msg);
-
-/* Remove an IPMI message from the BT queue */
-void bt_del_ipmi_msg(struct ipmi_msg *ipmi_msg);
+void bt_init(void);
#endif
diff --git a/include/ipmi.h b/include/ipmi.h
index 6181c53..78eb5cd 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -22,8 +22,6 @@
/*
* IPMI codes as defined by the standard.
*/
-#define IPMI_NETFN_APP_REQUEST 0x06
-#define IPMI_NETFN_APP_RESPONSE 0x07
#define IPMI_GET_DEVICE_ID_CMD 0x01
#define IPMI_COLD_RESET_CMD 0x02
#define IPMI_WARM_RESET_CMD 0x03
@@ -54,8 +52,6 @@
#define IPMI_CHASSIS_GET_SYS_BOOT_OPT_CMD 0x0b
#define IPMI_CHASSIS_GET_POH_COUNTER_CMD 0x0f
-#define IPMI_NETFN_CHASSIS_REQUEST 0x00
-#define IPMI_NETFN_CHASSIS_RESPONSE 0x01
/* 28.3. Chassis Control Command */
#define IPMI_CHASSIS_PWR_DOWN 0x00
@@ -65,11 +61,18 @@
#define IPMI_CHASSIS_PULSE_DIAG 0x04
#define IPMI_CHASSIS_SOFT_SHUTDOWN 0x05
-#define IPMI_NETFN_STORAGE_REQUEST 0x0a
-#define IPMI_NETFN_STORAGE_RESPONSE 0x0b
-#define IPMI_GET_SEL_INFO_CMD 0x40
-#define IPMI_GET_SEL_TIME_CMD 0x48
-#define IPMI_SET_SEL_TIME_CMD 0x49
+#define IPMI_CODE(netfn, cmd) ((netfn) << 8 | (cmd))
+#define IPMI_CMD(code) ((code) & 0xff)
+#define IPMI_NETFN(code) ((code) >> 8 & 0xff)
+
+#define IPMI_NETFN_CHASSIS 0x00
+#define IPMI_NETFN_STORAGE 0x0a
+#define IPMI_NETFN_APP 0x06
+
+#define IPMI_GET_SEL_INFO IPMI_CODE(IPMI_NETFN_STORAGE, 0x40)
+#define IPMI_GET_SEL_TIME IPMI_CODE(IPMI_NETFN_STORAGE, 0x48)
+#define IPMI_SET_SEL_TIME IPMI_CODE(IPMI_NETFN_STORAGE, 0x49)
+#define IPMI_CHASSIS_CONTROL IPMI_CODE(IPMI_NETFN_CHASSIS, 0x02)
/*
* IPMI response codes.
@@ -87,19 +90,57 @@
#define IPMI_NAK_ON_WRITE_ERR 0x83
#define IPMI_ERR_UNSPECIFIED 0xff
+#define IPMI_DEFAULT_INTERFACE 0
+
+struct ipmi_backend;
struct ipmi_msg {
+ struct ipmi_backend *backend;
uint8_t netfn;
uint8_t cmd;
uint8_t cc;
- uint8_t req_data_len;
- uint8_t resp_data_len;
+
+ /* Called when a response is received to the ipmi message */
+ void (*complete)(struct ipmi_msg *);
+
+ /* Called if non-NULL when the ipmi layer detects an error */
+ void (*error)(struct ipmi_msg *);
+ void *user_data;
+
+ uint8_t req_size;
+ uint8_t resp_size;
uint8_t *data;
};
+struct ipmi_backend {
+ struct ipmi_msg *(*alloc_msg)(size_t, size_t);
+ void (*free_msg)(struct ipmi_msg *);
+ int (*queue_msg)(struct ipmi_msg *);
+ int (*dequeue_msg)(struct ipmi_msg *);
+};
+
/* Initialise the IPMI interface */
void ipmi_init(void);
+void ipmi_free_msg(struct ipmi_msg *msg);
+
+struct ipmi_msg *ipmi_mkmsg_simple(uint32_t code, void *req_data, size_t req_size);
+struct ipmi_msg *ipmi_mkmsg(int interface, uint32_t code,
+ void (*complete)(struct ipmi_msg *),
+ void *user_data, void *req_data, size_t req_size,
+ size_t resp_size);
+
+int ipmi_sync_queue_msg(struct ipmi_msg *msg);
+
+/* Process a completed message */
+void ipmi_cmd_done(struct ipmi_msg *msg);
+
/* Change the power state of the P8 */
int64_t ipmi_opal_chassis_control(uint64_t request);
+/* Register a backend with the ipmi core. Currently we only support one. */
+void ipmi_register_backend(struct ipmi_backend *backend);
+
+/* Register rtc ipmi commands with as opal callbacks. */
+void ipmi_rtc_init(void);
+
#endif
diff --git a/platforms/bmc/palmetto.c b/platforms/bmc/palmetto.c
index c8ea281..217e542 100644
--- a/platforms/bmc/palmetto.c
+++ b/platforms/bmc/palmetto.c
@@ -23,6 +23,7 @@
#include <xscom.h>
#include <ast.h>
#include <ipmi.h>
+#include <bt.h>
#include "bmc.h"
@@ -203,8 +204,9 @@ static bool palmetto_probe(void)
/* Setup UART and use it as console with interrupts */
uart_init(true);
- /* Setup IPMI */
- ipmi_init();
+ /* Register the BT interface with the IPMI layer */
+ bt_init();
+ ipmi_rtc_init();
return true;
}
@@ -234,4 +236,3 @@ DECLARE_PLATFORM(palmetto) = {
.cec_power_down = palmetto_ipmi_power_down,
.cec_reboot = palmetto_ipmi_reboot,
};
-