diff options
Diffstat (limited to 'roms/skiboot/platforms/astbmc/pnor.c')
-rw-r--r-- | roms/skiboot/platforms/astbmc/pnor.c | 98 |
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; +} |