summaryrefslogtreecommitdiff
path: root/zephyr/shim
diff options
context:
space:
mode:
authorKeith Short <keithshort@chromium.org>2021-08-20 12:54:31 -0600
committerCommit Bot <commit-bot@chromium.org>2021-08-26 19:54:43 +0000
commit71c1a4e5f6b174c1cb9b65fdd6a14944820b308a (patch)
treecbc98ea373a2ae5d0b3721379155ce6553a893f5 /zephyr/shim
parented193ca2912e2e5a310cca4f87ce552b8832b5c3 (diff)
downloadchrome-ec-71c1a4e5f6b174c1cb9b65fdd6a14944820b308a.tar.gz
zephyr: compile NPCX monitor
Compile the NPCX monitor code under the Zephyr environment. BUG=b:197162681 BRANCH=none TEST=Build zephyr for volteer. Verify npcx_monitor.bin is created. Signed-off-by: Keith Short <keithshort@chromium.org> Change-Id: Idba6e013288eb9c300c91ea57313db08e13b2e97 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3116567 Reviewed-by: Jack Rosenthal <jrosenth@chromium.org> Reviewed-by: Wai-Hong Tam <waihong@google.com> Reviewed-by: CH Lin <chlin56@nuvoton.com>
Diffstat (limited to 'zephyr/shim')
-rw-r--r--zephyr/shim/chip/npcx/CMakeLists.txt7
-rw-r--r--zephyr/shim/chip/npcx/include/flash_chip.h3
-rw-r--r--zephyr/shim/chip/npcx/npcx_monitor/CMakeLists.txt47
-rw-r--r--zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.c343
-rw-r--r--zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.h33
-rw-r--r--zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.ld52
-rw-r--r--zephyr/shim/chip/npcx/npcx_monitor/registers.h360
7 files changed, 845 insertions, 0 deletions
diff --git a/zephyr/shim/chip/npcx/CMakeLists.txt b/zephyr/shim/chip/npcx/CMakeLists.txt
index a184d678f6..d3cd4b48fd 100644
--- a/zephyr/shim/chip/npcx/CMakeLists.txt
+++ b/zephyr/shim/chip/npcx/CMakeLists.txt
@@ -2,6 +2,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+# When building code coverage, the final Zephyr image isn't actually linked
+# and there's no valid image to program. Skip compiling and linking the NPCX
+# monitor when coverage is enabled.
+if (NOT DEFINED CONFIG_COVERAGE)
+ add_subdirectory(npcx_monitor)
+endif()
+
zephyr_library_include_directories(include)
zephyr_library_sources(clock.c)
diff --git a/zephyr/shim/chip/npcx/include/flash_chip.h b/zephyr/shim/chip/npcx/include/flash_chip.h
index c8b3426e69..622633c570 100644
--- a/zephyr/shim/chip/npcx/include/flash_chip.h
+++ b/zephyr/shim/chip/npcx/include/flash_chip.h
@@ -25,4 +25,7 @@
#define CONFIG_RW_STORAGE_OFF 0
+/* Use 4k sector erase for NPCX monitor flash erase operations. */
+#define NPCX_MONITOR_FLASH_ERASE_SIZE 0x1000
+
#endif /* __CROS_EC_FLASH_CHIP_H */
diff --git a/zephyr/shim/chip/npcx/npcx_monitor/CMakeLists.txt b/zephyr/shim/chip/npcx/npcx_monitor/CMakeLists.txt
new file mode 100644
index 0000000000..661eb86e91
--- /dev/null
+++ b/zephyr/shim/chip/npcx/npcx_monitor/CMakeLists.txt
@@ -0,0 +1,47 @@
+# Copyright 2021 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# The NPCX monitor source needs the chip type and flash layout information
+# provided by the board configuration. This is provided by
+# zephyr/shim/include/config_chip.h, so we need all the include directories
+# of the Zephyr application.
+zephyr_get_include_directories_for_lang(C zephyr_includes STRIP_PREFIX)
+
+# Something in the zephyr_get_compile_options_for_lang() output causes the
+# "-imacros" option to get dropped during expansion when passed to
+# target_compile_options(). Fetch the compile options directly from
+# zephyr_interface which works as expected.
+get_property(
+ zephyr_compile_options
+ TARGET zephyr_interface
+ PROPERTY INTERFACE_COMPILE_OPTIONS
+ )
+
+add_executable(npcx_monitor npcx_monitor.c)
+target_include_directories(npcx_monitor PRIVATE
+ "${PLATFORM_EC}/zephyr/shim/include"
+ "${PLATFORM_EC}/zephyr/shim/chip/npcx/include"
+ )
+target_include_directories(npcx_monitor PRIVATE "${zephyr_includes}")
+target_compile_options(npcx_monitor PRIVATE "${zephyr_compile_options}")
+
+target_link_options(npcx_monitor BEFORE PRIVATE
+ -nostdlib
+ -g
+ -mthumb
+ -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/npcx_monitor.ld
+ )
+
+# Create the NPCX monitor binary, locate it the root of the build
+# directory as it needs to be found by the flash_util script
+set(npcx_monitor_elf ${CMAKE_CURRENT_BINARY_DIR}/npcx_monitor.elf)
+set(npcx_monitor_bin ${CMAKE_BINARY_DIR}/npcx_monitor.bin)
+
+add_custom_target(generate_npcx_monitor
+ COMMAND ${CMAKE_OBJCOPY} -O binary ${npcx_monitor_elf} ${npcx_monitor_bin}
+ BYPRODUCTS ${npcx_monitor_bin}
+ DEPENDS npcx_monitor
+ )
+
+add_dependencies(zephyr generate_npcx_monitor)
diff --git a/zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.c b/zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.c
new file mode 100644
index 0000000000..2bd9455a91
--- /dev/null
+++ b/zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.c
@@ -0,0 +1,343 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * NPCX SoC spi flash update tool - monitor firmware
+ */
+
+#include <stdint.h>
+#include <sys/util.h>
+#include "config_chip.h"
+#include "npcx_monitor.h"
+#include "registers.h"
+
+/*
+ * TODO(b/197162681): This was copied from chip/npcx/spiflashfw but this
+ * needs to be moved to Zephyr upstream
+ */
+
+/*****************************************************************************/
+/* spi flash internal functions */
+void sspi_flash_pinmux(int enable)
+{
+ if (enable)
+ CLEAR_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI);
+ else
+ SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI);
+
+ /* CS0/1 pinmux */
+ if (enable) {
+#if (FIU_CHIP_SELECT == 1)
+ SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_F_SPI_CS1_1);
+#elif (FIU_CHIP_SELECT == 2)
+ SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_F_SPI_CS1_2);
+#endif
+ } else {
+ CLEAR_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_F_SPI_CS1_1);
+ CLEAR_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_F_SPI_CS1_2);
+ }
+}
+
+void sspi_flash_tristate(int enable)
+{
+ if (enable) {
+ /* Enable FIU pins to tri-state */
+ SET_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS);
+ } else {
+ /* Disable FIU pins to tri-state */
+ CLEAR_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS);
+ }
+}
+
+void sspi_flash_execute_cmd(uint8_t code, uint8_t cts)
+{
+ /* set UMA_CODE */
+ NPCX_UMA_CODE = code;
+ /* execute UMA flash transaction */
+ NPCX_UMA_CTS = cts;
+ while (IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE))
+ ;
+}
+
+void sspi_flash_cs_level(int level)
+{
+ /* level is high */
+ if (level) {
+ /* Set chip select to high */
+ SET_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
+ } else { /* level is low */
+ /* Set chip select to low */
+ CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
+ }
+}
+
+void sspi_flash_wait_ready(void)
+{
+ uint8_t mask = SPI_FLASH_SR1_BUSY;
+
+ /* Chip Select down. */
+ sspi_flash_cs_level(0);
+ /* Command for Read status register */
+ sspi_flash_execute_cmd(CMD_READ_STATUS_REG, MASK_CMD_ONLY);
+ do {
+ /* Read status register */
+ NPCX_UMA_CTS = MASK_RD_1BYTE;
+ while (IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE))
+ ;
+ } while (NPCX_UMA_DB0 & mask); /* Wait for Busy clear */
+ /* Chip Select high. */
+ sspi_flash_cs_level(1);
+}
+
+int sspi_flash_write_enable(void)
+{
+ uint8_t mask = SPI_FLASH_SR1_WEL;
+ /* Write enable command */
+ sspi_flash_execute_cmd(CMD_WRITE_EN, MASK_CMD_ONLY);
+ /* Wait for flash is not busy */
+ sspi_flash_wait_ready();
+
+ if (NPCX_UMA_DB0 & mask)
+ return 1;
+ else
+ return 0;
+}
+
+void sspi_flash_set_address(uint32_t dest_addr)
+{
+ uint8_t *addr = (uint8_t *)&dest_addr;
+ /* Write address */
+ NPCX_UMA_AB2 = addr[2];
+ NPCX_UMA_AB1 = addr[1];
+ NPCX_UMA_AB0 = addr[0];
+}
+
+void sspi_flash_burst_write(unsigned int dest_addr, unsigned int bytes,
+ const char *data)
+{
+ unsigned int i;
+ /* Chip Select down. */
+ sspi_flash_cs_level(0);
+ /* Set erase address */
+ sspi_flash_set_address(dest_addr);
+ /* Start write */
+ sspi_flash_execute_cmd(CMD_FLASH_PROGRAM, MASK_CMD_WR_ADR);
+ for (i = 0; i < bytes; i++) {
+ sspi_flash_execute_cmd(*data, MASK_CMD_WR_ONLY);
+ data++;
+ }
+ /* Chip Select up */
+ sspi_flash_cs_level(1);
+}
+
+int sspi_flash_physical_clear_stsreg(void)
+{
+ /* Disable tri-state */
+ sspi_flash_tristate(0);
+ /* Enable write */
+ sspi_flash_write_enable();
+
+ NPCX_UMA_DB0 = 0x0;
+ NPCX_UMA_DB1 = 0x0;
+
+ /* Write status register 1/2 */
+ sspi_flash_execute_cmd(CMD_WRITE_STATUS_REG, MASK_CMD_WR_2BYTE);
+
+ /* Wait writing completed */
+ sspi_flash_wait_ready();
+
+ /* Read status register 1/2 for checking */
+ sspi_flash_execute_cmd(CMD_READ_STATUS_REG, MASK_CMD_RD_1BYTE);
+ if (NPCX_UMA_DB0 != 0x00)
+ return 0;
+ sspi_flash_execute_cmd(CMD_READ_STATUS_REG2, MASK_CMD_RD_1BYTE);
+ if (NPCX_UMA_DB0 != 0x00)
+ return 0;
+ /* Enable tri-state */
+ sspi_flash_tristate(1);
+
+ return 1;
+}
+
+void sspi_flash_physical_write(int offset, int size, const char *data)
+{
+ int dest_addr = offset;
+ const int sz_page = CONFIG_FLASH_WRITE_IDEAL_SIZE;
+
+ /* Disable tri-state */
+ sspi_flash_tristate(0);
+
+ /* Write the data per CONFIG_FLASH_WRITE_IDEAL_SIZE bytes */
+ for (; size >= sz_page; size -= sz_page) {
+ /* Enable write */
+ sspi_flash_write_enable();
+ /* Burst UMA transaction */
+ sspi_flash_burst_write(dest_addr, sz_page, data);
+ /* Wait write completed */
+ sspi_flash_wait_ready();
+
+ data += sz_page;
+ dest_addr += sz_page;
+ }
+
+ /* Handle final partial page, if any */
+ if (size != 0) {
+ /* Enable write */
+ sspi_flash_write_enable();
+ /* Burst UMA transaction */
+ sspi_flash_burst_write(dest_addr, size, data);
+
+ /* Wait write completed */
+ sspi_flash_wait_ready();
+ }
+
+ /* Enable tri-state */
+ sspi_flash_tristate(1);
+}
+
+void sspi_flash_physical_erase(int offset, int size)
+{
+ /* Disable tri-state */
+ sspi_flash_tristate(0);
+
+ /* Alignment has been checked in upper layer */
+ for (; size > 0; size -= NPCX_MONITOR_FLASH_ERASE_SIZE,
+ offset += NPCX_MONITOR_FLASH_ERASE_SIZE) {
+ /* Enable write */
+ sspi_flash_write_enable();
+ /* Set erase address */
+ sspi_flash_set_address(offset);
+ /* Start erase */
+ sspi_flash_execute_cmd(CMD_SECTOR_ERASE, MASK_CMD_ADR);
+
+ /* Wait erase completed */
+ sspi_flash_wait_ready();
+ }
+
+ /* Enable tri-state */
+ sspi_flash_tristate(1);
+}
+
+int sspi_flash_verify(int offset, int size, const char *data)
+{
+ int i, result;
+ uint8_t *ptr_flash;
+ uint8_t *ptr_mram;
+ uint8_t cmp_data;
+
+ ptr_flash = (uint8_t *)(CONFIG_MAPPED_STORAGE_BASE + offset);
+ ptr_mram = (uint8_t *)data;
+ result = 1;
+
+ /* Disable tri-state */
+ sspi_flash_tristate(0);
+
+ /* Start to verify */
+ for (i = 0; i < size; i++) {
+ cmp_data = ptr_mram ? ptr_mram[i] : 0xFF;
+ if (ptr_flash[i] != cmp_data) {
+ result = 0;
+ break;
+ }
+ }
+
+ /* Enable tri-state */
+ sspi_flash_tristate(1);
+ return result;
+}
+
+int sspi_flash_get_image_used(const char *fw_base)
+{
+ const uint8_t *image;
+ int size = MAX(CONFIG_RO_SIZE, CONFIG_RW_SIZE); /* max size is 128KB */
+
+ image = (const uint8_t *)fw_base;
+ /*
+ * Scan backwards looking for 0xea byte, which is by definition the
+ * last byte of the image. See ec.lds.S for how this is inserted at
+ * the end of the image.
+ */
+ for (size--; size > 0 && image[size] != 0xea; size--)
+ ;
+
+ return size ? size + 1 : 0; /* 0xea byte IS part of the image */
+
+}
+
+/* Entry function of spi upload function */
+uint32_t __attribute__ ((section(".startup_text")))
+sspi_flash_upload(int spi_offset, int spi_size)
+{
+ /*
+ * Flash image has been uploaded to Code RAM
+ */
+ uint32_t sz_image;
+ uint32_t uut_tag;
+ const char *image_base;
+ uint32_t *flag_upload = (uint32_t *)SPI_PROGRAMMING_FLAG;
+ struct monitor_header_tag *monitor_header =
+ (struct monitor_header_tag *)NPCX_MONITOR_HEADER_ADDR;
+
+ *flag_upload = 0;
+
+ uut_tag = monitor_header->tag;
+ /* If it is UUT tag, read required parameters from header */
+ if (uut_tag == NPCX_MONITOR_UUT_TAG) {
+ sz_image = monitor_header->size;
+ spi_offset = monitor_header->dest_addr;
+ image_base = (const char *)(monitor_header->src_addr);
+ } else {
+ sz_image = spi_size;
+ image_base = (const char *)CONFIG_PROGRAM_MEMORY_BASE;
+ }
+
+ /* Unlock & stop watchdog */
+ NPCX_WDSDM = 0x87;
+ NPCX_WDSDM = 0x61;
+ NPCX_WDSDM = 0x63;
+
+ /* UMA Unlock */
+ CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK);
+
+ /*
+ * If UUT is used, assuming the target is the internal flash.
+ * Don't switch the pinmux and make sure bit 7 of DEVALT0 is set.
+ */
+ if (uut_tag == NPCX_MONITOR_UUT_TAG)
+ SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI);
+ else
+ /* Set pinmux first */
+ sspi_flash_pinmux(1);
+
+ /* Get size of image automatically */
+ if (sz_image == 0)
+ sz_image = sspi_flash_get_image_used(image_base);
+
+ /* Clear status reg of spi flash for protection */
+ if (sspi_flash_physical_clear_stsreg()) {
+ /* Start to erase */
+ sspi_flash_physical_erase(spi_offset, sz_image);
+ /* Start to write */
+ if (image_base != NULL)
+ sspi_flash_physical_write(spi_offset, sz_image,
+ image_base);
+ /* Verify data */
+ if (sspi_flash_verify(spi_offset, sz_image, image_base))
+ *flag_upload |= 0x02;
+ }
+ if (uut_tag != NPCX_MONITOR_UUT_TAG)
+ /* Disable pinmux */
+ sspi_flash_pinmux(0);
+
+ /* Mark we have finished upload work */
+ *flag_upload |= 0x01;
+
+ /* Return the status back to ROM code is required for UUT */
+ if (uut_tag == NPCX_MONITOR_UUT_TAG)
+ return *flag_upload;
+
+ /* Infinite loop */
+ for (;;)
+ ;
+}
+
diff --git a/zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.h b/zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.h
new file mode 100644
index 0000000000..c5415d94db
--- /dev/null
+++ b/zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.h
@@ -0,0 +1,33 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef __CROS_EC_NPCX_MONITOR_H
+#define __CROS_EC_NPCX_MONITOR_H
+
+#include <stdint.h>
+
+#define NPCX_MONITOR_UUT_TAG 0xA5075001
+#define NPCX_MONITOR_HEADER_ADDR 0x200C3000
+
+/* Flag to record the progress of programming SPI flash */
+#define SPI_PROGRAMMING_FLAG 0x200C4000
+
+struct monitor_header_tag {
+ /* offset 0x00: TAG NPCX_MONITOR_TAG */
+ uint32_t tag;
+ /* offset 0x04: Size of the binary being programmed (in bytes) */
+ uint32_t size;
+ /* offset 0x08: The RAM address of the binary to program into the SPI */
+ uint32_t src_addr;
+ /* offset 0x0C: The Flash address to be programmed (Absolute address) */
+ uint32_t dest_addr;
+ /* offset 0x10: Maximum allowable flash clock frequency */
+ uint8_t max_clock;
+ /* offset 0x11: SPI Flash read mode */
+ uint8_t read_mode;
+ /* offset 0x12: Reserved */
+ uint16_t reserved;
+} __packed;
+
+#endif /* __CROS_EC_NPCX_MONITOR_H */
diff --git a/zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.ld b/zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.ld
new file mode 100644
index 0000000000..03e38b0609
--- /dev/null
+++ b/zephyr/shim/chip/npcx/npcx_monitor/npcx_monitor.ld
@@ -0,0 +1,52 @@
+/* Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * NPCX SoC spi flash update tool
+ */
+
+/* Memory Spaces Definitions */
+MEMORY
+{
+ CODERAM (rx) : ORIGIN = 0x200C3020, LENGTH = 0xFE0
+}
+
+/*
+ * The entry point is informative, for debuggers and simulators,
+ * since the Cortex-M vector points to it anyway.
+ */
+ENTRY(sspi_flash_upload)
+
+
+/* Sections Definitions */
+
+SECTIONS
+{
+ .startup_text :
+ {
+ . = ALIGN(4);
+ *(.startup_text ) /* Startup code */
+ . = ALIGN(4);
+ } >CODERAM
+
+ /*
+ * The program code is stored in the .text section,
+ * which goes to CODERAM.
+ */
+ .text :
+ {
+ . = ALIGN(4);
+ *(.text .text.*) /* all remaining code */
+ *(.rodata .rodata.*) /* read-only data (constants) */
+ } >CODERAM
+
+ . = ALIGN(4);
+ _etext = .;
+
+ /*
+ * This address is used by the startup code to
+ * initialise the .data section.
+ */
+ _sidata = _etext;
+
+}
diff --git a/zephyr/shim/chip/npcx/npcx_monitor/registers.h b/zephyr/shim/chip/npcx/npcx_monitor/registers.h
new file mode 100644
index 0000000000..cc0a6b96fe
--- /dev/null
+++ b/zephyr/shim/chip/npcx/npcx_monitor/registers.h
@@ -0,0 +1,360 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Register map for NPCX processor
+ *
+ * This is meant to be temporary until the NPCX monitor support is moved
+ * to Zephyr upstream
+ */
+
+#ifndef __CROS_EC_REGISTERS_H
+#define __CROS_EC_REGISTERS_H
+
+/*
+ * The monitor code doesn't build cleanly under the Zephyr environment if
+ * include/common.h is included. Replicate the register access macros until
+ * this code is moved upstream.
+ */
+
+/* Macros to access registers */
+#define REG64_ADDR(addr) ((volatile uint64_t *)(addr))
+#define REG32_ADDR(addr) ((volatile uint32_t *)(addr))
+#define REG16_ADDR(addr) ((volatile uint16_t *)(addr))
+#define REG8_ADDR(addr) ((volatile uint8_t *)(addr))
+
+#define REG64(addr) (*REG64_ADDR(addr))
+#define REG32(addr) (*REG32_ADDR(addr))
+#define REG16(addr) (*REG16_ADDR(addr))
+#define REG8(addr) (*REG8_ADDR(addr))
+
+/* Standard macros / definitions */
+#define GENERIC_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define GENERIC_MIN(x, y) ((x) < (y) ? (x) : (y))
+#ifndef MAX
+#define MAX(a, b) \
+ ({ \
+ __typeof__(a) temp_a = (a); \
+ __typeof__(b) temp_b = (b); \
+ \
+ GENERIC_MAX(temp_a, temp_b); \
+ })
+#endif
+#ifndef MIN
+#define MIN(a, b) \
+ ({ \
+ __typeof__(a) temp_a = (a); \
+ __typeof__(b) temp_b = (b); \
+ \
+ GENERIC_MIN(temp_a, temp_b); \
+ })
+#endif
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+/******************************************************************************/
+/*
+ * Macro Functions
+ */
+/* Bit functions */
+#define SET_BIT(reg, bit) ((reg) |= (0x1 << (bit)))
+#define CLEAR_BIT(reg, bit) ((reg) &= (~(0x1 << (bit))))
+#define IS_BIT_SET(reg, bit) (((reg) >> (bit)) & (0x1))
+#define UPDATE_BIT(reg, bit, cond) { if (cond) \
+ SET_BIT(reg, bit); \
+ else \
+ CLEAR_BIT(reg, bit); }
+/* Field functions */
+#define GET_POS_FIELD(pos, size) pos
+#define GET_SIZE_FIELD(pos, size) size
+#define FIELD_POS(field) GET_POS_##field
+#define FIELD_SIZE(field) GET_SIZE_##field
+/* Read field functions */
+#define GET_FIELD(reg, field) \
+ _GET_FIELD_(reg, FIELD_POS(field), FIELD_SIZE(field))
+#define _GET_FIELD_(reg, f_pos, f_size) (((reg)>>(f_pos)) & ((1<<(f_size))-1))
+/* Write field functions */
+#define SET_FIELD(reg, field, value) \
+ _SET_FIELD_(reg, FIELD_POS(field), FIELD_SIZE(field), value)
+#define _SET_FIELD_(reg, f_pos, f_size, value) \
+ ((reg) = ((reg) & (~(((1 << (f_size))-1) << (f_pos)))) \
+ | ((value) << (f_pos)))
+
+
+/* NPCX7 & NPCX9 */
+#define NPCX_DEVALT(n) REG8(NPCX_SCFG_BASE_ADDR + 0x010 + (n))
+
+/******************************************************************************/
+/*
+ * NPCX (Nuvoton M4 EC) Register Definitions
+ */
+
+/* Modules Map */
+#define NPCX_ESPI_BASE_ADDR 0x4000A000
+#define NPCX_MDC_BASE_ADDR 0x4000C000
+#define NPCX_PMC_BASE_ADDR 0x4000D000
+#define NPCX_SIB_BASE_ADDR 0x4000E000
+#define NPCX_SHI_BASE_ADDR 0x4000F000
+#define NPCX_SHM_BASE_ADDR 0x40010000
+#define NPCX_GDMA_BASE_ADDR 0x40011000
+#define NPCX_FIU_BASE_ADDR 0x40020000
+#define NPCX_KBSCAN_REGS_BASE 0x400A3000
+#define NPCX_WOV_BASE_ADDR 0x400A4000
+#define NPCX_APM_BASE_ADDR 0x400A4800
+#define NPCX_GLUE_REGS_BASE 0x400A5000
+#define NPCX_BBRAM_BASE_ADDR 0x400AF000
+#define NPCX_PS2_BASE_ADDR 0x400B1000
+#define NPCX_HFCG_BASE_ADDR 0x400B5000
+#define NPCX_LFCG_BASE_ADDR 0x400B5100
+#define NPCX_FMUL2_BASE_ADDR 0x400B5200
+#define NPCX_MTC_BASE_ADDR 0x400B7000
+#define NPCX_MSWC_BASE_ADDR 0x400C1000
+#define NPCX_SCFG_BASE_ADDR 0x400C3000
+#define NPCX_KBC_BASE_ADDR 0x400C7000
+#define NPCX_ADC_BASE_ADDR 0x400D1000
+#define NPCX_SPI_BASE_ADDR 0x400D2000
+#define NPCX_PECI_BASE_ADDR 0x400D4000
+#define NPCX_TWD_BASE_ADDR 0x400D8000
+
+/* Multi-Modules Map */
+#define NPCX_PWM_BASE_ADDR(mdl) (0x40080000 + ((mdl) * 0x2000L))
+#define NPCX_GPIO_BASE_ADDR(mdl) (0x40081000 + ((mdl) * 0x2000L))
+#define NPCX_ITIM_BASE_ADDR(mdl) (0x400B0000 + ((mdl) * 0x2000L))
+#define NPCX_MIWU_BASE_ADDR(mdl) (0x400BB000 + ((mdl) * 0x2000L))
+#define NPCX_MFT_BASE_ADDR(mdl) (0x400E1000 + ((mdl) * 0x2000L))
+#define NPCX_PM_CH_BASE_ADDR(mdl) (0x400C9000 + ((mdl) * 0x2000L))
+
+
+/******************************************************************************/
+/* System Configuration (SCFG) Registers */
+#define NPCX_DEVCNT REG8(NPCX_SCFG_BASE_ADDR + 0x000)
+#define NPCX_STRPST REG8(NPCX_SCFG_BASE_ADDR + 0x001)
+#define NPCX_RSTCTL REG8(NPCX_SCFG_BASE_ADDR + 0x002)
+#define NPCX_DEV_CTL4 REG8(NPCX_SCFG_BASE_ADDR + 0x006)
+#define NPCX_LFCGCALCNT REG8(NPCX_SCFG_BASE_ADDR + 0x021)
+#define NPCX_PUPD_EN0 REG8(NPCX_SCFG_BASE_ADDR + 0x028)
+#define NPCX_PUPD_EN1 REG8(NPCX_SCFG_BASE_ADDR + 0x029)
+#define NPCX_SCFG_VER REG8(NPCX_SCFG_BASE_ADDR + 0x02F)
+
+#define TEST_BKSL REG8(NPCX_SCFG_BASE_ADDR + 0x037)
+#define TEST0 REG8(NPCX_SCFG_BASE_ADDR + 0x038)
+#define BLKSEL 0
+
+/* SCFG register fields */
+#define NPCX_DEVCNT_F_SPI_TRIS 6
+#define NPCX_DEVCNT_HIF_TYP_SEL_FIELD FIELD(2, 2)
+#define NPCX_DEVCNT_JEN1_HEN 5
+#define NPCX_DEVCNT_JEN0_HEN 4
+#define NPCX_STRPST_TRIST 1
+#define NPCX_STRPST_TEST 2
+#define NPCX_STRPST_JEN1 4
+#define NPCX_STRPST_JEN0 5
+#define NPCX_STRPST_SPI_COMP 7
+#define NPCX_RSTCTL_VCC1_RST_STS 0
+#define NPCX_RSTCTL_DBGRST_STS 1
+#define NPCX_RSTCTL_VCC1_RST_SCRATCH 3
+#define NPCX_RSTCTL_LRESET_PLTRST_MODE 5
+#define NPCX_RSTCTL_HIPRST_MODE 6
+#define NPCX_DEV_CTL4_F_SPI_SLLK 2
+#define NPCX_DEV_CTL4_SPI_SP_SEL 4
+#define NPCX_DEV_CTL4_WP_IF 5
+#define NPCX_DEV_CTL4_VCC1_RST_LK 6
+#define NPCX_DEVPU0_I2C0_0_PUE 0
+#define NPCX_DEVPU0_I2C0_1_PUE 1
+#define NPCX_DEVPU0_I2C1_0_PUE 2
+#define NPCX_DEVPU0_I2C2_0_PUE 4
+#define NPCX_DEVPU0_I2C3_0_PUE 6
+#define NPCX_DEVPU1_F_SPI_PUD_EN 7
+
+/* DEVALT */
+/* 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_CFG REG8(NPCX_FIU_BASE_ADDR + 0x000)
+#define NPCX_BURST_CFG REG8(NPCX_FIU_BASE_ADDR + 0x001)
+#define NPCX_RESP_CFG REG8(NPCX_FIU_BASE_ADDR + 0x002)
+#define NPCX_SPI_FL_CFG REG8(NPCX_FIU_BASE_ADDR + 0x014)
+#define NPCX_UMA_CODE REG8(NPCX_FIU_BASE_ADDR + 0x016)
+#define NPCX_UMA_AB0 REG8(NPCX_FIU_BASE_ADDR + 0x017)
+#define NPCX_UMA_AB1 REG8(NPCX_FIU_BASE_ADDR + 0x018)
+#define NPCX_UMA_AB2 REG8(NPCX_FIU_BASE_ADDR + 0x019)
+#define NPCX_UMA_DB0 REG8(NPCX_FIU_BASE_ADDR + 0x01A)
+#define NPCX_UMA_DB1 REG8(NPCX_FIU_BASE_ADDR + 0x01B)
+#define NPCX_UMA_DB2 REG8(NPCX_FIU_BASE_ADDR + 0x01C)
+#define NPCX_UMA_DB3 REG8(NPCX_FIU_BASE_ADDR + 0x01D)
+#define NPCX_UMA_CTS REG8(NPCX_FIU_BASE_ADDR + 0x01E)
+#define NPCX_UMA_ECTS REG8(NPCX_FIU_BASE_ADDR + 0x01F)
+#define NPCX_UMA_DB0_3 REG32(NPCX_FIU_BASE_ADDR + 0x020)
+#define NPCX_FIU_RD_CMD REG8(NPCX_FIU_BASE_ADDR + 0x030)
+#define NPCX_FIU_DMM_CYC REG8(NPCX_FIU_BASE_ADDR + 0x032)
+#define NPCX_FIU_EXT_CFG REG8(NPCX_FIU_BASE_ADDR + 0x033)
+#define NPCX_FIU_UMA_AB0_3 REG32(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
+
+/******************************************************************************/
+/* KBC Registers */
+#define NPCX_HICTRL REG8(NPCX_KBC_BASE_ADDR + 0x000)
+#define NPCX_HIIRQC REG8(NPCX_KBC_BASE_ADDR + 0x002)
+#define NPCX_HIKMST REG8(NPCX_KBC_BASE_ADDR + 0x004)
+#define NPCX_HIKDO REG8(NPCX_KBC_BASE_ADDR + 0x006)
+#define NPCX_HIMDO REG8(NPCX_KBC_BASE_ADDR + 0x008)
+#define NPCX_KBCVER REG8(NPCX_KBC_BASE_ADDR + 0x009)
+#define NPCX_HIKMDI REG8(NPCX_KBC_BASE_ADDR + 0x00A)
+#define NPCX_SHIKMDI REG8(NPCX_KBC_BASE_ADDR + 0x00B)
+
+/* KBC register field */
+#define NPCX_HICTRL_OBFKIE 0 /* Automatic Serial IRQ1 for KBC */
+#define NPCX_HICTRL_OBFMIE 1 /* Automatic Serial IRQ12 for Mouse*/
+#define NPCX_HICTRL_OBECIE 2 /* KBC OBE interrupt enable */
+#define NPCX_HICTRL_IBFCIE 3 /* KBC IBF interrupt enable */
+#define NPCX_HICTRL_PMIHIE 4 /* Automatic Serial IRQ11 for PMC1 */
+#define NPCX_HICTRL_PMIOCIE 5 /* PMC1 OBE interrupt enable */
+#define NPCX_HICTRL_PMICIE 6 /* PMC1 IBF interrupt enable */
+#define NPCX_HICTRL_FW_OBF 7 /* Firmware control over OBF */
+
+#define NPCX_HIKMST_OBF 0 /* KB output buffer is full */
+
+/******************************************************************************/
+/* Timer Watch Dog (TWD) Registers */
+#define NPCX_TWCFG REG8(NPCX_TWD_BASE_ADDR + 0x000)
+#define NPCX_TWCP REG8(NPCX_TWD_BASE_ADDR + 0x002)
+#define NPCX_TWDT0 REG16(NPCX_TWD_BASE_ADDR + 0x004)
+#define NPCX_T0CSR REG8(NPCX_TWD_BASE_ADDR + 0x006)
+#define NPCX_WDCNT REG8(NPCX_TWD_BASE_ADDR + 0x008)
+#define NPCX_WDSDM REG8(NPCX_TWD_BASE_ADDR + 0x00A)
+#define NPCX_TWMT0 REG16(NPCX_TWD_BASE_ADDR + 0x00C)
+#define NPCX_TWMWD REG8(NPCX_TWD_BASE_ADDR + 0x00E)
+#define NPCX_WDCP REG8(NPCX_TWD_BASE_ADDR + 0x010)
+
+/* TWD register fields */
+#define NPCX_TWCFG_LTWCFG 0
+#define NPCX_TWCFG_LTWCP 1
+#define NPCX_TWCFG_LTWDT0 2
+#define NPCX_TWCFG_LWDCNT 3
+#define NPCX_TWCFG_WDCT0I 4
+#define NPCX_TWCFG_WDSDME 5
+#define NPCX_TWCFG_WDRST_MODE 6
+#define NPCX_TWCFG_WDC2POR 7
+#define NPCX_T0CSR_RST 0
+#define NPCX_T0CSR_TC 1
+#define NPCX_T0CSR_WDLTD 3
+#define NPCX_T0CSR_WDRST_STS 4
+#define NPCX_T0CSR_WD_RUN 5
+#define NPCX_T0CSR_TESDIS 7
+
+/******************************************************************************/
+/* SPI Register */
+#define NPCX_SPI_DATA REG16(NPCX_SPI_BASE_ADDR + 0x00)
+#define NPCX_SPI_CTL1 REG16(NPCX_SPI_BASE_ADDR + 0x02)
+#define NPCX_SPI_STAT REG8(NPCX_SPI_BASE_ADDR + 0x04)
+
+/* SPI register fields */
+#define NPCX_SPI_CTL1_SPIEN 0
+#define NPCX_SPI_CTL1_SNM 1
+#define NPCX_SPI_CTL1_MOD 2
+#define NPCX_SPI_CTL1_EIR 5
+#define NPCX_SPI_CTL1_EIW 6
+#define NPCX_SPI_CTL1_SCM 7
+#define NPCX_SPI_CTL1_SCIDL 8
+#define NPCX_SPI_CTL1_SCDV 9
+#define NPCX_SPI_STAT_BSY 0
+#define NPCX_SPI_STAT_RBF 1
+
+/******************************************************************************/
+/* Flash Utiltiy definition */
+/*
+ * Flash commands for the W25Q16CV SPI flash
+ */
+#define CMD_READ_ID 0x9F
+#define CMD_READ_MAN_DEV_ID 0x90
+#define CMD_WRITE_EN 0x06
+#define CMD_WRITE_STATUS 0x50
+#define CMD_READ_STATUS_REG 0x05
+#define CMD_READ_STATUS_REG2 0x35
+#define CMD_WRITE_STATUS_REG 0x01
+#define CMD_FLASH_PROGRAM 0x02
+#define CMD_SECTOR_ERASE 0x20
+#define CMD_BLOCK_32K_ERASE 0x52
+#define CMD_BLOCK_64K_ERASE 0xd8
+#define CMD_PROGRAM_UINT_SIZE 0x08
+#define CMD_PAGE_SIZE 0x00
+#define CMD_READ_ID_TYPE 0x47
+#define CMD_FAST_READ 0x0B
+
+/*
+ * Status registers for the W25Q16CV SPI flash
+ */
+#define SPI_FLASH_SR2_SUS BIT(7)
+#define SPI_FLASH_SR2_CMP BIT(6)
+#define SPI_FLASH_SR2_LB3 BIT(5)
+#define SPI_FLASH_SR2_LB2 BIT(4)
+#define SPI_FLASH_SR2_LB1 BIT(3)
+#define SPI_FLASH_SR2_QE BIT(1)
+#define SPI_FLASH_SR2_SRP1 BIT(0)
+#define SPI_FLASH_SR1_SRP0 BIT(7)
+#define SPI_FLASH_SR1_SEC BIT(6)
+#define SPI_FLASH_SR1_TB BIT(5)
+#define SPI_FLASH_SR1_BP2 BIT(4)
+#define SPI_FLASH_SR1_BP1 BIT(3)
+#define SPI_FLASH_SR1_BP0 BIT(2)
+#define SPI_FLASH_SR1_WEL BIT(1)
+#define SPI_FLASH_SR1_BUSY BIT(0)
+
+
+/* 0: F_CS0 1: F_CS1_1(GPIO86) 2:F_CS1_2(GPIOA6) */
+#define FIU_CHIP_SELECT 0
+/* Create UMA control mask */
+#define MASK(bit) (0x1 << (bit))
+#define A_SIZE 0x03 /* 0: No ADR field 1: 3-bytes ADR field */
+#define C_SIZE 0x04 /* 0: 1-Byte CMD field 1:No CMD field */
+#define RD_WR 0x05 /* 0: Read 1: Write */
+#define DEV_NUM 0x06 /* 0: PVT is used 1: SHD is used */
+#define EXEC_DONE 0x07
+#define D_SIZE_1 0x01
+#define D_SIZE_2 0x02
+#define D_SIZE_3 0x03
+#define D_SIZE_4 0x04
+#define FLASH_SEL MASK(DEV_NUM)
+
+#define MASK_CMD_ONLY (MASK(EXEC_DONE) | FLASH_SEL)
+#define MASK_CMD_ADR (MASK(EXEC_DONE) | FLASH_SEL | MASK(A_SIZE))
+#define MASK_CMD_ADR_WR (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) \
+ |MASK(A_SIZE) | D_SIZE_1)
+#define MASK_RD_1BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_1)
+#define MASK_RD_2BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_2)
+#define MASK_RD_3BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_3)
+#define MASK_RD_4BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(C_SIZE) | D_SIZE_4)
+#define MASK_CMD_RD_1BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_1)
+#define MASK_CMD_RD_2BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_2)
+#define MASK_CMD_RD_3BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_3)
+#define MASK_CMD_RD_4BYTE (MASK(EXEC_DONE) | FLASH_SEL | D_SIZE_4)
+#define MASK_CMD_WR_ONLY (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR))
+#define MASK_CMD_WR_1BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) \
+ | MASK(C_SIZE) | D_SIZE_1)
+#define MASK_CMD_WR_2BYTE (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) \
+ | MASK(C_SIZE) | D_SIZE_2)
+#define MASK_CMD_WR_ADR (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) \
+ | MASK(A_SIZE))
+
+
+#endif /* __CROS_EC_REGISTERS_H */