aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/platforms/astbmc/pnor.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/platforms/astbmc/pnor.c')
-rw-r--r--roms/skiboot/platforms/astbmc/pnor.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/roms/skiboot/platforms/astbmc/pnor.c b/roms/skiboot/platforms/astbmc/pnor.c
new file mode 100644
index 000000000..64f2249d1
--- /dev/null
+++ b/roms/skiboot/platforms/astbmc/pnor.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2013-2019 IBM Corp. */
+
+#include <skiboot.h>
+#include <device.h>
+#include <console.h>
+#include <opal.h>
+#include <libflash/ipmi-hiomap.h>
+#include <libflash/mbox-flash.h>
+#include <libflash/libflash.h>
+#include <libflash/libffs.h>
+#include <libflash/blocklevel.h>
+#include <ast.h>
+
+#include "astbmc.h"
+
+enum ast_flash_style {
+ raw_flash,
+ raw_mem,
+ ipmi_hiomap,
+ mbox_hiomap,
+};
+
+static enum ast_flash_style ast_flash_get_fallback_style(void)
+{
+ if (ast_lpc_fw_mbox_hiomap())
+ return mbox_hiomap;
+
+ if (ast_lpc_fw_maps_flash())
+ return raw_flash;
+
+ return raw_mem;
+}
+
+int pnor_init(void)
+{
+ struct spi_flash_ctrl *pnor_ctrl = NULL;
+ struct blocklevel_device *bl = NULL;
+ enum ast_flash_style style;
+ int rc = 0;
+
+ if (ast_lpc_fw_ipmi_hiomap()) {
+ style = ipmi_hiomap;
+ rc = ipmi_hiomap_init(&bl);
+ }
+
+ if (!ast_lpc_fw_ipmi_hiomap() || rc) {
+ if (!ast_sio_is_enabled())
+ return -ENODEV;
+
+ style = ast_flash_get_fallback_style();
+ if (style == mbox_hiomap)
+ rc = mbox_flash_init(&bl);
+ else if (style == raw_flash)
+ rc = ast_sf_open(AST_SF_TYPE_PNOR, &pnor_ctrl);
+ else if (style == raw_mem)
+ rc = ast_sf_open(AST_SF_TYPE_MEM, &pnor_ctrl);
+ else {
+ prerror("Unhandled flash mode: %d\n", style);
+ return -ENODEV;
+ }
+ }
+
+ if (rc) {
+ prerror("PLAT: Failed to init PNOR driver\n");
+ goto fail;
+ }
+
+ if (style == raw_flash || style == raw_mem) {
+ rc = flash_init(pnor_ctrl, &bl, NULL);
+ if (rc)
+ goto fail;
+ }
+
+ rc = flash_register(bl);
+ if (!rc)
+ return 0;
+
+fail:
+ if (bl) {
+ switch (style) {
+ case raw_flash:
+ case raw_mem:
+ flash_exit(bl);
+ break;
+ case ipmi_hiomap:
+ ipmi_hiomap_exit(bl);
+ break;
+ case mbox_hiomap:
+ mbox_flash_exit(bl);
+ break;
+ }
+ }
+ if (pnor_ctrl)
+ ast_sf_close(pnor_ctrl);
+
+ return rc;
+}