aboutsummaryrefslogtreecommitdiff
path: root/contrib/loaders/flash
diff options
context:
space:
mode:
authorWealian Liao <WHLIAO@nuvoton.com>2020-11-26 10:25:09 +0800
committerOleksij Rempel <linux@rempel-privat.de>2021-09-02 06:42:54 +0000
commit385eedfc6f0b82c5d6715c740ee40bdce983ef04 (patch)
tree8989d8f92b88dcddfcd76a9da5c56477a2b9c581 /contrib/loaders/flash
parenta098816a6557e5882bf088ab12a06b94934f30ce (diff)
downloadriscv-openocd-385eedfc6f0b82c5d6715c740ee40bdce983ef04.zip
riscv-openocd-385eedfc6f0b82c5d6715c740ee40bdce983ef04.tar.gz
riscv-openocd-385eedfc6f0b82c5d6715c740ee40bdce983ef04.tar.bz2
flash/nor: add support for Nuvoton NPCX series flash
Added NPCX flash driver to support the Nuvoton NPCX series microcontrollers. Add config file for NPCX series. Change-Id: Ia10b019a3521f59ad1e10ccdc56827ba30c3eac8 Signed-off-by: Wealian Liao <WHLIAO@nuvoton.com> Signed-off-by: Mulin Chao <mlchao@nuvoton.com> Reviewed-on: https://review.openocd.org/c/openocd/+/5950 Tested-by: jenkins Reviewed-by: Oleksij Rempel <linux@rempel-privat.de>
Diffstat (limited to 'contrib/loaders/flash')
-rw-r--r--contrib/loaders/flash/npcx/Makefile65
-rw-r--r--contrib/loaders/flash/npcx/npcx_algo.inc60
-rw-r--r--contrib/loaders/flash/npcx/npcx_flash.c342
-rw-r--r--contrib/loaders/flash/npcx/npcx_flash.h179
-rw-r--r--contrib/loaders/flash/npcx/npcx_flash.lds58
-rw-r--r--contrib/loaders/flash/npcx/npcx_flash_config.h31
6 files changed, 735 insertions, 0 deletions
diff --git a/contrib/loaders/flash/npcx/Makefile b/contrib/loaders/flash/npcx/Makefile
new file mode 100644
index 0000000..293bd02
--- /dev/null
+++ b/contrib/loaders/flash/npcx/Makefile
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+BIN2C = ../../../../src/helper/bin2char.sh
+
+# Toolchain used in makefile
+CROSS_COMPILE ?= arm-none-eabi-
+CC = $(CROSS_COMPILE)gcc
+CPLUS = $(CROSS_COMPILE)g++
+CPP = $(CROSS_COMPILE)cpp
+LD = $(CROSS_COMPILE)gcc
+AS = $(CROSS_COMPILE)as
+OBJCOPY = $(CROSS_COMPILE)objcopy
+OBJDUMP = $(CROSS_COMPILE)objdump
+OBJSIZE = $(CROSS_COMPILE)size
+
+TARGET = npcx_algo
+OBJS := npcx_flash.o
+FLAGS = -mthumb -Os -ffunction-sections -fdata-sections -g -gdwarf-3 --specs=nano.specs
+FLAGS += -gstrict-dwarf -Wall -fno-strict-aliasing --asm
+
+CFLAGS = -c -I. -mcpu=cortex-m4 -fpack-struct
+
+PRE_LD_FILE = npcx_flash.lds
+LD_FILE = npcx_flash_generated.lds
+LDFLAGS = -Wl,-Map,lfw.map -Wl,-T$(LD_FILE) -nostartfiles
+
+all: $(TARGET).inc
+
+# Implicit rules
+%.o: %.c
+ -@ echo CC $@ from $<
+ @$(CC) $< $(FLAGS) $(CFLAGS) -o $@
+
+ $(LD_FILE): $(PRE_LD_FILE)
+ -@ echo Generate $@ from $<
+ -@$(CPP) $(PRE_LD_FILE) | grep -v '^#' >>$(LD_FILE)
+
+$(TARGET).elf: $(OBJS) $(LD_FILE)
+ -@ echo LD $@ from $<
+ @$(LD) -o $@ $< $(FLAGS) $(LDFLAGS)
+
+%.bin: %.elf
+ -@ echo OBJCOPY $@ from $<
+ -@ $(OBJCOPY) $< -O binary $@
+ -@ $(OBJSIZE) $< --format=berkeley
+
+%.inc: %.bin
+ @echo 'Building target: $@'
+ @echo 'Invoking Bin2Char Script'
+ $(BIN2C) < $< > $@
+ rm $< $*.elf
+ @echo 'Finished building target: $@'
+ @echo ' '
+
+clean:
+ @echo 'Cleaning Targets and Build Artifacts'
+ rm -rf *.inc *.bin *.elf *.map
+ rm -rf *.o *.d
+ rm -rf $(LD_FILE)
+ @echo 'Finished clean'
+ @echo ' '
+
+.PRECIOUS: %.bin
+
+.PHONY: all clean
diff --git a/contrib/loaders/flash/npcx/npcx_algo.inc b/contrib/loaders/flash/npcx/npcx_algo.inc
new file mode 100644
index 0000000..4312fdb
--- /dev/null
+++ b/contrib/loaders/flash/npcx/npcx_algo.inc
@@ -0,0 +1,60 @@
+/* Autogenerated with ../../../../src/helper/bin2char.sh */
+0x08,0xb5,0xdf,0xf8,0x08,0xd0,0x00,0xf0,0x2f,0xf9,0x00,0x00,0x48,0x15,0x0c,0x20,
+0x03,0x4b,0x18,0x70,0x19,0x72,0x08,0x33,0x1a,0x78,0xd2,0x09,0xfc,0xd1,0x70,0x47,
+0x16,0x00,0x02,0x40,0x70,0xb5,0x11,0x4c,0x23,0x78,0x03,0xf0,0xfd,0x03,0x23,0x70,
+0xc0,0x21,0x05,0x20,0xff,0xf7,0xec,0xff,0x0d,0x4a,0x0e,0x49,0x6f,0xf0,0x7f,0x43,
+0x6f,0xf0,0x2e,0x05,0x10,0x46,0x15,0x70,0x06,0x78,0xf6,0x09,0xfc,0xd1,0x0e,0x78,
+0xf6,0x07,0x01,0xd5,0x01,0x3b,0xf6,0xd1,0x22,0x78,0x42,0xf0,0x02,0x02,0x00,0x2b,
+0x22,0x70,0x0c,0xbf,0x03,0x20,0x00,0x20,0x70,0xbd,0x00,0xbf,0x1f,0x00,0x02,0x40,
+0x1e,0x00,0x02,0x40,0x1a,0x00,0x02,0x40,0x08,0xb5,0xc0,0x21,0x06,0x20,0xff,0xf7,
+0xc7,0xff,0xff,0xf7,0xcf,0xff,0x28,0xb9,0x03,0x4b,0x1b,0x78,0x13,0xf0,0x02,0x0f,
+0x08,0xbf,0x02,0x20,0x08,0xbd,0x00,0xbf,0x1a,0x00,0x02,0x40,0xf8,0xb5,0x12,0x4c,
+0x23,0x78,0x03,0xf0,0xfd,0x03,0x23,0x70,0x10,0x4b,0x17,0x46,0xc0,0xf3,0x07,0x42,
+0x1a,0x70,0xc0,0xf3,0x07,0x22,0xc0,0xb2,0x03,0xf8,0x01,0x2c,0x0e,0x46,0x03,0xf8,
+0x02,0x0c,0xe8,0x21,0x02,0x20,0xff,0xf7,0xa3,0xff,0x00,0x25,0xae,0x42,0x04,0xd8,
+0x23,0x78,0x43,0xf0,0x02,0x03,0x23,0x70,0xf8,0xbd,0x78,0x5d,0xe0,0x21,0xff,0xf7,
+0x97,0xff,0x01,0x35,0xf2,0xe7,0x00,0xbf,0x1f,0x00,0x02,0x40,0x19,0x00,0x02,0x40,
+0x70,0x47,0x2d,0xe9,0xf0,0x41,0x00,0xf1,0xff,0x06,0x26,0xf0,0xff,0x06,0x34,0x1a,
+0x8c,0x42,0x28,0xbf,0x0c,0x46,0x80,0x46,0x0d,0x46,0x17,0x46,0x5c,0xb1,0xff,0xf7,
+0xb3,0xff,0x58,0xb9,0x3a,0x46,0xa1,0xb2,0x40,0x46,0xff,0xf7,0xbf,0xff,0xff,0xf7,
+0x81,0xff,0x18,0xb9,0x27,0x44,0x2c,0x1b,0x14,0xb9,0x20,0x46,0xbd,0xe8,0xf0,0x81,
+0xb4,0xf5,0x80,0x7f,0x25,0x46,0x28,0xbf,0x4f,0xf4,0x80,0x75,0xff,0xf7,0x9c,0xff,
+0x00,0x28,0xf3,0xd1,0x3a,0x46,0xa9,0xb2,0x30,0x46,0xff,0xf7,0xa7,0xff,0xff,0xf7,
+0x69,0xff,0x00,0x28,0xea,0xd1,0x2f,0x44,0x2e,0x44,0x64,0x1b,0xe4,0xe7,0x00,0x00,
+0x2d,0xe9,0xf0,0x47,0x14,0x4e,0x15,0x4f,0xdf,0xf8,0x54,0x80,0x05,0x46,0x0c,0x46,
+0x8a,0x46,0x05,0xeb,0x04,0x09,0xa9,0xeb,0x0a,0x09,0xba,0xf1,0x00,0x0f,0x02,0xd1,
+0x50,0x46,0xbd,0xe8,0xf0,0x87,0xff,0xf7,0x77,0xff,0x00,0x28,0xf9,0xd1,0xc9,0xf3,
+0x07,0x43,0x33,0x70,0xc9,0xf3,0x07,0x23,0x5f,0xfa,0x89,0xf9,0x3b,0x70,0xc8,0x21,
+0x20,0x20,0x88,0xf8,0x00,0x90,0xff,0xf7,0x33,0xff,0xff,0xf7,0x3b,0xff,0x00,0x28,
+0xe7,0xd1,0xaa,0xf5,0x80,0x5a,0xdc,0xe7,0x19,0x00,0x02,0x40,0x18,0x00,0x02,0x40,
+0x17,0x00,0x02,0x40,0x08,0xb5,0xff,0xf7,0x57,0xff,0x38,0xb9,0xc0,0x21,0xc7,0x20,
+0xff,0xf7,0x1e,0xff,0xbd,0xe8,0x08,0x40,0xff,0xf7,0x24,0xbf,0x08,0xbd,0x00,0x00,
+0x38,0xb5,0xff,0xf7,0x49,0xff,0x04,0x46,0xc0,0xb9,0x0d,0x4b,0x0d,0x4d,0xf2,0x21,
+0x28,0x70,0x18,0x70,0x01,0x20,0xff,0xf7,0x0b,0xff,0xff,0xf7,0x13,0xff,0x04,0x46,
+0x60,0xb9,0xc1,0x21,0x05,0x20,0xff,0xf7,0x03,0xff,0x2b,0x78,0x2b,0xb9,0xc1,0x21,
+0x35,0x20,0xff,0xf7,0xfd,0xfe,0x2b,0x78,0x03,0xb1,0x02,0x24,0x20,0x46,0x38,0xbd,
+0x1b,0x00,0x02,0x40,0x1a,0x00,0x02,0x40,0x10,0xb5,0xc3,0x21,0x04,0x46,0x9f,0x20,
+0xff,0xf7,0xee,0xfe,0x06,0x4b,0x07,0x4a,0x19,0x78,0x01,0x33,0x00,0x20,0x1b,0x78,
+0x12,0x78,0x1b,0x02,0x43,0xea,0x01,0x43,0x13,0x43,0x23,0x60,0x10,0xbd,0x00,0xbf,
+0x1a,0x00,0x02,0x40,0x1c,0x00,0x02,0x40,0x08,0xb5,0x10,0x22,0x00,0x21,0x00,0xf0,
+0x4d,0xf8,0x00,0x20,0x08,0xbd,0x00,0x00,0x73,0xb5,0x21,0x48,0x20,0x4c,0xff,0xf7,
+0xf3,0xff,0x20,0x4a,0x13,0x78,0x43,0xf0,0x80,0x03,0x13,0x70,0xff,0xf7,0xb0,0xff,
+0x05,0x46,0x58,0xb9,0x1c,0x4e,0xe3,0x68,0x00,0x2b,0xfc,0xd0,0xa3,0x68,0x01,0x3b,
+0x03,0x2b,0x2a,0xd8,0xdf,0xe8,0x03,0xf0,0x04,0x18,0x20,0x23,0xe5,0x60,0xfd,0xe7,
+0x01,0xa8,0xff,0xf7,0xc1,0xff,0xa8,0xb9,0x01,0x9b,0x33,0x70,0x1a,0x0a,0x1b,0x0c,
+0x72,0x70,0xb3,0x70,0xf0,0x70,0x23,0x7b,0x25,0x73,0x63,0x7b,0x65,0x73,0xa3,0x7b,
+0xa5,0x73,0xe3,0x7b,0xe5,0x73,0xde,0xe7,0x20,0x68,0x61,0x68,0xff,0xf7,0x48,0xff,
+0x00,0x28,0xf0,0xd0,0xe0,0x60,0xfe,0xe7,0xff,0xf7,0x74,0xff,0xf8,0xe7,0x20,0x68,
+0x61,0x68,0x32,0x46,0xff,0xf7,0x05,0xff,0xf2,0xe7,0x01,0x20,0xf2,0xe7,0x00,0xbf,
+0x00,0x00,0x0c,0x20,0x10,0x30,0x0c,0x40,0x10,0x00,0x0c,0x20,0xf0,0xb5,0x05,0x00,
+0x83,0x07,0x4e,0xd0,0x54,0x1e,0x00,0x2a,0x46,0xd0,0x0a,0x06,0x12,0x0e,0x03,0x00,
+0x03,0x26,0x02,0xe0,0x01,0x35,0x01,0x3c,0x3e,0xd3,0x01,0x33,0x2a,0x70,0x33,0x42,
+0xf8,0xd1,0x03,0x2c,0x2f,0xd9,0xff,0x22,0x0a,0x40,0x15,0x02,0x15,0x43,0x2a,0x04,
+0x15,0x43,0x0f,0x2c,0x38,0xd9,0x27,0x00,0x10,0x3f,0x3f,0x09,0x3e,0x01,0xb4,0x46,
+0x1e,0x00,0x1a,0x00,0x10,0x36,0x66,0x44,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60,
+0x10,0x32,0xb2,0x42,0xf8,0xd1,0x0f,0x26,0x0c,0x22,0x01,0x37,0x3f,0x01,0x26,0x40,
+0xdb,0x19,0x37,0x00,0x22,0x42,0x1a,0xd0,0x3e,0x1f,0xb6,0x08,0xb4,0x00,0xa4,0x46,
+0x1a,0x00,0x1c,0x1d,0x64,0x44,0x20,0xc2,0xa2,0x42,0xfc,0xd1,0x03,0x24,0x01,0x36,
+0xb6,0x00,0x9b,0x19,0x3c,0x40,0x00,0x2c,0x06,0xd0,0x09,0x06,0x1c,0x19,0x09,0x0e,
+0x19,0x70,0x01,0x33,0x9c,0x42,0xfb,0xd1,0xf0,0xbc,0x02,0xbc,0x08,0x47,0x34,0x00,
+0xf1,0xe7,0x14,0x00,0x03,0x00,0xbc,0xe7,0x27,0x00,0xdd,0xe7,
diff --git a/contrib/loaders/flash/npcx/npcx_flash.c b/contrib/loaders/flash/npcx/npcx_flash.c
new file mode 100644
index 0000000..d60624a
--- /dev/null
+++ b/contrib/loaders/flash/npcx/npcx_flash.c
@@ -0,0 +1,342 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * Copyright (C) 2020 by Nuvoton Technology Corporation
+ * Mulin Chao <mlchao@nuvoton.com>
+ * Wealian Liao <WHLIAO@nuvoton.com>
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "npcx_flash.h"
+
+/*----------------------------------------------------------------------------
+ * NPCX flash driver
+ *----------------------------------------------------------------------------*/
+static void flash_execute_cmd(uint8_t code, uint8_t cts)
+{
+ /* Set UMA code */
+ NPCX_UMA_CODE = code;
+ /* Execute UMA flash transaction by CTS setting */
+ NPCX_UMA_CTS = cts;
+ /* Wait for transaction completed */
+ while (NPCX_IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE))
+ ;
+}
+
+static void flash_cs_level(uint8_t level)
+{
+ /* Program chip select pin to high/low level */
+ if (level)
+ NPCX_SET_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
+ else
+ NPCX_CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
+}
+
+static void flash_set_address(uint32_t dest_addr)
+{
+ uint8_t *addr = (uint8_t *)&dest_addr;
+
+ /* Set target flash address */
+ NPCX_UMA_AB2 = addr[2];
+ NPCX_UMA_AB1 = addr[1];
+ NPCX_UMA_AB0 = addr[0];
+}
+
+void delay(uint32_t i)
+{
+ while (i--)
+ ;
+}
+
+static int flash_wait_ready(uint32_t timeout)
+{
+ /* Chip Select down. -- Burst mode */
+ flash_cs_level(0);
+
+ /* Command for Read status register */
+ flash_execute_cmd(NPCX_CMD_READ_STATUS_REG, NPCX_MASK_CMD_ONLY);
+ while (timeout > 0) {
+ /* Read status register */
+ NPCX_UMA_CTS = NPCX_MASK_RD_1BYTE;
+ while (NPCX_IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE))
+ ;
+
+ if (!(NPCX_UMA_DB0 & NPCX_SPI_FLASH_SR1_BUSY))
+ break;
+
+ if (--timeout > 0)
+ delay(100);
+
+ }; /* Wait for Busy clear */
+
+ /* Chip Select high. */
+ flash_cs_level(1);
+
+ if (timeout == 0)
+ return NPCX_FLASH_STATUS_FAILED_TIMEOUT;
+
+ return NPCX_FLASH_STATUS_OK;
+}
+
+static int flash_write_enable(void)
+{
+ /* Write enable command */
+ flash_execute_cmd(NPCX_CMD_WRITE_EN, NPCX_MASK_CMD_ONLY);
+
+ /* Wait for flash is not busy */
+ int status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
+ if (status != NPCX_FLASH_STATUS_OK)
+ return status;
+
+ if (NPCX_UMA_DB0 & NPCX_SPI_FLASH_SR1_WEL)
+ return NPCX_FLASH_STATUS_OK;
+ else
+ return NPCX_FLASH_STATUS_FAILED;
+}
+
+static void flash_burst_write(uint32_t dest_addr, uint16_t bytes,
+ const uint8_t *data)
+{
+ /* Chip Select down -- Burst mode */
+ flash_cs_level(0);
+
+ /* Set write address */
+ flash_set_address(dest_addr);
+ /* Start programming */
+ flash_execute_cmd(NPCX_CMD_FLASH_PROGRAM, NPCX_MASK_CMD_WR_ADR);
+ for (uint32_t i = 0; i < bytes; i++) {
+ flash_execute_cmd(*data, NPCX_MASK_CMD_WR_ONLY);
+ data++;
+ }
+
+ /* Chip Select up */
+ flash_cs_level(1);
+}
+
+/* The data to write cannot cross 256 Bytes boundary */
+static int flash_program_write(uint32_t addr, uint32_t size,
+ const uint8_t *data)
+{
+ int status = flash_write_enable();
+ if (status != NPCX_FLASH_STATUS_OK)
+ return status;
+
+ flash_burst_write(addr, size, data);
+ return flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
+}
+
+int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data)
+{
+ int status;
+ uint32_t trunk_start = (offset + 0xff) & ~0xff;
+
+ /* write head */
+ uint32_t dest_addr = offset;
+ uint32_t write_len = ((trunk_start - offset) > size) ? size : (trunk_start - offset);
+
+ if (write_len) {
+ status = flash_program_write(dest_addr, write_len, data);
+ if (status != NPCX_FLASH_STATUS_OK)
+ return status;
+ data += write_len;
+ }
+
+ dest_addr = trunk_start;
+ size -= write_len;
+
+ /* write remaining data*/
+ while (size > 0) {
+ write_len = (size > NPCX_FLASH_WRITE_SIZE) ?
+ NPCX_FLASH_WRITE_SIZE : size;
+
+ status = flash_program_write(dest_addr, write_len, data);
+ if (status != NPCX_FLASH_STATUS_OK)
+ return status;
+
+ data += write_len;
+ dest_addr += write_len;
+ size -= write_len;
+ }
+
+ return NPCX_FLASH_STATUS_OK;
+}
+
+int flash_physical_erase(uint32_t offset, uint32_t size)
+{
+ /* Alignment has been checked in upper layer */
+ for (; size > 0; size -= NPCX_FLASH_ERASE_SIZE,
+ offset += NPCX_FLASH_ERASE_SIZE) {
+ /* Enable write */
+ int status = flash_write_enable();
+ if (status != NPCX_FLASH_STATUS_OK)
+ return status;
+
+ /* Set erase address */
+ flash_set_address(offset);
+ /* Start erase */
+ flash_execute_cmd(NPCX_CMD_SECTOR_ERASE, NPCX_MASK_CMD_ADR);
+ /* Wait erase completed */
+ status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
+ if (status != NPCX_FLASH_STATUS_OK)
+ return status;
+ }
+
+ return NPCX_FLASH_STATUS_OK;
+}
+
+int flash_physical_erase_all(void)
+{
+ /* Enable write */
+ int status = flash_write_enable();
+ if (status != NPCX_FLASH_STATUS_OK)
+ return status;
+
+ /* Start erase */
+ flash_execute_cmd(NPCX_CMD_CHIP_ERASE, NPCX_MASK_CMD_ONLY);
+
+ /* Wait erase completed */
+ status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
+ if (status != NPCX_FLASH_STATUS_OK)
+ return status;
+
+ return NPCX_FLASH_STATUS_OK;
+}
+
+int flash_physical_clear_stsreg(void)
+{
+ /* Enable write */
+ int status = flash_write_enable();
+ if (status != NPCX_FLASH_STATUS_OK)
+ return status;
+
+ NPCX_UMA_DB0 = 0x0;
+ NPCX_UMA_DB1 = 0x0;
+
+ /* Write status register 1/2 */
+ flash_execute_cmd(NPCX_CMD_WRITE_STATUS_REG, NPCX_MASK_CMD_WR_2BYTE);
+
+ /* Wait writing completed */
+ status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
+ if (status != NPCX_FLASH_STATUS_OK)
+ return status;
+
+ /* Read status register 1/2 for checking */
+ flash_execute_cmd(NPCX_CMD_READ_STATUS_REG, NPCX_MASK_CMD_RD_1BYTE);
+ if (NPCX_UMA_DB0 != 0x00)
+ return NPCX_FLASH_STATUS_FAILED;
+ flash_execute_cmd(NPCX_CMD_READ_STATUS_REG2, NPCX_MASK_CMD_RD_1BYTE);
+ if (NPCX_UMA_DB0 != 0x00)
+ return NPCX_FLASH_STATUS_FAILED;
+
+ return NPCX_FLASH_STATUS_OK;
+}
+
+int flash_get_id(uint32_t *id)
+{
+ flash_execute_cmd(NPCX_CMD_READ_ID, NPCX_MASK_CMD_RD_3BYTE);
+ *id = NPCX_UMA_DB0 << 16 | NPCX_UMA_DB1 << 8 | NPCX_UMA_DB2;
+
+ return NPCX_FLASH_STATUS_OK;
+}
+
+/*----------------------------------------------------------------------------
+ * flash loader function
+ *----------------------------------------------------------------------------*/
+uint32_t flashloader_init(struct npcx_flash_params *params)
+{
+ /* Initialize params buffers */
+ memset(params, 0, sizeof(struct npcx_flash_params));
+
+ return NPCX_FLASH_STATUS_OK;
+}
+
+/*----------------------------------------------------------------------------
+ * Functions
+ *----------------------------------------------------------------------------*/
+/* flashloader parameter structure */
+__attribute__ ((section(".buffers.g_cfg")))
+volatile struct npcx_flash_params g_cfg;
+/* data buffer */
+__attribute__ ((section(".buffers.g_buf")))
+uint8_t g_buf[NPCX_FLASH_LOADER_BUFFER_SIZE];
+
+int main(void)
+{
+ uint32_t id;
+
+ /* set buffer */
+ flashloader_init((struct npcx_flash_params *)&g_cfg);
+
+ /* Avoid F_CS0 toggles while programming the internal flash. */
+ NPCX_SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI);
+
+ /* clear flash status registers */
+ int status = flash_physical_clear_stsreg();
+ if (status != NPCX_FLASH_STATUS_OK) {
+ while (1)
+ g_cfg.sync = status;
+ }
+
+ while (1) {
+ /* wait command*/
+ while (g_cfg.sync == NPCX_FLASH_LOADER_WAIT)
+ ;
+
+ /* command handler */
+ switch (g_cfg.cmd) {
+ case NPCX_FLASH_CMD_GET_FLASH_ID:
+ status = flash_get_id(&id);
+ if (status == NPCX_FLASH_STATUS_OK) {
+ g_buf[0] = id & 0xff;
+ g_buf[1] = (id >> 8) & 0xff;
+ g_buf[2] = (id >> 16) & 0xff;
+ g_buf[3] = 0x00;
+ }
+ break;
+ case NPCX_FLASH_CMD_ERASE_SECTORS:
+ status = flash_physical_erase(g_cfg.addr, g_cfg.len);
+ break;
+ case NPCX_FLASH_CMD_ERASE_ALL:
+ status = flash_physical_erase_all();
+ break;
+ case NPCX_FLASH_CMD_PROGRAM:
+ status = flash_physical_write(g_cfg.addr,
+ g_cfg.len,
+ g_buf);
+ break;
+ default:
+ status = NPCX_FLASH_STATUS_FAILED_UNKNOWN_COMMAND;
+ break;
+ }
+
+ /* clear & set result for next command */
+ if (status != NPCX_FLASH_STATUS_OK) {
+ g_cfg.sync = status;
+ while (1)
+ ;
+ } else {
+ g_cfg.sync = NPCX_FLASH_LOADER_WAIT;
+ }
+ }
+
+ return 0;
+}
+
+__attribute__ ((section(".stack")))
+__attribute__ ((used))
+static uint32_t stack[NPCX_FLASH_LOADER_STACK_SIZE / 4];
+extern uint32_t _estack;
+extern uint32_t _bss;
+extern uint32_t _ebss;
+
+__attribute__ ((section(".entry")))
+void entry(void)
+{
+ /* set sp from end of stack */
+ __asm(" ldr sp, =_estack - 4");
+
+ main();
+
+ __asm(" bkpt #0x00");
+}
diff --git a/contrib/loaders/flash/npcx/npcx_flash.h b/contrib/loaders/flash/npcx/npcx_flash.h
new file mode 100644
index 0000000..cc4f1ad
--- /dev/null
+++ b/contrib/loaders/flash/npcx/npcx_flash.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * Copyright (C) 2020 by Nuvoton Technology Corporation
+ * Mulin Chao <mlchao@nuvoton.com>
+ * Wealian Liao <WHLIAO@nuvoton.com>
+ */
+
+#ifndef OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_H
+#define OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_H
+
+#include "npcx_flash_config.h"
+
+/* Bit functions */
+#define NPCX_SET_BIT(reg, bit) ((reg) |= (0x1 << (bit)))
+#define NPCX_CLEAR_BIT(reg, bit) ((reg) &= (~(0x1 << (bit))))
+#define NPCX_IS_BIT_SET(reg, bit) (((reg) >> (bit)) & (0x1))
+
+/* Field functions */
+#define NPCX_GET_POS_FIELD(pos, size) (pos)
+#define NPCX_GET_SIZE_FIELD(pos, size) (size)
+#define NPCX_FIELD_POS(field) NPCX_GET_POS_##field
+#define NPCX_FIELD_SIZE(field) NPCX_GET_SIZE_##field
+/* Read field functions */
+#define NPCX_GET_FIELD(reg, field) \
+ _NPCX_GET_FIELD_((reg), NPCX_FIELD_POS(field), NPCX_FIELD_SIZE(field))
+#define _NPCX_GET_FIELD_(reg, f_pos, f_size) \
+ (((reg) >> (f_pos)) & ((1 << (f_size)) - 1))
+/* Write field functions */
+#define NPCX_SET_FIELD(reg, field, value) \
+ _NPCX_SET_FIELD_((reg), NPCX_FIELD_POS(field), NPCX_FIELD_SIZE(field), (value))
+#define _NPCX_SET_FIELD_(reg, f_pos, f_size, value) \
+ ((reg) = ((reg) & (~(((1 << (f_size)) - 1) << (f_pos)))) | ((value) << (f_pos)))
+
+/* Register definitions */
+#define NPCX_REG32_ADDR(addr) ((volatile uint32_t *)(addr))
+#define NPCX_REG16_ADDR(addr) ((volatile uint16_t *)(addr))
+#define NPCX_REG8_ADDR(addr) ((volatile uint8_t *)(addr))
+
+#define NPCX_HW_BYTE(addr) (*NPCX_REG8_ADDR(addr))
+#define NPCX_HW_WORD(addr) (*NPCX_REG16_ADDR(addr))
+#define NPCX_HW_DWORD(addr) (*NPCX_REG32_ADDR(addr))
+
+/* Devalt */
+#define NPCX_SCFG_BASE_ADDR 0x400C3000
+#define NPCX_DEVCNT NPCX_HW_BYTE(NPCX_SCFG_BASE_ADDR + 0x000)
+#define NPCX_DEVALT(n) NPCX_HW_BYTE(NPCX_SCFG_BASE_ADDR + 0x010 + (n))
+
+#define NPCX_DEVCNT_HIF_TYP_SEL_FIELD FIELD(2, 2)
+#define NPCX_DEVCNT_JEN0_HEN 4
+#define NPCX_DEVCNT_JEN1_HEN 5
+#define NPCX_DEVCNT_F_SPI_TRIS 6
+
+/* Pin-mux for SPI/FIU */
+#define NPCX_DEVALT0_SPIP_SL 0
+#define NPCX_DEVALT0_GPIO_NO_SPIP 3
+#define NPCX_DEVALT0_F_SPI_CS1_2 4
+#define NPCX_DEVALT0_F_SPI_CS1_1 5
+#define NPCX_DEVALT0_F_SPI_QUAD 6
+#define NPCX_DEVALT0_NO_F_SPI 7
+
+/* Flash Interface Unit (FIU) registers */
+#define NPCX_FIU_BASE_ADDR 0x40020000
+#define NPCX_FIU_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x000)
+#define NPCX_BURST_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x001)
+#define NPCX_RESP_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x002)
+#define NPCX_SPI_FL_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x014)
+#define NPCX_UMA_CODE NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x016)
+#define NPCX_UMA_AB0 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x017)
+#define NPCX_UMA_AB1 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x018)
+#define NPCX_UMA_AB2 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x019)
+#define NPCX_UMA_DB0 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01A)
+#define NPCX_UMA_DB1 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01B)
+#define NPCX_UMA_DB2 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01C)
+#define NPCX_UMA_DB3 NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01D)
+#define NPCX_UMA_CTS NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01E)
+#define NPCX_UMA_ECTS NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x01F)
+#define NPCX_UMA_DB0_3 NPCX_HW_DWORD(NPCX_FIU_BASE_ADDR + 0x020)
+#define NPCX_FIU_RD_CMD NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x030)
+#define NPCX_FIU_DMM_CYC NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x032)
+#define NPCX_FIU_EXT_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x033)
+#define NPCX_FIU_UMA_AB0_3 NPCX_HW_DWORD(NPCX_FIU_BASE_ADDR + 0x034)
+
+/* FIU register fields */
+#define NPCX_RESP_CFG_IAD_EN 0
+#define NPCX_RESP_CFG_DEV_SIZE_EX 2
+#define NPCX_UMA_CTS_A_SIZE 3
+#define NPCX_UMA_CTS_C_SIZE 4
+#define NPCX_UMA_CTS_RD_WR 5
+#define NPCX_UMA_CTS_DEV_NUM 6
+#define NPCX_UMA_CTS_EXEC_DONE 7
+#define NPCX_UMA_ECTS_SW_CS0 0
+#define NPCX_UMA_ECTS_SW_CS1 1
+#define NPCX_UMA_ECTS_SEC_CS 2
+#define NPCX_UMA_ECTS_UMA_LOCK 3
+
+/* Flash UMA commands for npcx internal SPI flash */
+#define NPCX_CMD_READ_ID 0x9F
+#define NPCX_CMD_READ_MAN_DEV_ID 0x90
+#define NPCX_CMD_WRITE_EN 0x06
+#define NPCX_CMD_WRITE_STATUS 0x50
+#define NPCX_CMD_READ_STATUS_REG 0x05
+#define NPCX_CMD_READ_STATUS_REG2 0x35
+#define NPCX_CMD_WRITE_STATUS_REG 0x01
+#define NPCX_CMD_FLASH_PROGRAM 0x02
+#define NPCX_CMD_SECTOR_ERASE 0x20
+#define NPCX_CMD_PROGRAM_UINT_SIZE 0x08
+#define NPCX_CMD_PAGE_SIZE 0x00
+#define NPCX_CMD_READ_ID_TYPE 0x47
+#define NPCX_CMD_FAST_READ 0x0B
+#define NPCX_CMD_CHIP_ERASE 0xC7
+
+/*
+ * Status registers for SPI flash
+ */
+#define NPCX_SPI_FLASH_SR2_SUS (1 << 7)
+#define NPCX_SPI_FLASH_SR2_CMP (1 << 6)
+#define NPCX_SPI_FLASH_SR2_LB3 (1 << 5)
+#define NPCX_SPI_FLASH_SR2_LB2 (1 << 4)
+#define NPCX_SPI_FLASH_SR2_LB1 (1 << 3)
+#define NPCX_SPI_FLASH_SR2_QE (1 << 1)
+#define NPCX_SPI_FLASH_SR2_SRP1 (1 << 0)
+#define NPCX_SPI_FLASH_SR1_SRP0 (1 << 7)
+#define NPCX_SPI_FLASH_SR1_SEC (1 << 6)
+#define NPCX_SPI_FLASH_SR1_TB (1 << 5)
+#define NPCX_SPI_FLASH_SR1_BP2 (1 << 4)
+#define NPCX_SPI_FLASH_SR1_BP1 (1 << 3)
+#define NPCX_SPI_FLASH_SR1_BP0 (1 << 2)
+#define NPCX_SPI_FLASH_SR1_WEL (1 << 1)
+#define NPCX_SPI_FLASH_SR1_BUSY (1 << 0)
+
+#define NPCX_MASK_CMD_ONLY (0xC0)
+#define NPCX_MASK_CMD_ADR (0xC0 | 0x08)
+#define NPCX_MASK_CMD_ADR_WR (0xC0 | 0x20 | 0x08 | 0x01)
+#define NPCX_MASK_RD_1BYTE (0xC0 | 0x10 | 0x01)
+#define NPCX_MASK_RD_2BYTE (0xC0 | 0x10 | 0x02)
+#define NPCX_MASK_RD_3BYTE (0xC0 | 0x10 | 0x03)
+#define NPCX_MASK_RD_4BYTE (0xC0 | 0x10 | 0x04)
+#define NPCX_MASK_CMD_RD_1BYTE (0xC0 | 0x01)
+#define NPCX_MASK_CMD_RD_2BYTE (0xC0 | 0x02)
+#define NPCX_MASK_CMD_RD_3BYTE (0xC0 | 0x03)
+#define NPCX_MASK_CMD_RD_4BYTE (0xC0 | 0x04)
+#define NPCX_MASK_CMD_WR_ONLY (0xC0 | 0x20)
+#define NPCX_MASK_CMD_WR_1BYTE (0xC0 | 0x20 | 0x10 | 0x01)
+#define NPCX_MASK_CMD_WR_2BYTE (0xC0 | 0x20 | 0x10 | 0x02)
+#define NPCX_MASK_CMD_WR_ADR (0xC0 | 0x20 | 0x08)
+
+/* Flash loader parameters */
+struct __attribute__((__packed__)) npcx_flash_params {
+ uint32_t addr; /* Address in flash */
+ uint32_t len; /* Number of bytes */
+ uint32_t cmd; /* Command */
+ uint32_t sync; /* Handshake signal */
+};
+
+/* Flash trigger signal */
+enum npcx_flash_handshake {
+ NPCX_FLASH_LOADER_WAIT = 0x0, /* Idle */
+ NPCX_FLASH_LOADER_EXECUTE = 0xFFFFFFFF /* Execute Command */
+};
+
+/* Flash loader command */
+enum npcx_flash_commands {
+ NPCX_FLASH_CMD_NO_ACTION = 0, /* No action, default value */
+ NPCX_FLASH_CMD_GET_FLASH_ID, /* Get the internal flash ID */
+ NPCX_FLASH_CMD_ERASE_SECTORS, /* Erase unprotected sectors */
+ NPCX_FLASH_CMD_ERASE_ALL, /* Erase all */
+ NPCX_FLASH_CMD_PROGRAM, /* Program data */
+};
+
+/* Status */
+enum npcx_flash_status {
+ NPCX_FLASH_STATUS_OK = 0,
+ NPCX_FLASH_STATUS_FAILED_UNKNOWN_COMMAND,
+ NPCX_FLASH_STATUS_FAILED,
+ NPCX_FLASH_STATUS_FAILED_TIMEOUT,
+};
+
+#endif /* OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_H */
diff --git a/contrib/loaders/flash/npcx/npcx_flash.lds b/contrib/loaders/flash/npcx/npcx_flash.lds
new file mode 100644
index 0000000..0d78252
--- /dev/null
+++ b/contrib/loaders/flash/npcx/npcx_flash.lds
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "npcx_flash_config.h"
+
+/* Application memory map */
+MEMORY {
+ /* buffer + parameters */
+ BUFFER (RWX) : ORIGIN = NPCX_FLASH_LOADER_PARAMS_ADDR,
+ LENGTH = NPCX_FLASH_LOADER_PARAMS_SIZE + NPCX_FLASH_LOADER_BUFFER_SIZE
+
+ PROGRAM (RWX) : ORIGIN = NPCX_FLASH_LOADER_PROGRAM_ADDR,
+ LENGTH = NPCX_FLASH_LOADER_PROGRAM_SIZE
+}
+
+/* Sections used for flashing */
+SECTIONS
+{
+ .buffers (NOLOAD) :
+ {
+ _buffers = .;
+ *(.buffers.g_cfg)
+ *(.buffers.g_buf)
+ *(.buffers*)
+ _ebuffers = .;
+ } > BUFFER
+
+ .text :
+ {
+ _text = .;
+ *(.entry*)
+ *(.text*)
+ _etext = .;
+ } > PROGRAM
+
+ .data :
+ { _data = .;
+ *(.rodata*)
+ *(.data*)
+ _edata = .;
+ } > PROGRAM
+
+ .bss :
+ {
+ __bss_start__ = .;
+ _bss = .;
+ *(.bss*)
+ *(COMMON)
+ _ebss = .;
+ __bss_end__ = .;
+ } > PROGRAM
+
+ .stack (NOLOAD) :
+ {
+ _stack = .;
+ *(.stack*)
+ _estack = .;
+ } > PROGRAM
+}
diff --git a/contrib/loaders/flash/npcx/npcx_flash_config.h b/contrib/loaders/flash/npcx/npcx_flash_config.h
new file mode 100644
index 0000000..9ec1c5e
--- /dev/null
+++ b/contrib/loaders/flash/npcx/npcx_flash_config.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * Copyright (C) 2021 by Nuvoton Technology Corporation
+ * Mulin Chao <mlchao@nuvoton.com>
+ * Wealian Liao <WHLIAO@nuvoton.com>
+ */
+
+#ifndef OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_CONFIG_H
+#define OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_CONFIG_H
+
+#define NPCX_FLASH_ABORT_TIMEOUT 0xFFFFFF
+
+/* NPCX chip information */
+#define NPCX_FLASH_WRITE_SIZE 256L /* One page size for write */
+#define NPCX_FLASH_ERASE_SIZE 0x1000
+
+/* NPCX flash loader information */
+#define NPCX_FLASH_LOADER_WORKING_ADDR 0x200C0000
+#define NPCX_FLASH_LOADER_PARAMS_ADDR NPCX_FLASH_LOADER_WORKING_ADDR
+#define NPCX_FLASH_LOADER_PARAMS_SIZE 16
+#define NPCX_FLASH_LOADER_BUFFER_ADDR (NPCX_FLASH_LOADER_PARAMS_ADDR + NPCX_FLASH_LOADER_PARAMS_SIZE)
+#define NPCX_FLASH_LOADER_BUFFER_SIZE NPCX_FLASH_ERASE_SIZE
+#define NPCX_FLASH_LOADER_PROGRAM_ADDR (NPCX_FLASH_LOADER_BUFFER_ADDR + NPCX_FLASH_LOADER_BUFFER_SIZE)
+#define NPCX_FLASH_LOADER_PROGRAM_SIZE 0x1000
+
+/* Stack size in byte. 4 byte size alignment */
+#define NPCX_FLASH_LOADER_STACK_SIZE 400
+
+
+#endif /* OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_CONFIG_H */