This is an automated email from Gerrit.

"Ryan QIAN <jianghao.q...@outlook.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8695

-- gerrit

commit fc99ff9dad5375fdd7a45ea326d6e2c350696daf
Author: Ryan QIAN <jianghao.q...@hpmicro.com>
Date:   Tue Jan 7 15:09:18 2025 +0800

    contrib/loaders/flash/hpmicro: add hpmicro device xpi support
    
    - add xpi flash support for hpmicro devices
    
    Change-Id: I3531fdf20a34561c6f3fe6ac0b9af988d483aae7
    Signed-off-by: Ryan QIAN <jianghao.q...@hpmicro.com>

diff --git a/contrib/loaders/flash/hpmicro/Makefile 
b/contrib/loaders/flash/hpmicro/Makefile
new file mode 100644
index 0000000000..1b3ea9865d
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/Makefile
@@ -0,0 +1,51 @@
+# Copyright (c) 2023 HPMicro
+# SPDX-License-Identifier: BSD-3-Clause
+#
+BIN2C = ../../../../src/helper/bin2char.sh
+
+
+PROJECT=hpm_xpi_flash
+CROSS_COMPILE ?= riscv32-unknown-elf-
+CC=$(CROSS_COMPILE)gcc
+AS=$(CROSS_COMPILE)gcc
+OBJCOPY=$(CROSS_COMPILE)objcopy
+OBJDUMP=$(CROSS_COMPILE)objdump
+LD=$(CROSS_COMPILE)ld
+LDSCRIPT=linker.ld
+
+OPT=-O3
+
+ASFLAGS=
+CFLAGS=$(OPT) -fomit-frame-pointer -Wall
+LDFLAGS=-nostartfiles -T$(LDSCRIPT) -Wl,-Map=$(PROJECT).map -static 
-Wl,--gc-sections
+OBJS=$(ASRC:.S=.o) $(SRC:.c=.o)
+
+SRC=openocd_flash_algo.c
+ASRC=func_table.S
+
+all: $(OBJS) $(PROJECT).elf $(PROJECT).bin $(PROJECT).lst $(PROJECT).inc
+
+%o: %c
+       @$(CC) -c $(CFLAGS) -I . $< -o $@
+
+%o: %S
+       @$(AS) -c $(ASFLAGS) -I . $< -o $@
+
+%elf: $(OBJS)
+       @$(CC) $(OBJS) $(LDFLAGS) -o $@
+
+%lst: %elf
+       @$(OBJDUMP) -h -S $< > $@
+
+%bin: %elf
+       @$(OBJCOPY) -Obinary $< $@
+
+%inc: %bin
+       $(BIN2C) < $< > $@
+
+clean:
+       @-rm -f *.o *.elf *.lst *.bin *.inc
+
+.PHONY:        all clean
+
+.INTERMEDIATE: $(patsubst %.S,%.o,$(SRCS)) $(patsubst %.S,%.elf,$(SRCS)) 
$(patsubst %.S,%.bin,$(SRCS))
diff --git a/contrib/loaders/flash/hpmicro/func_table.S 
b/contrib/loaders/flash/hpmicro/func_table.S
new file mode 100644
index 0000000000..3bca76a498
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/func_table.S
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2021 HPMicro
+ */
+  .section .func_table, "ax"
+  .global _init
+_init:
+  jal flash_init
+  ebreak
+  jal flash_erase
+  ebreak
+  jal flash_program
+  ebreak
+  jal flash_read
+  ebreak
+  jal flash_get_info
+  ebreak
+  jal flash_erase_chip
+  ebreak
+  jal flash_deinit
+  ebreak
diff --git a/contrib/loaders/flash/hpmicro/hpm_common.h 
b/contrib/loaders/flash/hpmicro/hpm_common.h
new file mode 100644
index 0000000000..110f0b3eb1
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/hpm_common.h
@@ -0,0 +1,278 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2021-2023 HPMicro
+ */
+
+#ifndef _HPM_COMMON_H
+#define _HPM_COMMON_H
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+/**
+ *
+ * @brief COMMON driver APIs
+ * @defgroup common_interface COMMON driver APIs
+ * @{
+ *
+ */
+
+#define __R volatile const /* Define "read-only" permission */
+#define __RW volatile      /* Define "read-write" permission */
+#define __W volatile       /* Define "write-only" permission */
+
+#ifndef __I
+#define __I __R
+#endif
+
+#ifndef __IO
+#define __IO __RW
+#endif
+
+#ifndef __O
+#define __O __W
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a)   (sizeof(a) / sizeof((a)[0]))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define HPM_BITSMASK(val, offset) ((uint32_t)(val) << (offset))
+#define IS_HPM_BITMASK_SET(val, mask) (((uint32_t)(val) & (uint32_t)(mask)) != 
0U)
+#define IS_HPM_BIT_SET(val, offset) (((uint32_t)(val) & (1UL << (offset))) != 
0U)
+#define IS_HPM_BITMASK_CLR(val, mask) (((uint32_t)(val) & (uint32_t)(mask)) == 
0U)
+#define IS_HPM_BIT_CLR(val, offset) (((uint32_t)(val) & (1UL << (offset))) == 
0U)
+
+#define HPM_BREAK_IF(cond)  do {if (cond) break; } while (0)
+#define HPM_CONTINUE_IF(cond) do {if (cond) continue; } while (0)
+
+#define HPM_CHECK_RET(x)               \
+       do {                               \
+               stat = (x);                    \
+               if (status_success != stat) { \
+                       return stat;               \
+               }                              \
+       } while (false)
+
+#define SIZE_1KB (1024UL)
+#define SIZE_1MB (1048576UL)
+
+typedef uint32_t hpm_stat_t;
+
+/* @brief Enum definition for the Status group
+ * Rule:
+ *  [Group] 0-999 for the SoC driver and the corresponding components
+ *       1000 or above for the application status group
+ *  [Code]  Valid value: 0-999
+ *
+ */
+#define MAKE_STATUS(group, code) ((uint32_t)(group) * 1000U + (uint32_t)(code))
+/* @brief System status group definitions */
+enum {
+       status_group_common = 0,
+       status_group_uart = 1,
+       status_group_i2c = 2,
+       status_group_spi = 3,
+       status_group_usb = 4,
+       status_group_i2s = 5,
+       status_group_xpi = 6,
+       status_group_l1c,
+       status_group_dma,
+       status_group_femc,
+       status_group_sdp,
+       status_group_xpi_nor,
+       status_group_otp,
+       status_group_lcdc,
+       status_group_mbx,
+       status_group_rng,
+       status_group_pdma,
+       status_group_wdg,
+       status_group_pmic_sec,
+       status_group_can,
+       status_group_sdxc,
+       status_group_pcfg,
+       status_group_clk,
+       status_group_pllctl,
+       status_group_pllctlv2,
+       status_group_ffa,
+       status_group_mcan,
+
+       status_group_middleware_start = 500,
+       status_group_sdmmc = status_group_middleware_start,
+       status_group_audio_codec,
+       status_group_dma_manager,
+};
+
+/* @brief Common status code definitions */
+enum {
+       status_success = MAKE_STATUS(status_group_common, 0),
+       status_fail = MAKE_STATUS(status_group_common, 1),
+       status_invalid_argument = MAKE_STATUS(status_group_common, 2),
+       status_timeout = MAKE_STATUS(status_group_common, 3),
+};
+
+#if defined(__GNUC__)
+
+/* alway_inline */
+#define ATTR_ALWAYS_INLINE __attribute__((always_inline))
+
+/* weak */
+#define ATTR_WEAK __attribute__((weak))
+
+/* alignment */
+#define ATTR_ALIGN(alignment) __attribute__((aligned(alignment)))
+
+/* place var_declare at section_name, e.x. PLACE_AT(".target_section", var); */
+#define ATTR_PLACE_AT(section_name) __attribute__((section(section_name)))
+
+#define ATTR_PLACE_AT_WITH_ALIGNMENT(section_name, alignment) \
+ATTR_PLACE_AT(section_name) ATTR_ALIGN(alignment)
+
+#define ATTR_PLACE_AT_NONCACHEABLE ATTR_PLACE_AT(".noncacheable.bss")
+#define ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(alignment) \
+       ATTR_PLACE_AT_NONCACHEABLE ATTR_ALIGN(alignment)
+
+#define ATTR_PLACE_AT_NONCACHEABLE_BSS ATTR_PLACE_AT(".noncacheable.bss")
+#define ATTR_PLACE_AT_NONCACHEABLE_BSS_WITH_ALIGNMENT(alignment) \
+       ATTR_PLACE_AT_NONCACHEABLE_BSS ATTR_ALIGN(alignment)
+
+/* initialize variable x with y using PLACE_AT_NONCACHEABLE_INIT(x) = {y}; */
+#define ATTR_PLACE_AT_NONCACHEABLE_INIT ATTR_PLACE_AT(".noncacheable.init")
+#define ATTR_PLACE_AT_NONCACHEABLE_INIT_WITH_ALIGNMENT(alignment) \
+       ATTR_PLACE_AT_NONCACHEABLE_INIT ATTR_ALIGN(alignment)
+
+#define ATTR_RAMFUNC ATTR_PLACE_AT(".fast")
+#define ATTR_RAMFUNC_WITH_ALIGNMENT(alignment) \
+       ATTR_RAMFUNC ATTR_ALIGN(alignment)
+
+#define ATTR_SHARE_MEM ATTR_PLACE_AT(".sh_mem")
+
+#define NOP() __asm volatile("nop")
+#define WFI() __asm volatile("wfi")
+
+#define HPM_ATTR_MACHINE_INTERRUPT __attribute__ ((section(".isr_vector"), 
interrupt("machine"), aligned(4)))
+
+#elif defined(__ICCRISCV__)
+
+
+         /* alway_inline */
+#define ATTR_ALWAYS_INLINE __attribute__((always_inline))
+
+/* weak */
+#define ATTR_WEAK __weak
+
+/* alignment */
+#define ATTR_ALIGN(alignment) __attribute__((aligned(alignment)))
+
+/* place var_declare at section_name, e.x. PLACE_AT(".target_section", var); */
+#define ATTR_PLACE_AT(section_name) __attribute__((section(section_name)))
+
+#define ATTR_PLACE_AT_WITH_ALIGNMENT(section_name, alignment) \
+ATTR_PLACE_AT(section_name) ATTR_ALIGN(alignment)
+
+#define ATTR_PLACE_AT_NONCACHEABLE ATTR_PLACE_AT(".noncacheable.bss")
+#define ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(alignment) \
+       ATTR_PLACE_AT_NONCACHEABLE ATTR_ALIGN(alignment)
+
+#define ATTR_PLACE_AT_NONCACHEABLE_BSS ATTR_PLACE_AT(".noncacheable.bss")
+#define ATTR_PLACE_AT_NONCACHEABLE_BSS_WITH_ALIGNMENT(alignment) \
+       ATTR_PLACE_AT_NONCACHEABLE_BSS ATTR_ALIGN(alignment)
+
+/* initialize variable x with y using PLACE_AT_NONCACHEABLE_INIT(x) = {y}; */
+#define ATTR_PLACE_AT_NONCACHEABLE_INIT ATTR_PLACE_AT(".noncacheable.init")
+#define ATTR_PLACE_AT_NONCACHEABLE_INIT_WITH_ALIGNMENT(alignment) \
+       ATTR_PLACE_AT_NONCACHEABLE_INIT ATTR_ALIGN(alignment)
+
+#define ATTR_RAMFUNC ATTR_PLACE_AT(".fast")
+#define ATTR_RAMFUNC_WITH_ALIGNMENT(alignment) \
+       ATTR_RAMFUNC ATTR_ALIGN(alignment)
+
+#define ATTR_SHARE_MEM ATTR_PLACE_AT(".sh_mem")
+
+#define NOP() __asm volatile("nop")
+#define WFI() __asm volatile("wfi")
+
+#define HPM_ATTR_MACHINE_INTERRUPT __machine __interrupt
+
+#else
+#error Unknown toolchain
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief   Count bits set to 1
+ *
+ * @param value Data to be counted
+ *
+ * @return number of bits set to 1
+ */
+static inline uint32_t count_set_bits(uint32_t value)
+{
+       if (value == 0)
+               return 0;
+       return 1 + count_set_bits(value & (value - 1));
+}
+
+/**
+ * @brief   Count bits set to 1 from least significant bit
+ *
+ * @param value Data to be counted
+ *
+ * @return number of bits set to 1
+ * @return 0xFFFFFFFF if no bit was set to 1
+ */
+static inline uint32_t get_first_set_bit_from_lsb(uint32_t value)
+{
+       uint32_t i = 0;
+       if (!value)
+               return 0xFFFFFFFFUL;
+       while (value && !(value & 0x1)) {
+               value >>= 1;
+               i++;
+       }
+       return i;
+}
+
+/**
+ * @brief   Count bits set to 1 from most significant bit
+ *
+ * @param value Data to be counted
+ *
+ * @return number of bits set to 1
+ * @return 0xFFFFFFFF if no bit was set to 1
+ */
+static inline uint32_t get_first_set_bit_from_msb(uint32_t value)
+{
+       uint32_t i = 31;
+       if (!value)
+               return 0xFFFFFFFFUL;
+       while (value && !(value & 0x80000000)) {
+               value <<= 1;
+               value &= ~1;
+               i--;
+       }
+       return i;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+#endif /* _HPM_COMMON_H */
diff --git a/contrib/loaders/flash/hpmicro/hpm_romapi.h 
b/contrib/loaders/flash/hpmicro/hpm_romapi.h
new file mode 100644
index 0000000000..62dbce1ee7
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/hpm_romapi.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2021-2023 HPMicro
+ */
+
+#ifndef HPM_ROMAPI_H
+#define HPM_ROMAPI_H
+
+/**
+ * @brief ROM APIs
+ * @defgroup romapi_interface ROM APIs
+ * @{
+ */
+
+#include "hpm_common.h"
+#include "hpm_romapi_xpi_def.h"
+#include "hpm_romapi_xpi_soc_def.h"
+#include "hpm_romapi_xpi_nor_def.h"
+
+
+/***********************************************************************************************************************
+ *
+ *
+ *       Definitions
+ *
+ *
+ 
**********************************************************************************************************************/
+
+/**
+ * @brief Bootloader API table
+ */
+typedef struct {
+       /**< Bootloader API table: version */
+       const uint32_t version;
+       /**< Bootloader API table: copyright string address */
+       const char *copyright;
+       /**< Bootloader API table: run_bootloader API */
+       const uint32_t reserved0;
+       /**< Bootloader API table: otp driver interface address */
+       const uint32_t reserved1;
+       /**< Bootloader API table: xpi driver interface address */
+       const xpi_driver_interface_t *xpi_driver_if;
+       /**< Bootloader API table: xpi nor driver interface address */
+       const xpi_nor_driver_interface_t *xpi_nor_driver_if;
+       /**< Bootloader API table: xpi ram driver interface address */
+       const uint32_t reserved2;
+} bootloader_api_table_t;
+
+/**< Bootloader API table Root */
+#define ROM_API_TABLE_ROOT ((const bootloader_api_table_t *)0x2001FF00U)
+
+
+
+#endif /* HPM_ROMAPI_H */
diff --git a/contrib/loaders/flash/hpmicro/hpm_romapi_xpi_def.h 
b/contrib/loaders/flash/hpmicro/hpm_romapi_xpi_def.h
new file mode 100644
index 0000000000..7a3d8150fd
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/hpm_romapi_xpi_def.h
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2021 HPMicro
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef HPM_ROMAPI_XPI_DEF_H
+#define HPM_ROMAPI_XPI_DEF_H
+
+/**
+ * @brief XPI ROM APIs
+ * @defgroup xpi_interface XPI driver APIs
+ * @{
+ */
+
+#include "hpm_common.h"
+
+/**
+ *  @brief XPI_Type definitions for
+ *  @note For compatibility
+ */
+typedef uint32_t XPI_Type;
+
+/**
+ * @brief XPI Read Sample Clock source options
+ */
+typedef enum {
+    xpi_rxclksrc_internal_loopback = 0, /**< Internal loopback */
+    xpi_rxclksrc_dqs_loopback = 1,      /**< Loopback from DQS pad */
+    xpi_rxclksrc_external_dqs = 3,      /**< Read is driven by External DQS 
pad */
+} xpi_rxclksrc_type_t;
+
+
+/**
+ * @brief XPI pad definitions
+ */
+#define XPI_1PAD    (0U)    /**< Single pad */
+#define XPI_2PADS   (1U)    /**< Dual pads */
+#define XPI_4PADS   (2U)    /**< Quad pads */
+#define XPI_8PADS   (3U)    /**< Octal pads */
+
+/**
+ * @brief XPI IO pin group options
+ */
+typedef enum {
+    xpi_io_1st_group,       /**< First/Primary group */
+    xpi_io_2nd_group,       /**< Second/Secondary group */
+} xpi_io_group_t;
+
+/**
+ * @brief XPI Transfer Channel type definitions
+ */
+typedef enum {
+    xpi_xfer_channel_a1,                    /**< The address is based on the 
device connected to Channel A1 */
+    xpi_xfer_channel_a2,                    /**< The address is based on the 
device connected to Channel A2 */
+    xpi_xfer_channel_b1,                    /**< The address is based on the 
device connected to Channel B1 */
+    xpi_xfer_channel_b2,                    /**< The address is based on the 
device connected to Channel B2 */
+    xpi_xfer_channel_auto,                  /**< The channel is auto 
determined */
+} xpi_xfer_channel_t;
+
+/**
+ * @brief XPI Channel definitions
+ */
+typedef enum {
+    xpi_channel_a1,        /**< Port:  Channel A1 */
+    xpi_channel_a2,        /**< Port:  Channel A2 */
+    xpi_channel_b1,        /**< Port:  Channel B1 */
+    xpi_channel_b2,        /**< Port:  Channel B2 */
+} xpi_channel_t;
+
+/**
+ * @brief XPI APB Transfer type
+ */
+typedef enum {
+    xpi_apb_xfer_type_cmd,          /**< APB Command Type: Command only */
+    xpi_apb_xfer_type_config,       /**< APB Command Type: Configuration */
+    xpi_apb_xfer_type_read,         /**< APB Command Type: Read */
+    xpi_apb_xfer_type_write,        /**< APB Command Type: Write */
+} xpi_apb_xfer_type_t;
+
+/**
+ * @brief XPI Xfer Mode
+ */
+typedef enum {
+    xpi_xfer_mode_polling,      /**< Transfer mode: Polling */
+    xpi_xfer_mode_dma,          /**< Transfer mode: DMA */
+    xpi_xfer_mode_interrupt,    /**< Transfer mode: Interrupt */
+} xpi_xfer_mode_t;
+
+/**
+ * @brief XPI Xfer context
+ */
+typedef struct {
+    uint32_t addr;          /**< device address for XPI transfer */
+    uint8_t channel;           /**< channel for XPI transfer */
+    uint8_t cmd_type;       /**< command type for XPI transfer */
+    uint8_t seq_idx;        /**< Sequence index for XPI transfer */
+    uint8_t seq_num;        /**< Sequence number for XPI transfer */
+    uint32_t *buf;          /**< Buffer for XPI transfer */
+    uint32_t xfer_size;     /**< Transfer size in bytes */
+} xpi_xfer_ctx_t;
+
+/**
+ * @brief XPI instruction sequence
+ */
+typedef struct {
+    uint32_t entry[4];
+} xpi_instr_seq_t;
+
+/**
+ * @brief XPI Phase definitions
+ */
+#define XPI_PHASE_STOP            (0x00U)   /**< Phase: Stop */
+#define XPI_PHASE_CMD_SDR         (0x01U)   /**< Phase: Send CMD in SDR mode */
+#define XPI_PHASE_RADDR_SDR       (0x02U)   /**< Phase: Send Row Address in 
SDR Mode */
+#define XPI_PHASE_CADDR_SDR       (0x03U)   /**< Phase: Send Column Address in 
SDR Mode */
+#define XPI_PHASE_MODE4_SDR       (0x06U)   /**< Phase: Send Mode 4 in SDR 
Mode */
+#define XPI_PHASE_MODE8_SDR       (0x07U)   /**< Phase: Send Mode 8 in SDR 
Mode */
+#define XPI_PHASE_WRITE_SDR       (0x08U)   /**< Phase: Write data in SDR Mode 
*/
+#define XPI_PHASE_READ_SDR        (0x09U)   /**< Phase: Read data in SDR Mode 
*/
+#define XPI_PHASE_DUMMY_SDR       (0X0CU)   /**< Phase: Send Dummy in SDR Mode 
*/
+#define XPI_PHASE_DUMMY_RWDS_SDR  (0x0DU)   /**< Phase: Send Dummy RWDS  in 
SDR Mode */
+
+#define XPI_PHASE_CMD_DDR         (0x21U)   /**< Phase: Send CMD in DDR Mode */
+#define XPI_PHASE_RADDR_DDR       (0x22U)   /**< Phase: Send Raw Address in 
DDR Mode */
+#define XPI_PHASE_CADDR_DDR       (0x23U)   /**< Phase: Send Column address in 
DDR Mode */
+#define XPI_PHASE_MODE4_DDR       (0x26U)   /**< Phase: Send Mode 4 in DDR 
Mode */
+#define XPI_PHASE_MODE8_DDR       (0x27U)   /**< Phase: Send Mode 8 in DDR 
Mode */
+#define XPI_PHASE_WRITE_DDR       (0x28U)   /**< Phase: Write data in DDR Mode 
*/
+#define XPI_PHASE_READ_DDR        (0x29U)   /**< Phase: Read data in SDR Mode 
*/
+#define XPI_PHASE_DUMMY_DDR       (0x2CU)   /**< Phase: Send DUMMY in DDR Mode 
*/
+#define XPI_PHASE_DUMMY_RWDS_DDR  (0x2DU)   /**< Phase: Send DUMMY RWDS in DDR 
Mode */
+
+/**
+ * @brief XPI API command error codes
+ */
+enum {
+    status_xpi_apb_jump_on_cs = MAKE_STATUS(status_group_xpi, 1),
+    status_xpi_apb_unknown_inst = MAKE_STATUS(status_group_xpi, 2),
+    status_xpi_apb_dummy_sdr_in_ddr_seq = MAKE_STATUS(status_group_xpi, 3),
+    status_xpi_apb_dummy_ddr_in_sdr_seq = MAKE_STATUS(status_group_xpi, 4),
+    status_xpi_apb_exceed_addr_range = MAKE_STATUS(status_group_xpi, 5),
+    status_xpi_apb_seq_timeout = MAKE_STATUS(status_group_xpi, 6),
+    status_xpi_apb_cross_boundary = MAKE_STATUS(status_group_xpi, 7),
+};
+
+/**
+ * @brief Delay line definitions
+ */
+enum {
+    xpi_dll_half_cycle = 0xFU,
+    xpi_dll_quarter_cycle = 0x7U,
+    xpi_dll_sdr_default_cycle = xpi_dll_half_cycle,
+    xpi_dll_ddr_default_cycle = xpi_dll_quarter_cycle,
+};
+
+/**
+ * @brief XPI configuration structure
+ */
+typedef struct {
+    uint8_t rxclk_src;                      /**< Read sample clock source */
+    uint8_t reserved0[7];                   /**< Reserved */
+    uint8_t tx_watermark_in_dwords;         /**< Tx watermark in double words 
*/
+    uint8_t rx_watermark_in_dwords;         /**< Rx watermark in double words 
*/
+    uint8_t enable_differential_clk;        /**< Enable differential clock */
+    uint8_t reserved1[5];                   /**< Reserved */
+    uint32_t access_flags;                  /**< Access flags */
+} xpi_config_t;
+
+/**
+ * @brief XPI Device Configuration structure
+ */
+typedef struct {
+    uint32_t size_in_kbytes;                /**< Device size in kbytes */
+    uint32_t serial_root_clk_freq;          /**< XPI serial root clock 
frequency */
+
+    uint8_t enable_write_mask;              /**< Enable write mask, typically 
for PSRAM/HyperRAM */
+    uint8_t data_valid_time;                /**< Data valid time, Unit 0.1ns */
+    uint8_t reserved0[2];
+
+    uint8_t cs_hold_time;                   /**< CS hold time, cycles in terms 
of FLASH clock */
+    uint8_t cs_setup_time;                  /**< CS setup time, cycles in 
terms of FLASH clock */
+    uint16_t cs_interval;                   /**< CS interval, cycles in terms 
of FLASH clock */
+
+    uint8_t reserved1;
+    uint8_t column_addr_size;               /**< Column address bits */
+    uint8_t enable_word_address;            /**< Enable word address, for 
HyperFLASH/HyperRAM */
+    uint8_t dly_target;                     /**< Delay target */
+
+    uint8_t ahb_write_seq_idx;              /**< AHB write sequence index */
+    uint8_t ahb_write_seq_num;              /**< AHB write sequence number */
+    uint8_t ahb_read_seq_idx;               /**< AHB read sequence index */
+    uint8_t ahb_read_seq_num;               /**< AHB read sequence number */
+
+    uint8_t ahb_write_wait_interval;        /**< AHB write wait interval, in 
terms of FLASH clock */
+    uint8_t reserved2[3];
+} xpi_device_config_t;
+
+/**
+ * @brief SUB Instruction
+ * @param [in] phase Phase
+ * @param [in] pad  Pad for Phase
+ * @param [in] op   Operand for Phase
+ */
+#define SUB_INSTR(phase, pad, op) ((uint32_t)(((uint16_t)(phase) << 10) | 
((uint16_t)(pad) << 8) | ((uint16_t)(op))))
+/**
+ * @brief Generate a single word INSTRUCTION sequence word
+ * @note  Here intentionally use the MACRO because when the arguments are 
constant value, the compiler
+ *        can generate the const entry word during pre-processing
+ */
+#define XPI_INSTR_SEQ(phase0, pad0, op0, phase1, pad1, op1) (SUB_INSTR(phase0, 
pad0, op0) | (SUB_INSTR(phase1, pad1, op1)<<16))
+
+typedef struct {
+    struct {
+        uint8_t priority;                   /* Offset: 0x00 */
+        uint8_t master_idx;                 /* Offset: 0x01 */
+        uint8_t buf_size_in_dword;          /* Offset: 0x02 */
+        bool enable_prefetch;               /* Offset: 0x03 */
+    } entry[8];
+} xpi_ahb_buffer_cfg_t;
+
+/**
+ * @brief XPI driver interface
+ */
+typedef struct {
+    /**< XPI driver interface: version */
+    uint32_t version;
+    /**< XPI driver interface: get default configuration */
+    hpm_stat_t (*get_default_config)(xpi_config_t *xpi_config);
+    /**< XPI driver interface: get default device configuration */
+    hpm_stat_t (*get_default_device_config)(xpi_device_config_t *dev_config);
+    /**< XPI driver interface: initialize the XPI using xpi_config */
+    hpm_stat_t (*init)(XPI_Type *base, xpi_config_t *xpi_config);
+    /**< XPI driver interface: configure the AHB buffer */
+    hpm_stat_t (*config_ahb_buffer)(XPI_Type *base, xpi_ahb_buffer_cfg_t 
*ahb_buf_cfg);
+    /**< XPI driver interface: configure the device */
+    hpm_stat_t (*config_device)(XPI_Type *base, xpi_device_config_t *dev_cfg, 
xpi_channel_t channel);
+    /**< XPI driver interface: update instruction talbe */
+    hpm_stat_t (*update_instr_table)(XPI_Type *base, const uint32_t 
*inst_base, uint32_t seq_idx, uint32_t num);
+    /**< XPI driver interface: transfer command/data using block interface */
+    hpm_stat_t (*transfer_blocking)(XPI_Type *base, xpi_xfer_ctx_t *xfer);
+    /**< Software reset the XPI controller */
+    void (*software_reset)(XPI_Type *base);
+    /**< XPI driver interface: Check whether IP is idle */
+    bool (*is_idle)(XPI_Type *base);
+    /**< XPI driver interface: update delay line setting */
+    void (*update_dllcr)(XPI_Type *base,
+                         uint32_t serial_root_clk_freq,
+                         uint32_t data_valid_time,
+                         xpi_channel_t channel,
+                         uint32_t dly_target);
+    /**< XPI driver interface: Get absolute address for APB transfer */
+    hpm_stat_t
+    (*get_abs_apb_xfer_addr)(XPI_Type *base, xpi_xfer_channel_t channel, 
uint32_t in_addr, uint32_t *out_addr);
+} xpi_driver_interface_t;
+
+/**
+ * @}
+ */
+
+#endif /* HPM_ROMAPI_XPI_DEF_H */
diff --git a/contrib/loaders/flash/hpmicro/hpm_romapi_xpi_nor_def.h 
b/contrib/loaders/flash/hpmicro/hpm_romapi_xpi_nor_def.h
new file mode 100644
index 0000000000..7ef634574b
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/hpm_romapi_xpi_nor_def.h
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2021 HPMicro
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef HPM_ROMAPI_XPI_NOR_DEF_H
+#define HPM_ROMAPI_XPI_NOR_DEF_H
+
+/**
+ * @brief XPI NOR ROM APIs
+ * @defgroup xpi_nor_interface XPI NOR driver APIs
+ * @ingroup romapi_interfaces
+ * @{
+ */
+
+
+#include "hpm_common.h"
+#include "hpm_romapi_xpi_def.h"
+
+#define XPI_NOR_CFG_TAG 0x524f4E58U /**< ASCII: "XNOR" */
+
+/**
+ * @brief XPI NOR properties
+ */
+enum {
+    xpi_nor_property_total_size,                            /**< Total size in 
bytes */
+    xpi_nor_property_page_size,                             /**< Page size in 
bytes */
+    xpi_nor_property_sector_size,                           /**<sector size in 
bytes */
+    xpi_nor_property_block_size,                            /**< block size in 
bytes */
+    xpi_nor_property_max = xpi_nor_property_block_size,
+};
+
+
+/**
+ * @brief XPI NOR safe frequency option
+ */
+enum {
+    xpi_nor_clk_safe_clk_freq = 1,
+};
+
+/**
+ * @brief XPI NOR miscellaneous options
+ */
+enum {
+    xpi_nor_option_misc_spi_only = 1,           /**< SPI only */
+    xpi_nor_option_misc_internal_loopback = 2,  /**< Internal loopback mode */
+    xpi_nor_option_misc_ext_dqs = 3,            /**< External DQS pin */
+};
+
+/**
+ * @brief XPI NOR connection option
+ */
+enum {
+    xpi_nor_connection_sel_chna_cs0,               /**< Channel A, CS0 */
+    xpi_nor_connection_sel_chnb_cs0,               /**< Channel B, CS0 */
+    xpi_nor_connection_sel_chna_cs0_chnb_cs0,     /**< Channel A + Channel B, 
CS0 */
+    xpi_nor_connection_sel_chna_cs0_cs1,           /**< Channel A, CS0 + CS1 */
+    xpi_nor_connection_sel_chnb_cs0_cs1            /**< Channel B, CS0 + CS1 */
+};
+
+/**
+ * @brief QE bit enable sequence option
+ */
+typedef enum {
+    xpi_nor_quad_en_auto_or_ignore = 0U,                        /**< Auto 
enable or ignore */
+    xpi_nor_quad_en_set_bit6_in_status_reg1 = 1U,               /**< QE bit is 
at bit6 in Status register 1 */
+    xpi_nor_quad_en_set_bit1_in_status_reg2 = 2U,               /**< QE bit is 
at bit1 in Status register 2 register 2 */
+    xpi_nor_quad_en_set_bit7_in_status_reg2 = 3U,               /**< QE bit is 
at bit7 in Status register 2 */
+    xpi_nor_quad_en_set_bi1_in_status_reg2_via_0x31_cmd = 4U,   /**< QE bit is 
in status register 2 and configured by CMD 0x31 */
+} xpi_nor_quad_enable_seq_t;
+
+/**
+ * @brief XPI working mode
+ */
+typedef enum {
+    xpi_working_mode_extend_spi,    /**< XPI works in extended SPI mode, 
including 1-1-1, 1-2-2, 1-4-4, 1-8-8 */
+    xpi_working_mode_xpi,           /**< XPI works in XPI mode, including, 
1-1-1, 2-2-2, 4-4-4, 8-8-8 */
+    xpi_working_mode_hyperbus,      /**< XPI works in HyperBus mode */
+} xpi_working_mode_t;
+
+
+/**
+ * @brief XPI NOR configuration command type
+ */
+typedef enum {
+    xpi_nor_cfg_cmd_type_no_cfg = 0U,   /**< No configuration */
+    xpi_nor_cfg_cmd_type_generic = 1U,  /**< Generic configuration */
+    xpi_nor_cfg_cmd_type_spi2xpi = 2U,  /**< SPI to XPI mode */
+    xpi_nor_cfg_cmd_type_xpi2spi = 3U,  /**< XPI to SPI mode */
+} xpi_nor_cfg_cmd_type_t;
+
+/**
+ * @brief XPI NOR probe options
+ */
+typedef enum {
+    xpi_nor_probe_sfdp_sdr = 0U,    /**< Probe FLASH using SFDP and set FLASH 
to SDR mode */
+    xpi_nor_probe_sfdp_ddr = 1U,    /**< Probe FLASH using SDP and set FLASH 
to DDR mode */
+    xpi_nor_quad_read_0xeb = 2U,    /**< Set FLASH to default Quad I/O read in 
SDR mode */
+    xpi_nor_dual_read_0xbb = 3U,    /**< Set FLASH to default Dual I/O read in 
SDR mode */
+    xpi_nor_hyperbus_1v8 = 4U,      /**< Probe FLASH using HyperBus in 1.8V 
voltage */
+    xpi_nor_hyperbus_3v0 = 5U,      /**< Probe FLASH using HyperBus in 3.0V 
voltage */
+    xpi_nor_octabus_ddr = 6U,       /**< Probe FLASH using Macronix OctaBus 
and configure FLASH to OPI DDR mode */
+    xpi_nor_octabus_sdr = 7U,       /**< Probe FLASH using Macronix OctaBus 
and configure FLASH to OPI SDR mode */
+    xpi_nor_xccela_ddr = 8U,        /**< Probe FLASH using Xccela Protocol and 
configure FLASH to OPI DDR mode */
+    xpi_nor_xccela_sdr = 9U,        /**< Probe FLASH using Xccela Protocol and 
configure FLASH to SDR mode */
+    xpi_nor_ecoxip_ddr = 10U,       /**< Probe FLASH using EcoXiP Protocol and 
configure FLASH to OPI DDR mode */
+    xpi_nor_ecoxip_sdr = 11U,       /**< Probe FLASH using EcoXiP Protocol and 
configure FLASH to SDR mode */
+} xpi_nor_probe_t;
+
+/**
+ * @brief Standard XPI NOR seuqnce index definitions
+ */
+typedef enum {
+    xpi_std_nor_seq_idx_read = 0U,                     /**< 0 - Read */
+    xpi_std_nor_seq_idx_page_program = 1U,             /**< 1 - Page Program */
+    xpi_std_nor_seq_idx_read_status = 2U,              /**< 2 - Read Status */
+    xpi_std_nor_seq_idx_read_status_xpi = 3U,          /**< 3 - Read Status in 
xSPI mode */
+    xpi_std_nor_seq_idx_write_enable = 4U,             /**< 4 - Write Enable */
+    xpi_std_nor_seq_idx_write_enable_xpi = 5U,         /**< 5 - Write Enable 
in xSPI mode */
+    xpi_std_nor_seq_idx_erase_sector = 6U,             /**< 6 - Erase sector */
+    xpi_std_nor_seq_idx_erase_block = 7U,              /**< 7 - Erase block */
+    xpi_std_nor_seq_idx_erase_chip = 8U,               /**< 8 - Erase full 
chip */
+    xpi_std_nor_seq_idx_max = 9,                       /**< 9 */
+} xpi_std_nor_instr_idx_t;
+
+/**
+ * @brief XPI NOR option tag
+ */
+#define XPI_NOR_CFG_OPTION_TAG (0xfcf90U)
+
+/**
+ * @brief XPI NOR configuration option
+ *        The ROM SW can detect the FLASH configuration based on the following 
structure specified by the end-user
+ */
+typedef struct {
+    union {
+        struct {
+            uint32_t words: 4;       /**< Option words, exclude the header 
itself */
+            uint32_t reserved: 8;    /**< Reserved for future use */
+            uint32_t tag: 20;        /**< Must be 0xfcf90 */
+        };
+        uint32_t U;
+    } header;
+    union {
+        struct {
+            uint32_t freq_opt: 4;                /**< 1 - 30MHz, others, SoC 
specific setting */
+            uint32_t misc: 4;                    /**< Not used for now */
+            uint32_t dummy_cycles: 8;            /**< 0 - Auto detected/ use 
predefined value, others - specified by end-user */
+            uint32_t quad_enable_seq: 4;         /**< See the 
xpi_nor_quad_enable_seq_t definitions for more details */
+            uint32_t cmd_pads_after_init: 4;     /**< See the xpi_data_pad_t 
definitions for more details */
+            uint32_t cmd_pads_after_por: 4;      /**< See the xpi_data_pad_t 
definitions for more details */
+            uint32_t probe_type: 4;              /**< See the xpi_nor_probe_t 
definitions for more details */
+        };
+        uint32_t U;
+    } option0;
+    union {
+        struct {
+            uint32_t drive_strength: 8;      /**< IO drive strength, 0 - 
pre-defined, Others - specified by end-user */
+            uint32_t connection_sel: 4;      /**< Device connection selection: 
0 - PORTA, 1 - PORTB, 2 - Parallel mode */
+            uint32_t pin_group_sel: 4;       /**< Pin group selection, 0 - 1st 
group, 1 - 2nd group, by default, the pin group is 1st group */
+            uint32_t io_voltage: 4;          /**< SoC pad voltage, 0 - 3.0V, 
1-1.8V */
+            uint32_t reserved: 12;           /**< Reserved for future use */
+        };
+        uint32_t U;
+    } option1;
+    union {
+        struct {
+            uint32_t flash_size_option:8;               /**< FLASH size option 
*/
+            uint32_t flash_sector_size_option:4;        /**< FLASH sector size 
option */
+            uint32_t flash_sector_erase_cmd_option:4;   /**< Sector Erase 
command option */
+            uint32_t reserved:20;
+        };
+        uint32_t U;
+    } option2;
+} xpi_nor_config_option_t;
+
+/**
+ * @brief Sector size options
+ */
+enum {
+    serial_nor_sector_size_4kb,     /**< Sector size: 4KB */
+    serial_nor_sector_size_32kb,    /**< Sector size: 32KB */
+    serial_nor_sector_size_64kb,    /**< Sector size: 64KB */
+    serial_nor_sector_size_256kb,   /**< Sector size: 256KB */
+};
+
+/**
+ * @brief Sector erase command options
+ */
+enum  {
+    serial_nor_erase_type_4kb,      /**< Sector erase command: 4KB Erase */
+    serial_nor_erase_type_32kb,     /**< Sector erase command: 32KB Erase */
+    serial_nor_erase_type_64kb,     /**< Sector erase command: 64KB Erase */
+    serial_nor_erase_type_256kb,    /**< Sector erase command: 256KB Erase */
+};
+
+/**
+ * @brief FLASH size options
+ */
+enum {
+    flash_size_4mb,     /**< FLASH size: 4MB */
+    flash_size_8mb,     /**< FLASH size: 8MB */
+    flash_size_16mb,    /**< FLASH size: 16MB */
+};
+
+/**
+ * @brief Device Mode configuration structure
+ */
+typedef struct {
+    uint8_t cfg_cmd_type;       /**< Configuration command type */
+    uint8_t param_size;         /**< Size for parameter */
+} device_mode_cfg_t;
+
+/**
+ * @brief Device mode parameter structure
+ */
+typedef struct {
+    uint32_t instr_seq[4];  /**< Command Instruction sequence*/
+    uint32_t param;         /**< Parameter */
+} device_mode_param_t;
+
+/**
+ * @brief XPI NOR device information structure
+ */
+typedef struct {
+    uint32_t size_in_kbytes;                /**< Device Size in Kilobytes, 
offset 0x00 */
+    uint16_t page_size;                     /**< Page size, offset 0x04 */
+    uint16_t sector_size_kbytes;            /**< Sector size in kilobytes, 
offset 0x06 */
+    uint16_t block_size_kbytes;             /**< Block size in kilobytes, 
offset 0x08 */
+    uint8_t busy_offset;                    /**< Busy offset, offset 0x0a */
+    uint8_t busy_polarity;                  /**< Busy polarity, offset 0x0b */
+    uint8_t data_pads;                      /**< Device Size in Kilobytes, 
offset 0x0c */
+    uint8_t en_ddr_mode;                    /**< Enable DDR mode, offset 0x0d 
*/
+    uint8_t clk_freq_for_device_cfg;        /**< Clk frequency for device 
configuration offset 0x0e */
+    uint8_t working_mode_por;               /**< Working mode after POR reset 
offset 0x0f */
+    uint8_t working_mode;                   /**< The device working mode, 
offset 0x10 */
+    uint8_t en_diff_clk;                    /**< Enable Differential clock, 
offset 0x11 */
+    uint8_t data_valid_time;                /**< Data valid time, in 0.1ns, 
offset 0x12 */
+    uint8_t en_half_clk_for_non_read_cmd;   /**< Enable half clock for 
non-read command, offset 0x13 */
+    uint8_t clk_freq_for_non_read_cmd;      /**< Enable safe clock for 
non-read command, offset 0x14 */
+    uint8_t dll_dly_target;                 /**< XPI DLL Delay Target, offset 
0x15 */
+    uint8_t io_voltage;                     /**< IO voltage, offset 0x16 */
+    uint8_t reserved0;                      /**< Reserved for future use, 
offset 0x17 */
+    uint8_t cs_hold_time;                   /**< CS hold time, 0 - default 
value, others - user specified value, offset 0x18 */
+    uint8_t cs_setup_time;                  /**< CS setup time, 0 - default 
value, others - user specified value, offset 0x19 */
+    uint8_t cs_interval;                    /**< CS interval, intervals 
between to CS active, offset 0x1a */
+    uint8_t en_dev_mode_cfg;                /**< Enable device mode 
configuration, offset 0x1b */
+    uint32_t flash_state_ctx;               /**< Flash state context, offset 
0x1c  */
+    device_mode_cfg_t mode_cfg_list[2];     /**< Mode configuration sequences, 
offset 0x20 */
+    uint32_t mode_cfg_param[2];             /**< Mode configuration 
parameters, offset 0x24 */
+    uint32_t reserved1;                     /**< Reserved for future use, 
offset 0x2C */
+    struct {
+        uint32_t entry[4];
+    } cfg_instr_seq[2];                      /**< Mode Configuration 
Instruction sequence, offset 0x30 */
+} xpi_device_info_t;
+
+/**
+ * @brief XPI NOR configuration structure
+ */
+typedef struct {
+    uint32_t tag;                         /**< Must be "XNOR", offset 0x000 */
+    uint32_t reserved0;                   /**< Reserved for future use, offset 
0x004 */
+    uint8_t rxclk_src;                    /**< RXCLKSRC value, offset 0x008 */
+    uint8_t clk_freq;                     /**< Clock frequency, offset 0x009 */
+    uint8_t drive_strength;               /**< Drive strength, offset 0x0a */
+    uint8_t column_addr_size;             /**< Column address size, offset 
0x0b */
+    uint8_t rxclk_src_for_init;           /**< RXCLKSRC during FLASH 
initialization, offset 0x0c */
+    uint8_t config_in_progress;           /**< Indicate whether device 
configuration is in progress, offset: 0x0d */
+    uint8_t reserved[2];                  /**< Reserved for future use, offset 
0x00f */
+    struct {
+        uint8_t enable;                   /**<  Port enable flag, 0 - not 
enabled, 1 - enabled */
+        uint8_t group;                    /**< 0 - 1st IO group, 1 - 2nd IO 
group */
+        uint8_t reserved[2];
+    } chn_info[4];                        /**< Device connection information */
+    xpi_device_info_t device_info;       /**< Device info, offset 0x20 */
+    xpi_instr_seq_t instr_set[xpi_std_nor_seq_idx_max];/**< Standard 
instruction sequence table, offset 0x70 */
+} xpi_nor_config_t;
+
+/**
+ * @brief FLASH runtime context structure
+ */
+typedef union {
+    struct {
+        uint32_t wait_time: 7;              /**< Wait time */
+        uint32_t wait_time_unit: 1;         /**< 0 - 10us, 1 - 1ms */
+        uint32_t reset_gpio: 8;             /**<Reset GPIO */
+        uint32_t restore_sequence: 4;       /**<Restore sequence */
+        uint32_t exit_no_cmd_sequence: 4;   /**< Exit no-cmd sequence */
+        uint32_t current_mode: 4;           /**< Current FLASH mode */
+        uint32_t por_mode: 4;               /**< FLASH mode upon Power-on 
Reset */
+    };
+    uint32_t U;
+} flash_run_context_t;
+
+/**
+ * @brief XPI NOR API error codes
+ */
+enum {
+    status_xpi_nor_sfdp_not_found = MAKE_STATUS(status_group_xpi_nor, 0),      
                 /**<  SFDP table was not found */
+    status_xpi_nor_ddr_read_dummy_cycle_probe_failed = 
MAKE_STATUS(status_group_xpi_nor, 1),    /**<  Probing Dummy cyles for DDR read 
failed */
+    status_xpi_nor_flash_not_found = MAKE_STATUS(status_group_xpi_nor, 2),     
                 /**< FLASH was not detected */
+};
+
+/**
+ * @brief XPI NOR driver interface
+ */
+typedef struct {
+    /**< XPI NOR driver interface: API version */
+    uint32_t version;
+    /**< XPI NOR driver interface: Get FLASH configuration */
+    hpm_stat_t (*get_config)(XPI_Type *base, xpi_nor_config_t *nor_cfg, 
xpi_nor_config_option_t *cfg_option);
+    /**< XPI NOR driver interface: initialize FLASH */
+    hpm_stat_t (*init)(XPI_Type *base, xpi_nor_config_t *nor_config);
+    /**< XPI NOR driver interface: Enable write access to FLASH */
+    hpm_stat_t
+    (*enable_write)(XPI_Type *base, xpi_xfer_channel_t channel, const 
xpi_nor_config_t *nor_config, uint32_t addr);
+    /**< XPI NOR driver interface: Get FLASH status register */
+    hpm_stat_t (*get_status)(XPI_Type *base,
+                             xpi_xfer_channel_t channel,
+                             const xpi_nor_config_t *nor_config,
+                             uint32_t addr,
+                             uint16_t *out_status);
+    /**< XPI NOR driver interface: Wait when FLASH is still busy */
+    hpm_stat_t
+    (*wait_busy)(XPI_Type *base, xpi_xfer_channel_t channel, const 
xpi_nor_config_t *nor_config, uint32_t addr);
+    /**< XPI NOR driver interface: erase a specified FLASH region */
+    hpm_stat_t (*erase)(XPI_Type *base,
+                        xpi_xfer_channel_t channel,
+                        const xpi_nor_config_t *nor_config,
+                        uint32_t start,
+                        uint32_t length);
+    /**< XPI NOR driver interface: Erase the whole FLASH */
+    hpm_stat_t (*erase_chip)(XPI_Type *base, xpi_xfer_channel_t channel, const 
xpi_nor_config_t *nor_config);
+    /**< XPI NOR driver interface: Erase specified FLASH sector */
+    hpm_stat_t
+    (*erase_sector)(XPI_Type *base, xpi_xfer_channel_t channel, const 
xpi_nor_config_t *nor_config, uint32_t addr);
+    /**< XPI NOR driver interface: Erase specified FLASH block */
+    hpm_stat_t
+    (*erase_block)(XPI_Type *base, xpi_xfer_channel_t channel, const 
xpi_nor_config_t *nor_config, uint32_t addr);
+    /**< XPI NOR driver interface: Program data to specified FLASH address */
+    hpm_stat_t (*program)(XPI_Type *base,
+                          xpi_xfer_channel_t channel,
+                          const xpi_nor_config_t *nor_config,
+                          const uint32_t *src,
+                          uint32_t dst_addr,
+                          uint32_t length);
+    /**< XPI NOR driver interface: read data from specified FLASH address */
+    hpm_stat_t (*read)(XPI_Type *base,
+                       xpi_xfer_channel_t channel,
+                       const xpi_nor_config_t *nor_config,
+                       uint32_t *dst,
+                       uint32_t start,
+                       uint32_t length);
+    /**< XPI NOR driver interface: program FLASH page using nonblocking 
interface */
+    hpm_stat_t (*page_program_nonblocking)(XPI_Type *base,
+                                           xpi_xfer_channel_t channel,
+                                           const xpi_nor_config_t *nor_config,
+                                           const uint32_t *src,
+                                           uint32_t dst_addr,
+                                           uint32_t length);
+    /**< XPI NOR driver interface: erase FLASH sector using nonblocking 
interface */
+    hpm_stat_t (*erase_sector_nonblocking)(XPI_Type *base,
+                                           xpi_xfer_channel_t channel,
+                                           const xpi_nor_config_t *nor_config,
+                                           uint32_t addr);
+    /**< XPI NOR driver interface: erase FLASH block using nonblocking 
interface */
+    hpm_stat_t (*erase_block_nonblocking)(XPI_Type *base,
+                                          xpi_xfer_channel_t channel,
+                                          const xpi_nor_config_t *nor_config,
+                                          uint32_t addr);
+    /**< XPI NOR driver interface: erase the whole FLASh using nonblocking 
interface */
+    hpm_stat_t (*erase_chip_nonblocking)(XPI_Type *base,
+                                         xpi_xfer_channel_t channel,
+                                         const xpi_nor_config_t *nor_config);
+
+    uint32_t reserved0[3];
+
+    /**< XPI NOR driver interface: automatically configuration flash based on 
the cfg_option setting */
+    hpm_stat_t (*auto_config)(XPI_Type *base, xpi_nor_config_t *nor_cfg, 
xpi_nor_config_option_t *cfg_option);
+
+    /**< XPI NOR driver interface: Get FLASH properties */
+    hpm_stat_t (*get_property)(XPI_Type *base, xpi_nor_config_t *nor_cfg, 
uint32_t property_id, uint32_t *value);
+
+    uint32_t reserved1;
+
+    /**< Post Erase Sector Nonblocking operation: For Hybrid mode only */
+    hpm_stat_t (*post_erase_sector_nonblocking)(XPI_Type *base, 
xpi_xfer_channel_t chn, xpi_nor_config_t *nor_cfg, uint32_t addr);
+
+     /**< Post Erase Block Nonblocking operation: For Hybrid mode only */
+    hpm_stat_t (*post_erase_block_nonblocking)(XPI_Type *base, 
xpi_xfer_channel_t chn, xpi_nor_config_t *nor_cfg, uint32_t addr);
+
+    /**< Post Erase Chip Nonblocking operation: For Hybrid mode only */
+    hpm_stat_t (*post_erase_chip_nonblocking)(XPI_Type *base, 
xpi_xfer_channel_t chn, xpi_nor_config_t *nor_cfg);
+
+     /**< Post Page Program Nonblocking operation: For Hybrid mode only */
+    hpm_stat_t (*post_page_program_nonblocking)(XPI_Type *base, 
xpi_xfer_channel_t chn, xpi_nor_config_t *nor_config,
+                                           const uint32_t *src, uint32_t 
dst_addr, uint32_t length);
+    /**< Turn on the power for Internal FLASH */
+    void (*sip_flash_power_on)(XPI_Type *base);
+
+    /**< Turn off the power for Internal FLASH */
+    void (*sip_flash_power_off)(XPI_Type *base);
+
+    /**< Enable Hybrid mode */
+    void (*enable_hybrid_xpi)(XPI_Type *base);
+
+    /**< Disable Hybrid mode */
+    void (*disable_hybrid_xpi)(XPI_Type *base);
+
+} xpi_nor_driver_interface_t;
+
+/**
+ * @}
+ */
+
+#endif /* HPM_ROMAPI_XPI_NOR_DEF_H */
\ No newline at end of file
diff --git a/contrib/loaders/flash/hpmicro/hpm_romapi_xpi_soc_def.h 
b/contrib/loaders/flash/hpmicro/hpm_romapi_xpi_soc_def.h
new file mode 100644
index 0000000000..690ab42229
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/hpm_romapi_xpi_soc_def.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2021 HPMicro
+ */
+
+#ifndef HPM_ROMAPI_XPI_SOC_DEF_H
+#define HPM_ROMAPI_XPI_SOC_DEF_H
+
+#include "hpm_common.h"
+#include "hpm_romapi_xpi_def.h"
+
+/***********************************************************************************************************************
+ * Definitions
+ 
**********************************************************************************************************************/
+
+#define XPI_CLK_OUT_FREQ_OPTION_30MHz (1U)
+#define XPI_CLK_OUT_FREQ_OPTION_50MHz (2U)
+#define XPI_CLK_OUT_FREQ_OPTION_66MHz (3U)
+#define XPI_CLK_OUT_FREQ_OPTION_80MHz (4U)
+#define XPI_CLK_OUT_FREQ_OPTION_104MHz (5U)
+#define XPI_CLK_OUT_FREQ_OPTION_120MHz (6U)
+#define XPI_CLK_OUT_FREQ_OPTION_133MHz (7U)
+#define XPI_CLK_OUT_FREQ_OPTION_166MHz (8U)
+#define XPI_CLK_OUT_FREQ_OPTION_200MHz (9U)
+
+
+typedef struct {
+       uint8_t data_pads;
+       xpi_channel_t channel;
+       xpi_io_group_t io_group;
+       uint8_t drive_strength;
+       bool enable_dqs;
+       bool enable_diff_clk;
+} xpi_io_config_t;
+
+typedef enum {
+       xpi_freq_type_typical,
+       xpi_freq_type_mhz,
+} clk_freq_type_t;
+
+typedef enum {
+       xpi_clk_src_auto,
+       xpi_clk_src_osc,
+       xpi_clk_src_pll0clk0,
+       xpi_clk_src_pll1clk0,
+       xpi_clk_src_pll1clk1,
+       xpi_clk_src_pll2clk0,
+       xpi_clk_src_pll2clk1,
+       xpi_clk_src_pll3clk0,
+       xpi_clk_src_pll4clk0,
+} xpi_clk_src_t;
+
+
+typedef union {
+       struct {
+               uint8_t freq;
+               bool enable_ddr;
+               xpi_clk_src_t clk_src;
+               clk_freq_type_t freq_type;
+       };
+       uint32_t freq_opt;
+} xpi_clk_config_t;
+
+typedef enum {
+       xpi_clock_bus,
+       xpi_clock_serial_root,
+       xpi_clock_serial,
+} xpi_clock_t;
+
+#endif /* HPM_ROMAPI_XPI_SOC_DEF_H */
diff --git a/contrib/loaders/flash/hpmicro/hpm_xpi_flash.elf 
b/contrib/loaders/flash/hpmicro/hpm_xpi_flash.elf
new file mode 100755
index 0000000000..777db69dfa
Binary files /dev/null and b/contrib/loaders/flash/hpmicro/hpm_xpi_flash.elf 
differ
diff --git a/contrib/loaders/flash/hpmicro/hpm_xpi_flash.h 
b/contrib/loaders/flash/hpmicro/hpm_xpi_flash.h
new file mode 100644
index 0000000000..55f160b390
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/hpm_xpi_flash.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2021 hpmicro
+ */
+
+#ifndef HPM_XPI_FLASH_H
+#define HPM_XPI_FLASH_H
+
+#define FLASH_INIT     (0)
+#define FLASH_ERASE   (0x6)
+#define FLASH_PROGRAM (0xc)
+#define FLASH_READ (0x12)
+#define FLASH_GET_INFO (0x18)
+#define FLASH_ERASE_CHIP (0x1e)
+
+uint8_t flash_algo[] = {
+#include "hpm_xpi_flash.inc"
+};
+
+#endif
diff --git a/contrib/loaders/flash/hpmicro/hpm_xpi_flash.inc 
b/contrib/loaders/flash/hpmicro/hpm_xpi_flash.inc
new file mode 100644
index 0000000000..75cd228b11
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/hpm_xpi_flash.inc
@@ -0,0 +1,72 @@
+/* Autogenerated with ../../../../src/helper/bin2char.sh */
+0xef,0x00,0x20,0x05,0x02,0x90,0xef,0x00,0x00,0x12,0x02,0x90,0xef,0x00,0x80,0x1f,
+0x02,0x90,0xef,0x00,0xa0,0x22,0x02,0x90,0xef,0x00,0xe0,0x25,0x02,0x90,0xef,0x00,
+0x40,0x27,0x02,0x90,0xef,0x00,0x80,0x28,0x02,0x90,0x9c,0x41,0x05,0x47,0xbd,0x8b,
+0x63,0x7b,0xf7,0x00,0x9c,0x45,0x05,0x67,0x13,0x07,0x07,0xf0,0xf9,0x8f,0x13,0x07,
+0x00,0x10,0x63,0x83,0xe7,0x00,0x82,0x80,0x23,0x20,0x05,0x06,0x23,0x22,0x05,0x06,
+0x82,0x80,0x39,0x71,0x22,0xdc,0x13,0x04,0x00,0x2b,0x83,0x47,0x44,0x00,0x06,0xde,
+0x18,0xc0,0xd1,0xef,0x26,0xda,0xba,0x84,0x13,0x07,0x84,0x00,0x4e,0xd6,0x52,0xd4,
+0xb2,0x89,0x2e,0x8a,0x13,0x06,0x00,0x10,0x81,0x45,0x3a,0x85,0x4a,0xd8,0x56,0xd2,
+0x36,0x89,0xb7,0x0a,0x02,0x20,0x02,0xcc,0x02,0xce,0x0d,0x2e,0x83,0xa6,0x4a,0xf1,
+0x93,0x57,0x79,0x00,0x89,0x8b,0xf4,0x46,0xaa,0x85,0x52,0xc6,0x4e,0xc8,0x4a,0xca,
+0x23,0x24,0xf4,0x10,0x70,0x00,0x26,0x85,0x93,0x8a,0x0a,0xf0,0x82,0x96,0x29,0xed,
+0x03,0xa7,0x4a,0x01,0xb7,0x07,0x01,0x56,0x93,0x87,0xf7,0x2f,0x14,0x43,0x63,0xf5,
+0xd7,0x00,0x3c,0x5b,0x08,0x40,0x82,0x97,0xb2,0x47,0x05,0x47,0xbd,0x8b,0x63,0x7b,
+0xf7,0x00,0xd2,0x47,0x05,0x67,0x13,0x07,0x07,0xf0,0xf9,0x8f,0x13,0x07,0x00,0x10,
+0x63,0x8d,0xe7,0x02,0x83,0x47,0x44,0x00,0x23,0x0e,0x04,0x02,0x81,0xe7,0x85,0x47,
+0x23,0x02,0xf4,0x00,0xd2,0x54,0x42,0x59,0xb2,0x59,0x22,0x5a,0x92,0x5a,0xf2,0x50,
+0x62,0x54,0x01,0x45,0x21,0x61,0x82,0x80,0xf2,0x50,0x62,0x54,0xd2,0x54,0x42,0x59,
+0xb2,0x59,0x22,0x5a,0x92,0x5a,0x21,0x61,0x82,0x80,0x1c,0x40,0x23,0xa0,0x07,0x06,
+0x23,0xa2,0x07,0x06,0xc1,0xb7,0xb7,0x07,0x02,0x20,0x83,0xa6,0x47,0xf1,0x01,0x11,
+0xb7,0x07,0x01,0x56,0x98,0x42,0x22,0xcc,0x4a,0xc8,0x06,0xce,0x26,0xca,0x4e,0xc6,
+0x56,0xc2,0x93,0x87,0xf7,0x2f,0x2e,0x89,0x32,0x84,0x63,0xf4,0xe7,0x00,0x33,0x89,
+0xa5,0x00,0x93,0x09,0x00,0x2b,0x83,0xd4,0x09,0x03,0xaa,0x04,0x63,0x69,0x94,0x06,
+0xb3,0x7a,0x99,0x02,0x52,0xc4,0x33,0x8a,0x54,0x41,0x63,0x80,0x44,0x03,0x9c,0x4e,
+0x83,0xa5,0x89,0x10,0x03,0xa5,0x09,0x00,0x52,0x87,0xca,0x86,0x13,0x86,0x89,0x00,
+0x82,0x97,0x05,0xed,0x05,0x8c,0x56,0x94,0x52,0x99,0x63,0xf1,0x84,0x04,0x37,0x0a,
+0x02,0x20,0x93,0x0a,0x80,0x2b,0x13,0x0a,0x0a,0xf0,0x21,0xa0,0x26,0x99,0x63,0xf1,
+0x84,0x06,0x83,0x27,0x4a,0x01,0x83,0xa5,0x89,0x10,0x03,0xa5,0x09,0x00,0xdc,0x53,
+0xca,0x86,0x56,0x86,0x82,0x97,0x05,0x8c,0x75,0xd1,0x22,0x4a,0xf2,0x40,0x62,0x44,
+0xd2,0x44,0x42,0x49,0xb2,0x49,0x92,0x4a,0x05,0x61,0x82,0x80,0x22,0x4a,0x01,0x45,
+0x75,0xd4,0x93,0x0a,0x80,0x2b,0xb7,0x07,0x02,0x20,0x93,0x87,0x07,0xf0,0xdc,0x4b,
+0x22,0x87,0x62,0x44,0x83,0xa5,0x89,0x10,0x03,0xa5,0x09,0x00,0xf2,0x40,0xd2,0x44,
+0xb2,0x49,0x9c,0x4f,0xca,0x86,0x56,0x86,0x42,0x49,0x92,0x4a,0x05,0x61,0x82,0x87,
+0x22,0x4a,0xd1,0xbf,0xb7,0x07,0x02,0x20,0x83,0xa8,0x47,0xf1,0xb7,0x07,0x01,0x56,
+0x13,0x88,0xf7,0x2f,0x03,0xa3,0x08,0x00,0x2e,0x87,0xb6,0x87,0x63,0x74,0x68,0x00,
+0x33,0x87,0xa5,0x00,0x13,0x08,0x00,0x2b,0x83,0xa8,0x88,0x02,0x83,0x25,0x88,0x10,
+0x03,0x25,0x08,0x00,0xb2,0x86,0x13,0x06,0x88,0x00,0x82,0x88,0xb7,0x07,0x02,0x20,
+0x03,0xa3,0x47,0xf1,0xb7,0x07,0x01,0x56,0x13,0x88,0xf7,0x2f,0x03,0x2e,0x03,0x00,
+0xae,0x88,0x32,0x87,0xb6,0x87,0x63,0x74,0xc8,0x01,0x33,0x07,0xa6,0x00,0x13,0x08,
+0x00,0x2b,0x03,0x23,0xc3,0x02,0x83,0x25,0x88,0x10,0x03,0x25,0x08,0x00,0xc6,0x86,
+0x13,0x06,0x88,0x00,0x02,0x83,0x81,0xcd,0x93,0x07,0x00,0x2b,0x98,0x57,0x83,0xd7,
+0xe7,0x02,0x01,0x45,0x2a,0x07,0xaa,0x07,0x98,0xc1,0xdc,0xc1,0x82,0x80,0x09,0x45,
+0x82,0x80,0xb7,0x07,0x02,0x20,0x93,0x87,0x07,0xf0,0xdc,0x4b,0x13,0x06,0x00,0x2b,
+0x83,0x25,0x86,0x10,0x08,0x42,0xdc,0x4f,0x21,0x06,0x82,0x87,0x82,0x80,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x43,0x2a,0x87,
+0x63,0x73,0xc3,0x02,0x93,0x77,0xf7,0x00,0xbd,0xef,0xad,0xe5,0x93,0x76,0x06,0xff,
+0x3d,0x8a,0xba,0x96,0x0c,0xc3,0x4c,0xc3,0x0c,0xc7,0x4c,0xc7,0x41,0x07,0xe3,0x6b,
+0xd7,0xfe,0x11,0xe2,0x82,0x80,0xb3,0x06,0xc3,0x40,0x8a,0x06,0x97,0x02,0x00,0x00,
+0x96,0x96,0x67,0x80,0xa6,0x00,0x23,0x07,0xb7,0x00,0xa3,0x06,0xb7,0x00,0x23,0x06,
+0xb7,0x00,0xa3,0x05,0xb7,0x00,0x23,0x05,0xb7,0x00,0xa3,0x04,0xb7,0x00,0x23,0x04,
+0xb7,0x00,0xa3,0x03,0xb7,0x00,0x23,0x03,0xb7,0x00,0xa3,0x02,0xb7,0x00,0x23,0x02,
+0xb7,0x00,0xa3,0x01,0xb7,0x00,0x23,0x01,0xb7,0x00,0xa3,0x00,0xb7,0x00,0x23,0x00,
+0xb7,0x00,0x82,0x80,0x93,0xf5,0xf5,0x0f,0x93,0x96,0x85,0x00,0xd5,0x8d,0x93,0x96,
+0x05,0x01,0xd5,0x8d,0x61,0xb7,0x93,0x96,0x27,0x00,0x97,0x02,0x00,0x00,0x96,0x96,
+0x86,0x82,0xe7,0x80,0x86,0xfa,0x96,0x80,0xc1,0x17,0x1d,0x8f,0x3e,0x96,0xe3,0x74,
+0xc3,0xf8,0xa5,0xb7,
diff --git a/contrib/loaders/flash/hpmicro/hpm_xpi_flash.lst 
b/contrib/loaders/flash/hpmicro/hpm_xpi_flash.lst
new file mode 100644
index 0000000000..9e8cb3c506
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/hpm_xpi_flash.lst
@@ -0,0 +1,351 @@
+
+hpm_xpi_flash.elf:     file format elf32-littleriscv
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         00000464  00000000  00000000  00001000  2**2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .riscv.attributes 0000005c  00000000  00000000  00001464  2**0
+                  CONTENTS, READONLY
+  2 .comment      0000001b  00000000  00000000  000014c0  2**0
+                  CONTENTS, READONLY
+
+Disassembly of section .text:
+
+00000000 <_init>:
+   0:  052000ef                jal     52 <flash_init>
+   4:  9002                    ebreak
+   6:  120000ef                jal     126 <flash_erase>
+   a:  9002                    ebreak
+   c:  1f8000ef                jal     204 <flash_program>
+  10:  9002                    ebreak
+  12:  22a000ef                jal     23c <flash_read>
+  16:  9002                    ebreak
+  18:  25e000ef                jal     276 <flash_get_info>
+  1c:  9002                    ebreak
+  1e:  274000ef                jal     292 <flash_erase_chip>
+  22:  9002                    ebreak
+  24:  288000ef                jal     2ac <flash_deinit>
+  28:  9002                    ebreak
+
+0000002a <refresh_device_size>:
+  2a:  419c                    lw      a5,0(a1)
+  2c:  4705                    li      a4,1
+  2e:  8bbd                    andi    a5,a5,15
+  30:  00f77b63                bgeu    a4,a5,46 <refresh_device_size+0x1c>
+  34:  459c                    lw      a5,8(a1)
+  36:  6705                    lui     a4,0x1
+  38:  f0070713                addi    a4,a4,-256 # f00 <__bss_end__+0xa9c>
+  3c:  8ff9                    and     a5,a5,a4
+  3e:  10000713                li      a4,256
+  42:  00e78363                beq     a5,a4,48 <refresh_device_size+0x1e>
+  46:  8082                    ret
+  48:  06052023                sw      zero,96(a0)
+  4c:  06052223                sw      zero,100(a0)
+  50:  8082                    ret
+
+00000052 <flash_init>:
+  52:  7139                    addi    sp,sp,-64
+  54:  dc22                    sw      s0,56(sp)
+  56:  2b000413                li      s0,688
+  5a:  00444783                lbu     a5,4(s0)
+  5e:  de06                    sw      ra,60(sp)
+  60:  c018                    sw      a4,0(s0)
+  62:  efd1                    bnez    a5,fe <flash_init+0xac>
+  64:  da26                    sw      s1,52(sp)
+  66:  84ba                    mv      s1,a4
+  68:  00840713                addi    a4,s0,8
+  6c:  d64e                    sw      s3,44(sp)
+  6e:  d452                    sw      s4,40(sp)
+  70:  89b2                    mv      s3,a2
+  72:  8a2e                    mv      s4,a1
+  74:  10000613                li      a2,256
+  78:  4581                    li      a1,0
+  7a:  853a                    mv      a0,a4
+  7c:  d84a                    sw      s2,48(sp)
+  7e:  d256                    sw      s5,36(sp)
+  80:  8936                    mv      s2,a3
+  82:  20020ab7                lui     s5,0x20020
+  86:  cc02                    sw      zero,24(sp)
+  88:  ce02                    sw      zero,28(sp)
+  8a:  2e0d                    jal     3bc <memset>
+  8c:  f14aa683                lw      a3,-236(s5) # 2001ff14 
<__bss_end__+0x2001fab0>
+  90:  00795793                srli    a5,s2,0x7
+  94:  8b89                    andi    a5,a5,2
+  96:  46f4                    lw      a3,76(a3)
+  98:  85aa                    mv      a1,a0
+  9a:  c652                    sw      s4,12(sp)
+  9c:  c84e                    sw      s3,16(sp)
+  9e:  ca4a                    sw      s2,20(sp)
+  a0:  10f42423                sw      a5,264(s0)
+  a4:  0070                    addi    a2,sp,12
+  a6:  8526                    mv      a0,s1
+  a8:  f00a8a93                addi    s5,s5,-256
+  ac:  9682                    jalr    a3
+  ae:  ed29                    bnez    a0,108 <flash_init+0xb6>
+  b0:  014aa703                lw      a4,20(s5)
+  b4:  560107b7                lui     a5,0x56010
+  b8:  2ff78793                addi    a5,a5,767 # 560102ff 
<__bss_end__+0x5600fe9b>
+  bc:  4314                    lw      a3,0(a4)
+  be:  00d7f563                bgeu    a5,a3,c8 <flash_init+0x76>
+  c2:  5b3c                    lw      a5,112(a4)
+  c4:  4008                    lw      a0,0(s0)
+  c6:  9782                    jalr    a5
+  c8:  47b2                    lw      a5,12(sp)
+  ca:  4705                    li      a4,1
+  cc:  8bbd                    andi    a5,a5,15
+  ce:  00f77b63                bgeu    a4,a5,e4 <flash_init+0x92>
+  d2:  47d2                    lw      a5,20(sp)
+  d4:  6705                    lui     a4,0x1
+  d6:  f0070713                addi    a4,a4,-256 # f00 <__bss_end__+0xa9c>
+  da:  8ff9                    and     a5,a5,a4
+  dc:  10000713                li      a4,256
+  e0:  02e78d63                beq     a5,a4,11a <flash_init+0xc8>
+  e4:  00444783                lbu     a5,4(s0)
+  e8:  02040e23                sb      zero,60(s0)
+  ec:  e781                    bnez    a5,f4 <flash_init+0xa2>
+  ee:  4785                    li      a5,1
+  f0:  00f40223                sb      a5,4(s0)
+  f4:  54d2                    lw      s1,52(sp)
+  f6:  5942                    lw      s2,48(sp)
+  f8:  59b2                    lw      s3,44(sp)
+  fa:  5a22                    lw      s4,40(sp)
+  fc:  5a92                    lw      s5,36(sp)
+  fe:  50f2                    lw      ra,60(sp)
+ 100:  5462                    lw      s0,56(sp)
+ 102:  4501                    li      a0,0
+ 104:  6121                    addi    sp,sp,64
+ 106:  8082                    ret
+ 108:  50f2                    lw      ra,60(sp)
+ 10a:  5462                    lw      s0,56(sp)
+ 10c:  54d2                    lw      s1,52(sp)
+ 10e:  5942                    lw      s2,48(sp)
+ 110:  59b2                    lw      s3,44(sp)
+ 112:  5a22                    lw      s4,40(sp)
+ 114:  5a92                    lw      s5,36(sp)
+ 116:  6121                    addi    sp,sp,64
+ 118:  8082                    ret
+ 11a:  401c                    lw      a5,0(s0)
+ 11c:  0607a023                sw      zero,96(a5)
+ 120:  0607a223                sw      zero,100(a5)
+ 124:  b7c1                    j       e4 <flash_init+0x92>
+
+00000126 <flash_erase>:
+ 126:  200207b7                lui     a5,0x20020
+ 12a:  f147a683                lw      a3,-236(a5) # 2001ff14 
<__bss_end__+0x2001fab0>
+ 12e:  1101                    addi    sp,sp,-32
+ 130:  560107b7                lui     a5,0x56010
+ 134:  4298                    lw      a4,0(a3)
+ 136:  cc22                    sw      s0,24(sp)
+ 138:  c84a                    sw      s2,16(sp)
+ 13a:  ce06                    sw      ra,28(sp)
+ 13c:  ca26                    sw      s1,20(sp)
+ 13e:  c64e                    sw      s3,12(sp)
+ 140:  c256                    sw      s5,4(sp)
+ 142:  2ff78793                addi    a5,a5,767 # 560102ff 
<__bss_end__+0x5600fe9b>
+ 146:  892e                    mv      s2,a1
+ 148:  8432                    mv      s0,a2
+ 14a:  00e7f463                bgeu    a5,a4,152 <flash_erase+0x2c>
+ 14e:  00a58933                add     s2,a1,a0
+ 152:  2b000993                li      s3,688
+ 156:  0309d483                lhu     s1,48(s3)
+ 15a:  04aa                    slli    s1,s1,0xa
+ 15c:  06946963                bltu    s0,s1,1ce <flash_erase+0xa8>
+ 160:  02997ab3                remu    s5,s2,s1
+ 164:  c452                    sw      s4,8(sp)
+ 166:  41548a33                sub     s4,s1,s5
+ 16a:  03448063                beq     s1,s4,18a <flash_erase+0x64>
+ 16e:  4e9c                    lw      a5,24(a3)
+ 170:  1089a583                lw      a1,264(s3)
+ 174:  0009a503                lw      a0,0(s3)
+ 178:  8752                    mv      a4,s4
+ 17a:  86ca                    mv      a3,s2
+ 17c:  00898613                addi    a2,s3,8
+ 180:  9782                    jalr    a5
+ 182:  ed05                    bnez    a0,1ba <flash_erase+0x94>
+ 184:  8c05                    sub     s0,s0,s1
+ 186:  9456                    add     s0,s0,s5
+ 188:  9952                    add     s2,s2,s4
+ 18a:  0484f163                bgeu    s1,s0,1cc <flash_erase+0xa6>
+ 18e:  20020a37                lui     s4,0x20020
+ 192:  2b800a93                li      s5,696
+ 196:  f00a0a13                addi    s4,s4,-256 # 2001ff00 
<__bss_end__+0x2001fa9c>
+ 19a:  a021                    j       1a2 <flash_erase+0x7c>
+ 19c:  9926                    add     s2,s2,s1
+ 19e:  0684f163                bgeu    s1,s0,200 <flash_erase+0xda>
+ 1a2:  014a2783                lw      a5,20(s4)
+ 1a6:  1089a583                lw      a1,264(s3)
+ 1aa:  0009a503                lw      a0,0(s3)
+ 1ae:  53dc                    lw      a5,36(a5)
+ 1b0:  86ca                    mv      a3,s2
+ 1b2:  8656                    mv      a2,s5
+ 1b4:  9782                    jalr    a5
+ 1b6:  8c05                    sub     s0,s0,s1
+ 1b8:  d175                    beqz    a0,19c <flash_erase+0x76>
+ 1ba:  4a22                    lw      s4,8(sp)
+ 1bc:  40f2                    lw      ra,28(sp)
+ 1be:  4462                    lw      s0,24(sp)
+ 1c0:  44d2                    lw      s1,20(sp)
+ 1c2:  4942                    lw      s2,16(sp)
+ 1c4:  49b2                    lw      s3,12(sp)
+ 1c6:  4a92                    lw      s5,4(sp)
+ 1c8:  6105                    addi    sp,sp,32
+ 1ca:  8082                    ret
+ 1cc:  4a22                    lw      s4,8(sp)
+ 1ce:  4501                    li      a0,0
+ 1d0:  d475                    beqz    s0,1bc <flash_erase+0x96>
+ 1d2:  2b800a93                li      s5,696
+ 1d6:  200207b7                lui     a5,0x20020
+ 1da:  f0078793                addi    a5,a5,-256 # 2001ff00 
<__bss_end__+0x2001fa9c>
+ 1de:  4bdc                    lw      a5,20(a5)
+ 1e0:  8722                    mv      a4,s0
+ 1e2:  4462                    lw      s0,24(sp)
+ 1e4:  1089a583                lw      a1,264(s3)
+ 1e8:  0009a503                lw      a0,0(s3)
+ 1ec:  40f2                    lw      ra,28(sp)
+ 1ee:  44d2                    lw      s1,20(sp)
+ 1f0:  49b2                    lw      s3,12(sp)
+ 1f2:  4f9c                    lw      a5,24(a5)
+ 1f4:  86ca                    mv      a3,s2
+ 1f6:  8656                    mv      a2,s5
+ 1f8:  4942                    lw      s2,16(sp)
+ 1fa:  4a92                    lw      s5,4(sp)
+ 1fc:  6105                    addi    sp,sp,32
+ 1fe:  8782                    jr      a5
+ 200:  4a22                    lw      s4,8(sp)
+ 202:  bfd1                    j       1d6 <flash_erase+0xb0>
+
+00000204 <flash_program>:
+ 204:  200207b7                lui     a5,0x20020
+ 208:  f147a883                lw      a7,-236(a5) # 2001ff14 
<__bss_end__+0x2001fab0>
+ 20c:  560107b7                lui     a5,0x56010
+ 210:  2ff78813                addi    a6,a5,767 # 560102ff 
<__bss_end__+0x5600fe9b>
+ 214:  0008a303                lw      t1,0(a7)
+ 218:  872e                    mv      a4,a1
+ 21a:  87b6                    mv      a5,a3
+ 21c:  00687463                bgeu    a6,t1,224 <flash_program+0x20>
+ 220:  00a58733                add     a4,a1,a0
+ 224:  2b000813                li      a6,688
+ 228:  0288a883                lw      a7,40(a7)
+ 22c:  10882583                lw      a1,264(a6)
+ 230:  00082503                lw      a0,0(a6)
+ 234:  86b2                    mv      a3,a2
+ 236:  00880613                addi    a2,a6,8
+ 23a:  8882                    jr      a7
+
+0000023c <flash_read>:
+ 23c:  200207b7                lui     a5,0x20020
+ 240:  f147a303                lw      t1,-236(a5) # 2001ff14 
<__bss_end__+0x2001fab0>
+ 244:  560107b7                lui     a5,0x56010
+ 248:  2ff78813                addi    a6,a5,767 # 560102ff 
<__bss_end__+0x5600fe9b>
+ 24c:  00032e03                lw      t3,0(t1)
+ 250:  88ae                    mv      a7,a1
+ 252:  8732                    mv      a4,a2
+ 254:  87b6                    mv      a5,a3
+ 256:  01c87463                bgeu    a6,t3,25e <flash_read+0x22>
+ 25a:  00a60733                add     a4,a2,a0
+ 25e:  2b000813                li      a6,688
+ 262:  02c32303                lw      t1,44(t1)
+ 266:  10882583                lw      a1,264(a6)
+ 26a:  00082503                lw      a0,0(a6)
+ 26e:  86c6                    mv      a3,a7
+ 270:  00880613                addi    a2,a6,8
+ 274:  8302                    jr      t1
+
+00000276 <flash_get_info>:
+ 276:  cd81                    beqz    a1,28e <flash_get_info+0x18>
+ 278:  2b000793                li      a5,688
+ 27c:  5798                    lw      a4,40(a5)
+ 27e:  02e7d783                lhu     a5,46(a5)
+ 282:  4501                    li      a0,0
+ 284:  072a                    slli    a4,a4,0xa
+ 286:  07aa                    slli    a5,a5,0xa
+ 288:  c198                    sw      a4,0(a1)
+ 28a:  c1dc                    sw      a5,4(a1)
+ 28c:  8082                    ret
+ 28e:  4509                    li      a0,2
+ 290:  8082                    ret
+
+00000292 <flash_erase_chip>:
+ 292:  200207b7                lui     a5,0x20020
+ 296:  f0078793                addi    a5,a5,-256 # 2001ff00 
<__bss_end__+0x2001fa9c>
+ 29a:  4bdc                    lw      a5,20(a5)
+ 29c:  2b000613                li      a2,688
+ 2a0:  10862583                lw      a1,264(a2)
+ 2a4:  4208                    lw      a0,0(a2)
+ 2a6:  4fdc                    lw      a5,28(a5)
+ 2a8:  0621                    addi    a2,a2,8
+ 2aa:  8782                    jr      a5
+
+000002ac <flash_deinit>:
+ 2ac:  8082                    ret
+       ...
+
+000002b0 <xpi_base>:
+ 2b0:  0000 0000                                   ....
+
+000002b4 <xpi_inited>:
+ 2b4:  0000 0000                                   ....
+
+000002b8 <nor_config>:
+       ...
+
+000003b8 <channel>:
+ 3b8:  0000 0000                                   ....
+
+000003bc <memset>:
+ 3bc:  433d                    li      t1,15
+ 3be:  872a                    mv      a4,a0
+ 3c0:  02c37363                bgeu    t1,a2,3e6 <memset+0x2a>
+ 3c4:  00f77793                andi    a5,a4,15
+ 3c8:  efbd                    bnez    a5,446 <memset+0x8a>
+ 3ca:  e5ad                    bnez    a1,434 <memset+0x78>
+ 3cc:  ff067693                andi    a3,a2,-16
+ 3d0:  8a3d                    andi    a2,a2,15
+ 3d2:  96ba                    add     a3,a3,a4
+ 3d4:  c30c                    sw      a1,0(a4)
+ 3d6:  c34c                    sw      a1,4(a4)
+ 3d8:  c70c                    sw      a1,8(a4)
+ 3da:  c74c                    sw      a1,12(a4)
+ 3dc:  0741                    addi    a4,a4,16
+ 3de:  fed76be3                bltu    a4,a3,3d4 <memset+0x18>
+ 3e2:  e211                    bnez    a2,3e6 <memset+0x2a>
+ 3e4:  8082                    ret
+ 3e6:  40c306b3                sub     a3,t1,a2
+ 3ea:  068a                    slli    a3,a3,0x2
+ 3ec:  00000297                auipc   t0,0x0
+ 3f0:  9696                    add     a3,a3,t0
+ 3f2:  00a68067                jr      10(a3)
+ 3f6:  00b70723                sb      a1,14(a4)
+ 3fa:  00b706a3                sb      a1,13(a4)
+ 3fe:  00b70623                sb      a1,12(a4)
+ 402:  00b705a3                sb      a1,11(a4)
+ 406:  00b70523                sb      a1,10(a4)
+ 40a:  00b704a3                sb      a1,9(a4)
+ 40e:  00b70423                sb      a1,8(a4)
+ 412:  00b703a3                sb      a1,7(a4)
+ 416:  00b70323                sb      a1,6(a4)
+ 41a:  00b702a3                sb      a1,5(a4)
+ 41e:  00b70223                sb      a1,4(a4)
+ 422:  00b701a3                sb      a1,3(a4)
+ 426:  00b70123                sb      a1,2(a4)
+ 42a:  00b700a3                sb      a1,1(a4)
+ 42e:  00b70023                sb      a1,0(a4)
+ 432:  8082                    ret
+ 434:  0ff5f593                zext.b  a1,a1
+ 438:  00859693                slli    a3,a1,0x8
+ 43c:  8dd5                    or      a1,a1,a3
+ 43e:  01059693                slli    a3,a1,0x10
+ 442:  8dd5                    or      a1,a1,a3
+ 444:  b761                    j       3cc <memset+0x10>
+ 446:  00279693                slli    a3,a5,0x2
+ 44a:  00000297                auipc   t0,0x0
+ 44e:  9696                    add     a3,a3,t0
+ 450:  8286                    mv      t0,ra
+ 452:  fa8680e7                jalr    -88(a3)
+ 456:  8096                    mv      ra,t0
+ 458:  17c1                    addi    a5,a5,-16
+ 45a:  8f1d                    sub     a4,a4,a5
+ 45c:  963e                    add     a2,a2,a5
+ 45e:  f8c374e3                bgeu    t1,a2,3e6 <memset+0x2a>
+ 462:  b7a5                    j       3ca <memset+0xe>
diff --git a/contrib/loaders/flash/hpmicro/hpm_xpi_flash.map 
b/contrib/loaders/flash/hpmicro/hpm_xpi_flash.map
new file mode 100644
index 0000000000..d603e7af09
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/hpm_xpi_flash.map
@@ -0,0 +1,110 @@
+Archive member included to satisfy reference by file (symbol)
+
+/Volumes/Data/toolchains/riscv32-unknown-elf-multilib-2024.12.16-macos-intel/bin/../lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/lib/libc.a(libc_a-memset.o)
+                              openocd_flash_algo.o (memset)
+
+Discarded input sections
+
+ .text          0x00000000        0x0 func_table.o
+ .data          0x00000000        0x0 func_table.o
+ .bss           0x00000000        0x0 func_table.o
+ .text          0x00000000        0x0 openocd_flash_algo.o
+ .data          0x00000000        0x0 openocd_flash_algo.o
+ .bss           0x00000000        0x0 openocd_flash_algo.o
+ .data          0x00000000        0x0 
/Volumes/Data/toolchains/riscv32-unknown-elf-multilib-2024.12.16-macos-intel/bin/../lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/lib/libc.a(libc_a-memset.o)
+ .bss           0x00000000        0x0 
/Volumes/Data/toolchains/riscv32-unknown-elf-multilib-2024.12.16-macos-intel/bin/../lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/lib/libc.a(libc_a-memset.o)
+
+Memory Configuration
+
+Name             Origin             Length             Attributes
+*default*        0x00000000         0xffffffff
+
+Linker script and memory map
+
+LOAD func_table.o
+LOAD openocd_flash_algo.o
+LOAD 
/Volumes/Data/toolchains/riscv32-unknown-elf-multilib-2024.12.16-macos-intel/bin/../lib/gcc/riscv32-unknown-elf/14.2.0/libgcc.a
+START GROUP
+LOAD 
/Volumes/Data/toolchains/riscv32-unknown-elf-multilib-2024.12.16-macos-intel/bin/../lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/lib/libc.a
+LOAD 
/Volumes/Data/toolchains/riscv32-unknown-elf-multilib-2024.12.16-macos-intel/bin/../lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/lib/libgloss.a
+END GROUP
+LOAD 
/Volumes/Data/toolchains/riscv32-unknown-elf-multilib-2024.12.16-macos-intel/bin/../lib/gcc/riscv32-unknown-elf/14.2.0/libgcc.a
+
+.text           0x00000000      0x464
+ *(.func_table)
+ .func_table    0x00000000       0x2a func_table.o
+                0x00000000                _init
+ *(.flash_algo.text*)
+ .flash_algo.text
+                0x0000002a      0x284 openocd_flash_algo.o
+                0x0000002a                refresh_device_size
+                0x00000052                flash_init
+                0x00000126                flash_erase
+                0x00000204                flash_program
+                0x0000023c                flash_read
+                0x00000276                flash_get_info
+                0x00000292                flash_erase_chip
+                0x000002ac                flash_deinit
+ *(.rodata)
+ *(.rodata*)
+ *(.flash_algo.data*)
+ *fill*         0x000002ae        0x2 
+ .flash_algo.data
+                0x000002b0      0x10c openocd_flash_algo.o
+                0x000002b0                xpi_base
+                0x000002b4                xpi_inited
+                0x000002b8                nor_config
+                0x000003b8                channel
+ *(.text)
+ .text          0x000003bc       0xa8 
/Volumes/Data/toolchains/riscv32-unknown-elf-multilib-2024.12.16-macos-intel/bin/../lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/lib/libc.a(libc_a-memset.o)
+                0x000003bc                memset
+ *(.text*)
+                0x00000464                        __etext = .
+
+.discard        0x00000464        0x0
+                0x00000464                        __noncacheable_start__ = .
+                0x00000464                        __noncacheable_bss_start__ = 
.
+                0x00000464                        __bss_start__ = .
+                0x00000464                        __bss_end__ = .
+                0x00000464                        __noncacheable_bss_end__ = .
+                0x00000464                        _end = .
+                0x00000464                        __noncacheable_init_start__ 
= .
+                0x00000464                        __data_start__ = .
+                0x00000464                        __data_end__ = .
+                0x00000464                        __noncacheable_init_end__ = .
+                0x00000464                        __noncacheable_end__ = .
+                0x00000464                        __heap_start__ = .
+                0x00000464                        __heap_end__ = .
+                0x00000464                        __ramfunc_start__ = .
+                0x00000464                        __ramfunc_end__ = .
+                0x00000464                        __noncacheable_bss_start__ = 
.
+                0x00000464                        __noncacheable_bss_end__ = .
+                0x00000464                        __noncacheable_init_start__ 
= .
+                0x00000464                        __noncacheable_init_end__ = .
+                0x00000464                        __tdata_start__ = .
+                0x00000464                        __tdata_end__ = .
+                0x00000464                        __tbss_start__ = .
+                0x00000464                        __tbss_end__ = .
+                0x00000464                        __data_load_addr__ = .
+                0x00000464                        __fast_load_addr__ = .
+                0x00000464                        __tdata_load_addr__ = .
+                0x00000464                        
__noncacheable_init_load_addr__ = .
+OUTPUT(hpm_xpi_flash.elf elf32-littleriscv)
+
+.riscv.attributes
+                0x00000000       0x5c
+ .riscv.attributes
+                0x00000000       0x5a func_table.o
+ .riscv.attributes
+                0x0000005a       0x5c openocd_flash_algo.o
+ .riscv.attributes
+                0x000000b6       0x5a 
/Volumes/Data/toolchains/riscv32-unknown-elf-multilib-2024.12.16-macos-intel/bin/../lib/gcc/riscv32-unknown-elf/14.2.0/../../../../riscv32-unknown-elf/lib/libc.a(libc_a-memset.o)
+
+.comment        0x00000000       0x1b
+ .comment       0x00000000       0x1b openocd_flash_algo.o
+                                 0x1c (size before relaxing)
+
+.note.GNU-stack
+                0x00000000        0x0
+ .note.GNU-stack
+                0x00000000        0x0 openocd_flash_algo.o
diff --git a/contrib/loaders/flash/hpmicro/linker.ld 
b/contrib/loaders/flash/hpmicro/linker.ld
new file mode 100644
index 0000000000..6621f6c3d2
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/linker.ld
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2021 HPMicro
+ */
+ENTRY(_init)
+
+SECTIONS
+{
+       .text : {
+               *(.func_table)
+               KEEP(*(.flash_algo.text*))
+               KEEP(*(.rodata))
+               KEEP(*(.rodata*))
+               KEEP(*(.flash_algo.data*))
+               *(.text)
+               *(.text*)
+               __etext = .;
+       }
+       .discard : {
+               __noncacheable_start__ = .;
+               __noncacheable_bss_start__ = .;
+               __bss_start__ = .;
+               __bss_end__ = .;
+               __noncacheable_bss_end__ = .;
+               _end = .;
+               __noncacheable_init_start__ = .;
+               __data_start__ = .;
+               __data_end__ = .;
+               __noncacheable_init_end__ = .;
+               __noncacheable_end__ = .;
+               __heap_start__ = .;
+               __heap_end__ = .;
+               __ramfunc_start__ = .;
+               __ramfunc_end__ = .;
+               __noncacheable_bss_start__ = .;
+               __noncacheable_bss_end__ = .;
+               __noncacheable_init_start__ = .;
+               __noncacheable_init_end__ = .;
+               __tdata_start__ = .;
+               __tdata_end__ = .;
+               __tbss_start__ = .;
+               __tbss_end__ = .;
+               __data_load_addr__ = .;
+               __fast_load_addr__ = .;
+               __tdata_load_addr__ = .;
+               __noncacheable_init_load_addr__ = .;
+       }
+}
diff --git a/contrib/loaders/flash/hpmicro/openocd_flash_algo.c 
b/contrib/loaders/flash/hpmicro/openocd_flash_algo.c
new file mode 100644
index 0000000000..b238a997fc
--- /dev/null
+++ b/contrib/loaders/flash/hpmicro/openocd_flash_algo.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2024 HPMicro
+ */
+
+#include "hpm_romapi.h"
+
+#define XPI_USE_PORT_B_MASK (0x100)
+#define XPI_USE_PORT_A_MASK (0)
+#define XPI_USE_PORT_SHIFT (0x8)
+
+#define ROMAPI_SUPPORTS_HYBRIDXPI() 
(ROM_API_TABLE_ROOT->xpi_nor_driver_if->version >= 0x56010300)
+
+typedef struct {
+       uint32_t total_sz_in_bytes;
+       uint32_t sector_sz_in_bytes;
+} hpm_flash_info_t;
+
+__attribute__ ((section(".flash_algo.data"))) xpi_nor_config_t nor_config;
+__attribute__ ((section(".flash_algo.data"))) bool xpi_inited = false;
+__attribute__ ((section(".flash_algo.data"))) uint32_t channel = 
xpi_channel_a1;
+__attribute__ ((section(".flash_algo.data"))) XPI_Type *xpi_base;
+
+
+__attribute__ ((section(".flash_algo.text"))) void 
refresh_device_size(XPI_Type *base, xpi_nor_config_option_t *option)
+{
+       volatile uint32_t *dev_size = (volatile uint32_t *)((uint32_t)base + 
0x60);
+       bool enable_channelb = false;
+       if (option->header.words > 1)
+               enable_channelb = option->option1.connection_sel == 
xpi_nor_connection_sel_chnb_cs0;
+       if (enable_channelb) {
+               dev_size[0] = 0;
+               dev_size[1] = 0;
+       }
+}
+
+__attribute__ ((section(".flash_algo.text"))) uint32_t flash_init(uint32_t 
flash_base, uint32_t header,
+               uint32_t opt0, uint32_t opt1, uint32_t xpi_base_addr)
+{
+       uint32_t i = 0;
+       xpi_nor_config_option_t cfg_option;
+       hpm_stat_t stat = status_success;
+
+       xpi_base = (XPI_Type *)xpi_base_addr;
+       if (xpi_inited)
+               return stat;
+
+       for (i = 0; i < sizeof(cfg_option); i++)
+               *((uint8_t *)&cfg_option + i) = 0;
+       for (i = 0; i < sizeof(nor_config); i++)
+               *((uint8_t *)&nor_config + i) = 0;
+
+       cfg_option.header.U = header;
+       cfg_option.option0.U = opt0;
+       cfg_option.option1.U = opt1;
+
+       if (opt1 & XPI_USE_PORT_B_MASK)
+               channel = xpi_channel_b1;
+       else
+               channel = xpi_channel_a1;
+
+       stat = ROM_API_TABLE_ROOT->xpi_nor_driver_if->auto_config(xpi_base, 
&nor_config, &cfg_option);
+       if (stat)
+               return stat;
+
+       if (ROMAPI_SUPPORTS_HYBRIDXPI())
+               
ROM_API_TABLE_ROOT->xpi_nor_driver_if->enable_hybrid_xpi(xpi_base);
+
+       refresh_device_size(xpi_base, &cfg_option);
+
+
+       nor_config.device_info.clk_freq_for_non_read_cmd = 0;
+       if (!xpi_inited)
+               xpi_inited = true;
+       return stat;
+}
+
+__attribute__ ((section(".flash_algo.text"))) uint32_t flash_erase(uint32_t 
flash_base, uint32_t address, uint32_t size)
+{
+       hpm_stat_t stat = status_success;
+       uint32_t left, start, block_size, align;
+
+       left = size;
+       start = address;
+       if (ROMAPI_SUPPORTS_HYBRIDXPI())
+               start += flash_base;
+       block_size = nor_config.device_info.block_size_kbytes * 1024;
+       if (left >= block_size) {
+               align = block_size - (start % block_size);
+               if (align != block_size) {
+                       stat = 
ROM_API_TABLE_ROOT->xpi_nor_driver_if->erase(xpi_base, channel, &nor_config, 
start, align);
+                       if (stat != status_success)
+                               return stat;
+                       left -= align;
+                       start += align;
+               }
+               while (left > block_size) {
+                       stat = 
ROM_API_TABLE_ROOT->xpi_nor_driver_if->erase_block(xpi_base, channel, 
&nor_config, start);
+                       if (stat != status_success)
+                               break;
+                       left -= block_size;
+                       start += block_size;
+               }
+       }
+       if (stat == status_success && left)
+               stat = ROM_API_TABLE_ROOT->xpi_nor_driver_if->erase(xpi_base, 
channel, &nor_config, start, left);
+       return stat;
+}
+
+__attribute__ ((section(".flash_algo.text"))) uint32_t flash_program(uint32_t 
flash_base, uint32_t address,
+               uint32_t *buf, uint32_t size)
+{
+       hpm_stat_t stat;
+
+       if (ROMAPI_SUPPORTS_HYBRIDXPI())
+               address += flash_base;
+       stat = ROM_API_TABLE_ROOT->xpi_nor_driver_if->program(xpi_base, 
channel, &nor_config, buf, address, size);
+       return stat;
+}
+
+__attribute__ ((section(".flash_algo.text"))) uint32_t flash_read(uint32_t 
flash_base, uint32_t *buf,
+               uint32_t address, uint32_t size)
+{
+       hpm_stat_t stat;
+
+       if (ROMAPI_SUPPORTS_HYBRIDXPI())
+               address += flash_base;
+       stat = ROM_API_TABLE_ROOT->xpi_nor_driver_if->read(xpi_base, channel, 
&nor_config, buf, address, size);
+       return stat;
+}
+
+__attribute__ ((section(".flash_algo.text"))) uint32_t flash_get_info(uint32_t 
flash_base, hpm_flash_info_t *flash_info)
+{
+       if (!flash_info)
+               return status_invalid_argument;
+
+       flash_info->total_sz_in_bytes = nor_config.device_info.size_in_kbytes 
<< 10;
+       flash_info->sector_sz_in_bytes = 
nor_config.device_info.sector_size_kbytes << 10;
+       return status_success;
+}
+
+__attribute__ ((section(".flash_algo.text"))) uint32_t 
flash_erase_chip(uint32_t flash_base)
+{
+       return ROM_API_TABLE_ROOT->xpi_nor_driver_if->erase_chip(xpi_base, 
channel, &nor_config);
+}
+
+__attribute__ ((section(".flash_algo.text"))) void flash_deinit(void)
+{
+       return;
+}

-- 


Reply via email to