summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Chao <mlchao@nuvoton.com>2015-06-25 18:12:09 +0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-06-26 18:57:32 +0000
commit957638c78cc5aa0ba37ef281e2c6a09215c5d60e (patch)
treebc783f701e5b968449bfe3652e8cc20680620c8d
parentccb6b15d514b695b9ea472aa98d5f1730d58e244 (diff)
downloadchrome-ec-957638c78cc5aa0ba37ef281e2c6a09215c5d60e.tar.gz
nuc: Add SHI driver for arm-based platform in chip folder.
Add npcx_evb_arm board-level driver for arm-based platform. Add header.c: for booting from NPCX5M5G A3 Booter. Remove lfw folder due to those functionalitie have been replaced with Booter Modified drivers for Patch Set 1: 1. flash.c: Implement UMA lock, tri-state and selection register lock functionalities 2. hwtimer.c: Add ITIM32 for hwtimer 3. lpc.c: Add checking for LRESET 4. system.c: Modified CODERAM_ARCH functions for NPCX5M5G A3 Booter. 5. uart.c: Add support for module 2 Patch Set 2: 6. lpc.c: Modified lpc_get_pltrst_asserted() func Patch Set 3: 7. minimize the changes for CONFIG_CODERAM_ARCH in common layer 8. comments of Patch Set1/2 Patch Set 4: 9. Modified CONFIG_RO_MEM_OFF point to ro image and keep header as a part of ec.RO.flat. 10. Fixed RO_FRID and RW_FRID issues which caused by CONFIG_CODERAM_ARCH. Patch Set 5: 11. Modified system.c in common folder for supporting *_STORAGE_OFF. 12. Use *_STORAGE_OFF in firmware_image.lds.S to indicate flat file layout in flash. Patch Set 6: 13. rebase to newest version 14. system.c: Modified for the newest include/system.h Patch Set 7: 15. Merge from version 0625 BUG=chrome-os-partner:34346 TEST=make buildall -j; test nuvoton IC specific drivers BRANCH=none Change-Id: Ifd7c10b81b5781ccd75bb2558dc236486976e8ed Signed-off-by: Ian Chao <mlchao@nuvoton.com> Reviewed-on: https://chromium-review.googlesource.com/272034 Reviewed-by: Shawn N <shawnn@chromium.org> Tested-by: Shawn N <shawnn@chromium.org> Commit-Queue: Shawn N <shawnn@chromium.org>
-rw-r--r--Makefile.rules10
l---------board/npcx_evb/Makefile1
-rw-r--r--board/npcx_evb/board.c2
-rw-r--r--board/npcx_evb/board.h9
-rw-r--r--board/npcx_evb/gpio.inc32
l---------board/npcx_evb_arm/Makefile1
-rw-r--r--board/npcx_evb_arm/board.c131
-rw-r--r--board/npcx_evb_arm/board.h90
-rw-r--r--board/npcx_evb_arm/build.mk12
-rw-r--r--board/npcx_evb_arm/ec.tasklist23
-rw-r--r--board/npcx_evb_arm/gpio.inc64
-rw-r--r--chip/npcx/build.mk8
-rw-r--r--chip/npcx/clock.c31
-rw-r--r--chip/npcx/config_chip.h48
-rw-r--r--chip/npcx/fan.c6
-rw-r--r--chip/npcx/flash.c109
-rw-r--r--chip/npcx/gpio.c46
-rw-r--r--chip/npcx/header.c72
-rw-r--r--chip/npcx/hwtimer.c108
-rw-r--r--chip/npcx/hwtimer_chip.h13
-rw-r--r--chip/npcx/i2c.c2
-rw-r--r--chip/npcx/jtag.c2
-rw-r--r--chip/npcx/lfw/ec_lfw.c141
-rw-r--r--chip/npcx/lfw/ec_lfw.ld122
-rw-r--r--chip/npcx/lpc.c179
-rw-r--r--chip/npcx/openocd/npcx.cfg2
-rw-r--r--chip/npcx/openocd/npcx_cmds.tcl68
-rw-r--r--chip/npcx/pwm.c4
-rw-r--r--chip/npcx/registers.h192
-rw-r--r--chip/npcx/rom_chip.h66
-rw-r--r--chip/npcx/shi.c859
-rw-r--r--chip/npcx/shi_chip.h21
-rw-r--r--chip/npcx/system.c233
-rw-r--r--chip/npcx/system_chip.h2
-rw-r--r--chip/npcx/uart.c24
-rw-r--r--chip/npcx/watchdog.c6
-rw-r--r--common/firmware_image.lds.S6
-rw-r--r--common/fmap.c5
-rw-r--r--core/cortex-m/ec.lds.S19
-rwxr-xr-xutil/flash_ec6
40 files changed, 2094 insertions, 681 deletions
diff --git a/Makefile.rules b/Makefile.rules
index a1199bbd7d..5f52fc38c8 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -261,16 +261,6 @@ $(npcx-flash-fw-bin):
-Wl,-Map,$(out)/$(npcx-flash-fw).map
-@ $(OBJCOPY) -O binary $(out)/$(npcx-flash-fw).elf $@
-# TODO: optional make rules for PROJECT_EXTRA
-$(npcx-lfw-bin):
- $(if $(V),,@echo ' EXTBIN ' $(subst $(out)/,,$@) ; )
- -@ mkdir -p $(@D)
- -@ $(CC) $(CFLAGS) -MMD -MF $(out)/$(npcx-lfw).d -c $(npcx-lfw).c \
- -o $(out)/$(npcx-lfw).o
- -@ $(CC) $(out)/$(npcx-lfw).o $(LDFLAGS) -o $(out)/$(npcx-lfw).elf \
- -Wl,-T,$(npcx-lfw).ld -Wl,-Map,$(out)/$(npcx-lfw).map
- -@ $(OBJCOPY) -O binary $(out)/$(npcx-lfw).elf $@
-
.PHONY: xrefs
xrefs: $(call targ_if_prog,etags,$(out)/TAGS) \
$(call targ_if_prog,ctags,$(out)/tags)
diff --git a/board/npcx_evb/Makefile b/board/npcx_evb/Makefile
new file mode 120000
index 0000000000..94aaae2c4d
--- /dev/null
+++ b/board/npcx_evb/Makefile
@@ -0,0 +1 @@
+../../Makefile \ No newline at end of file
diff --git a/board/npcx_evb/board.c b/board/npcx_evb/board.c
index 1dacb2ec5c..9523c3b937 100644
--- a/board/npcx_evb/board.c
+++ b/board/npcx_evb/board.c
@@ -97,7 +97,7 @@ const struct mft_t mft_channels[] = {
.module = NPCX_MFT_MODULE_1,
.port = NPCX_MFT_MODULE_PORT_TA,
.default_count = 0xFFFF,
-#ifdef CONFIG_MFT_INPUT_LFCLK
+#ifdef NPCX_MFT_INPUT_LFCLK
.freq = 32768,
#else
.freq = 2000000,
diff --git a/board/npcx_evb/board.h b/board/npcx_evb/board.h
index 6395947133..f4059151fc 100644
--- a/board/npcx_evb/board.h
+++ b/board/npcx_evb/board.h
@@ -16,6 +16,7 @@
#define CONFIG_PECI
#define CONFIG_PWM
#define CONFIG_SPI
+#define CONFIG_LPC /* Used in Intel-based platform for host interface */
/* Optional features */
#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */
@@ -42,8 +43,12 @@
#define CONFIG_FANS 1
/* Optional feature - used by nuvoton */
-#define CONFIG_PWM_INPUT_LFCLK /* PWM use LFCLK for input clock */
-#define CONFIG_MFT_INPUT_LFCLK /* MFT use LFCLK for input clock */
+#define NPCX_PWM_INPUT_LFCLK /* PWM use LFCLK for input clock */
+#define NPCX_MFT_INPUT_LFCLK /* MFT use LFCLK for input clock */
+#define NPCX_I2C0_BUS2 0 /* 0:GPIOB4/B5 1:GPIOB2/B3 as I2C0 */
+#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */
+#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/
+#define NPCX_TACH_SEL2 0 /* 0:GPIO40/A4 1:GPIO93/D3 as TACH */
/* Optional for testing */
#undef CONFIG_PSTORE
diff --git a/board/npcx_evb/gpio.inc b/board/npcx_evb/gpio.inc
index 4c6114c784..c51ecc9c05 100644
--- a/board/npcx_evb/gpio.inc
+++ b/board/npcx_evb/gpio.inc
@@ -5,20 +5,22 @@
* found in the LICENSE file.
*/
+/********************** Inputs with interrupt handlers are first for efficiency **********************/
/* TODO: Redefine debug 2 inputs */
-GPIO_INT(RECOVERY_L, PIN(0, 0), GPIO_PULL_UP | GPIO_INT_BOTH, switch_interrupt) /* Recovery signal from servo */
-GPIO_INT(WP_L, PIN(9, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, switch_interrupt) /* Write protect input */
+GPIO_INT(RECOVERY_L, PIN(0, 0), GPIO_PULL_UP | GPIO_INT_BOTH, switch_interrupt) /* Recovery signal from servo */
+GPIO_INT(WP_L, PIN(9, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, switch_interrupt) /* Write protect input */
-/* For testing 8042 commands, we need the following GPIOs */
+/* For testing keyboard commands, we need the following 4 GPIOs */
/* TODO: Redefine 4 inputs */
-GPIO_INT(POWER_BUTTON_L, PIN(0, 2), GPIO_PULL_UP | GPIO_INT_BOTH, power_button_interrupt) /* Power button */
-GPIO_INT(LID_OPEN, PIN(3, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, lid_interrupt) /* Lid switch */
+GPIO_INT(POWER_BUTTON_L, PIN(0, 2), GPIO_PULL_UP | GPIO_INT_BOTH, power_button_interrupt) /* Power button */
+GPIO_INT(LID_OPEN, PIN(3, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, lid_interrupt) /* Lid switch */
+/**************************** Need a empty line between GPIO_INT and GPIO ****************************/
GPIO(ENTERING_RW, PIN(3, 6), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */
GPIO(PCH_WAKE_L, PIN(5, 0), GPIO_OUT_HIGH) /* Wake signal output to PCH */
/* Used for module testing */
-GPIO(PGOOD_FAN, PIN(C, 7), GPIO_PULL_UP | GPIO_INPUT) /* Power Good for FAN test */
+GPIO(PGOOD_FAN, PIN(C, 7), GPIO_PULL_UP | GPIO_INPUT) /* Power Good for FAN test */
GPIO(SPI_CS_L, PIN(A, 5), GPIO_OUT_HIGH) /* SPI_CS Ready, Low Active. */
/*
@@ -35,14 +37,28 @@ GPIO(BOARD_VERSION3, PIN(6, 6), GPIO_INPUT) /* Board version stuffing r
#ifdef CONFIG_KEYBOARD_COL2_INVERTED
GPIO(KBD_KSO2, PIN(1, 7), GPIO_OUT_LOW) /* Negative edge triggered keyboard irq. */
#endif
+
+/**************************** Alternate pins for UART/I2C/ADC/SPI/PWM/MFT ****************************/
/* Alternate pins for UART/I2C/ADC/SPI/PWM/MFT */
+#if NPCX_UART_MODULE2
+ALTERNATE(PIN_MASK(6, 0x30), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO64/65 */
+#else
ALTERNATE(PIN_MASK(1, 0x03), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO10/11 */
-ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB4/B5 */
+#endif
+#if NPCX_I2C0_BUS2
+ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB2/B3 */
+#else
+ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB4/B5 */
+#endif
ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1SDA GPIO87 */
ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1SCL/I2C2SDA/I2C2SCL GPIO90/91/92 */
ALTERNATE(PIN_MASK(4, 0x38), 1, MODULE_ADC, 0) /* ADC GPIO45/44/43 */
-ALTERNATE(PIN_MASK(A, 0x0A), 1, MODULE_SPI, 0) /* SPIP_MOSI/SPIP_SCLK GPIOA3/A1 */
+ALTERNATE(PIN_MASK(A, 0x0A), 1, MODULE_SPI, 0) /* SPIP_MOSI/SPIP_SCLK GPIOA3/A1 */
ALTERNATE(PIN_MASK(9, 0x20), 1, MODULE_SPI, 0) /* SPIP_MISO GPIO95 */
ALTERNATE(PIN_MASK(C, 0x04), 3, MODULE_PWM_KBLIGHT, 0) /* PWM1 for PWM/KBLIGHT Test GPIOC2 */
ALTERNATE(PIN_MASK(C, 0x08), 7, MODULE_PWM_FAN, 0) /* PWM0 for PWM/FAN Test GPIOC3 */
+#if NPCX_TACH_SEL2
+ALTERNATE(PIN_MASK(9, 0x08), 3, MODULE_PWM_FAN, 0) /* MFT-1/TA1_TACH1 for FAN GPIO93 */
+#else
ALTERNATE(PIN_MASK(4, 0x01), 3, MODULE_PWM_FAN, 0) /* MFT-1/TA1_TACH1 for FAN Test GPIO40 */
+#endif
diff --git a/board/npcx_evb_arm/Makefile b/board/npcx_evb_arm/Makefile
new file mode 120000
index 0000000000..94aaae2c4d
--- /dev/null
+++ b/board/npcx_evb_arm/Makefile
@@ -0,0 +1 @@
+../../Makefile \ No newline at end of file
diff --git a/board/npcx_evb_arm/board.c b/board/npcx_evb_arm/board.c
new file mode 100644
index 0000000000..56eb9b5635
--- /dev/null
+++ b/board/npcx_evb_arm/board.c
@@ -0,0 +1,131 @@
+/* Copyright 2015 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.
+ */
+/* EC for Nuvoton M4 EB configuration */
+
+#include "adc.h"
+#include "adc_chip.h"
+#include "backlight.h"
+#include "chipset.h"
+#include "common.h"
+#include "driver/temp_sensor/tmp006.h"
+#include "extpower.h"
+#include "fan.h"
+#include "fan_chip.h"
+#include "gpio.h"
+#include "i2c.h"
+#include "keyboard_scan.h"
+#include "lid_switch.h"
+#include "peci.h"
+#include "power.h"
+#include "power_button.h"
+#include "pwm.h"
+#include "pwm_chip.h"
+#include "registers.h"
+#include "switch.h"
+#include "temp_sensor.h"
+#include "temp_sensor_chip.h"
+#include "timer.h"
+#include "thermal.h"
+#include "util.h"
+#include "shi_chip.h"
+
+#include "gpio_list.h"
+
+/******************************************************************************/
+/* ADC channels. Must be in the exactly same order as in enum adc_channel. */
+const struct adc_t adc_channels[] = {
+ [ADC_CH_0] = {"ADC0", NPCX_ADC_INPUT_CH0, ADC_MAX_VOLT,
+ ADC_READ_MAX+1, 0},
+ [ADC_CH_1] = {"ADC1", NPCX_ADC_INPUT_CH1, ADC_MAX_VOLT,
+ ADC_READ_MAX+1, 0},
+ [ADC_CH_2] = {"ADC2", NPCX_ADC_INPUT_CH2, ADC_MAX_VOLT,
+ ADC_READ_MAX+1, 0},
+};
+BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
+
+/******************************************************************************/
+/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */
+const struct pwm_t pwm_channels[] = {
+ [PWM_CH_FAN] = {
+ .channel = 0,
+ /*
+ * flags can reverse the PWM output signal according to
+ * the board design
+ */
+ .flags = PWM_CONFIG_ACTIVE_LOW,
+ /*
+ * freq_operation = freq_input / prescaler_divider
+ * freq_output = freq_operation / cycle_pulses
+ * and freq_output <= freq_mft
+ */
+ .freq = 34,
+ /*
+ * cycle_pulses = (cycle_pulses * freq_output) *
+ * RPM_EDGES * RPM_SCALE * 60 / poles / rpm_min
+ */
+ .cycle_pulses = 480,
+ },
+ [PWM_CH_KBLIGHT] = {
+ .channel = 1,
+ .flags = 0,
+ .freq = 10000,
+ .cycle_pulses = 100,
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT);
+
+/******************************************************************************/
+/* Physical fans. These are logically separate from pwm_channels. */
+const struct fan_t fans[] = {
+ [FAN_CH_0] = {
+ .flags = FAN_USE_RPM_MODE,
+ .rpm_min = 1020,
+ .rpm_start = 1020,
+ .rpm_max = 8190,
+ .ch = 0,/* Use PWM/MFT to control fan */
+ .pgood_gpio = GPIO_PGOOD_FAN,
+ .enable_gpio = -1,
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT);
+
+/******************************************************************************/
+/* MFT channels. These are logically separate from mft_channels. */
+const struct mft_t mft_channels[] = {
+ [MFT_CH_0] = {
+ .module = NPCX_MFT_MODULE_1,
+ .port = NPCX_MFT_MODULE_PORT_TA,
+ .default_count = 0xFFFF,
+#ifdef NPCX_MFT_INPUT_LFCLK
+ .freq = 32768,
+#else
+ .freq = 2000000,
+#endif
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT);
+
+/******************************************************************************/
+/* I2C ports */
+const struct i2c_port_t i2c_ports[] = {
+ {"master", I2C_PORT_MASTER, 100,
+ GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA},
+};
+const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+
+/******************************************************************************/
+/* Keyboard scan setting */
+struct keyboard_scan_config keyscan_config = {
+ .output_settle_us = 40,
+ .debounce_down_us = 6 * MSEC,
+ .debounce_up_us = 30 * MSEC,
+ .scan_period_us = 1500,
+ .min_post_scan_delay_us = 1000,
+ .poll_timeout_us = SECOND,
+ .actual_key_mask = {
+ 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff,
+ 0xa4, 0xff, 0xf6, 0x55, 0xfa, 0xc8 /* full set */
+ },
+};
diff --git a/board/npcx_evb_arm/board.h b/board/npcx_evb_arm/board.h
new file mode 100644
index 0000000000..62856cda56
--- /dev/null
+++ b/board/npcx_evb_arm/board.h
@@ -0,0 +1,90 @@
+/* Copyright 2015 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.
+ */
+
+/* Configuration for Nuvoton M4 EB */
+
+#ifndef __CROS_EC_BOARD_H
+#define __CROS_EC_BOARD_H
+
+/* Support Code RAM architecture (Run code in RAM) */
+#define CONFIG_CODERAM_ARCH
+
+/* Optional modules */
+#define CONFIG_ADC
+#define CONFIG_PWM
+#define CONFIG_SHI /* Used in ARM-based platform for host interface */
+
+/* Optional features */
+#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */
+#define CONFIG_SPI_FLASH_SIZE 0x00800000 /* 8MB spi flash */
+#define CONFIG_SPI_FLASH_W25Q64
+#define CONFIG_KEYBOARD_BOARD_CONFIG
+#define CONFIG_KEYBOARD_PROTOCOL_MKBP /* Instead of 8042 protocol of keyboard */
+#define CONFIG_POWER_BUTTON
+#define CONFIG_VBOOT_HASH
+#define CONFIG_PWM_KBLIGHT
+#define CONFIG_BOARD_VERSION
+
+/* Optional features for test commands */
+#define CONFIG_CMD_TASKREADY
+#define CONFIG_CMD_STACKOVERFLOW
+#define CONFIG_CMD_JUMPTAGS
+#define CONFIG_CMD_FLASH
+#define CONFIG_CMD_SPI_FLASH
+#define CONFIG_CMD_SCRATCHPAD
+#define CONFIG_CMD_I2CWEDGE
+
+#define CONFIG_UART_HOST 0
+#define CONFIG_FANS 1
+
+/* Optional feature - used by nuvoton */
+#define NPCX_PWM_INPUT_LFCLK /* PWM use LFCLK for input clock */
+#define NPCX_MFT_INPUT_LFCLK /* MFT use LFCLK for input clock */
+#define NPCX_I2C0_BUS2 0 /* 0:GPIOB4/B5 1:GPIOB2/B3 as I2C0 */
+#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */
+#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/
+#define NPCX_TACH_SEL2 0 /* 0:GPIO40/A4 1:GPIO93/D3 as TACH */
+
+/* Optional for testing */
+#undef CONFIG_PSTORE
+#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */
+
+/* Single I2C port, where the EC is the master. */
+#define I2C_PORT_MASTER 0
+#define I2C_PORT_HOST 0
+
+#ifndef __ASSEMBLER__
+
+enum adc_channel {
+ ADC_CH_0 = 0,
+ ADC_CH_1,
+ ADC_CH_2,
+ ADC_CH_COUNT
+};
+
+enum pwm_channel {
+ PWM_CH_FAN,
+ PWM_CH_KBLIGHT,
+ /* Number of PWM channels */
+ PWM_CH_COUNT
+};
+
+enum fan_channel {
+ FAN_CH_0,
+ /* Number of FAN channels */
+ FAN_CH_COUNT
+};
+
+enum mft_channel {
+ MFT_CH_0,
+ /* Number of MFT channels */
+ MFT_CH_COUNT
+};
+
+#include "gpio_signal.h"
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* __CROS_EC_BOARD_H */
diff --git a/board/npcx_evb_arm/build.mk b/board/npcx_evb_arm/build.mk
new file mode 100644
index 0000000000..ebebf140d8
--- /dev/null
+++ b/board/npcx_evb_arm/build.mk
@@ -0,0 +1,12 @@
+# -*- makefile -*-
+# Copyright 2015 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.
+#
+# Board specific files build
+#
+
+# the IC is Nuvoton M-Series EC
+CHIP:=npcx
+
+board-y=board.o
diff --git a/board/npcx_evb_arm/ec.tasklist b/board/npcx_evb_arm/ec.tasklist
new file mode 100644
index 0000000000..a44d142596
--- /dev/null
+++ b/board/npcx_evb_arm/ec.tasklist
@@ -0,0 +1,23 @@
+/* Copyright 2015 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.
+ */
+
+/**
+ * List of enabled tasks in the priority order
+ *
+ * The first one has the lowest priority.
+ *
+ * For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and
+ * TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries,
+ * where :
+ * 'n' is the name of the task
+ * 'r' is the main routine of the task
+ * 'd' is an opaque parameter passed to the routine at startup
+ * 's' is the stack size in bytes; must be a multiple of 8
+ */
+#define CONFIG_TASK_LIST \
+ TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, TASK_STACK_SIZE) \
+ TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE)
diff --git a/board/npcx_evb_arm/gpio.inc b/board/npcx_evb_arm/gpio.inc
new file mode 100644
index 0000000000..410ac90894
--- /dev/null
+++ b/board/npcx_evb_arm/gpio.inc
@@ -0,0 +1,64 @@
+/* -*- mode:c -*-
+ *
+ * Copyright 2015 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.
+ */
+
+/********************** Inputs with interrupt handlers are first for efficiency **********************/
+/* TODO: Redefine debug 2 inputs */
+GPIO_INT(RECOVERY_L, PIN(0, 0), GPIO_PULL_UP | GPIO_INT_BOTH, switch_interrupt) /* Recovery signal from servo */
+GPIO_INT(WP_L, PIN(9, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, switch_interrupt) /* Write protect input */
+/* Used for ARM based platform */
+GPIO_INT(SHI_CS_L, PIN(5, 3), GPIO_INT_FALLING,shi_cs_event) /* SHI CS Ready, Low Active. */
+/* For testing keyboard commands, we need the following 4 GPIOs */
+/* TODO: Redefine 4 inputs */
+GPIO_INT(POWER_BUTTON_L, PIN(0, 2), GPIO_PULL_UP | GPIO_INT_BOTH, power_button_interrupt) /* Power button */
+GPIO_INT(LID_OPEN, PIN(3, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, lid_interrupt) /* Lid switch */
+
+/**************************** Need a empty line between GPIO_INT and GPIO ****************************/
+GPIO(ENTERING_RW, PIN(3, 6), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */
+GPIO(PCH_WAKE_L, PIN(5, 0), GPIO_OUT_HIGH) /* Wake signal output to PCH */
+/* For testing keyboard mkbp */
+GPIO(EC_INT, PIN(7, 4), GPIO_ODR_HIGH) /* Interrupt pin for keyboard mkbp */
+/* Used for module testing */
+GPIO(PGOOD_FAN, PIN(C, 7), GPIO_PULL_UP | GPIO_INPUT) /* Power Good for FAN test */
+
+/*
+ * I2C pins should be configured as inputs until I2C module is
+ * initialized. This will avoid driving the lines unintentionally.
+ */
+GPIO(MASTER_I2C_SCL, PIN(B, 5), GPIO_INPUT)
+GPIO(MASTER_I2C_SDA, PIN(B, 4), GPIO_INPUT)
+/* Used for board version command */
+GPIO(BOARD_VERSION1, PIN(6, 4), GPIO_INPUT) /* Board version stuffing resistor 1 */
+GPIO(BOARD_VERSION2, PIN(6, 5), GPIO_INPUT) /* Board version stuffing resistor 2 */
+GPIO(BOARD_VERSION3, PIN(6, 6), GPIO_INPUT) /* Board version stuffing resistor 3 */
+#ifdef CONFIG_KEYBOARD_COL2_INVERTED
+GPIO(KBD_KSO2, PIN(1, 7), GPIO_OUT_LOW) /* Negative edge triggered keyboard irq. */
+#endif
+
+/**************************** Alternate pins for UART/I2C/ADC/SPI/PWM/MFT ****************************/
+/* Alternate pins for UART/I2C/ADC/SPI/PWM/MFT */
+#if NPCX_UART_MODULE2
+ALTERNATE(PIN_MASK(6, 0x30), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO64/65 */
+#else
+ALTERNATE(PIN_MASK(1, 0x03), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO10/11 */
+#endif
+#if NPCX_I2C0_BUS2
+ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB2/B3 */
+#else
+ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB4/B5 */
+#endif
+ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1SDA GPIO87 */
+ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1SCL/I2C2SDA/I2C2SCL GPIO90/91/92 */
+ALTERNATE(PIN_MASK(4, 0x38), 1, MODULE_ADC, 0) /* ADC GPIO45/44/43 */
+ALTERNATE(PIN_MASK(A, 0x0A), 1, MODULE_SPI, 0) /* SPIP_MOSI/SPIP_SCLK GPIOA3/A1 */
+ALTERNATE(PIN_MASK(9, 0x20), 1, MODULE_SPI, 0) /* SPIP_MISO GPIO95 */
+ALTERNATE(PIN_MASK(C, 0x04), 3, MODULE_PWM_KBLIGHT, 0) /* PWM1 for PWM/KBLIGHT Test GPIOC2 */
+ALTERNATE(PIN_MASK(C, 0x08), 7, MODULE_PWM_FAN, 0) /* PWM0 for PWM/FAN Test GPIOC3 */
+#if NPCX_TACH_SEL2
+ALTERNATE(PIN_MASK(9, 0x08), 3, MODULE_PWM_FAN, 0) /* MFT-1/TA1_TACH1 for FAN GPIO93 */
+#else
+ALTERNATE(PIN_MASK(4, 0x01), 3, MODULE_PWM_FAN, 0) /* MFT-1/TA1_TACH1 for FAN Test GPIO40 */
+#endif
diff --git a/chip/npcx/build.mk b/chip/npcx/build.mk
index 7ad02aaf30..011396eccc 100644
--- a/chip/npcx/build.mk
+++ b/chip/npcx/build.mk
@@ -12,7 +12,7 @@ CORE:=cortex-m
CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4
# Required chip modules
-chip-y=clock.o gpio.o hwtimer.o jtag.o system.o uart.o
+chip-y=header.o clock.o gpio.o hwtimer.o jtag.o system.o uart.o
# Optional chip modules
chip-$(CONFIG_ADC)+=adc.o
@@ -21,17 +21,13 @@ chip-$(CONFIG_FLASH)+=flash.o
chip-$(CONFIG_I2C)+=i2c.o
chip-$(CONFIG_LPC)+=lpc.o
chip-$(CONFIG_PECI)+=peci.o
+chip-$(CONFIG_SHI)+=shi.o
# pwm functions are implemented with the fan functions
chip-$(CONFIG_PWM)+=pwm.o fan.o
chip-$(CONFIG_SPI)+=spi.o
chip-$(CONFIG_WATCHDOG)+=watchdog.o
chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
-# little FW for booting
-npcx-lfw=chip/npcx/lfw/ec_lfw
-npcx-lfw-bin=${out}/$(npcx-lfw).bin
-PROJECT_EXTRA+=${npcx-lfw-bin}
-
# spi flash program fw for openocd
npcx-flash-fw=chip/npcx/spiflashfw/ec_npcxflash
npcx-flash-fw-bin=${out}/$(npcx-flash-fw).bin
diff --git a/chip/npcx/clock.c b/chip/npcx/clock.c
index 6f21e8e016..c59516043b 100644
--- a/chip/npcx/clock.c
+++ b/chip/npcx/clock.c
@@ -175,7 +175,7 @@ int clock_get_apb2_freq(void)
void clock_wait_cycles(uint32_t cycles)
{
asm("1: subs %0, #1\n"
- " bne 1b\n" :: "r"(cycles));
+ " bne 1b\n" : : "r"(cycles));
}
#ifdef CONFIG_LOW_POWER_IDLE
@@ -190,35 +190,30 @@ void clock_refresh_console_in_use(void)
void clock_uart2gpio(void)
{
/* Is pimux to UART? */
- if (IS_BIT_SET(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL)) {
+ if (npcx_is_uart()) {
/* Change pinmux to GPIO and disable UART IRQ */
task_disable_irq(NPCX_IRQ_UART);
- CLEAR_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL);
-
- /*Enable MIWU for GPIO (UARTRX) */
- SET_BIT(NPCX_WKEN(1, 1), 0);
+ /* Set to GPIO */
+ npcx_uart2gpio();
+ /* Enable MIWU for GPIO (UARTRX) */
+ npcx_enable_wakeup(1);
/* Clear Pending bit of GPIO (UARTRX) */
- if (IS_BIT_SET(NPCX_WKPND(1, 1), 0))
- SET_BIT(NPCX_WKPCL(1, 1), 0);
- /* Disable MIWU IRQ */
- task_disable_irq(NPCX_IRQ_WKINTB_1);
+ npcx_clear_wakeup_event();
}
}
void clock_gpio2uart(void)
{
/* Is Pending bit of GPIO (UARTRX) */
- if (IS_BIT_SET(NPCX_WKPND(1, 1), 0)) {
+ if (npcx_is_wakeup_from_gpio()) {
/* Clear Pending bit of GPIO (UARTRX) */
- SET_BIT(NPCX_WKPCL(1, 1), 0);
+ uart_clear_wakeup_event();
/* Refresh console in-use timer */
clock_refresh_console_in_use();
- /* Disable MIWU & IRQ for GPIO (UARTRX) */
- CLEAR_BIT(NPCX_WKEN(1, 1), 0);
- /* Enable MIWU IRQ */
- task_enable_irq(NPCX_IRQ_WKINTB_1);
+ /* Disable MIWU for GPIO (UARTRX) */
+ uart_enable_miwu_wakeup(0);
/* Go back CR_SIN*/
- SET_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL);
+ npcx_gpio2uart();
/* Enable uart again */
task_enable_irq(NPCX_IRQ_UART);
}
@@ -227,7 +222,7 @@ void clock_gpio2uart(void)
/* Idle task. Executed when no tasks are ready to be scheduled. */
void __idle(void)
{
-#ifdef SUPPORT_JTAG
+#if (CHIP_VERSION < 3)
while (1) {
/*
* TODO:(ML) JTAG bug: if debugger is connected,
diff --git a/chip/npcx/config_chip.h b/chip/npcx/config_chip.h
index cd951e1f22..f7e1541250 100644
--- a/chip/npcx/config_chip.h
+++ b/chip/npcx/config_chip.h
@@ -35,9 +35,9 @@
/*****************************************************************************/
/* Memory mapping */
#define CONFIG_RAM_BASE 0x200C0000 /* memory map address of data ram */
-#define CONFIG_RAM_SIZE 0x00008000 /* 32KB data ram */
-#define CONFIG_CDRAM_BASE 0x10088000 /* memory map address of code ram */
-#define CONFIG_CDRAM_SIZE 0x00020000 /* 128KB code ram */
+#define CONFIG_RAM_SIZE (0x00008000 - 0x800) /* 30KB data ram */
+#define CONFIG_CDRAM_BASE 0x100A8000 /* memory map address of code ram */
+#define CONFIG_CDRAM_SIZE 0x00018000 /* 96KB code ram */
#define CONFIG_FLASH_BASE 0x64000000 /* memory address of spi-flash */
#define CONFIG_LPRAM_BASE 0x40001600 /* memory address of low power ram */
#define CONFIG_LPRAM_SIZE 0x00000620 /* 1568B low power ram */
@@ -61,38 +61,44 @@
#define CONFIG_FLASH_ERASE_SIZE 0x00001000 /* sector erase size 4K bytes */
#define CONFIG_FLASH_WRITE_SIZE 0x00000001 /* minimum write size */
-#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 /* one page size for write */
-#define CONFIG_FLASH_PHYSICAL_SIZE 0x00040000 /* 256KB Flash used for EC */
+#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 /* one page size for write */
+/* 128 KB alignment for SPI status registers protection */
+#define CONFIG_FLASH_PHYSICAL_SIZE 0x40000 /* 256 KB Flash used for EC */
/* No PSTATE; uses a real SPI flash */
#undef CONFIG_FLASH_PSTATE
+/* Header support which is used by booter to copy FW from flash to code ram */
+#define NPCX_RO_HEADER
+
/****************************************************************************/
-/* Define our flash layout. */
+/* Define npcx flash layout. */
/* Size of one firmware image in flash */
#ifndef CONFIG_FW_IMAGE_SIZE
#define CONFIG_FW_IMAGE_SIZE (CONFIG_FLASH_PHYSICAL_SIZE / 2)
#endif
-/* RO firmware offset of flash */
-#define CONFIG_RO_MEM_OFF 0
+/* The storage offset of ec.RO.flat which is used for CONFIG_CDRAM_ARCH */
#define CONFIG_RO_STORAGE_OFF 0
-#define CONFIG_RO_SIZE CONFIG_FW_IMAGE_SIZE
+#ifdef NPCX_RO_HEADER
+#define CONFIG_RO_HDR_MEM_OFF 0x0
+#define CONFIG_RO_HDR_SIZE 0x40
+/* RO firmware offset in flash */
+#define CONFIG_RO_MEM_OFF CONFIG_RO_HDR_SIZE
+#else
+#define CONFIG_RO_MEM_OFF 0x0
+#endif
+#define CONFIG_RO_SIZE CONFIG_CDRAM_SIZE /* 96KB for RO FW */
#define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE
-/* RW firmware is one firmware image offset from the start */
-#define CONFIG_RW_MEM_OFF CONFIG_FW_IMAGE_SIZE
-#define CONFIG_RW_STORAGE_OFF CONFIG_FW_IMAGE_SIZE
-#define CONFIG_RW_SIZE CONFIG_FW_IMAGE_SIZE
+/* The storage offset of ec.RW.flat which is used for CONFIG_CDRAM_ARCH */
+#define CONFIG_RW_STORAGE_OFF CONFIG_FW_IMAGE_SIZE /* 128 KB alignemnt */
+/* RW firmware offset in flash */
+#define CONFIG_RW_MEM_OFF CONFIG_RW_STORAGE_OFF
+#define CONFIG_RW_SIZE CONFIG_CDRAM_SIZE /* 96KB for RW FW */
#define CONFIG_WP_OFF CONFIG_RO_STORAGE_OFF
-#define CONFIG_WP_SIZE CONFIG_RO_SIZE
-
-/*
- * The offset from top of flash wich used by booter
- * the main funcationality to copy iamge from spi-flash to code ram
- */
-#define CONFIG_LFW_OFFSET 0x1000
+#define CONFIG_WP_SIZE CONFIG_FW_IMAGE_SIZE
/****************************************************************************/
/* Customize the build */
@@ -101,11 +107,9 @@
#define CONFIG_ADC
#define CONFIG_FPU
#define CONFIG_I2C
-#define CONFIG_LPC
#define CONFIG_PECI
#define CONFIG_SWITCH
#define CONFIG_MPU
-#define CONFIG_SPI
/* Compile for running from RAM instead of flash */
/* #define COMPILE_FOR_RAM */
diff --git a/chip/npcx/fan.c b/chip/npcx/fan.c
index 5ba20cf315..20208dccdc 100644
--- a/chip/npcx/fan.c
+++ b/chip/npcx/fan.c
@@ -114,7 +114,7 @@ static void mft_startmeasure(int ch)
int mft_ch = fan_op_ch(ch, NPCX_FAN_OP_MFT);
/* Start measurement */
-#ifdef CONFIG_MFT_INPUT_LFCLK
+#ifdef NPCX_MFT_INPUT_LFCLK
/* Set the LFCLK clock. */
if (NPCX_MFT_MODULE_PORT_TB == mft_channels[mft_ch].port)
NPCX_TCKC(mft_channels[mft_ch].module) =
@@ -199,7 +199,7 @@ static void mft_finalmeasure(int ch)
* @return none
* @notes changed when initial or HOOK_FREQ_CHANGE command
*/
-#ifndef CONFIG_MFT_INPUT_LFCLK
+#ifndef NPCX_MFT_INPUT_LFCLK
void mft_freq_changed(void)
{
uint16_t prescaler_divider = 0;
@@ -243,7 +243,7 @@ static void fan_config(int ch, int enable_mft_read_rpm)
& (~(((1<<3)-1)<<NPCX_TMCTRL_MDSEL)))
| (NPCX_MFT_MDSEL_5<<NPCX_TMCTRL_MDSEL);
-#ifndef CONFIG_MFT_INPUT_LFCLK
+#ifndef NPCX_MFT_INPUT_LFCLK
/* Set MFT operation frequence */
mft_freq_changed();
/* Set the active power mode. */
diff --git a/chip/npcx/flash.c b/chip/npcx/flash.c
index 30091a39f0..161f65b6d1 100644
--- a/chip/npcx/flash.c
+++ b/chip/npcx/flash.c
@@ -19,6 +19,7 @@
int all_protected; /* Has all-flash protection been requested? */
int addr_prot_start;
int addr_prot_length;
+uint8_t flag_prot_inconsistent;
#define FLASH_ABORT_TIMEOUT 10000
@@ -179,15 +180,6 @@ static int reg_to_protect(uint8_t sr1, uint8_t sr2, unsigned int *start,
if (sec && bp == 6)
return EC_ERROR_INVAL;
- /*
- * If SRP0 is not set, flash is not protected because status register
- * can be rewritten.
- */
- if (!(sr1 & SPI_FLASH_SR1_SRP0)) {
- *start = *len = 0;
- return EC_SUCCESS;
- }
-
/* Determine granularity (4kb sector or 64kb block) */
/* Computation using 2 * 1024 is correct */
size = sec ? (2 * 1024) : (64 * 1024);
@@ -212,6 +204,20 @@ static int reg_to_protect(uint8_t sr1, uint8_t sr2, unsigned int *start,
*len = CONFIG_FLASH_SIZE - *len;
}
+ /*
+ * If SRP0 is not set, flash is not protected because status register
+ * can be rewritten.
+ */
+ if (!(sr1 & SPI_FLASH_SR1_SRP0)) {
+ /* Set protection inconsistent if len != 0*/
+ if (*len != 0)
+ flag_prot_inconsistent = 1;
+ *start = *len = 0;
+ return EC_SUCCESS;
+ }
+ /* Flag for checking protection inconsistent */
+ flag_prot_inconsistent = 0;
+
return EC_SUCCESS;
}
@@ -385,6 +391,22 @@ void flash_burst_write(unsigned int dest_addr, unsigned int bytes,
flash_cs_level(1);
}
+int flash_uma_lock(int enable)
+{
+ UPDATE_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK, enable);
+ return EC_SUCCESS;
+}
+
+int flash_spi_sel_lock(int enable)
+{
+ /*
+ * F_SPI_QUAD, F_SPI_CS1_1/2, F_SPI_TRIS become read-only
+ * if this bit is set
+ */
+ UPDATE_BIT(NPCX_DEV_CTL4, NPCX_DEV_CTL4_F_SPI_SLLK, enable);
+ return IS_BIT_SET(NPCX_DEV_CTL4, NPCX_DEV_CTL4_F_SPI_SLLK);
+}
+
/*****************************************************************************/
/* Physical layer APIs */
@@ -595,6 +617,10 @@ int flash_physical_erase(int offset, int size)
int flash_physical_get_protect(int bank)
{
uint32_t addr = bank * CONFIG_FLASH_BANK_SIZE;
+ /* All UMA transaction is locked means all banks are protected */
+ if (IS_BIT_SET(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK))
+ return EC_ERROR_ACCESS_DENIED;
+
return flash_check_prot_reg(addr, CONFIG_FLASH_BANK_SIZE);
}
@@ -611,6 +637,8 @@ uint32_t flash_physical_get_protect_flags(void)
* TODO: If status register protects a range, but SRP0 is not set,
* flags should indicate EC_FLASH_PROTECT_ERROR_INCONSISTENT.
*/
+ if (flag_prot_inconsistent)
+ flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT;
/* Read all-protected state from our shadow copy */
if (all_protected)
@@ -621,9 +649,18 @@ uint32_t flash_physical_get_protect_flags(void)
int flash_physical_protect_now(int all)
{
- if (all)
+ if (all) {
all_protected = 1;
-
+ /*
+ * Set UMA_LOCK bit for locking all UMA transaction.
+ * But we still can read directly from flash mapping address
+ */
+ flash_uma_lock(1);
+ } else {
+ all_protected = 0;
+ /* Unlocking all UMA transaction */
+ flash_uma_lock(0);
+ }
/* TODO: if all, disable SPI interface */
return EC_SUCCESS;
@@ -634,14 +671,26 @@ int flash_physical_protect_at_boot(enum flash_wp_range range)
{
switch (range) {
case FLASH_WP_NONE:
+ /* Unlock UMA transactions */
+ if (IS_BIT_SET(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK))
+ CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK);
/* Clear protection bits in status register */
return flash_set_status_for_prot(0, 0);
case FLASH_WP_RO:
+ /* Unlock UMA transactions */
+ if (IS_BIT_SET(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK))
+ CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK);
/* Protect read-only */
return flash_write_prot_reg(
WP_BANK_OFFSET*CONFIG_FLASH_BANK_SIZE,
WP_BANK_COUNT*CONFIG_FLASH_BANK_SIZE);
case FLASH_WP_ALL:
+ /* Protect all */
+ /*
+ * Set UMA_LOCK bit for locking all UMA transaction.
+ * But we still can read directly from flash mapping address
+ */
+ return flash_uma_lock(1);
default:
return EC_ERROR_INVAL;
}
@@ -686,5 +735,43 @@ int flash_pre_init(void)
CLEAR_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS);
#endif
+ return EC_SUCCESS;
+}
+
+/*****************************************************************************/
+/* Console commands */
+
+static int command_flash_spi_sel_lock(int argc, char **argv)
+{
+ int ena;
+
+ if (argc > 1) {
+ if (!parse_bool(argv[1], &ena))
+ return EC_ERROR_PARAM1;
+ ena = flash_spi_sel_lock(ena);
+ }
+ ccprintf("Enabled: %d\n", ena);
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(flash_spi_sel_lock, command_flash_spi_sel_lock,
+ "[0 | 1]",
+ "Lock spi flash interface selection",
+ NULL);
+
+static int command_flash_tristate(int argc, char **argv)
+{
+ int ena;
+
+ if (argc > 1) {
+ if (!parse_bool(argv[1], &ena))
+ return EC_ERROR_PARAM1;
+ flash_tristate(ena);
+ }
+ ccprintf("Enabled: %d\n", ena);
return EC_SUCCESS;
}
+DECLARE_CONSOLE_COMMAND(flash_tristate, command_flash_tristate,
+ "[0 | 1]",
+ "Tristate spi flash pins",
+ NULL);
+
diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c
index 0b9b4b664f..34634943b3 100644
--- a/chip/npcx/gpio.c
+++ b/chip/npcx/gpio.c
@@ -218,12 +218,12 @@ struct gpio_alt_map {
const struct gpio_alt_map gpio_alt_table[] = {
/* I2C Module */
-#if I2C0_BUS0
- { NPCX_GPIO(B, 4), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SDA */
- { NPCX_GPIO(B, 5), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SCL */
-#else
+#if NPCX_I2C0_BUS2
{ NPCX_GPIO(B, 2), NPCX_ALT(2, I2C0_1_SL)}, /* SMB0SDA */
{ NPCX_GPIO(B, 3), NPCX_ALT(2, I2C0_1_SL)}, /* SMB0SCL */
+#else
+ { NPCX_GPIO(B, 4), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SDA */
+ { NPCX_GPIO(B, 5), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SCL */
#endif
{ NPCX_GPIO(8, 7), NPCX_ALT(2, I2C1_0_SL)}, /* SMB1SDA */
{ NPCX_GPIO(9, 0), NPCX_ALT(2, I2C1_0_SL)}, /* SMB1SCL */
@@ -237,9 +237,14 @@ const struct gpio_alt_map gpio_alt_table[] = {
{ NPCX_GPIO(4, 3), NPCX_ALT(6, ADC2_SL)}, /* ADC2 */
{ NPCX_GPIO(4, 2), NPCX_ALT(6, ADC3_SL)}, /* ADC3 */
{ NPCX_GPIO(4, 1), NPCX_ALT(6, ADC4_SL)}, /* ADC4 */
- /* UART Module */
- { NPCX_GPIO(1, 0), NPCX_ALT(9, NO_KSO08_SL)}, /* CR_SIN/KSO09/GPIO10*/
- { NPCX_GPIO(1, 1), NPCX_ALT(9, NO_KSO09_SL)}, /* CR_SOUT/KSO10/GPIO11*/
+ /* UART Module 1/2 */
+#if NPCX_UART_MODULE2
+ { NPCX_GPIO(6, 4), NPCX_ALT(C, UART_SL2)}, /* CR_SIN */
+ { NPCX_GPIO(6, 5), NPCX_ALT(C, UART_SL2)}, /* CR_SOUT */
+#else
+ { NPCX_GPIO(1, 0), NPCX_ALT(9, NO_KSO08_SL)}, /* CR_SIN/KSO09 */
+ { NPCX_GPIO(1, 1), NPCX_ALT(9, NO_KSO09_SL)}, /* CR_SOUT/KSO10 */
+#endif
/* SPI Module */
{ NPCX_GPIO(9, 5), NPCX_ALT(0, SPIP_SL)}, /* SPIP_MISO */
{ NPCX_GPIO(A, 5), NPCX_ALT(0, SPIP_SL)}, /* SPIP_CS1 */
@@ -255,24 +260,24 @@ const struct gpio_alt_map gpio_alt_table[] = {
{ NPCX_GPIO(C, 0), NPCX_ALT(4, PWM6_SL)}, /* PWM6 */
{ NPCX_GPIO(6, 0), NPCX_ALT(4, PWM7_SL)}, /* PWM7 */
/* MFT Module */
-#if TACH_SEL1
- { NPCX_GPIO(4, 0), NPCX_ALT(3, TA1_TACH1_SL1)},/* TA1_TACH1 */
- { NPCX_GPIO(A, 4), NPCX_ALT(3, TB1_TACH2_SL1)},/* TB1_TACH2 */
-#else
+#if NPCX_TACH_SEL2
{ NPCX_GPIO(9, 3), NPCX_ALT(C, TA1_TACH1_SL2)},/* TA1_TACH1 */
{ NPCX_GPIO(D, 3), NPCX_ALT(C, TB1_TACH2_SL2)},/* TB1_TACH2 */
+#else
+ { NPCX_GPIO(4, 0), NPCX_ALT(3, TA1_TACH1_SL1)},/* TA1_TACH1 */
+ { NPCX_GPIO(A, 4), NPCX_ALT(3, TB1_TACH2_SL1)},/* TB1_TACH2 */
#endif
/* JTAG Module */
-#if !(JTAG1)
- { NPCX_GPIO(2, 1), NPCX_ALT(5, NJEN0_EN) }, /* TCLK */
- { NPCX_GPIO(1, 7), NPCX_ALT(5, NJEN0_EN) }, /* TDI */
- { NPCX_GPIO(1, 6), NPCX_ALT(5, NJEN0_EN) }, /* TDO */
- { NPCX_GPIO(2, 0), NPCX_ALT(5, NJEN0_EN) }, /* TMS */
-#else
+#if NPCX_JTAG_MODULE2
{ NPCX_GPIO(D, 5), NPCX_ALT(5, NJEN1_EN) }, /* TCLK */
{ NPCX_GPIO(E, 2), NPCX_ALT(5, NJEN1_EN) }, /* TDI */
{ NPCX_GPIO(D, 4), NPCX_ALT(5, NJEN1_EN) }, /* TDO */
{ NPCX_GPIO(E, 5), NPCX_ALT(5, NJEN1_EN) }, /* TMS */
+#else
+ { NPCX_GPIO(2, 1), NPCX_ALT(5, NJEN0_EN) }, /* TCLK */
+ { NPCX_GPIO(1, 7), NPCX_ALT(5, NJEN0_EN) }, /* TDI */
+ { NPCX_GPIO(1, 6), NPCX_ALT(5, NJEN0_EN) }, /* TDO */
+ { NPCX_GPIO(2, 0), NPCX_ALT(5, NJEN0_EN) }, /* TMS */
#endif
/* 01 for PWRGD_OUT*/
};
@@ -560,6 +565,13 @@ void gpio_pre_init(void)
SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_GPIO_NO_SPIP);
SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI);
+#ifdef CONFIG_SHI
+ /* Switching to eSPI mode for SHI interface */
+ NPCX_DEVCNT |= 0x08;
+ /* Alternate Intel bus interface LPC/eSPI to GPIOs first */
+ SET_BIT(NPCX_DEVALT(ALT_GROUP_1), NPCX_DEVALT1_NO_LPC_ESPI);
+#endif
+
/* Clear all pending bits of GPIOS*/
for (i = 0; i < 2; i++)
for (j = 0; j < 8; j++)
diff --git a/chip/npcx/header.c b/chip/npcx/header.c
new file mode 100644
index 0000000000..ff0c50eb3b
--- /dev/null
+++ b/chip/npcx/header.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+/*
+ * Booter header for Chrome EC.
+ *
+ * This header is used by Nuvoton EC Booter.
+ */
+
+#include <stdint.h>
+#include "registers.h"
+#include "config_chip.h"
+
+/* Signature used by fw header */
+#define SIG_FW_EC 0x2A3B4D5E
+
+/* Definition used by error detection configuration */
+#define CHECK_CRC 0x00
+#define CHECK_CHECKSUM 0x01
+#define ERROR_DETECTION_EN 0x02
+#define ERROR_DETECTION_DIS 0x00
+
+/* Code RAM addresses use by header */
+#define FW_START_ADDR CONFIG_CDRAM_BASE /* Put FW at the begin of CODE RAM */
+
+/* TODO: It will be filled automatically by ECST */
+/* The entry point of reset handler (filled by ECST tool)*/
+#define FW_ENTRY_ADDR 0x100A8169
+
+/* Error detection addresses use by header (A offset relative to flash image) */
+#define ERRCHK_START_ADDR 0x0
+#define ERRCHK_END_ADDR 0x0
+
+/* Firmware Size -> Booter loads RO region after hard reset (16 bytes aligned)*/
+#define FW_SIZE CONFIG_RO_SIZE
+
+/* FW Header used by NPCX5M5G Booter */
+struct __packed fw_header_t {
+ uint32_t anchor; /* A constant used to verify FW header */
+ uint16_t ext_anchor; /* Enable/disable firmware header CRC check */
+ uint8_t spi_max_freq; /* Spi maximum allowable clock frequency */
+ uint8_t spi_read_mode; /* Spi read mode used for firmware loading */
+ uint8_t cfg_err_detect; /* FW load error detection configuration */
+ uint32_t fw_load_addr; /* Firmware load start address */
+ uint32_t fw_entry; /* Firmware entry point */
+ uint32_t err_detect_start_addr; /* FW error detect start address */
+ uint32_t err_detect_end_addr; /* FW error detect end address */
+ uint32_t fw_length; /* Firmware length in bytes */
+ uint8_t flash_size; /* Indicate SPI flash size */
+ uint8_t reserved[26]; /* Reserved bytes */
+ uint32_t sig_header; /* The CRC signature of the firmware header */
+ uint32_t sig_fw_image; /* The CRC or Checksum of the firmware image */
+} __aligned(1);
+
+__attribute__ ((section(".header")))
+const struct fw_header_t fw_header = {
+ /* 00 */ SIG_FW_EC,
+ /* 04 */ 0x54E1, /* Header CRC check Enable/Disable -> AB1Eh/54E1h */
+ /* 06 */ 0x04, /* 20/25/33/40/50 MHz -> 00/01/02/03/04h */
+ /* 07 */ 0x03, /* Normal/Fast/Rev/D_IO/Q_IO Mode -> 00/01/02/03/04h */
+ /* 08 */ 0x00, /* Disable CRC check functionality */
+ /* 09 */ FW_START_ADDR,
+ /* 0D */ FW_ENTRY_ADDR,/* Filling by ECST tool with -usearmrst option */
+ /* 11 */ ERRCHK_START_ADDR,
+ /* 15 */ ERRCHK_END_ADDR,
+ /* 19 */ FW_SIZE,/* Filling by ECST tool */
+ /* 1D */ 0x0F, /* Flash Size 1/2/4/8/16 Mbytes -> 01/03/07/0F/1Fh */
+ /* 1E-3F Other fields are filled by ECST tool or reserved */
+};
diff --git a/chip/npcx/hwtimer.c b/chip/npcx/hwtimer.c
index 80bb903e67..5607222b4d 100644
--- a/chip/npcx/hwtimer.c
+++ b/chip/npcx/hwtimer.c
@@ -15,15 +15,15 @@
#include "task.h"
#include "timer.h"
-/* (2^TICK_ITIM_DEPTH us) between 2 ticks of timer */
-#define TICK_ITIM_DEPTH 16 /* Depth of ITIM Unit: bits */
-#define TICK_INTERVAL (1 << TICK_ITIM_DEPTH) /* Unit: us */
-#define TICK_INTERVAL_MASK (TICK_INTERVAL - 1) /* Mask of interval */
-#define TICK_ITIM_MAX_CNT (TICK_INTERVAL - 1) /* Maximum counter value */
-
-/* 32-bits counter value */
-static volatile uint32_t cur_cnt_us;
-static volatile uint32_t pre_cnt_us;
+/* Use ITIM32 as main hardware timer */
+#define TICK_ITIM32_MAX_CNT 0xFFFFFFFF
+
+/* Depth of event timer */
+#define TICK_EVT_DEPTH 16 /* Depth of event timer Unit: bits */
+#define TICK_EVT_INTERVAL (1 << TICK_EVT_DEPTH) /* Unit: us */
+#define TICK_EVT_INTERVAL_MASK (TICK_EVT_INTERVAL - 1) /* Mask of interval */
+#define TICK_EVT_MAX_CNT (TICK_EVT_INTERVAL - 1) /* Maximum event counter */
+
/* Time when event will be expired unit:us */
static volatile uint32_t evt_expired_us;
/* 32-bits event counter */
@@ -36,20 +36,20 @@ static volatile uint32_t cur_cnt_us_dbg;
/*****************************************************************************/
/* Internal functions */
-void init_hw_timer(int itim_no, enum ITIM16_SOURCE_CLOCK_T source)
+void init_hw_timer(int itim_no, enum ITIM_SOURCE_CLOCK_T source)
{
/* Use internal 32K clock/APB2 for ITIM16 */
- UPDATE_BIT(NPCX_ITCTS(itim_no), NPCX_ITIM16_CKSEL,
- source != ITIM16_SOURCE_CLOCK_APB2);
+ UPDATE_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_CKSEL,
+ source != ITIM_SOURCE_CLOCK_APB2);
/* Clear timeout status */
- SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITIM16_TO_STS);
+ SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_TO_STS);
/* ITIM timeout interrupt enable */
- SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITIM16_TO_IE);
+ SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_TO_IE);
/* ITIM timeout wake-up enable */
- SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITIM16_TO_WUE);
+ SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_TO_WUE);
}
/*****************************************************************************/
@@ -70,18 +70,18 @@ void __hw_clock_event_set(uint32_t deadline)
#endif
/* Event module disable */
- CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_ITEN);
+ CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);
/*
* ITIM count down : event expired : Unit: 1/32768 sec
* It must exceed evt_expired_us for process_timers function
*/
evt_cnt = ((uint32_t)(evt_cnt_us*inv_evt_tick)+1)-1;
- if (evt_cnt > TICK_ITIM_MAX_CNT)
- evt_cnt = TICK_ITIM_MAX_CNT;
+ if (evt_cnt > TICK_EVT_MAX_CNT)
+ evt_cnt = TICK_EVT_MAX_CNT;
NPCX_ITCNT16(ITIM_EVENT_NO) = evt_cnt;
/* Event module enable */
- SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_ITEN);
+ SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);
/* Enable interrupt of ITIM */
task_enable_irq(ITIM16_INT(ITIM_EVENT_NO));
@@ -102,7 +102,7 @@ uint32_t __hw_clock_get_sleep_time(void)
interrupt_disable();
/* Event has been triggered but timer ISR dosen't handle it */
- if (IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_TO_STS))
+ if (IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_TO_STS))
sleep_time = (uint32_t) (evt_cnt+1)*evt_tick;
/* Event hasn't been triggered */
else
@@ -116,7 +116,7 @@ uint32_t __hw_clock_get_sleep_time(void)
void __hw_clock_event_clear(void)
{
/* ITIM event module disable */
- CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_ITEN);
+ CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);
/* Disable interrupt of Event */
task_disable_irq(ITIM16_INT(ITIM_EVENT_NO));
@@ -129,21 +129,15 @@ void __hw_clock_event_clear(void)
/* Irq for hwtimer event */
void __hw_clock_event_irq(void)
{
- int delay;
/* Clear timeout status for event */
- SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_TO_STS);
+ SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_TO_STS);
/* ITIM event module disable */
- CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_ITEN);
+ CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);
/* Disable interrupt of event */
task_disable_irq(ITIM16_INT(ITIM_EVENT_NO));
- /* Workaround for tick interrupt latency */
- delay = evt_expired_us - __hw_clock_source_read();
- if (delay > 0)
- cur_cnt_us += delay;
-
/* Clear event parameters */
evt_expired_us = 0;
evt_cnt = 0;
@@ -160,49 +154,43 @@ DECLARE_IRQ(ITIM16_INT(ITIM_EVENT_NO) , __hw_clock_event_irq, 1);
/* Returns the value of the free-running counter used as clock. */
uint32_t __hw_clock_source_read(void)
{
- uint32_t us;
- uint32_t cnt = NPCX_ITCNT16(ITIM_TIME_NO);
- /* Is timeout expired? - but timer ISR dosen't handle it */
- if (IS_BIT_SET(NPCX_ITCTS(ITIM_TIME_NO), NPCX_ITIM16_TO_STS))
- us = TICK_INTERVAL;
- else
- us = TICK_INTERVAL - cnt;
-
+ uint32_t cnt = NPCX_ITCNT32;
#if DEBUG_TMR
- cur_cnt_us_dbg = cur_cnt_us + us;
+ cur_cnt_us_dbg = TICK_ITIM32_MAX_CNT - cnt;
#endif
- return cur_cnt_us + us;
+ return TICK_ITIM32_MAX_CNT - cnt;
}
/* Override the current value of the hardware counter */
void __hw_clock_source_set(uint32_t ts)
{
+#if DEBUG_TMR
+ cur_cnt_us_dbg = TICK_ITIM32_MAX_CNT - ts;
+#endif
+ /* ITIM32 module disable */
+ CLEAR_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_ITEN);
/* Set current time */
- cur_cnt_us = ts;
+ NPCX_ITCNT32 = TICK_ITIM32_MAX_CNT - ts;
+ /* ITIM32 module enable */
+ SET_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_ITEN);
+
}
/* Irq for hwtimer tick */
void __hw_clock_source_irq(void)
{
/* Is timeout trigger trigger? */
- if (IS_BIT_SET(NPCX_ITCTS(ITIM_TIME_NO), NPCX_ITIM16_TO_STS)) {
+ if (IS_BIT_SET(NPCX_ITCTS(ITIM32), NPCX_ITCTS_TO_STS)) {
/* Clear timeout status*/
- SET_BIT(NPCX_ITCTS(ITIM_TIME_NO), NPCX_ITIM16_TO_STS);
-
- /* Store previous time counter value */
- pre_cnt_us = cur_cnt_us;
- /* Increase TICK_INTERVAL unit:us */
- cur_cnt_us += TICK_INTERVAL;
-
- /* Is 32-bits timer count overflow? */
- if (pre_cnt_us > cur_cnt_us)
- process_timers(1);
+ SET_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_TO_STS);
+ /* 32-bits timer count overflow */
+ process_timers(1);
} else { /* Handle soft trigger */
process_timers(0);
}
}
-DECLARE_IRQ(NPCX_IRQ_ITIM16_1, __hw_clock_source_irq, 1);
+DECLARE_IRQ(NPCX_IRQ_ITIM32, __hw_clock_source_irq, 1);
static void update_prescaler(void)
{
@@ -211,7 +199,7 @@ static void update_prescaler(void)
* Ttick_unit = (PRE_8+1) * Tapb2_clk
* PRE_8 = (Ttick_unit/Tapb2_clk) -1
*/
- NPCX_ITPRE(ITIM_TIME_NO) = (clock_get_apb2_freq() / SECOND) - 1;
+ NPCX_ITPRE(ITIM32) = (clock_get_apb2_freq() / SECOND) - 1;
/* Set event tick unit = 1/32768 sec */
NPCX_ITPRE(ITIM_EVENT_NO) = 0;
@@ -230,14 +218,14 @@ int __hw_clock_source_init(uint32_t start_t)
CGC_MODE_RUN | CGC_MODE_SLEEP);
/* init tick & event timer first */
- init_hw_timer(ITIM_TIME_NO, ITIM16_SOURCE_CLOCK_APB2);
- init_hw_timer(ITIM_EVENT_NO, ITIM16_SOURCE_CLOCK_32K);
+ init_hw_timer(ITIM32, ITIM_SOURCE_CLOCK_APB2);
+ init_hw_timer(ITIM_EVENT_NO, ITIM_SOURCE_CLOCK_32K);
/* Set initial prescaler */
update_prescaler();
- /* ITIM count down : TICK_INTERVAL expired*/
- NPCX_ITCNT16(ITIM_TIME_NO) = TICK_ITIM_MAX_CNT;
+ /* ITIM count down : TICK_ITIM32_MAX_CNT us expired */
+ NPCX_ITCNT32 = TICK_ITIM32_MAX_CNT;
/*
* Override the count with the start value now that counting has
@@ -246,10 +234,10 @@ int __hw_clock_source_init(uint32_t start_t)
__hw_clock_source_set(start_t);
/* ITIM module enable */
- SET_BIT(NPCX_ITCTS(ITIM_TIME_NO), NPCX_ITIM16_ITEN);
+ SET_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_ITEN);
/* Enable interrupt of ITIM */
- task_enable_irq(ITIM16_INT(ITIM_TIME_NO));
+ task_enable_irq(NPCX_IRQ_ITIM32);
- return ITIM16_INT(ITIM_TIME_NO);
+ return NPCX_IRQ_ITIM32;
}
diff --git a/chip/npcx/hwtimer_chip.h b/chip/npcx/hwtimer_chip.h
index 732ef8fac4..b529bce463 100644
--- a/chip/npcx/hwtimer_chip.h
+++ b/chip/npcx/hwtimer_chip.h
@@ -8,19 +8,18 @@
#ifndef __CROS_EC_HWTIMER_CHIP_H
#define __CROS_EC_HWTIMER_CHIP_H
-/* Channel definition for ITIM16 */
-#define ITIM_TIME_NO ITIM16_1
-#define ITIM_EVENT_NO ITIM16_2
+/* Channel definition for ITIM */
+#define ITIM_EVENT_NO ITIM16_1
#define ITIM_WDG_NO ITIM16_5
/* Clock source for ITIM16 */
-enum ITIM16_SOURCE_CLOCK_T {
- ITIM16_SOURCE_CLOCK_APB2 = 0,
- ITIM16_SOURCE_CLOCK_32K = 1,
+enum ITIM_SOURCE_CLOCK_T {
+ ITIM_SOURCE_CLOCK_APB2 = 0,
+ ITIM_SOURCE_CLOCK_32K = 1,
};
/* Initialize ITIM16 timer */
-void init_hw_timer(int itim_no, enum ITIM16_SOURCE_CLOCK_T source);
+void init_hw_timer(int itim_no, enum ITIM_SOURCE_CLOCK_T source);
/* Returns time delay cause of deep idle */
uint32_t __hw_clock_get_sleep_time(void);
diff --git a/chip/npcx/i2c.c b/chip/npcx/i2c.c
index 03b48c2864..fd21aebbf9 100644
--- a/chip/npcx/i2c.c
+++ b/chip/npcx/i2c.c
@@ -557,4 +557,4 @@ static void i2c_init(void)
task_enable_irq(i2c_irqs[port]);
}
}
-DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_DEFAULT);
+DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_INIT_I2C);
diff --git a/chip/npcx/jtag.c b/chip/npcx/jtag.c
index 05dda6fa78..aeef35e9c8 100644
--- a/chip/npcx/jtag.c
+++ b/chip/npcx/jtag.c
@@ -11,6 +11,8 @@
void jtag_pre_init(void)
{
+ /* Setting for fixing JTAG issue */
+ NPCX_DBGCTRL = 0x04;
/* Enable automatic freeze mode */
CLEAR_BIT(NPCX_DBGFRZEN3, NPCX_DBGFRZEN3_GLBL_FRZ_DIS);
}
diff --git a/chip/npcx/lfw/ec_lfw.c b/chip/npcx/lfw/ec_lfw.c
deleted file mode 100644
index c3a505ce69..0000000000
--- a/chip/npcx/lfw/ec_lfw.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/* Copyright (c) 2014 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.
- *
- * NPCX5M5G SoC little FW used by booter
- */
-
-#include <stdint.h>
-#include "registers.h"
-#include "config_chip.h"
-#include "ec_lfw.h"
-#include "system_chip.h"
-
-/* size of little FW */
-#define LFW_SIZE 0x1000
-/* signature used by booter */
-#define SIG_GOOGLE_EC 0x55AA650E
-/* little FW located on TOP of Flash - 4K */
-#define FW_ADDR (CONFIG_SPI_FLASH_SIZE - 0x1000)
-
-/* Header used by NPCX5M5G Booter */
-struct booter_header_t {
- uint32_t signature; /* A constant used to verify FW pointer is valid */
- uint32_t pointer_fw;/* Holds the BootLoader location in the flash */
-};
-
-__attribute__ ((section(".booter_pointer")))
-const struct booter_header_t booter_header = {
- /* 00 */ SIG_GOOGLE_EC,
- /* 04 */ FW_ADDR
-};
-
-
-/* Original sp during sysjump */
-uint32_t org_sp;
-
-/*****************************************************************************/
-/* flash internal functions */
-
-void __attribute__ ((section(".instrucion_ram")))
-flash_burst_copy_fw_to_mram(uint32_t addr_flash, uint32_t addr_mram,
- uint32_t size)
-{
- uint32_t bit32_idx;
- uint32_t bit32_size;
- uint32_t *bit32_ptr_mram;
-
- bit32_ptr_mram = (uint32_t *)addr_mram;
-
- /* Round it up and get it in 4 bytes */
- bit32_size = (size+3) / 4;
-
- /* Set chip select to low */
- CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
-
- /* Write flash address */
- NPCX_UMA_AB2 = (uint8_t)((addr_flash & 0xFF0000)>>16);
- NPCX_UMA_AB1 = (uint8_t)((addr_flash & 0xFF00)>>8);
- NPCX_UMA_AB0 = (uint8_t)((addr_flash & 0xFF));
-
- NPCX_UMA_CODE = CMD_FAST_READ;
- NPCX_UMA_CTS = MASK_CMD_ADR_WR;
- /* wait for UMA to complete */
- while (IS_BIT_SET(NPCX_UMA_CTS, EXEC_DONE))
- ;
-
- /* Start to burst read and copy data to Code RAM */
- for (bit32_idx = 0; bit32_idx < bit32_size; bit32_idx++) {
- /* 1101 0100 - EXEC, RD, NO CMD, NO ADDR, 4 bytes */
- NPCX_UMA_CTS = MASK_RD_4BYTE;
- while (IS_BIT_SET(NPCX_UMA_CTS, EXEC_DONE))
- ;
- /* copy data to Code RAM */
- bit32_ptr_mram[bit32_idx] = NPCX_UMA_DB0_3;
- }
-
- /* Set chip select to high */
- SET_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
-}
-
-void __attribute__ ((section(".instrucion_ram")))
-bin2ram(void)
-{
- /* copy image from RO base */
- if (IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION))
- flash_burst_copy_fw_to_mram(CONFIG_RO_MEM_OFF,
- CONFIG_CDRAM_BASE, CONFIG_RO_SIZE - LFW_SIZE);
- /* copy image from RW base */
- else
- flash_burst_copy_fw_to_mram(CONFIG_RW_MEM_OFF,
- CONFIG_CDRAM_BASE, CONFIG_RW_SIZE - LFW_SIZE);
-
- /* Disable FIU pins to tri-state */
- CLEAR_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS);
-
-
- /* Distinguish reboot or sysjump */
- if (org_sp < CONFIG_RAM_BASE) {
- /* restore sp from begin of RO image */
- asm volatile("ldr r0, =0x10088000\n"
- "ldr r1, [r0]\n"
- "mov sp, r1\n");
- } else {
- /* restore sp from sysjump */
- asm volatile("mov sp, %0" : : "r"(org_sp));
- }
-
- /* Jump to reset ISR */
- asm volatile(
- "ldr r0, =0x10088004\n"
- "ldr r1, [r0]\n"
- "mov pc, r1\n");
-}
-
-/* Entry function of little FW */
-void __attribute__ ((section(".startup_text"), noreturn))
-entry_lfw(void)
-{
- uint32_t i;
-
- /* Backup sp value */
- asm volatile("mov %0, sp" : "=r"(org_sp));
- /* initialize sp with Data RAM */
- asm volatile(
- "ldr r0, =0x100A8000\n"
- "mov sp, r0\n");
-
- /* Copy the bin2ram code to RAM */
- for (i = 0; i < &__iram_fw_end - &__iram_fw_start; i++)
- *(&__iram_fw_start + i) = *(&__flash_fw_start + i);
-
- /* Copy ram log of booter into bbram */
- NPCX_BBRAM(BBRM_DATA_INDEX_RAMLOG) = *((uint8_t *)ADDR_BOOT_RAMLOG);
-
- /* Run code in RAM */
- bin2ram();
-
- /* Should never reach this */
- for (;;)
- ;
-}
diff --git a/chip/npcx/lfw/ec_lfw.ld b/chip/npcx/lfw/ec_lfw.ld
deleted file mode 100644
index dd93bba89e..0000000000
--- a/chip/npcx/lfw/ec_lfw.ld
+++ /dev/null
@@ -1,122 +0,0 @@
-/* Copyright (c) 2014 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.
- *
- * NPCX5M5G SoC little FW for booting
- */
-
-/* Memory Spaces Definitions */
-MEMORY
-{
- FLASH (rx) : ORIGIN = 0x647FF000, LENGTH = 4K - 256
- POINTER(r) : ORIGIN = 0x647FFF00, LENGTH = 256
- CODERAM(rx): ORIGIN = 0x100A7C00, LENGTH = 1K - 256
- RAM (xrw) : ORIGIN = 0x100A7F00, LENGTH = 256
-}
-
-/*
- * The entry point is informative, for debuggers and simulators,
- * since the Cortex-M vector points to it anyway.
- */
-ENTRY(entry_lfw)
-
-/* Sections Definitions */
-
-SECTIONS
-{
-
- /*
- * The beginning of the startup code
- */
- .startup_text :
- {
- . = ALIGN(4);
- *(.startup_text ) /* Startup code */
- . = ALIGN(4);
- } >FLASH
-
-
- /*
- * The program code is stored in the .text section,
- * which goes to FLASH.
- */
- .text :
- {
- . = ALIGN(4);
- *(.text .text.*) /* all remaining code */
- *(.rodata .rodata.*) /* read-only data (constants) */
- } >FLASH
-
- . = ALIGN(4);
-
- __flash_fw_start = .;
- .instrucion_ram : AT(__flash_fw_start)
- {
- . = ALIGN(4);
- __iram_fw_start = .;
- *(.instrucion_ram .instrucion_ram.*) /* CODERAM in 0x200C0000 */
- __iram_fw_end = .;
- } > CODERAM
-
- /*
- * The POINTER section used for booter
- */
- .booter_pointer :
- {
- . = ALIGN(4);
- KEEP(*(.booter_pointer)) /* Booter pointer in 0xFFFF00 */
- } > POINTER
-
- . = ALIGN(4);
- _etext = .;
-
- /*
- * This address is used by the startup code to
- * initialise the .data section.
- */
- _sidata = _etext;
-
- /*
- * The initialised data section.
- * The program executes knowing that the data is in the RAM
- * but the loader puts the initial values in the FLASH (inidata).
- * It is one task of the startup to copy the initial values from
- * FLASH to RAM.
- */
- .data : AT ( _sidata )
- {
- . = ALIGN(4);
-
- /* This is used by the startup code to initialise the .data section */
- __data_start__ = . ;
- *(.data_begin .data_begin.*)
-
- *(.data .data.*)
-
- *(.data_end .data_end.*)
- . = ALIGN(4);
-
- /* This is used by the startup code to initialise the .data section */
- __data_end__ = . ;
-
- } > RAM
-
-
- /*
- * The uninitialised data section. NOLOAD is used to avoid
- * the "section `.bss' type changed to PROGBITS" warning
- */
- .bss (NOLOAD) :
- {
- . = ALIGN(4);
- __bss_start__ = .; /* standard newlib definition */
- *(.bss_begin .bss_begin.*)
-
- *(.bss .bss.*)
- *(COMMON)
-
- *(.bss_end .bss_end.*)
- . = ALIGN(4);
- __bss_end__ = .; /* standard newlib definition */
- } >RAM
-} \ No newline at end of file
diff --git a/chip/npcx/lpc.c b/chip/npcx/lpc.c
index 595edf28e9..6a2a85742f 100644
--- a/chip/npcx/lpc.c
+++ b/chip/npcx/lpc.c
@@ -30,6 +30,15 @@
#define LPC_SYSJUMP_TAG 0x4c50 /* "LP" */
+/* Timeout to wait PLTRST is deasserted */
+#define LPC_PLTRST_TIMEOUT_US 800000
+
+/* Super-IO index and register definitions */
+#define SIO_OFFSET 0x4E
+#define INDEX_SID 0x20
+#define INDEX_CHPREV 0x24
+#define INDEX_SRID 0x27
+
static uint32_t host_events; /* Currently pending SCI/SMI events */
static uint32_t event_mask[3]; /* Event masks for each type */
static struct host_packet lpc_packet;
@@ -46,7 +55,6 @@ static uint8_t * const cmd_params = (uint8_t *)shm_mem_host_cmd +
static struct ec_lpc_host_args * const lpc_host_args =
(struct ec_lpc_host_args *)shm_mem_host_cmd;
-
#ifdef CONFIG_KEYBOARD_IRQ_GPIO
static void keyboard_irq_assert(void)
{
@@ -358,12 +366,6 @@ void lpc_clear_acpi_status_mask(uint8_t mask)
/* TODO (crbug.com/p/38224): Implement */
}
-int lpc_get_pltrst_asserted(void)
-{
- /* Read PLTRST status*/
- return (NPCX_MSWCTL1 & 0x04) ? 0 : 1;
-}
-
/**
* Handle write to ACPI I/O port
*
@@ -544,6 +546,158 @@ static void lpc_post_sysjump(void)
memcpy(event_mask, prev_mask, sizeof(event_mask));
}
+int lpc_get_pltrst_asserted(void)
+{
+ /* Read PLTRST status */
+ return (NPCX_MSWCTL1 & 0x04) ? 1 : 0;
+}
+
+/* Super-IO read/write function */
+void lpc_sib_write_reg(uint8_t io_offset, uint8_t index_value,
+ uint8_t io_data)
+{
+ /* Disable interrupts */
+ interrupt_disable();
+
+ /* Lock host CFG module */
+ SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
+ /* Enable Core-to-Host Modules Access */
+ SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
+ /* Enable Core access to CFG module */
+ SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
+ /* Verify Core read/write to host modules is not in progress */
+ while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
+ ;
+ while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
+ ;
+
+ /* Specify the io_offset A0 = 0. the index register is accessed */
+ NPCX_IHIOA = io_offset;
+ /* Write the data. This starts the write access to the host module */
+ NPCX_IHD = index_value;
+ /* Wait while Core write operation is in progress */
+ while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
+ ;
+
+ /* Specify the io_offset A0 = 1. the data register is accessed */
+ NPCX_IHIOA = io_offset+1;
+ /* Write the data. This starts the write access to the host module */
+ NPCX_IHD = io_data;
+ /* Wait while Core write operation is in progress */
+ while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
+ ;
+
+ /* Disable Core access to CFG module */
+ CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
+ /* Disable Core-to-Host Modules Access */
+ CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
+ /* unlock host CFG module */
+ CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
+
+ /* Enable interrupts */
+ interrupt_enable();
+}
+
+uint8_t lpc_sib_read_reg(uint8_t io_offset, uint8_t index_value)
+{
+ uint8_t data_value;
+
+ /* Disable interrupts */
+ interrupt_disable();
+
+ /* Lock host CFG module */
+ SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
+ /* Enable Core-to-Host Modules Access */
+ SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
+ /* Enable Core access to CFG module */
+ SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
+ /* Verify Core read/write to host modules is not in progress */
+ while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
+ ;
+ while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
+ ;
+
+
+ /* Specify the io_offset A0 = 0. the index register is accessed */
+ NPCX_IHIOA = io_offset;
+ /* Write the data. This starts the write access to the host module */
+ NPCX_IHD = index_value;
+ /* Wait while Core write operation is in progress */
+ while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
+ ;
+
+ /* Specify the io_offset A0 = 1. the data register is accessed */
+ NPCX_IHIOA = io_offset+1;
+ /* Start a Core read from host module */
+ SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD);
+ /* Wait while Core read operation is in progress */
+ while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
+ ;
+ /* Read the data */
+ data_value = NPCX_IHD;
+
+ /* Disable Core access to CFG module */
+ CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
+ /* Disable Core-to-Host Modules Access */
+ CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
+ /* unlock host CFG module */
+ CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
+
+ /* Enable interrupts */
+ interrupt_enable();
+
+ return data_value;
+}
+
+/* For LPC host register initial via SIB module */
+void lpc_host_register_init(void){
+
+ timestamp_t deadline;
+
+ deadline.val = 0;
+ deadline = get_time();
+ deadline.val += LPC_PLTRST_TIMEOUT_US;
+
+ /* Make sure PLTRST is de-asserted. Or any setting for LPC is useless */
+ while (lpc_get_pltrst_asserted())
+ if (timestamp_expired(deadline, NULL)) {
+ CPRINTS("PLTRST is asserted. LPC settings are ignored");
+ return;
+ }
+
+ /* Setting PMC2 */
+ /* LDN register = 0x12(PMC2) */
+ lpc_sib_write_reg(SIO_OFFSET, 0x07, 0x12);
+ /* CMD port is 0x200 */
+ lpc_sib_write_reg(SIO_OFFSET, 0x60, 0x02);
+ lpc_sib_write_reg(SIO_OFFSET, 0x61, 0x00);
+ /* Data port is 0x204 */
+ lpc_sib_write_reg(SIO_OFFSET, 0x62, 0x02);
+ lpc_sib_write_reg(SIO_OFFSET, 0x63, 0x04);
+ /* enable PMC2 */
+ lpc_sib_write_reg(SIO_OFFSET, 0x30, 0x01);
+
+ /* Setting SHM */
+ /* LDN register = 0x0F(SHM) */
+ lpc_sib_write_reg(SIO_OFFSET, 0x07, 0x0F);
+ /* WIN1&2 mapping to IO */
+ lpc_sib_write_reg(SIO_OFFSET, 0xF1,
+ lpc_sib_read_reg(SIO_OFFSET, 0xF1) | 0x30);
+ /* Host Command on the IO:0x0800 */
+ lpc_sib_write_reg(SIO_OFFSET, 0xF7, 0x00);
+ lpc_sib_write_reg(SIO_OFFSET, 0xF6, 0x00);
+ lpc_sib_write_reg(SIO_OFFSET, 0xF5, 0x08);
+ lpc_sib_write_reg(SIO_OFFSET, 0xF4, 0x00);
+ /* WIN1 as Host Command on the IO:0x0800 */
+ lpc_sib_write_reg(SIO_OFFSET, 0xFB, 0x00);
+ lpc_sib_write_reg(SIO_OFFSET, 0xFA, 0x00);
+ /* WIN2 as MEMMAP on the IO:0x900 */
+ lpc_sib_write_reg(SIO_OFFSET, 0xF9, 0x09);
+ lpc_sib_write_reg(SIO_OFFSET, 0xF8, 0x00);
+ /* enable SHM */
+ lpc_sib_write_reg(SIO_OFFSET, 0x30, 0x01);
+}
+
static void lpc_init(void)
{
/* Enable clock for LPC peripheral */
@@ -643,8 +797,17 @@ static void lpc_init(void)
update_host_event_status();
+ /*
+ * TODO: For testing LPC with Chromebox, please make sure LPC_CLK is
+ * generated before executing this function. EC needs LPC_CLK to access
+ * LPC register through SIB module. For Chromebook platform, this
+ * functionality should be done by BIOS or executed in hook function of
+ * HOOK_CHIPSET_STARTUP
+ */
+#ifdef BOARD_NPCX_EVB
/* initial IO port address via SIB-write modules */
- system_lpc_host_register_init();
+ lpc_host_register_init();
+#endif
}
/* Enable LPC ACPI-EC interrupts */
diff --git a/chip/npcx/openocd/npcx.cfg b/chip/npcx/openocd/npcx.cfg
index ccc53437bb..cd00715d72 100644
--- a/chip/npcx/openocd/npcx.cfg
+++ b/chip/npcx/openocd/npcx.cfg
@@ -43,7 +43,7 @@ target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position \
-work-area-size $_WORKAREASIZE
# JTAG speed
-adapter_khz 1000
+adapter_khz 100
adapter_nsrst_delay 100
if {$using_jtag} {
diff --git a/chip/npcx/openocd/npcx_cmds.tcl b/chip/npcx/openocd/npcx_cmds.tcl
index 63ed2932bc..a32afccf03 100644
--- a/chip/npcx/openocd/npcx_cmds.tcl
+++ b/chip/npcx/openocd/npcx_cmds.tcl
@@ -10,15 +10,13 @@ source [find mem_helper.tcl]
proc flash_npcx {image_path image_offset image_size spifw_image} {
set UPLOAD_FLAG 0x200C4000;
- # Clear whole 128KB Code RAM
- mwb 0x10088000 0xFF 0x20000
+ # Clear whole 96KB Code RAM
+ mwb 0x100A8000 0xFF 0x18000
# Upload binary image to Code RAM
- fast_load_image $image_path 0x10088000
- fast_load
+ load_image $image_path 0x100A8000
# Upload program spi image FW to lower 16KB Data RAM
- fast_load_image $spifw_image 0x200C0000
- fast_load
+ load_image $spifw_image 0x200C0000
# Set sp to upper 16KB Data RAM
reg sp 0x200C8000
@@ -48,71 +46,67 @@ proc flash_npcx {image_path image_offset image_size spifw_image} {
halt
}
-proc flash_npcx_ro {image_offset} {
- # 128 KB for RO& RW regions
- set fw_size 0x20000
+proc flash_npcx_ro {image_dir image_offset} {
+ set MPU_RNR 0xE000ED98;
+ set MPU_RASR 0xE000EDA0;
+
+ # 96 KB for RO& RW regions
+ set fw_size 0x18000
# images path
- set outdir ../../../build/npcx_evb
- set ro_image_path $outdir/ec.RO.flat
- set spifw_image $outdir/chip/npcx/spiflashfw/ec_npcxflash.bin
+ set ro_image_path $image_dir/ec.RO.flat
+ set spifw_image $image_dir/chip/npcx/spiflashfw/ec_npcxflash.bin
# Halt CPU first
halt
+ adapter_khz 1000
+
+ # diable MPU for Data RAM
+ mww $MPU_RNR 0x1
+ mww $MPU_RASR 0x0
+
echo "*** Start to program RO region ***"
- # Write to lower 128kB from offset
+ # Write to lower 96kB from offset
flash_npcx $ro_image_path $image_offset $fw_size $spifw_image
echo "*** Finish program RO region ***"
- # Reset CPU
- reset
}
-proc flash_npcx_evb {image_offset} {
+proc flash_npcx_all {image_dir image_offset} {
set MPU_RNR 0xE000ED98;
set MPU_RASR 0xE000EDA0;
- # 128 KB for RO& RW regions
- set fw_size 0x20000
- # 4K little FW
- set lfw_size 0x1000
+ # 96 KB for RO& RW regions
+ set fw_size 0x18000
# 8M spi-flash
set flash_size 0x800000
# images path
- set outdir ../../../build/npcx_evb
- set ro_image_path $outdir/ec.RO.flat
- set rw_image_path $outdir/ec.RW.bin
- set lfw_image_path $outdir/chip/npcx/lfw/ec_lfw.bin
- set spifw_image $outdir/chip/npcx/spiflashfw/ec_npcxflash.bin
+ set ro_image_path $image_dir/ec.RO.flat
+ set rw_image_path $image_dir/ec.RW.bin
+ set spifw_image $image_dir/chip/npcx/spiflashfw/ec_npcxflash.bin
# images offset
- set rw_image_offset [expr ($image_offset + $fw_size)]
- set lfw_image_offset [expr ($flash_size - $lfw_size)]
+ set rw_image_offset [expr ($image_offset + 0x20000)]
# Halt CPU first
halt
- # diable MPU for Data RAM first
+ adapter_khz 1000
+
+ # diable MPU for Data RAM
mww $MPU_RNR 0x1
mww $MPU_RASR 0x0
echo "*** Start to program RO region ***"
- # Write to lower 128kB from offset
+ # Write to lower 96kB from offset
flash_npcx $ro_image_path $image_offset $fw_size $spifw_image
echo "*** Finish program RO region ***\r\n"
echo "*** Start to program RW region ***"
- # Write to upper 128kB from offset
+ # Write to upper 96kB from offset
flash_npcx $rw_image_path $rw_image_offset $fw_size $spifw_image
echo "*** Finish program RW region ***\r\n"
- echo "*** Start to program LFW region ***"
- # Write to top of flash minus 4KB
- flash_npcx $lfw_image_path $lfw_image_offset $lfw_size $spifw_image
- echo "*** Finish program LFW region ***\r\n"
-
- # Reset CPU
- reset
}
proc halt_npcx_cpu { } {
diff --git a/chip/npcx/pwm.c b/chip/npcx/pwm.c
index 752ffe47fe..4a8ba4dace 100644
--- a/chip/npcx/pwm.c
+++ b/chip/npcx/pwm.c
@@ -65,7 +65,7 @@ void pwm_freq_changed(void)
* Using PWM Frequency and Resolution we calculate
* prescaler for input clock
*/
-#ifdef CONFIG_PWM_INPUT_LFCLK
+#ifdef NPCX_PWM_INPUT_LFCLK
prescaler_divider = (uint32_t)(32768 /
(pwm_channels[pwm_init_ch].freq)
/(pwm_channels[pwm_init_ch].cycle_pulses));
@@ -226,7 +226,7 @@ void pwm_config(enum pwm_channel ch)
| (NPCX_PWM_CLOCK_APB2_LFCLK<<NPCX_PWMCTLEX_FCK_SEL);
if (ch == PWM_CH_FAN) {
-#ifdef CONFIG_PWM_INPUT_LFCLK
+#ifdef NPCX_PWM_INPUT_LFCLK
/* Select default LFCLK clock input to PWM module */
SET_BIT(NPCX_PWMCTL(pwm_channels[ch].channel),
NPCX_PWMCTL_CKSEL);
diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h
index 21a0609d64..aa741ba805 100644
--- a/chip/npcx/registers.h
+++ b/chip/npcx/registers.h
@@ -27,12 +27,7 @@
*/
/* Global Definition */
-#define CHIP_NPCX5M5G
-#define SUPPORT_JTAG
-#define I2C0_BUS0 1 /* Use I2C0_SDA0/1 I2C0_SCL0/1 */
-#define TACH_SEL1 1 /* Use TACH_SEL1 or TACH_SEL2 */
-#define JTAG1 0 /* Use JTAG0/1 JTAG1 only support
- 132-Pins package*/
+#define CHIP_VERSION 3 /* A3 version */
#define I2C_7BITS_ADDR 0
#define I2C_LEVEL_SUPPORT 1
/* Switcher of features */
@@ -49,6 +44,7 @@
#define DEBUG_SPI 0
#define DEBUG_FLH 0
#define DEBUG_PECI 0
+#define DEBUG_SHI 1
#define DEBUG_CLK 1
/* Modules Map */
@@ -61,6 +57,7 @@
#define NPCX_GLUE_REGS_BASE 0x400A5000
#define NPCX_BBRAM_BASE_ADDR 0x400AF000
#define NPCX_HFCG_BASE_ADDR 0x400B5000
+#define NPCX_SHI_BASE_ADDR 0x4000F000
#define NPCX_MTC_BASE_ADDR 0x400B7000
#define NPCX_MSWC_BASE_ADDR 0x400C1000
#define NPCX_SCFG_BASE_ADDR 0x400C3000
@@ -75,6 +72,7 @@
#define NPCX_PWM_BASE_ADDR(mdl) (0x40080000 + ((mdl) * 0x2000L))
#define NPCX_GPIO_BASE_ADDR(mdl) (0x40081000 + ((mdl) * 0x2000L))
#define NPCX_ITIM16_BASE_ADDR(mdl) (0x400B0000 + ((mdl) * 0x2000L))
+#define NPCX_ITIM32_BASE_ADDR 0x400BC000
#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))
@@ -168,7 +166,7 @@
#define NPCX_IRQ_WKINTC_0 NPCX_IRQ_15
#define NPCX_IRQ16_NOUSED NPCX_IRQ_16
#define NPCX_IRQ_ITIM16_3 NPCX_IRQ_17
-#define NPCX_IRQ_ESPI NPCX_IRQ_18
+#define NPCX_IRQ_SHI NPCX_IRQ_18
#define NPCX_IRQ19_NOUSED NPCX_IRQ_19
#define NPCX_IRQ20_NOUSED NPCX_IRQ_20
#define NPCX_IRQ_PS2 NPCX_IRQ_21
@@ -196,7 +194,7 @@
#define NPCX_IRQ_ITIM16_4 NPCX_IRQ_43
#define NPCX_IRQ_ITIM16_5 NPCX_IRQ_44
#define NPCX_IRQ_ITIM16_6 NPCX_IRQ_45
-#define NPCX_IRQ46_NOUSED NPCX_IRQ_46
+#define NPCX_IRQ_ITIM32 NPCX_IRQ_46
#define NPCX_IRQ_WKINTA_1 NPCX_IRQ_47
#define NPCX_IRQ_WKINTB_1 NPCX_IRQ_48
#define NPCX_IRQ_KSI_WKINTC_1 NPCX_IRQ_49
@@ -393,6 +391,7 @@ enum {
#define GPIO_D GPIO_PORT_D
#define GPIO_E GPIO_PORT_E
#define GPIO_F GPIO_PORT_F
+#define DUMMY_GPIO_BANK GPIO_PORT_0
/******************************************************************************/
/* MSWC Registers */
@@ -411,6 +410,7 @@ enum {
#define NPCX_RSTCTL REG8(NPCX_SCFG_BASE_ADDR + 0x002)
#define NPCX_DEV_CTL4 REG8(NPCX_SCFG_BASE_ADDR + 0x006)
#define NPCX_DEVALT(n) REG8(NPCX_SCFG_BASE_ADDR + 0x010 + n)
+#define NPCX_LFCGCALCNT REG8(NPCX_SCFG_BASE_ADDR + 0x021)
#define NPCX_DEVPU0 REG8(NPCX_SCFG_BASE_ADDR + 0x028)
#define NPCX_DEVPU1 REG8(NPCX_SCFG_BASE_ADDR + 0x029)
#define NPCX_LV_GPIO_CTL0 REG8(NPCX_SCFG_BASE_ADDR + 0x02A)
@@ -458,6 +458,7 @@ enum {
#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_DEVPU0_I2C0_0_PUE 0
#define NPCX_DEVPU0_I2C0_1_PUE 1
@@ -550,17 +551,21 @@ enum {
#define NPCX_DEVALTA_32KCLKIN_SL 3
#define NPCX_DEVALTA_NO_VCC1_RST 4
#define NPCX_DEVALTA_NO_PECI_EN 6
-#define NPCX_DEVALTA_UART_SL 7
+#define NPCX_DEVALTA_UART_SL1 7
#define NPCX_DEVALTB_RXD_SL 0
#define NPCX_DEVALTB_TXD_SL 1
+#define NPCX_DEVALTC_UART_SL2 0
+#define NPCX_DEVALTC_SHI_SL 1
#define NPCX_DEVALTC_PS2_3_SL2 3
#define NPCX_DEVALTC_TA1_TACH1_SL2 4
#define NPCX_DEVALTC_TB1_TACH2_SL2 5
#define NPCX_DEVALTC_TA2_SL2 6
#define NPCX_DEVALTC_TB2_SL2 7
+#define NPCX_LFCGCALCNT_LPREG_CTL_EN 1
+
/******************************************************************************/
/* Development and Debug Support (DBG) Registers */
#define NPCX_DBGCTRL REG8(NPCX_SCFG_BASE_ADDR + 0x074)
@@ -645,6 +650,17 @@ enum {
#define NPCX_SMBADDR7_SAEN 7
#define NPCX_SMBADDR8_SAEN 7
+/*
+ * SMB enumeration
+ * I2C Port.
+ */
+enum NPCX_I2C_PORT_T {
+ NPCX_I2C_PORT0 = 0, /* I2C port 0, bus 0/1*/
+ NPCX_I2C_PORT1 = 1, /* I2C port 1 */
+ NPCX_I2C_PORT2 = 2, /* I2C port 2 */
+ NPCX_I2C_PORT3 = 3, /* I2C port 3 */
+};
+
/******************************************************************************/
/* Power Management Controller (PMC) Registers */
#define NPCX_PMCSR REG8(NPCX_PMC_BASE_ADDR + 0x000)
@@ -694,6 +710,7 @@ enum {
#define NPCX_PWDWN_CTL4_PECI_PD 5
#define NPCX_PWDWN_CTL4_PWM6_PD 6
#define NPCX_PWDWN_CTL4_SPIP_PD 7
+#define NPCX_PWDWN_CTL5_SHI_PD 1
#define NPCX_PWDWN_CTL5_MRFSH_DIS 2
#define NPCX_PWDWN_CTL5_C2HACC_PD 3
#define NPCX_PWDWN_CTL5_SHM_REG_PD 4
@@ -724,6 +741,15 @@ enum {
CGC_OFFSET_ESPI = 5,
};
+enum NPCX_PMC_PWDWN_CTL_T {
+ NPCX_PMC_PWDWN_1 = 0,
+ NPCX_PMC_PWDWN_2 = 1,
+ NPCX_PMC_PWDWN_3 = 2,
+ NPCX_PMC_PWDWN_4 = 3,
+ NPCX_PMC_PWDWN_5 = 4,
+ NPCX_PMC_PWDWN_6 = 5,
+};
+
#define CGC_KBS_MASK (1 << NPCX_PWDWN_CTL1_KBS_PD)
#define CGC_UART_MASK (1 << NPCX_PWDWN_CTL1_UART_PD)
#define CGC_FAN_MASK (1 << NPCX_PWDWN_CTL1_MFT1_PD)
@@ -779,6 +805,7 @@ enum {
#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
/******************************************************************************/
/* Shared Memory (SHM) Registers */
@@ -1072,7 +1099,7 @@ enum PM_CHANNEL_T {
#define NPCX_TWUEN_TCWEN 2
#define NPCX_TWUEN_TDWEN 3
/******************************************************************************/
-/*ITIM16 Define*/
+/* ITIM16/32 Define */
#define ITIM16_INT(module) CONCAT2(NPCX_IRQ_, module)
/* ITIM16 registers */
@@ -1081,12 +1108,15 @@ enum PM_CHANNEL_T {
#define NPCX_ITCNT16(n) REG16(NPCX_ITIM16_BASE_ADDR(n) + 0x002)
#define NPCX_ITCTS(n) REG8(NPCX_ITIM16_BASE_ADDR(n) + 0x004)
+/* ITIM32 registers */
+#define NPCX_ITCNT32 REG32(NPCX_ITIM32_BASE_ADDR + 0x008)
+
/* ITIM16 register fields */
-#define NPCX_ITIM16_TO_STS 0
-#define NPCX_ITIM16_TO_IE 2
-#define NPCX_ITIM16_TO_WUE 3
-#define NPCX_ITIM16_CKSEL 4
-#define NPCX_ITIM16_ITEN 7
+#define NPCX_ITCTS_TO_STS 0
+#define NPCX_ITCTS_TO_IE 2
+#define NPCX_ITCTS_TO_WUE 3
+#define NPCX_ITCTS_CKSEL 4
+#define NPCX_ITCTS_ITEN 7
/* ITIM16 enumeration*/
enum ITIM16_MODULE_T {
@@ -1096,10 +1126,62 @@ enum ITIM16_MODULE_T {
ITIM16_4,
ITIM16_5,
ITIM16_6,
- ITIM16_MODULE_COUNT,
+ ITIM32,
+ ITIM_MODULE_COUNT,
};
/******************************************************************************/
+/* Serial Host Interface (SHI) Registers */
+#define NPCX_SHICFG1 REG8(NPCX_SHI_BASE_ADDR + 0x001)
+#define NPCX_SHICFG2 REG8(NPCX_SHI_BASE_ADDR + 0x002)
+#define NPCX_I2CADDR1 REG8(NPCX_SHI_BASE_ADDR + 0x003)
+#define NPCX_I2CADDR2 REG8(NPCX_SHI_BASE_ADDR + 0x004)
+#define NPCX_EVENABLE REG8(NPCX_SHI_BASE_ADDR + 0x005)
+#define NPCX_EVSTAT REG8(NPCX_SHI_BASE_ADDR + 0x006)
+#define NPCX_SHI_CAPABILITY REG8(NPCX_SHI_BASE_ADDR + 0x007)
+#define NPCX_STATUS REG8(NPCX_SHI_BASE_ADDR + 0x008)
+#define NPCX_IBUFSTAT REG8(NPCX_SHI_BASE_ADDR + 0x00A)
+#define NPCX_OBUFSTAT REG8(NPCX_SHI_BASE_ADDR + 0x00B)
+#define NPCX_ADVCFG REG8(NPCX_SHI_BASE_ADDR + 0x00E)
+#define NPCX_OBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x020 + (n))
+#define NPCX_IBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x060 + (n))
+
+/* SHI register fields */
+#define NPCX_SHICFG1_EN 0
+#define NPCX_SHICFG1_MODE 1
+#define NPCX_SHICFG1_WEN 2
+#define NPCX_SHICFG1_AUTIBF 3
+#define NPCX_SHICFG1_AUTOBE 4
+#define NPCX_SHICFG1_DAS 5
+#define NPCX_SHICFG1_CPOL 6
+#define NPCX_SHICFG1_IWRAP 7
+#define NPCX_SHICFG2_SIMUL 0
+#define NPCX_SHICFG2_BUSY 1
+#define NPCX_SHICFG2_ONESHOT 2
+#define NPCX_SHICFG2_SLWU 3
+#define NPCX_SHICFG2_REEN 4
+#define NPCX_SHICFG2_RESTART 5
+#define NPCX_SHICFG2_REEVEN 6
+#define NPCX_EVENABLE_OBEEN 0
+#define NPCX_EVENABLE_OBHEEN 1
+#define NPCX_EVENABLE_IBFEN 2
+#define NPCX_EVENABLE_IBHFEN 3
+#define NPCX_EVENABLE_EOREN 4
+#define NPCX_EVENABLE_EOWEN 5
+#define NPCX_EVENABLE_STSREN 6
+#define NPCX_EVENABLE_IBOREN 7
+#define NPCX_EVSTAT_OBE 0
+#define NPCX_EVSTAT_OBHE 1
+#define NPCX_EVSTAT_IBF 2
+#define NPCX_EVSTAT_IBHF 3
+#define NPCX_EVSTAT_EOR 4
+#define NPCX_EVSTAT_EOW 5
+#define NPCX_EVSTAT_STSR 6
+#define NPCX_EVSTAT_IBOR 7
+#define NPCX_STATUS_OBES 6
+#define NPCX_STATUS_IBFS 7
+
+/******************************************************************************/
/* Monotonic Counter (MTC) Registers */
#define NPCX_TTC REG32(NPCX_MTC_BASE_ADDR + 0x000)
#define NPCX_WTC REG32(NPCX_MTC_BASE_ADDR + 0x004)
@@ -1115,6 +1197,12 @@ enum ITIM16_MODULE_T {
#define NPCX_LPRAM_CTRL REG32(0x40001044)
/******************************************************************************/
+/* Nuvoton internal used only registers */
+#define NPCX_INTERNAL_CTRL1 REG8(0x400DB000)
+#define NPCX_INTERNAL_CTRL2 REG8(0x400DD000)
+#define NPCX_INTERNAL_CTRL3 REG8(0x400DF000)
+
+/******************************************************************************/
/* Optional M4 Registers */
#define CPU_DHCSR REG32(0xE000EDF0)
#define CPU_MPU_CTRL REG32(0xE000ED94)
@@ -1196,4 +1284,76 @@ enum ITIM16_MODULE_T {
#define MASK_CMD_WR_ADR (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) \
| MASK(A_SIZE))
+/******************************************************************************/
+/* Inline functions */
+/* This routine checks pending bit of GPIO wake-up functionality */
+static inline int uart_is_wakeup_from_gpio(void)
+{
+#if NPCX_UART_MODULE2
+ return IS_BIT_SET(NPCX_WKPND(1, 6), 4);
+#else
+ return IS_BIT_SET(NPCX_WKPND(1, 1), 0);
+#endif
+}
+
+/* This routine clear pending bit of GPIO wake-up functionality */
+static inline void uart_clear_wakeup_event(void)
+{
+#if NPCX_UART_MODULE2
+ SET_BIT(NPCX_WKPND(1, 6), 4);
+#else
+ SET_BIT(NPCX_WKPND(1, 1), 0);
+#endif
+}
+
+/* This routine checks wake-up functionality from GPIO is enabled or not */
+static inline int uart_is_enable_wakeup(void)
+{
+#if NPCX_UART_MODULE2
+ return IS_BIT_SET(NPCX_WKEN(1, 6), 4);
+#else
+ return IS_BIT_SET(NPCX_WKEN(1, 1), 0);
+#endif
+}
+
+/* This routine enables wake-up functionality from GPIO on UART rx pin */
+static inline void uart_enable_wakeup(int enable)
+{
+#if NPCX_UART_MODULE2
+ UPDATE_BIT(NPCX_WKEN(1, 6), 4, enable);
+#else
+ UPDATE_BIT(NPCX_WKEN(1, 1), 0, enable);
+#endif
+}
+
+/* This routine checks functionality is UART rx or not */
+static inline int npcx_is_uart(void)
+{
+#if NPCX_UART_MODULE2
+ return IS_BIT_SET(NPCX_DEVALT(0x0C), NPCX_DEVALTC_UART_SL2);
+#else
+ return IS_BIT_SET(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL1);
+#endif
+}
+
+/* This routine switches the functionality from UART rx to GPIO */
+static inline void npcx_uart2gpio(void)
+{
+#if NPCX_UART_MODULE2
+ CLEAR_BIT(NPCX_DEVALT(0x0C), NPCX_DEVALTC_UART_SL2);
+#else
+ CLEAR_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL1);
+#endif
+}
+
+/* This routine switches the functionality from GPIO to UART rx */
+static inline void npcx_gpio2uart(void)
+{
+#if NPCX_UART_MODULE2
+ CLEAR_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL1);
+ SET_BIT(NPCX_DEVALT(0x0C), NPCX_DEVALTC_UART_SL2);
+#else
+ SET_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL1);
+#endif
+}
#endif /* __CROS_EC_REGISTERS_H */
diff --git a/chip/npcx/rom_chip.h b/chip/npcx/rom_chip.h
new file mode 100644
index 0000000000..6d635f6c4d
--- /dev/null
+++ b/chip/npcx/rom_chip.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2015 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_ROM_CHIP_H_
+#define __CROS_EC_ROM_CHIP_H_
+
+/******************************************************************************/
+/*
+ * Enumerations of ROM api functions
+ */
+enum API_SIGN_OPTIONS_T {
+ SIGN_NO_CHECK = 0,
+ SIGN_CRC_CHECK = 1,
+};
+
+enum API_RETURN_STATUS_T {
+ /* Successful download */
+ API_RET_STATUS_OK = 0,
+ /* Address is outside of flash or not 4 bytes aligned. */
+ API_RET_STATUS_INVALID_SRC_ADDR = 1,
+ /* Address is outside of RAM or not 4 bytes aligned. */
+ API_RET_STATUS_INVALID_DST_ADDR = 2,
+ /* Size is 0 or not 4 bytes aligned. */
+ API_RET_STATUS_INVALID_SIZE = 3,
+ /* Flash Address + Size is out of flash. */
+ API_RET_STATUS_INVALID_SIZE_OUT_OF_FLASH = 4,
+ /* RAM Address + Size is out of RAM. */
+ API_RET_STATUS_INVALID_SIZE_OUT_OF_RAM = 5,
+ /* Wrong sign option. */
+ API_RET_STATUS_INVALID_SIGN = 6,
+ /* Error during Code copy. */
+ API_RET_STATUS_COPY_FAILED = 7,
+ /* Execution Address is outside of RAM */
+ API_RET_STATUS_INVALID_EXE_ADDR = 8,
+ /* Bad CRC value */
+ API_RET_STATUS_INVALID_SIGNATURE = 9,
+};
+
+/******************************************************************************/
+/*
+ * Macro functions of ROM api functions
+ */
+#define ADDR_DOWNLOAD_FROM_FLASH (*(volatile uint32_t *) 0x40)
+#define download_from_flash(src_offset, dest_addr, size, sign, exe_addr, \
+ status) \
+ (((download_from_flash_ptr) ADDR_DOWNLOAD_FROM_FLASH) \
+ (src_offset, dest_addr, size, sign, exe_addr, status))
+
+/******************************************************************************/
+/*
+ * Declarations of ROM api functions
+ */
+typedef void (*download_from_flash_ptr) (
+ uint32_t src_offset, /* The offset of the data to be downloaded */
+ uint32_t dest_addr, /* The address of the downloaded data in the RAM*/
+ uint32_t size, /* Number of bytes to download */
+ enum API_SIGN_OPTIONS_T sign, /* Need CRC check or not */
+ uint32_t exe_addr, /* jump to this address after download if not zero */
+ enum API_RETURN_STATUS_T *status /* Status fo download */
+);
+
+
+
+#endif /* __CROS_EC_ROM_CHIP_H_ */
diff --git a/chip/npcx/shi.c b/chip/npcx/shi.c
new file mode 100644
index 0000000000..755f043abe
--- /dev/null
+++ b/chip/npcx/shi.c
@@ -0,0 +1,859 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+/*
+ * SHI driver for Chrome EC.
+ *
+ * This uses Input/Output buffer to handle SPI transmission and reception.
+ */
+
+#include "chipset.h"
+#include "clock.h"
+#include "console.h"
+#include "gpio.h"
+#include "task.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "registers.h"
+#include "spi.h"
+#include "system.h"
+#include "timer.h"
+#include "util.h"
+
+#if !(DEBUG_SHI)
+#define CPUTS(...)
+#define CPRINTS(...)
+#define CPRINTF(...)
+#else
+#define CPUTS(outstr) cputs(CC_SPI, outstr)
+#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args)
+#define CPRINTF(format, args...) cprintf(CC_SPI, format, ## args)
+#endif
+
+/* SHI Bus definition */
+#define SHI_OBUF_FULL_SIZE 64 /* Full output buffer size */
+#define SHI_IBUF_FULL_SIZE 64 /* Full input buffer size */
+#define SHI_OBUF_HALF_SIZE (SHI_OBUF_FULL_SIZE/2) /* Half output buffer size */
+#define SHI_IBUF_HALF_SIZE (SHI_IBUF_FULL_SIZE/2) /* Half input buffer size */
+
+/* Start address of SHI output buffer */
+#define SHI_OBUF_START_ADDR (volatile uint8_t *)(NPCX_SHI_BASE_ADDR + 0x020)
+/* Middle address of SHI output buffer */
+#define SHI_OBUF_HALF_ADDR (SHI_OBUF_START_ADDR + SHI_OBUF_HALF_SIZE)
+/* Top address of SHI output buffer */
+#define SHI_OBUF_FULL_ADDR (SHI_OBUF_START_ADDR + SHI_IBUF_FULL_SIZE)
+/*
+ * Valid offset of SHI output buffer to write.
+ * When SIMUL bit is set, IBUFPTR can be used instead of OBUFPTR
+ */
+#define SHI_OBUF_VALID_OFFSET ((NPCX_IBUFSTAT + SHI_OUT_PREAMBLE_LENGTH) % \
+ SHI_OBUF_FULL_SIZE)
+/* Start address of SHI input buffer */
+#define SHI_IBUF_START_ADDR (volatile uint8_t *)(NPCX_SHI_BASE_ADDR + 0x060)
+/* Current address of SHI input buffer */
+#define SHI_IBUF_CUR_ADDR (SHI_IBUF_START_ADDR + NPCX_IBUFSTAT)
+
+/*
+ * Timeout to wait for SHI request packet
+ *
+ * This affects the slowest SPI clock we can support. A delay of 8192 us
+ * permits a 512-byte request at 500 KHz, assuming the master starts sending
+ * bytes as soon as it asserts chip select. That's as slow as we would
+ * practically want to run the SHI interface, since running it slower
+ * significantly impacts firmware update times.
+ */
+#define SHI_CMD_RX_TIMEOUT_US 8192
+
+/* Timeout for glitch case. Make sure it will exceed 8 SPI clocks */
+#define SHI_GLITCH_TIMEOUT_US 10
+
+/*
+ * Max data size for a version 3 request/response packet. This is big enough
+ * to handle a request/response header, flash write offset/size, and 512 bytes
+ * of flash data.
+ */
+#define SHI_MAX_REQUEST_SIZE 0x220
+#define SHI_MAX_RESPONSE_SIZE 0x220
+
+/*
+ * The AP blindly clocks back bytes over the SPI interface looking for a
+ * framing byte. So this preamble must always precede the actual response
+ * packet.
+ */
+
+#define SHI_OUT_PREAMBLE_LENGTH 2
+/*
+ * Space allocation of the past-end status byte (EC_SPI_PAST_END) in the out_msg
+ * buffer.
+ */
+#define EC_SPI_PAST_END_LENGTH 1
+/*
+ * Space allocation of the frame status byte (EC_SPI_FRAME_START) in the out_msg
+ * buffer.
+ */
+#define EC_SPI_FRAME_START_LENGTH 1
+
+/*
+ * Offset of output parameters needs to account for pad and framing bytes and
+ * one last past-end byte at the end so any additional bytes clocked out by
+ * the AP will have a known and identifiable value.
+ */
+#define SHI_PROTO2_OFFSET (EC_PROTO2_RESPONSE_HEADER_BYTES + 1)
+#define SHI_PROTO2_OVERHEAD (SHI_PROTO2_OFFSET + \
+ EC_PROTO2_RESPONSE_TRAILER_BYTES + 1)
+#define SHI_PROTO3_OVERHEAD (EC_SPI_PAST_END_LENGTH + EC_SPI_FRAME_START_LENGTH)
+
+/*
+ * Our input and output msg buffers. These must be large enough for our largest
+ * message, including protocol overhead, and must be 32-bit aligned.
+ */
+static uint8_t out_msg[SHI_MAX_RESPONSE_SIZE];
+static uint8_t in_msg[SHI_MAX_REQUEST_SIZE];
+
+/* Parameters used by host protocols */
+static struct host_cmd_handler_args args;
+static struct host_packet shi_packet;
+
+/* Function pointer for handler of host request */
+void (*request_handler)(void);
+
+enum shi_state {
+ /* SHI not enabled (initial state, and when chipset is off) */
+ SHI_STATE_DISABLED = 0,
+ /* Ready to receive next request */
+ SHI_STATE_READY_TO_RECV,
+ /* Complete transaction but need to initialize */
+ SHI_STATE_NOT_READY,
+ /* Receiving request */
+ SHI_STATE_RECEIVING,
+ /* Processing request */
+ SHI_STATE_PROCESSING,
+ /* Sending response */
+ SHI_STATE_SENDING,
+ /* State machine mismatch, timeout, or protocol we can't handle. */
+ SHI_STATE_ERROR,
+} state;
+
+/* SHI bus parameters */
+struct shi_bus_parameters {
+ uint8_t *rx_msg; /* Entry pointer of msg rx buffer */
+ uint8_t *tx_msg; /* Entry pointer of msg tx buffer */
+ volatile uint8_t *rx_buf; /* Entry pointer of receive buffer */
+ volatile uint8_t *tx_buf; /* Entry pointer of transmit buffer */
+ uint16_t sz_received; /* Size of received data in bytes */
+ uint16_t sz_sending; /* Size of sending data in bytes */
+ uint16_t sz_request; /* request bytes need to receive */
+ uint16_t sz_response; /* response bytes need to receive */
+ timestamp_t rx_deadline; /* deadline of receiving */
+ uint8_t pre_ibufstat; /* Previous IBUFSTAT value */
+} shi_params;
+
+/* Forward declaraction */
+static void shi_reset_prepare(void);
+static void shi_error(int need_reset);
+static void shi_fill_out_status(uint8_t status);
+static void shi_write_half_outbuf(void);
+static void shi_write_outbuf_wait(uint16_t szbytes);
+static int shi_read_inbuf_wait(uint16_t szbytes);
+
+/*****************************************************************************/
+/* V2 protocol layer functions */
+
+/**
+ * The format of a reply is as per the command interface, with a number of
+ * preamble bytes before it.
+ *
+ * The format of a reply is a sequence of bytes:
+ *
+ * <hdr> <status> <len> <msg bytes> <sum> [<postamble byte>...]
+ *
+ * The hdr byte is just a tag to indicate that the real message follows. It
+ * signals the end of any preamble required by the interface.
+ *
+ * The length is the entire packet size, including the header, length bytes,
+ * message payload, checksum, and postamble byte.
+ *
+ * We keep an eye on the SHI_CS_L line - if this goes high then the transaction
+ * is over so there is no point in trying to send the reply.
+ */
+static void shi_reply_response(enum ec_status status, uint8_t *msg_ptr,
+ int msg_len)
+{
+ int need_copy = msg_ptr != out_msg + SHI_PROTO2_OFFSET;
+ int sum, i;
+
+ ASSERT(msg_len + SHI_PROTO2_OVERHEAD <= sizeof(out_msg));
+
+ /* Add our header bytes - the first one might not actually be sent */
+ out_msg[0] = EC_SPI_FRAME_START;
+ out_msg[1] = status;
+ out_msg[2] = msg_len & 0xff;
+
+ /*
+ * Calculate the checksum; includes the status and message length bytes
+ * but not the pad and framing bytes since those are stripped by the AP
+ * driver.
+ */
+ sum = status + msg_len;
+ for (i = 0; i < msg_len; i++) {
+ int ch = msg_ptr[i];
+ sum += ch;
+ if (need_copy)
+ out_msg[i + SHI_PROTO2_OFFSET] = ch;
+ }
+
+ /* Add the checksum and get ready to send */
+ out_msg[SHI_PROTO2_OFFSET + msg_len] = sum & 0xff;
+ out_msg[SHI_PROTO2_OFFSET + msg_len + 1] = EC_SPI_PAST_END;
+
+ /* Computing sending bytes of response */
+ shi_params.sz_response = msg_len + SHI_PROTO2_OVERHEAD;
+
+ /*
+ * Before the state is set to SENDING, any CS de-assertion would
+ * give up sending.
+ */
+ if (state == SHI_STATE_PROCESSING) {
+ /*
+ * Disable SHI interrupt until we have prepared
+ * the first package to output
+ */
+ task_disable_irq(NPCX_IRQ_SHI);
+ /* Transmit the reply */
+ state = SHI_STATE_SENDING;
+ CPRINTF("SND-");
+ /* Start to fill output buffer with msg buffer */
+ shi_write_outbuf_wait(shi_params.sz_response);
+ /* Enable SHI interrupt */
+ task_enable_irq(NPCX_IRQ_SHI);
+ }
+ /*
+ * If we're not processing, then the AP has already terminated the
+ * transaction, and won't be listening for a response.
+ */
+ else {
+ /* Reset SHI and prepare to next transaction again */
+ shi_reset_prepare();
+ CPRINTF("END\n");
+ return;
+ }
+}
+
+/**
+ * Called for V2 protocol to indicate that a command has completed
+ *
+ * Some commands can continue for a while. This function is called by
+ * host_command when it completes.
+ *
+ */
+static void shi_send_response(struct host_cmd_handler_args *args)
+{
+ enum ec_status result = args->result;
+
+ if (args->response_size > args->response_max)
+ result = EC_RES_INVALID_RESPONSE;
+
+ /* Transmit the reply */
+ args->response_size += (EC_SPI_PAST_END_LENGTH +
+ EC_SPI_FRAME_START_LENGTH);
+ shi_reply_response(result, args->response, args->response_size);
+}
+
+void shi_handle_host_command(void)
+{
+ uint16_t sz_inbuf_int = shi_params.sz_request / SHI_IBUF_HALF_SIZE;
+ uint16_t cnt_inbuf_int = shi_params.sz_received / SHI_IBUF_HALF_SIZE;
+ if (sz_inbuf_int - cnt_inbuf_int)
+ /* Need to receive data from buffer */
+ return;
+ else {
+ uint16_t remain_bytes = shi_params.sz_request
+ - shi_params.sz_received;
+ /* Move to processing state immediately */
+ state = SHI_STATE_PROCESSING;
+ CPRINTF("PRC-");
+ /* Read remaining bytes from input buffer directly */
+ if (!shi_read_inbuf_wait(remain_bytes))
+ return shi_error(1);
+ }
+
+ /* Fill output buffer to indicate we`re processing request */
+ shi_fill_out_status(EC_SPI_PROCESSING);
+
+ /* Set up parameters for host request */
+ args.params = in_msg + 3;
+ args.send_response = shi_send_response;
+
+ /* Allow room for the header bytes */
+ args.response = out_msg + SHI_PROTO2_OFFSET;
+ args.response_max = sizeof(out_msg) - SHI_PROTO2_OVERHEAD;
+ args.response_size = 0;
+ args.result = EC_RES_SUCCESS;
+
+ /* Go to common-layer to handle request */
+ host_command_received(&args);
+}
+
+/*****************************************************************************/
+/* V3 protocol layer functions */
+
+/**
+ * Called to send a response back to the host.
+ *
+ * Some commands can continue for a while. This function is called by
+ * host_command when it completes.
+ *
+ */
+static void shi_send_response_packet(struct host_packet *pkt)
+{
+ /* Append our past-end byte, which we reserved space for. */
+ ((uint8_t *) pkt->response)[pkt->response_size + 0] = EC_SPI_PAST_END;
+
+ /* Computing sending bytes of response */
+ shi_params.sz_response = pkt->response_size + SHI_PROTO3_OVERHEAD;
+
+ /*
+ * Before the state is set to SENDING, any CS de-assertion would
+ * give up sending.
+ */
+ if (state == SHI_STATE_PROCESSING) {
+ /*
+ * Disable SHI interrupt until we have prepared
+ * the first package to output
+ */
+ task_disable_irq(NPCX_IRQ_SHI);
+ /* Transmit the reply */
+ state = SHI_STATE_SENDING;
+ CPRINTF("SND-");
+ /* Start to fill output buffer with msg buffer */
+ shi_write_outbuf_wait(shi_params.sz_response);
+ /* Enable SHI interrupt */
+ task_enable_irq(NPCX_IRQ_SHI);
+ }
+ /*
+ * If we're not processing, then the AP has already terminated the
+ * transaction, and won't be listening for a response.
+ */
+ else {
+ /* Reset SHI and prepare to next transaction again */
+ shi_reset_prepare();
+ CPRINTF("END\n");
+ return;
+ }
+}
+
+void shi_handle_host_package(void)
+{
+ uint16_t sz_inbuf_int = shi_params.sz_request / SHI_IBUF_HALF_SIZE;
+ uint16_t cnt_inbuf_int = shi_params.sz_received / SHI_IBUF_HALF_SIZE;
+ if (sz_inbuf_int - cnt_inbuf_int)
+ /* Need to receive data from buffer */
+ return;
+ else {
+ uint16_t remain_bytes = shi_params.sz_request
+ - shi_params.sz_received;
+ /* Move to processing state immediately */
+ state = SHI_STATE_PROCESSING;
+ CPRINTF("PRC-");
+ /* Read remaining bytes from input buffer directly */
+ if (!shi_read_inbuf_wait(remain_bytes))
+ return shi_error(1);
+ }
+ /* Fill output buffer to indicate we`re processing request */
+ shi_fill_out_status(EC_SPI_PROCESSING);
+
+ /* Set up parameters for host request */
+ shi_packet.send_response = shi_send_response_packet;
+
+ shi_packet.request = in_msg;
+ shi_packet.request_temp = NULL;
+ shi_packet.request_max = sizeof(in_msg);
+ shi_packet.request_size = shi_params.sz_request;
+
+ /* Put FRAME_START in first byte */
+ out_msg[0] = EC_SPI_FRAME_START;
+ shi_packet.response = out_msg + 1;
+
+ /* Reserve space for frame start and trailing past-end byte */
+ shi_packet.response_max = sizeof(out_msg) - SHI_PROTO3_OVERHEAD;
+ shi_packet.response_size = 0;
+ shi_packet.driver_result = EC_RES_SUCCESS;
+
+ /* Go to common-layer to handle request */
+ host_packet_receive(&shi_packet);
+}
+
+/* Parse header for version of spi-protocol */
+static void shi_parse_header(void)
+{
+ /* Wait for version, command, length bytes */
+ if (!shi_read_inbuf_wait(3))
+ return shi_error(1);
+
+ if (in_msg[0] == EC_HOST_REQUEST_VERSION) {
+ /* Protocol version 3 */
+ struct ec_host_request *r = (struct ec_host_request *) in_msg;
+ int pkt_size;
+ /*
+ * If request is over 32 bytes,
+ * we need to modified the algorithm again.
+ */
+ ASSERT(sizeof(*r) < SHI_IBUF_HALF_SIZE);
+
+ /* Wait for the rest of the command header */
+ if (!shi_read_inbuf_wait(sizeof(*r) - 3))
+ return shi_error(1);
+
+ /* Check how big the packet should be */
+ pkt_size = host_request_expected_size(r);
+ if (pkt_size == 0 || pkt_size > sizeof(in_msg))
+ return shi_error(0);
+
+ /* Computing total bytes need to receive */
+ shi_params.sz_request = pkt_size;
+
+ /* Set handler for host_package */
+ request_handler = shi_handle_host_package;
+
+ } else if (in_msg[0] >= EC_CMD_VERSION0) {
+ /*
+ * Protocol version 2
+ * TODO(crosbug.com/p/20257): Remove once kernel supports
+ * version 3.
+ */
+ args.version = in_msg[0] - EC_CMD_VERSION0;
+ args.command = in_msg[1];
+ args.params_size = in_msg[2];
+
+ /* Computing remaining received bytes */
+ shi_params.sz_request = args.params_size + 3;
+
+ /* Set handler for host_command */
+ request_handler = shi_handle_host_command;
+ } else {
+ /* Invalid version number */
+ return shi_error(0);
+ }
+ /* run receiving handler */
+ request_handler();
+}
+
+/*****************************************************************************/
+/* IC specific low-level driver */
+
+/* This routine fills out all SHI output buffer with status byte */
+static void shi_fill_out_status(uint8_t status)
+{
+ uint16_t i;
+ uint16_t offset = SHI_OBUF_VALID_OFFSET;
+
+ /* Fill out all output buffer with status byte */
+ for (i = offset; i < SHI_OBUF_FULL_SIZE; i++)
+ NPCX_OBUF(i) = status;
+ for (i = 0; i < offset; i++)
+ NPCX_OBUF(i) = status;
+}
+
+/*
+ * This routine write SHI next half output buffer from msg buffer
+ */
+static void shi_write_half_outbuf(void)
+{
+ uint16_t i;
+ uint16_t size = MIN(SHI_OBUF_HALF_SIZE,
+ shi_params.sz_response - shi_params.sz_sending);
+ /* Fill half output buffer */
+ for (i = 0; i < size; i++, shi_params.sz_sending++)
+ *(shi_params.tx_buf++) = *(shi_params.tx_msg++);
+}
+
+/*
+ * This routine write SHI output buffer from msg buffer until
+ * we have sent a certain number of bytes or output buffer is full
+ */
+static void shi_write_outbuf_wait(uint16_t szbytes)
+{
+ uint16_t i;
+ static uint16_t offset, size;
+ offset = SHI_OBUF_VALID_OFFSET;
+ shi_params.tx_buf = SHI_OBUF_START_ADDR + offset;
+
+ /* Fill half output buffer */
+ size = MIN(SHI_OBUF_HALF_SIZE - (offset % SHI_OBUF_HALF_SIZE),
+ szbytes - shi_params.sz_sending);
+ for (i = 0; i < size; i++, shi_params.sz_sending++)
+ *(shi_params.tx_buf++) = *(shi_params.tx_msg++);
+
+ /* Write data from bottom address again */
+ if (shi_params.tx_buf == SHI_OBUF_FULL_ADDR)
+ shi_params.tx_buf = SHI_OBUF_START_ADDR;
+
+ /* Fill next half output buffer */
+ size = MIN(SHI_OBUF_HALF_SIZE, szbytes - shi_params.sz_sending);
+ for (i = 0; i < size; i++, shi_params.sz_sending++)
+ *(shi_params.tx_buf++) = *(shi_params.tx_msg++);
+}
+
+/* This routine copies SHI half input buffer data to msg buffer */
+static void shi_read_half_inbuf(void)
+{
+ /*
+ * Copy to read buffer until reaching middle/top address of
+ * input buffer or completing receiving data
+ */
+ do {
+ /* Restore data to msg buffer */
+ *(shi_params.rx_msg++) = *(shi_params.rx_buf++);
+ shi_params.sz_received++;
+ } while (shi_params.sz_received % SHI_IBUF_HALF_SIZE
+ && shi_params.sz_received != shi_params.sz_request);
+}
+
+/*
+ * This routine make sure input buffer status register is valid or it will
+ * return flase after timeout
+ */
+static int shi_check_inbuf_valid(void)
+{
+ timestamp_t deadline = get_time();
+ deadline.val += SHI_GLITCH_TIMEOUT_US;
+ /*
+ * If input buffer pointer is no changed after timeout, it will
+ * return false
+ */
+ while (NPCX_IBUFSTAT == shi_params.pre_ibufstat)
+ if (timestamp_expired(deadline, NULL))
+ return 0;
+ /* valid package */
+ return 1;
+}
+
+/*
+ * This routine read SHI input buffer to msg buffer until
+ * we have received a certain number of bytes
+ */
+static int shi_read_inbuf_wait(uint16_t szbytes)
+{
+ uint16_t i;
+
+ /* Copy data to msg buffer from input buffer */
+ for (i = 0; i < szbytes; i++, shi_params.sz_received++) {
+ /*
+ * If input buffer pointer equals pointer which wants to read,
+ * it means data is not ready.
+ */
+ while (shi_params.rx_buf == SHI_IBUF_CUR_ADDR)
+ if (timestamp_expired(shi_params.rx_deadline, NULL))
+ return 0;
+ /* Restore data to msg buffer */
+ *(shi_params.rx_msg++) = *(shi_params.rx_buf++);
+ }
+ return 1;
+}
+
+/* This routine handles bus error condition */
+static void shi_error(int need_reset)
+{
+ uint16_t i;
+ /* State machine mismatch, timeout, or protocol we can't handle. */
+ shi_fill_out_status(EC_SPI_RX_BAD_DATA);
+ state = SHI_STATE_ERROR;
+
+ CPRINTS("ERR-[");
+ CPRINTF("in_msg=[");
+ for (i = 0; i < shi_params.sz_received; i++)
+ CPRINTF("%02x ", in_msg[i]);
+ CPRINTF("]\n");
+
+ /*
+ * If glitch occurred or losing clocks, EVSTAT_EOR/W
+ * will not generate. We need to reset SHI bus here.
+ */
+ if (need_reset)
+ shi_reset_prepare();
+}
+
+/* This routine handles all interrupts of this module */
+void shi_int_handler(void)
+{
+ uint8_t stat_reg;
+
+ /* Read status register and clear interrupt status early*/
+ stat_reg = NPCX_EVSTAT;
+ NPCX_EVSTAT = stat_reg;
+
+ /*
+ * End of data for read/write transaction. ie SHI_CS is deasserted.
+ * Host completed or aborted transaction
+ */
+ if (IS_BIT_SET(stat_reg, NPCX_EVSTAT_EOR)) {
+ /* Already reset in shi_error or not */
+ if (state != SHI_STATE_READY_TO_RECV)
+ /*
+ * Mark not ready to prevent the other
+ * transaction immediately
+ */
+ NPCX_OBUF(0) = EC_SPI_NOT_READY;
+ CPRINTF("CSH-");
+ /*
+ * If the buffer is still used by the host command.
+ * Change tx buffer to NOT_READY
+ */
+ if (state == SHI_STATE_PROCESSING) {
+ /*
+ * Mark state to NOT_READY for waiting host executes
+ * response function
+ */
+ state = SHI_STATE_NOT_READY;
+ CPRINTF("WAIT-");
+ return;
+ }
+ /* reset SHI and prepare to next transaction again */
+ shi_reset_prepare();
+ CPRINTF("END\n");
+ return;
+ }
+
+ /*
+ * Indicate input/output buffer pointer reaches the half buffer size.
+ * Transaction is processing.
+ */
+ if (IS_BIT_SET(stat_reg, NPCX_EVSTAT_IBHF)) {
+ if (state == SHI_STATE_RECEIVING) {
+ /* Read data from input to msg buffer */
+ shi_read_half_inbuf();
+ return request_handler();
+ } else if (state == SHI_STATE_SENDING) {
+ /* Write data from bottom address again */
+ shi_params.tx_buf = SHI_OBUF_START_ADDR;
+ /* Write data from msg buffer to output buffer */
+ return shi_write_half_outbuf();
+ } else if (state == SHI_STATE_PROCESSING)
+ /* Wait for host handles request */
+ return;
+ else
+ /* Unexpected status */
+ return shi_error(1);
+ }
+
+ /*
+ * Indicate input/output buffer pointer reaches the full buffer size.
+ * Transaction is processing.
+ */
+ if (IS_BIT_SET(stat_reg, NPCX_EVSTAT_IBF)) {
+ if (state == SHI_STATE_RECEIVING) {
+ /* read data from input to msg buffer */
+ shi_read_half_inbuf();
+ /* Read to bottom address again */
+ shi_params.rx_buf = SHI_IBUF_START_ADDR;
+ return request_handler();
+ } else if (state == SHI_STATE_SENDING)
+ /* Write data from msg buffer to output buffer */
+ return shi_write_half_outbuf();
+ else if (state == SHI_STATE_PROCESSING)
+ /* Wait for host handles request */
+ return;
+ else
+ /* Unexpected status */
+ return shi_error(1);
+ }
+}
+/*
+ * The interrupt priority for SHI interrupt should be higher than
+ * GPIO. Then we could receive CS-deasserted event even in CS-asserted ISR.
+ */
+DECLARE_IRQ(NPCX_IRQ_SHI, shi_int_handler, 0);
+
+/* Handle an CS assert event on the SHI_CS_L pin */
+void shi_cs_event(enum gpio_signal signal)
+{
+ /* If not enabled, ignore glitches on SHI_CS_L */
+ if (state == SHI_STATE_DISABLED)
+ return;
+
+ /*
+ * TODO (ML): Glitches on SHI_CS_L will cause SHI doesn`t generate
+ * 'End of data for read/write transaction interrupt' and IBUFSTAT will
+ * keep previous value without clocks. (Workaround) Need to reset it
+ * manually in CS assert ISR.
+ */
+ if (NPCX_IBUFSTAT == shi_params.pre_ibufstat) {
+ if (!shi_check_inbuf_valid()) {
+ CPRINTS("ERR-GTH");
+ shi_reset_prepare();
+ CPRINTS("END\n");
+ return;
+ }
+ }
+
+ /* Chip select is low = asserted */
+ if (state != SHI_STATE_READY_TO_RECV) {
+ /*
+ * AP started a transaction but we weren't ready for it.
+ * Tell AP we weren't ready, and ignore the received data.
+ * The driver should change status later when complete handling
+ * response from host
+ */
+ NPCX_OBUF(0) = EC_SPI_NOT_READY;
+ CPRINTS("CSL-NRDY");
+ /*
+ * If status still is error, reset SHI Bus and
+ * abort this transaction.
+ */
+ if (state == SHI_STATE_ERROR) {
+ CPRINTS("ERR-");
+ shi_reset_prepare();
+ CPRINTS("END\n");
+ return;
+ }
+ return;
+ }
+
+ /* We're now inside a transaction */
+ state = SHI_STATE_RECEIVING;
+ CPRINTF("CSL-RV-");
+
+ /* Setup deadline time for receiving */
+ shi_params.rx_deadline = get_time();
+ shi_params.rx_deadline.val += SHI_CMD_RX_TIMEOUT_US;
+
+ /* Read first three bytes to parse which protocol is receiving */
+ shi_parse_header();
+}
+
+/*****************************************************************************/
+/* Hook functions for chipset and initialization */
+
+/* Reset SHI bus and prepare next transaction */
+static void shi_reset_prepare(void)
+{
+ uint16_t i;
+ state = SHI_STATE_NOT_READY;
+
+ /* Initialize parameters of next transaction */
+ shi_params.rx_msg = in_msg;
+ shi_params.tx_msg = out_msg;
+ shi_params.rx_buf = SHI_IBUF_START_ADDR;
+ shi_params.tx_buf = SHI_OBUF_HALF_ADDR;
+ shi_params.sz_received = 0;
+ shi_params.sz_sending = 0;
+ shi_params.sz_request = 0;
+ shi_params.sz_response = 0;
+ /* Record last IBUFSTAT for glitch case */
+ shi_params.pre_ibufstat = NPCX_IBUFSTAT;
+
+ /*
+ * Fill output buffer to indicate we`re
+ * ready to receive next transaction
+ */
+ for (i = 1; i < SHI_OBUF_FULL_SIZE; i++)
+ NPCX_OBUF(i) = EC_SPI_RECEIVING;
+ NPCX_OBUF(0) = EC_SPI_OLD_READY;
+
+ /* Enable SHI & WEN functionality */
+ NPCX_SHICFG1 = 0x85;
+
+ /* Ready to receive */
+ state = SHI_STATE_READY_TO_RECV;
+ CPRINTF("RDY-");
+}
+DECLARE_HOOK(HOOK_CHIPSET_RESUME, shi_reset_prepare, HOOK_PRIO_DEFAULT);
+
+/* Disable SHI bus */
+static void shi_disable(void)
+{
+ state = SHI_STATE_DISABLED;
+
+ /* Disable pullup and interrupts on SHI_CS_L */
+ gpio_set_flags(GPIO_SHI_CS_L, GPIO_INPUT);
+
+ /* Set SPI pins to inputs so we don't leak power when AP is off */
+ gpio_config_module(MODULE_SPI, 0);
+}
+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, shi_disable, HOOK_PRIO_DEFAULT);
+
+static void shi_init(void)
+{
+ /* Power on SHI module first */
+ CLEAR_BIT(NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_5), NPCX_PWDWN_CTL5_SHI_PD);
+ /*
+ * Mux SHI related pins
+ * SHI_SDI SHI_SDO SHI_CS# SHI_SCLK are selected to device pins
+ */
+ SET_BIT(NPCX_DEVALT(ALT_GROUP_C), NPCX_DEVALTC_SHI_SL);
+
+ /*
+ * SHICFG1 (SHI Configuration 1) setting
+ * [7] - IWRAP = 1: Wrap input buffer to the first address
+ * [6] - CPOL = 0: Sampling on rising edge and output on falling edge
+ * [5] - DAS = 0: return STATUS reg data after Status command
+ * [4] - AUTOBE = 0: Automatically update the OBES bit in STATUS reg
+ * [3] - AUTIBF = 0: Automatically update the IBFS bit in STATUS reg
+ * [2] - WEN = 0: Enable host write to input buffer
+ * [1] - Reserved 0
+ * [0] - ENABLE = 0: Disable SHI at the beginning
+ */
+ NPCX_SHICFG1 = 0x80;
+
+ /*
+ * SHICFG2 (SHI Configuration 2) setting
+ * [7] - Reserved 0
+ * [6] - REEVEN = 0: Restart events are not used
+ * [5] - Reserved 0
+ * [4] - REEN = 0: Restart transactions are not used
+ * [3] - SLWU = 0: Seem-less wake-up is enabled by default
+ * [2] - ONESHOT= 0: WEN is cleared at the end of a write transaction
+ * [1] - BUSY = 0: SHI bus is busy 0: idle.
+ * [0] - SIMUL = 1: Turn on simultaneous Read/Write
+ */
+ NPCX_SHICFG2 = 0x01;
+
+ /*
+ * EVENABLE (Event Enable) setting
+ * [7] - IBOREN = 0: Input buffer overrun interrupt enable
+ * [6] - STSREN = 0: status read interrupt disable
+ * [5] - EOWEN = 0: End-of-Data for Write Transaction Interrupt Enable
+ * [4] - EOREN = 1: End-of-Data for Read Transaction Interrupt Enable
+ * [3] - IBHFEN = 1: Input Buffer Half Full Interrupt Enable
+ * [2] - IBFEN = 1: Input Buffer Full Interrupt Enable
+ * [1] - OBHEEN = 0: Output Buffer Half Empty Interrupt Enable
+ * [0] - OBEEN = 0: Output Buffer Empty Interrupt Enable
+ */
+ NPCX_EVENABLE = 0x1C;
+
+ /* Clear SHI events status register */
+ NPCX_EVSTAT = 0XFF;
+
+ /* Enable SHI_CS_L interrupt */
+ gpio_enable_interrupt(GPIO_SHI_CS_L);
+
+ /* If chipset is already on, prepare for transactions */
+#if !(DEBUG_SHI)
+ if (chipset_in_state(CHIPSET_STATE_ON))
+#endif
+ shi_reset_prepare();
+}
+DECLARE_HOOK(HOOK_INIT, shi_init, HOOK_PRIO_DEFAULT);
+
+/**
+ * Get protocol information
+ */
+static int shi_get_protocol_info(struct host_cmd_handler_args *args)
+{
+ struct ec_response_get_protocol_info *r = args->response;
+
+ memset(r, 0, sizeof(*r));
+ r->protocol_versions = (1 << 2) | (1 << 3);
+ r->max_request_packet_size = SHI_MAX_REQUEST_SIZE;
+ r->max_response_packet_size = SHI_MAX_RESPONSE_SIZE;
+ r->flags = EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED;
+
+ args->response_size = sizeof(*r);
+
+ return EC_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, shi_get_protocol_info,
+EC_VER_MASK(0));
diff --git a/chip/npcx/shi_chip.h b/chip/npcx/shi_chip.h
new file mode 100644
index 0000000000..2edd513bfc
--- /dev/null
+++ b/chip/npcx/shi_chip.h
@@ -0,0 +1,21 @@
+/* Copyright (c) 2015 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-specific SHI module for Chrome EC */
+
+#ifndef SHI_CHIP_H_
+#define SHI_CHIP_H_
+
+#ifdef CONFIG_SHI
+/**
+ * Called when the NSS level changes, signalling the start of a SHI
+ * transaction.
+ *
+ * @param signal GPIO signal that changed
+ */
+void shi_cs_event(enum gpio_signal signal);
+#endif
+
+#endif /* SHI_CHIP_H_ */
diff --git a/chip/npcx/system.c b/chip/npcx/system.c
index e1ae1c134a..2a872d0b66 100644
--- a/chip/npcx/system.c
+++ b/chip/npcx/system.c
@@ -18,17 +18,12 @@
#include "util.h"
#include "hwtimer_chip.h"
#include "system_chip.h"
+#include "rom_chip.h"
/* Flags for BBRM_DATA_INDEX_WAKE */
#define HIBERNATE_WAKE_MTC (1 << 0) /* MTC alarm */
#define HIBERNATE_WAKE_PIN (1 << 1) /* Wake pin */
-/* Super-IO index and register definitions */
-#define SIO_OFFSET 0x4E
-#define INDEX_SID 0x20
-#define INDEX_CHPREV 0x24
-#define INDEX_SRID 0x27
-
/* equivalent to 250us according to 48MHz core clock */
#define MTC_TTC_LOAD_DELAY 1500
#define MTC_ALARM_MASK ((1 << 25) - 1)
@@ -38,109 +33,16 @@
/* ROM address of chip revision */
#define CHIP_REV_ADDR 0x00007FFC
+/* Console output macros */
+#define CPUTS(outstr) cputs(CC_SYSTEM, outstr)
+#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
+
/* Begin address for the .lpram section; defined in linker script */
uintptr_t __lpram_fw_start = CONFIG_LPRAM_BASE;
/*****************************************************************************/
/* Internal functions */
-/* Super-IO read/write function */
-void system_sib_write_reg(uint8_t io_offset, uint8_t index_value,
- uint8_t io_data)
-{
- /* Disable interrupts */
- interrupt_disable();
-
- /* Lock host CFG module */
- SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
- /* Enable Core-to-Host Modules Access */
- SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
- /* Enable Core access to CFG module */
- SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
- /* Verify Core read/write to host modules is not in progress */
- while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
- ;
- while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
- ;
-
- /* Specify the io_offset A0 = 0. the index register is accessed */
- NPCX_IHIOA = io_offset;
- /* Write the data. This starts the write access to the host module */
- NPCX_IHD = index_value;
- /* Wait while Core write operation is in progress */
- while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
- ;
-
- /* Specify the io_offset A0 = 1. the data register is accessed */
- NPCX_IHIOA = io_offset+1;
- /* Write the data. This starts the write access to the host module */
- NPCX_IHD = io_data;
- /* Wait while Core write operation is in progress */
- while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
- ;
-
- /* Disable Core access to CFG module */
- CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
- /* Disable Core-to-Host Modules Access */
- CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
- /* unlock host CFG module */
- CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
-
- /* Enable interrupts */
- interrupt_enable();
-}
-
-uint8_t system_sib_read_reg(uint8_t io_offset, uint8_t index_value)
-{
- uint8_t data_value;
-
- /* Disable interrupts */
- interrupt_disable();
-
- /* Lock host CFG module */
- SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
- /* Enable Core-to-Host Modules Access */
- SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
- /* Enable Core access to CFG module */
- SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
- /* Verify Core read/write to host modules is not in progress */
- while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
- ;
- while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
- ;
-
-
- /* Specify the io_offset A0 = 0. the index register is accessed */
- NPCX_IHIOA = io_offset;
- /* Write the data. This starts the write access to the host module */
- NPCX_IHD = index_value;
- /* Wait while Core write operation is in progress */
- while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
- ;
-
- /* Specify the io_offset A0 = 1. the data register is accessed */
- NPCX_IHIOA = io_offset+1;
- /* Start a Core read from host module */
- SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD);
- /* Wait while Core read operation is in progress */
- while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
- ;
- /* Read the data */
- data_value = NPCX_IHD;
-
- /* Disable Core access to CFG module */
- CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
- /* Disable Core-to-Host Modules Access */
- CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
- /* unlock host CFG module */
- CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
-
- /* Enable interrupts */
- interrupt_enable();
-
- return data_value;
-}
-
void system_watchdog_reset(void)
{
/* Unlock & stop watchdog registers */
@@ -277,17 +179,11 @@ void system_check_reset_cause(void)
}
/* Watchdog Reset */
-#ifndef CHIP_NPCX5M5G
if (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS)) {
flags |= RESET_FLAG_WATCHDOG;
/* Clear watchdog reset status initially*/
SET_BIT(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS);
}
-#else
- /* Workaround method to check watchdog reset */
- if (NPCX_BBRAM(BBRM_DATA_INDEX_RAMLOG) & 0x04)
- flags |= RESET_FLAG_WATCHDOG;
-#endif
if ((hib_wake_flags & HIBERNATE_WAKE_PIN))
flags |= RESET_FLAG_WAKE_PIN;
@@ -356,12 +252,12 @@ __enter_hibernate_in_lpram(void)
{
/* Disable Code RAM first */
- SET_BIT(NPCX_PWDWN_CTL(5), NPCX_PWDWN_CTL5_MRFSH_DIS);
+ SET_BIT(NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_5), NPCX_PWDWN_CTL5_MRFSH_DIS);
SET_BIT(NPCX_DISIDL_CTL, NPCX_DISIDL_CTL_RAM_DID);
while (1) {
- /* Set deep idle - instant wake-up mode*/
- NPCX_PMCSR = 0x7;
+ /* Set deep idle mode*/
+ NPCX_PMCSR = 0x6;
/* Enter deep idle, wake-up by GPIOxx or RTC */
asm("wfi");
@@ -424,11 +320,11 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
interrupt_disable();
/* ITIM event module disable */
- CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_ITEN);
+ CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);
/* ITIM time module disable */
- CLEAR_BIT(NPCX_ITCTS(ITIM_TIME_NO), NPCX_ITIM16_ITEN);
+ CLEAR_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_ITEN);
/* ITIM watchdog warn module disable */
- CLEAR_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITIM16_ITEN);
+ CLEAR_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN);
/*
* Set RTC interrupt in time to wake up before
@@ -545,12 +441,21 @@ void system_pre_init(void)
*/
/* Power-down the modules we don't need */
- NPCX_PWDWN_CTL(0) = 0xF9; /* Skip SDP_PD FIU_PD */
- NPCX_PWDWN_CTL(1) = 0xFF;
- NPCX_PWDWN_CTL(2) = 0x8F;
- NPCX_PWDWN_CTL(3) = 0xF4; /* Skip ITIM2/1_PD */
- NPCX_PWDWN_CTL(4) = 0xF8;
- NPCX_PWDWN_CTL(5) = 0x85; /* Skip ITIM5_PD */
+ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_1) = 0xF9; /* Skip SDP_PD FIU_PD */
+ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_2) = 0xFF;
+ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_3) = 0x0F; /* Skip GDMA */
+ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_4) = 0xF4; /* Skip ITIM2/1_PD */
+ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_5) = 0xF8;
+ NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_6) = 0x85; /* Skip ITIM5_PD */
+
+ /* Power down the modules used internally */
+ NPCX_INTERNAL_CTRL1 = 0x03;
+ NPCX_INTERNAL_CTRL2 = 0x03;
+ NPCX_INTERNAL_CTRL3 = 0x03;
+
+ /* Enable low-power regulator */
+ CLEAR_BIT(NPCX_LFCGCALCNT, NPCX_LFCGCALCNT_LPREG_CTL_EN);
+ SET_BIT(NPCX_LFCGCALCNT, NPCX_LFCGCALCNT_LPREG_CTL_EN);
/*
* Configure LPRAM in the MPU as a regular memory
@@ -637,12 +542,9 @@ const char *system_get_chip_name(void)
const char *system_get_chip_revision(void)
{
static char rev[4];
-#ifndef CHIP_NPCX5M5G
- uint8_t rev_num = system_sib_read_reg(SIO_OFFSET, INDEX_CHPREV);
-#else
/* Read ROM data for chip revision directly */
uint8_t rev_num = *((uint8_t *)CHIP_REV_ADDR);
-#endif
+
*(rev) = 'A';
*(rev + 1) = '.';
*(rev + 2) = system_to_hex((rev_num & 0xF0) >> 4);
@@ -789,58 +691,53 @@ DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_VALUE,
system_rtc_set_value,
EC_VER_MASK(0));
-/* For LPC host register initial via SIB module */
-void system_lpc_host_register_init(void){
- /* Setting PMC2 */
- /* LDN register = 0x12(PMC2) */
- system_sib_write_reg(SIO_OFFSET, 0x07, 0x12);
- /* CMD port is 0x200 */
- system_sib_write_reg(SIO_OFFSET, 0x60, 0x02);
- system_sib_write_reg(SIO_OFFSET, 0x61, 0x00);
- /* Data port is 0x204 */
- system_sib_write_reg(SIO_OFFSET, 0x62, 0x02);
- system_sib_write_reg(SIO_OFFSET, 0x63, 0x04);
- /* enable PMC2 */
- system_sib_write_reg(SIO_OFFSET, 0x30, 0x01);
-
- /* Setting SHM */
- /* LDN register = 0x0F(SHM) */
- system_sib_write_reg(SIO_OFFSET, 0x07, 0x0F);
- /* WIN1&2 mapping to IO */
- system_sib_write_reg(SIO_OFFSET, 0xF1,
- system_sib_read_reg(SIO_OFFSET, 0xF1) | 0x30);
- /* Host Command on the IO:0x0800 */
- system_sib_write_reg(SIO_OFFSET, 0xF7, 0x00);
- system_sib_write_reg(SIO_OFFSET, 0xF6, 0x00);
- system_sib_write_reg(SIO_OFFSET, 0xF5, 0x08);
- system_sib_write_reg(SIO_OFFSET, 0xF4, 0x00);
- /* WIN1 as Host Command on the IO:0x0800 */
- system_sib_write_reg(SIO_OFFSET, 0xFB, 0x00);
- system_sib_write_reg(SIO_OFFSET, 0xFA, 0x00);
- /* WIN2 as MEMMAP on the IO:0x900 */
- system_sib_write_reg(SIO_OFFSET, 0xF9, 0x09);
- system_sib_write_reg(SIO_OFFSET, 0xF8, 0x00);
- /* enable SHM */
- system_sib_write_reg(SIO_OFFSET, 0x30, 0x01);
-}
#ifdef CONFIG_CODERAM_ARCH
-uint32_t system_get_lfw_address(void)
+void system_jump_to_booter(void)
{
- /* Little FW located on top of flash - 4K */
- uint32_t jump_addr = (CONFIG_FLASH_BASE + CONFIG_SPI_FLASH_SIZE
- - CONFIG_LFW_OFFSET + 1);
+ enum API_RETURN_STATUS_T status;
+ static uint32_t flash_offset;
+ static uint32_t flash_used;
+ static uint32_t addr_entry;
+ /* RO region FW */
+ if (IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION)) {
+ flash_offset = CONFIG_RO_MEM_OFF;
+ flash_used = CONFIG_RO_SIZE;
+ } else { /* RW region FW */
+ flash_offset = CONFIG_RW_MEM_OFF;
+ flash_used = CONFIG_RW_SIZE;
+ }
+
+ /* Make sure the reset vector is inside the destination image */
+ addr_entry = *(uintptr_t *)(flash_offset + CONFIG_FLASH_BASE + 4);
+
+ download_from_flash(
+ flash_offset, /* The offset of the data in spi flash */
+ CONFIG_CDRAM_BASE, /* The address of the downloaded data */
+ flash_used, /* Number of bytes to download */
+ SIGN_NO_CHECK, /* Need CRC check or not */
+ addr_entry, /* jump to this address after download */
+ &status /* Status fo download */
+ );
+}
+
+uint32_t system_get_lfw_address()
+{
+ /*
+ * In A3 version, we don't use little FW anymore
+ * We provide the alternative function in ROM
+ */
+ uint32_t jump_addr = (uint32_t)system_jump_to_booter;
return jump_addr;
}
void system_set_image_copy(enum system_image_copy_t copy)
{
- /* Jump to RO region -- set flag */
- if (copy == SYSTEM_IMAGE_RO)
- SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION);
- else /* Jump to RW region -- clear flag */
+ /* Jump to RW region -- clear flag */
+ if (copy == SYSTEM_IMAGE_RW)
CLEAR_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION);
-
+ else /* Jump to RO region -- set flag */
+ SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION);
}
enum system_image_copy_t system_get_shrspi_image_copy(void)
diff --git a/chip/npcx/system_chip.h b/chip/npcx/system_chip.h
index 2cafb9649f..fab0ca37fc 100644
--- a/chip/npcx/system_chip.h
+++ b/chip/npcx/system_chip.h
@@ -18,8 +18,6 @@ enum bbram_data_index {
BBRM_DATA_INDEX_RAMLOG = 32, /* RAM log for Booter */
};
-/* Init lpc register through SIB */
-void system_lpc_host_register_init(void);
/* Issue a watchdog reset*/
void system_watchdog_reset(void);
/* Check reset cause and return reset flags */
diff --git a/chip/npcx/uart.c b/chip/npcx/uart.c
index 893b02aa84..570ded4285 100644
--- a/chip/npcx/uart.c
+++ b/chip/npcx/uart.c
@@ -26,13 +26,11 @@ int uart_init_done(void)
void uart_tx_start(void)
{
- if (IS_BIT_SET(NPCX_WKEN(1, 1), 0)) {
- /* disable MIWU*/
- CLEAR_BIT(NPCX_WKEN(1, 1), 0);
- /* go back to original setting */
- task_enable_irq(NPCX_IRQ_WKINTB_1);
- /* Go back CR_SIN*/
- SET_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL);
+ if (uart_is_enable_wakeup()) {
+ /* disable MIWU */
+ uart_enable_wakeup(0);
+ /* Set pin-mask for UART */
+ npcx_gpio2uart();
/* enable uart again from MIWU mode */
task_enable_irq(NPCX_IRQ_UART);
}
@@ -146,9 +144,16 @@ static void uart_config(void)
{
uint32_t div, opt_dev, min_deviation, clk, calc_baudrate, deviation;
uint8_t prescalar, opt_prescalar, i;
- /* Enable the port */
+
/* Configure pins from GPIOs to CR_UART */
gpio_config_module(MODULE_UART, 1);
+ /* Enable MIWU IRQ of UART*/
+#if NPCX_UART_MODULE2
+ task_enable_irq(NPCX_IRQ_WKINTG_1);
+#else
+ task_enable_irq(NPCX_IRQ_WKINTB_1);
+
+#endif
/* Calculated UART baudrate , clock source from APB2 */
opt_prescalar = opt_dev = 0;
@@ -193,8 +198,7 @@ void uart_init(void)
clock_enable_peripheral(CGC_OFFSET_UART, mask, CGC_MODE_ALL);
/* Set pin-mask for UART */
- SET_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL);
- gpio_config_module(MODULE_UART, 1);
+ npcx_gpio2uart();
/* Configure UARTs (identically) */
uart_config();
diff --git a/chip/npcx/watchdog.c b/chip/npcx/watchdog.c
index 036a768bb6..6d61ad9581 100644
--- a/chip/npcx/watchdog.c
+++ b/chip/npcx/watchdog.c
@@ -26,7 +26,7 @@
void watchdog_init_warning_timer(void)
{
/* init watchdog timer first */
- init_hw_timer(ITIM_WDG_NO, ITIM16_SOURCE_CLOCK_32K);
+ init_hw_timer(ITIM_WDG_NO, ITIM_SOURCE_CLOCK_32K);
/*
* prescaler to TIMER_TICK
@@ -40,7 +40,7 @@ void watchdog_init_warning_timer(void)
/* ITIM count down : event expired*/
NPCX_ITCNT16(ITIM_WDG_NO) = CONFIG_WATCHDOG_PERIOD_MS-1;
/* Event module enable */
- SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITIM16_ITEN);
+ SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN);
/* Enable interrupt of ITIM */
task_enable_irq(ITIM16_INT(ITIM_WDG_NO));
}
@@ -49,7 +49,7 @@ void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
{
int wd_cnt;
/* Clear timeout status for event */
- SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITIM16_TO_STS);
+ SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_TO_STS);
/* Read watchdog counter from TWMWD */
wd_cnt = NPCX_TWMWD;
diff --git a/common/firmware_image.lds.S b/common/firmware_image.lds.S
index af6aa927b5..089e032d57 100644
--- a/common/firmware_image.lds.S
+++ b/common/firmware_image.lds.S
@@ -14,7 +14,13 @@ MEMORY
SECTIONS
{
. = ALIGN(CONFIG_FLASH_BANK_SIZE);
+#if defined(NPCX_RO_HEADER)
+/* Replace *_MEM_OFF with *_STORAGE_OFF to indicate flat file contains header
+ * or some struture which doesn't belong to FW */
+ .image.RO : AT(CONFIG_FLASH_BASE + CONFIG_RO_STORAGE_OFF) {
+#else
.image.RO : AT(CONFIG_FLASH_BASE + CONFIG_RO_MEM_OFF) {
+#endif
*(.image.RO)
} > FLASH =0xff
. = ALIGN(CONFIG_FLASH_BANK_SIZE);
diff --git a/common/fmap.c b/common/fmap.c
index 16b45c9db6..e61df8d968 100644
--- a/common/fmap.c
+++ b/common/fmap.c
@@ -20,7 +20,12 @@
* For address containing CONFIG_FLASH_BASE (symbols in *.RO.lds.S and
* variable), this computes the offset to the start of the image on flash.
*/
+
+#ifdef NPCX_RO_HEADER
+#define RELATIVE_RO(addr) ((addr) - CONFIG_CDRAM_BASE)
+#else
#define RELATIVE_RO(addr) ((addr) - CONFIG_FLASH_BASE - CONFIG_RO_MEM_OFF)
+#endif
struct fmap_header {
char fmap_signature[FMAP_SIGNATURE_SIZE];
diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S
index df3898e255..d637860329 100644
--- a/core/cortex-m/ec.lds.S
+++ b/core/cortex-m/ec.lds.S
@@ -18,6 +18,15 @@ OUTPUT_ARCH(BFD_ARCH)
ENTRY(reset)
MEMORY
{
+#if defined(SECTION_IS_RO) && defined(NPCX_RO_HEADER)
+ /*
+ * Header structure used by npcx booter in RO region.
+ * Please notice the location of header must be in front of FW
+ * which needs copy. But header itself won't be copied to code ram
+ * by booter.
+ */
+ FLASH_HDR (rx) : ORIGIN = FW_OFF(RO_HDR), LENGTH = FW_SIZE(RO_HDR)
+#endif
FLASH (rx) : ORIGIN = FW_OFF(SECTION), LENGTH = FW_SIZE(SECTION)
IRAM (rw) : ORIGIN = CONFIG_RAM_BASE, LENGTH = CONFIG_RAM_SIZE
#ifdef CONFIG_CODERAM_ARCH
@@ -45,6 +54,11 @@ MEMORY
}
SECTIONS
{
+#if defined(SECTION_IS_RO) && defined(NPCX_RO_HEADER)
+ .header : {
+ KEEP(*(.header))
+ } > FLASH_HDR
+#endif
.text : {
OUTDIR/core/CORE/init.o (.text.vecttable)
. = ALIGN(4);
@@ -66,7 +80,7 @@ SECTIONS
/* Entering deep idle FW for better power consumption */
KEEP(*(.lowpower_ram))
__flash_lpfw_end = .;
- } > CDRAM AT > FLASH
+ } > CDRAM AT > FLASH
#else
#ifdef COMPILE_FOR_RAM
} > IRAM
@@ -182,7 +196,7 @@ SECTIONS
#endif
. = ALIGN(4);
#ifdef CONFIG_CODERAM_ARCH
- } > CDRAM AT > FLASH
+ } > CDRAM AT > FLASH
#else
#ifdef COMPILE_FOR_RAM
} > IRAM
@@ -219,7 +233,6 @@ SECTIONS
.data : {
#else
#ifdef CONFIG_CODERAM_ARCH
- __data_start = . ;
.data : AT(LOADADDR(.rodata) + SIZEOF(.rodata)) {
#else
.data : AT(ADDR(.rodata) + SIZEOF(.rodata)) {
diff --git a/util/flash_ec b/util/flash_ec
index c25c347004..0b9cc52b42 100755
--- a/util/flash_ec
+++ b/util/flash_ec
@@ -82,6 +82,7 @@ BOARDS_STM32_DFU=(
BOARDS_NPCX=(
npcx_evb
+ npcx_evb_arm
)
BOARDS_MEC1322=(
@@ -389,6 +390,7 @@ function flash_lm4() {
function flash_npcx() {
OCD_PATH="${EC_DIR}/chip/npcx/openocd"
+ IMG_PATH="${EC_DIR}/build/${BOARD}"
setup_openocd
dut_control jtag_buf_on_flex_en:on
@@ -396,12 +398,12 @@ function flash_npcx() {
if [ "${FLAGS_ro}" = ${FLAGS_TRUE} ] ; then
# Program RO region only
- OCD_CMDS="init; flash_npcx_ro ${FLAGS_offset}; shutdown;"
+ OCD_CMDS="init; flash_npcx_ro ${IMG_PATH} ${FLAGS_offset}; shutdown;"
sudo openocd -s "${OCD_PATH}" -f "${OCD_CFG}" -c "${OCD_CMDS}" || \
die "Failed to program ${IMG}"
else
# Program all EC regions
- OCD_CMDS="init; flash_npcx_evb ${FLAGS_offset}; shutdown;"
+ OCD_CMDS="init; flash_npcx_all ${IMG_PATH} ${FLAGS_offset}; shutdown;"
sudo openocd -s "${OCD_PATH}" -f "${OCD_CFG}" -c "${OCD_CMDS}" || \
die "Failed to program ${IMG}"
fi