@@ -23,6 +23,7 @@
#include <device.h>
#include <libflash/libflash.h>
#include <libflash/libffs.h>
+#include <libflash/mbox-flash.h>
#include <libflash/blocklevel.h>
#include <libflash/ecc.h>
#include <libstb/secureboot.h>
@@ -76,6 +77,14 @@ void flash_release(void)
unlock(&flash_lock);
}
+void flash_unregister(void)
+{
+ struct blocklevel_device *bl = system_flash->bl;
+
+ if (dt_find_compatible_node(dt_root, NULL, "mbox"))
+ mbox_flash_exit(bl);
+}
+
static int flash_nvram_info(uint32_t *total_size)
{
int rc;
@@ -961,6 +961,9 @@ void __attribute__((noreturn)) p9_sbe_terminate(const char *msg)
if (!dt_find_by_path(opal_node, "dump"))
goto out_reboot;
+ /* Unregister flash. It will request BMC MBOX reset */
+ flash_unregister();
+
dt_for_each_compatible(dt_root, xn, "ibm,xscom") {
chip_id = dt_get_chip_id(xn);
@@ -218,6 +218,7 @@ extern int flash_start_preload_resource(enum resource_id id, uint32_t subid,
extern int flash_resource_loaded(enum resource_id id, uint32_t idx);
extern bool flash_reserve(void);
extern void flash_release(void);
+extern void flash_unregister(void);
#define FLASH_SUBPART_ALIGNMENT 0x1000
#define FLASH_SUBPART_HEADER_SIZE FLASH_SUBPART_ALIGNMENT
extern int flash_subpart_info(void *part_header, uint32_t header_len,
@@ -816,6 +816,27 @@ static int mbox_flash_read(struct blocklevel_device *bl, uint64_t pos,
return rc;
}
+static int mbox_flash_reset(struct blocklevel_device *bl)
+{
+ int rc;
+ struct mbox_flash_data *mbox_flash;
+ struct bmc_mbox_msg msg = MSG_CREATE(MBOX_C_RESET_STATE);
+
+ mbox_flash = container_of(bl, struct mbox_flash_data, bl);
+
+ rc = msg_send(mbox_flash, &msg, mbox_flash->timeout);
+ if (rc) {
+ prlog(PR_ERR, "Failed to enqueue/send BMC MBOX RESET msg\n");
+ return rc;
+ }
+ if (wait_for_bmc(mbox_flash, mbox_flash->timeout)) {
+ prlog(PR_ERR, "Error waiting for BMC\n");
+ return rc;
+ }
+
+ return OPAL_SUCCESS;
+}
+
static int mbox_flash_get_info(struct blocklevel_device *bl, const char **name,
uint64_t *total_size, uint32_t *erase_granule)
{
@@ -1165,6 +1186,8 @@ void mbox_flash_exit(struct blocklevel_device *bl)
{
struct mbox_flash_data *mbox_flash;
if (bl) {
+ mbox_flash_reset(bl);
+
mbox_flash = container_of(bl, struct mbox_flash_data, bl);
free(mbox_flash);
}