summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/npcx_evb/board.c30
-rw-r--r--board/npcx_evb/board.h2
-rw-r--r--board/npcx_evb/gpio.inc10
-rw-r--r--chip/npcx/adc.c11
-rw-r--r--chip/npcx/build.mk2
-rw-r--r--chip/npcx/chip_temp_sensor.c32
-rw-r--r--chip/npcx/clock.c2
-rw-r--r--chip/npcx/config_chip.h4
-rw-r--r--chip/npcx/fan.c25
-rw-r--r--chip/npcx/flash.c11
-rw-r--r--chip/npcx/gpio.c69
-rw-r--r--chip/npcx/i2c.c5
-rw-r--r--chip/npcx/keyboard_raw.c29
-rw-r--r--chip/npcx/lfw/ec_lfw.c29
-rw-r--r--chip/npcx/lpc.c6
-rw-r--r--chip/npcx/openocd/npcx_cmds.tcl41
-rw-r--r--chip/npcx/peci.c6
-rw-r--r--chip/npcx/pwm.c40
-rw-r--r--chip/npcx/registers.h16
-rw-r--r--chip/npcx/spi.c6
-rw-r--r--chip/npcx/spiflashfw/ec_npcxflash.c47
-rw-r--r--chip/npcx/system.c195
-rw-r--r--chip/npcx/system_chip.h15
-rw-r--r--chip/npcx/watchdog.c25
-rw-r--r--common/system.c4
25 files changed, 419 insertions, 243 deletions
diff --git a/board/npcx_evb/board.c b/board/npcx_evb/board.c
index 890c3b2f1f..1dacb2ec5c 100644
--- a/board/npcx_evb/board.c
+++ b/board/npcx_evb/board.c
@@ -49,14 +49,22 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
const struct pwm_t pwm_channels[] = {
[PWM_CH_FAN] = {
.channel = 0,
- .flags = 0,
-#ifdef CONFIG_PWM_INPUT_LFCLK
- .freq = 20000, /* Need <= mft freq */
-#else
- .freq = 3000000,
-#endif
- /* 0xEA60=3000000*60/2/1500,0x190=20000*60/2/1500 */
- .cycle_pulses = 0x190,
+ /*
+ * 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,
@@ -72,14 +80,14 @@ BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT);
const struct fan_t fans[] = {
[FAN_CH_0] = {
.flags = FAN_USE_RPM_MODE,
- .rpm_min = 1500,
- .rpm_start = 1500,
+ .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,
},
-};/*TODO: (Benson_TBD_1) rpm_min/rpm_max not confirm */
+};
BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT);
/******************************************************************************/
diff --git a/board/npcx_evb/board.h b/board/npcx_evb/board.h
index c8dd5f6139..1fde31633d 100644
--- a/board/npcx_evb/board.h
+++ b/board/npcx_evb/board.h
@@ -46,7 +46,7 @@
/* Optional for testing */
#undef CONFIG_PSTORE
-#define CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */
+#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */
/* Single I2C port, where the EC is the master. */
#define I2C_PORT_MASTER 0
diff --git a/board/npcx_evb/gpio.inc b/board/npcx_evb/gpio.inc
index 08837dfea1..be8f5838ad 100644
--- a/board/npcx_evb/gpio.inc
+++ b/board/npcx_evb/gpio.inc
@@ -31,7 +31,9 @@ GPIO(MASTER_I2C_SDA, B, 4, GPIO_INPUT, NULL)
GPIO(BOARD_VERSION1, 6, 4, GPIO_INPUT, NULL) /* Board version stuffing resistor 1 */
GPIO(BOARD_VERSION2, 6, 5, GPIO_INPUT, NULL) /* Board version stuffing resistor 2 */
GPIO(BOARD_VERSION3, 6, 6, GPIO_INPUT, NULL) /* Board version stuffing resistor 3 */
-
+#ifdef CONFIG_KEYBOARD_COL2_INVERTED
+GPIO(KBD_KSO2, 1, 7, GPIO_OUT_LOW, NULL) /* Negative edge triggered keyboard irq. */
+#endif
/* Alternate pins for UART/I2C/ADC/SPI/PWM/MFT */
ALTERNATE(1, 0x03, 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO10/11 */
ALTERNATE(B, 0x30, 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB4/B5 */
@@ -40,6 +42,6 @@ ALTERNATE(9, 0x07, 1, MODULE_I2C, 0) /* I2C1SCL/I2C2SDA/I2C2SCL GPIO
ALTERNATE(4, 0x38, 1, MODULE_ADC, 0) /* ADC GPIO45/44/43 */
ALTERNATE(A, 0x0A, 1, MODULE_SPI, 0) /* SPIP_MOSI/SPIP_SCLK GPIOA3/A1 */
ALTERNATE(9, 0x20, 1, MODULE_SPI, 0) /* SPIP_MISO GPIO95 */
-ALTERNATE(C, 0x04, 1, MODULE_PWM_KBLIGHT, 0) /* PWM1 for PWM/KBLIGHT Test GPIOC2 */
-ALTERNATE(C, 0x08, 1, MODULE_PWM_FAN, 0) /* PWM0 for PWM/FAN Test GPIOC3 */
-ALTERNATE(4, 0x01, 1, MODULE_PWM_FAN, 0) /* MFT-1/TA1_TACH1 for FAN Test GPIOD3 */
+ALTERNATE(C, 0x04, 3, MODULE_PWM_KBLIGHT, 0) /* PWM1 for PWM/KBLIGHT Test GPIOC2 */
+ALTERNATE(C, 0x08, 7, MODULE_PWM_FAN, 0) /* PWM0 for PWM/FAN Test GPIOC3 */
+ALTERNATE(4, 0x01, 3, MODULE_PWM_FAN, 0) /* MFT-1/TA1_TACH1 for FAN Test GPIO40 */
diff --git a/chip/npcx/adc.c b/chip/npcx/adc.c
index a715b08bfb..7096f9f1d1 100644
--- a/chip/npcx/adc.c
+++ b/chip/npcx/adc.c
@@ -137,10 +137,6 @@ int adc_read_channel(enum adc_channel ch)
mutex_lock(&adc_lock);
- /* Enable ADC clock (bit4 mask = 0x10) */
- clock_enable_peripheral(CGC_OFFSET_ADC, CGC_ADC_MASK,
- CGC_MODE_RUN | CGC_MODE_SLEEP);
-
if (start_single_and_wait(adc->input_ch, ADC_TIMEOUT_US)) {
if ((adc->input_ch ==
((NPCX_ASCADD>>NPCX_ASCADD_SADDR)&((1<<5)-1)))
@@ -154,9 +150,6 @@ int adc_read_channel(enum adc_channel ch)
} else {
value = ADC_READ_ERROR;
}
- /* Disable ADC clock (bit4 mask = 0x10) */
- clock_disable_peripheral(CGC_OFFSET_ADC, CGC_ADC_MASK,
- CGC_MODE_RUN | CGC_MODE_SLEEP);
mutex_unlock(&adc_lock);
@@ -219,6 +212,10 @@ static void adc_init(void)
/* Configure pins from GPIOs to ADCs */
gpio_config_module(MODULE_ADC, 1);
+ /* Enable ADC clock (bit4 mask = 0x10) */
+ clock_enable_peripheral(CGC_OFFSET_ADC, CGC_ADC_MASK,
+ CGC_MODE_RUN | CGC_MODE_SLEEP);
+
/* Enable ADC */
SET_BIT(NPCX_ADCCNF, NPCX_ADCCNF_ADCEN);
diff --git a/chip/npcx/build.mk b/chip/npcx/build.mk
index c3f9a1c3de..7ad02aaf30 100644
--- a/chip/npcx/build.mk
+++ b/chip/npcx/build.mk
@@ -15,7 +15,7 @@ CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4
chip-y=clock.o gpio.o hwtimer.o jtag.o system.o uart.o
# Optional chip modules
-chip-$(CONFIG_ADC)+=adc.o chip_temp_sensor.o
+chip-$(CONFIG_ADC)+=adc.o
chip-$(CONFIG_FANS)+=fan.o
chip-$(CONFIG_FLASH)+=flash.o
chip-$(CONFIG_I2C)+=i2c.o
diff --git a/chip/npcx/chip_temp_sensor.c b/chip/npcx/chip_temp_sensor.c
deleted file mode 100644
index 7d2df97dbc..0000000000
--- a/chip/npcx/chip_temp_sensor.c
+++ /dev/null
@@ -1,32 +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.
- */
-
-/* Temperature sensor module for Chrome EC */
-
-#include "adc.h"
-#include "adc_chip.h"
-#include "common.h"
-#include "hooks.h"
-
-/* Initialize temperature reading to a sane value (27 C) */
-static int last_val = C_TO_K(27);
-
-static void chip_temp_sensor_poll(void)
-{
-#ifdef CONFIG_CMD_ECTEMP
- last_val = adc_read_channel(ADC_CH_EC_TEMP);
-#endif
-}
-DECLARE_HOOK(HOOK_SECOND, chip_temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR);
-
-int chip_temp_sensor_get_val(int idx, int *temp_ptr)
-{
- if (last_val == ADC_READ_ERROR)
- return EC_ERROR_UNKNOWN;
-
- *temp_ptr = last_val;
-
- return EC_SUCCESS;
-}
diff --git a/chip/npcx/clock.c b/chip/npcx/clock.c
index c96261c543..6f21e8e016 100644
--- a/chip/npcx/clock.c
+++ b/chip/npcx/clock.c
@@ -231,7 +231,7 @@ void __idle(void)
while (1) {
/*
* TODO:(ML) JTAG bug: if debugger is connected,
- * CPU can't enter wfi. Rev.B will fix it.
+ * CPU can't enter wfi. Rev A3 will fix it.
*/
;
};
diff --git a/chip/npcx/config_chip.h b/chip/npcx/config_chip.h
index 88afba0266..611112aa63 100644
--- a/chip/npcx/config_chip.h
+++ b/chip/npcx/config_chip.h
@@ -54,8 +54,10 @@
/* Default task stack size */
#define TASK_STACK_SIZE 512
-/* SPI Flash Spec of W25Q20CV */
+/* Address of RAM log used by Booter */
+#define ADDR_BOOT_RAMLOG 0x100C7FC0
+/* SPI Flash Spec of W25Q20CV */
#define CONFIG_FLASH_BANK_SIZE 0x00001000 /* protect bank size 4K bytes */
#define CONFIG_FLASH_ERASE_SIZE 0x00001000 /* sector erase size 4K bytes */
#define CONFIG_FLASH_WRITE_SIZE 0x00000001 /* minimum write size */
diff --git a/chip/npcx/fan.c b/chip/npcx/fan.c
index 924f7716f4..5ba20cf315 100644
--- a/chip/npcx/fan.c
+++ b/chip/npcx/fan.c
@@ -59,11 +59,12 @@ enum npcx_mft_clk_src {
* RPM = (n - 1) * m * f * 60 / poles / TACH
* n = Fan number of edges = (RPM_EDGES + 1)
* m = Fan multiplier defined by RANGE
- * f = PWM and MFT freq
+ * f = PWM and MFT operation freq
* poles = 2
*/
#define RPM_TO_TACH(pwm_channel, rpm) \
- MIN(((uint32_t)(pwm_channels[pwm_channel].freq)*30*RPM_EDGES*RPM_SCALE \
+ MIN(((uint32_t)(pwm_channels[pwm_channel].freq) \
+ *(pwm_channels[pwm_channel].cycle_pulses)*30*RPM_EDGES*RPM_SCALE \
/MAX((rpm), 1)), (pwm_channels[pwm_channel].cycle_pulses))
#define TACH_TO_RPM(mft_channel, tach) \
@@ -73,6 +74,7 @@ enum npcx_mft_clk_src {
/* Global variables */
static volatile struct tacho_status_t tacho_status;
static int rpm_target;
+static int pre_duty;
static int rpm_actual = -1;
static int fan_init_ch;
/**
@@ -231,8 +233,6 @@ static void fan_config(int ch, int enable_mft_read_rpm)
fan_init_ch = ch;
pwm_config(pwm_ch);
- /* Mux mft */
- CLEAR_BIT(NPCX_DEVALT(3), NPCX_DEVALT3_TB1_TACH2_SL1);
/* Configure pins from GPIOs to FAN */
gpio_config_module(MODULE_PWM_FAN, 1);
@@ -418,7 +418,8 @@ int fan_get_rpm_actual(int ch)
}
/* Start measure and return previous value when fan is working*/
if ((fan_get_enabled(ch)) && (fan_get_duty(ch))) {
- if (tacho_status.cur_state == TACHO_IN_IDLE) {
+ if ((tacho_status.cur_state == TACHO_IN_IDLE)
+ || (pre_duty != fan_get_duty(ch))) {
CPRINTS("mft_startmeasure");
if ((0 == rpm_actual) || (-1 == rpm_actual))
rpm_actual = fans[ch].rpm_min;
@@ -436,10 +437,12 @@ int fan_get_rpm_actual(int ch)
/* Measurement is active - stop the measurement */
mft_stopmeasure(fan_init_ch);
/* Need to avoid underflow state happen */
- rpm_actual = fans[ch].rpm_max;
+ rpm_actual = 0;
/*
- * Flag TDPND means mft underflow happen then complete
- * measurement immediately
+ * Flag TDPND means mft underflow happen,
+ * but let MFT still can re-measure actual rpm
+ * when user change pwm/fan duty during
+ * TACHO_UNDERFLOW state.
*/
tacho_status.cur_state = TACHO_UNDERFLOW;
CPRINTS("TACHO_UNDERFLOW");
@@ -496,6 +499,7 @@ int fan_get_rpm_actual(int ch)
tacho_status.cur_state = TACHO_IN_IDLE;
}
+ pre_duty = fan_get_duty(ch);
return rpm_actual;
}
@@ -550,7 +554,7 @@ enum fan_status fan_get_status(int ch)
rpm_actual = fan_get_rpm_actual(ch);
- if (((fan_get_duty(ch)) && (0 == rpm_actual))
+ if (((fan_get_duty(ch)) && (rpm_actual < fans[ch].rpm_min))
|| ((!fan_get_duty(ch)) && (rpm_actual)))
return FAN_STATUS_FRUSTRATED;
else if ((rpm_actual == 0) && (!fan_get_duty(ch)))
@@ -572,7 +576,8 @@ int fan_is_stalled(int ch)
rpm_actual = fan_get_rpm_actual(ch);
/* Check for normal condition, others are stall condition */
- if ((!fan_get_enabled(ch)) || ((fan_get_duty(ch)) && (rpm_actual))
+ if ((!fan_get_enabled(ch)) || ((fan_get_duty(ch))
+ && (rpm_actual >= fans[ch].rpm_min))
|| ((!fan_get_duty(ch)) && (!rpm_actual)))
return 0;
diff --git a/chip/npcx/flash.c b/chip/npcx/flash.c
index 3114848c3f..04122896b1 100644
--- a/chip/npcx/flash.c
+++ b/chip/npcx/flash.c
@@ -555,7 +555,6 @@ int flash_physical_erase(int offset, int size)
if (flash_check_prot_range(offset, CONFIG_FLASH_ERASE_SIZE))
return EC_ERROR_ACCESS_DENIED;
-
/*
* Reload the watchdog timer, so that erasing many flash pages
* doesn't cause a watchdog reset. May not need this now that
@@ -603,17 +602,9 @@ int flash_physical_protect_now(int all)
all_protected = 1;
flash_write_prot_reg(0, CONFIG_FLASH_PHYSICAL_SIZE);
} else {
- /* Protect the read-only section and persistent state */
-#ifdef CONFIG_PSTATE_AT_END
+ /* Protect the read-only section */
flash_write_prot_reg(RO_BANK_OFFSET*CONFIG_FLASH_BANK_SIZE,
RO_BANK_COUNT*CONFIG_FLASH_BANK_SIZE);
- flash_write_prot_reg(PSTATE_BANK * CONFIG_FLASH_BANK_SIZE,
- CONFIG_FLASH_BANK_SIZE);
-#else
- /* PSTATE immediately follows RO, in the first half of flash */
- flash_write_prot_reg(RO_BANK_OFFSET*CONFIG_FLASH_BANK_SIZE,
- (RO_BANK_COUNT+1) * CONFIG_FLASH_BANK_SIZE);
-#endif
}
return EC_SUCCESS;
diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c
index bd046c0683..8afd7d05fb 100644
--- a/chip/npcx/gpio.c
+++ b/chip/npcx/gpio.c
@@ -15,6 +15,8 @@
#include "task.h"
#include "timer.h"
#include "util.h"
+#include "system.h"
+#include "system_chip.h"
/* Marco functions for GPIO WUI/ALT table */
#define NPCX_GPIO(grp, pin) \
@@ -31,6 +33,10 @@
#define NPCX_ALT(grp, pin) \
ALT_GROUP_##grp, ALT_PIN(grp, pin)
+/* Flags for PWM IO type */
+#define PWM_IO_FUNC (1 << 1) /* PWM optional func bit */
+#define PWM_IO_OD (1 << 2) /* PWM IO open-drain bit */
+
struct gpio_wui_map {
uint8_t gpio_port;
uint8_t gpio_mask;
@@ -299,6 +305,23 @@ int gpio_find_irq_from_io(uint8_t port, uint8_t mask)
return -1;
}
+void gpio_pwm_io_type_sel(uint8_t alt_mask, uint8_t func)
+{
+ uint8_t chan = 0;
+ do {
+ alt_mask = (alt_mask >> 1);
+ if (alt_mask == 0)
+ break;
+ chan++;
+ } while (1);
+
+ /* Set PWM open drain output is open drain type*/
+ if (func & PWM_IO_OD)
+ SET_BIT(NPCX_PWMCTLEX(chan), NPCX_PWMCTLEX_OD_OUT);
+ else /* Set PWM open drain output is push-pull type*/
+ CLEAR_BIT(NPCX_PWMCTLEX(chan), NPCX_PWMCTLEX_OD_OUT);
+}
+
int gpio_alt_sel(uint8_t port, uint8_t mask, uint8_t func)
{
int i;
@@ -309,8 +332,13 @@ int gpio_alt_sel(uint8_t port, uint8_t mask, uint8_t func)
/* Enable alternative function if func >=0 */
if (func <= 0) /* GPIO functionality */
NPCX_DEVALT(map->alt_group) &= ~(map->alt_mask);
- else
+ else {
NPCX_DEVALT(map->alt_group) |= (map->alt_mask);
+ /* PWM optional functionality */
+ if (func & PWM_IO_FUNC)
+ gpio_pwm_io_type_sel(map->alt_mask,
+ func);
+ }
return 1;
}
}
@@ -492,27 +520,31 @@ int gpio_disable_interrupt(enum gpio_signal signal)
int gpio_is_reboot_warm(void)
{
- /* Check for debugger or watch-dog Warm reset */
- if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_DBGRST_STS)
- /* TODO: 5M5G has cleared WDRST_STS bit in booter */
-#if !defined(CHIP_NPCX5M5G)
- /* watch-dog warm reset */
- || (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS)
- && (IS_BIT_SET(NPCX_TWCFG, NPCX_TWCFG_WDRST_MODE))))
-#else
- )
-#endif
- return 1;
- else
+ uint32_t reset_flags;
+ /*
+ * Check reset cause here,
+ * gpio_pre_init is executed faster than system_pre_init
+ */
+ system_check_reset_cause();
+ reset_flags = system_get_reset_flags();
+
+ if ((reset_flags & RESET_FLAG_RESET_PIN) ||
+ (reset_flags & RESET_FLAG_POWER_ON) ||
+ (reset_flags & RESET_FLAG_WATCHDOG) ||
+ (reset_flags & RESET_FLAG_HARD) ||
+ (reset_flags & RESET_FLAG_SOFT))
return 0;
+ else
+ return 1;
}
void gpio_pre_init(void)
{
const struct gpio_info *g = gpio_list;
+ const struct gpio_wui_map *map;
+ int is_warm = gpio_is_reboot_warm();
int flags;
int i, j;
- int is_warm = gpio_is_reboot_warm();
uint32_t ksi_mask = (~((1<<KEYBOARD_ROWS)-1)) & KB_ROW_MASK;
uint32_t ks0_mask = (~((1<<KEYBOARD_COLS)-1)) & KB_COL_MASK;
@@ -533,7 +565,6 @@ void gpio_pre_init(void)
for (j = 0; j < 8; j++)
NPCX_WKPCL(i, j) = 0xFF;
-
/* No support enable clock for the GPIO port in run and sleep. */
/* Set flag for each GPIO pin in gpio_list */
for (i = 0; i < GPIO_COUNT; i++, g++) {
@@ -541,7 +572,6 @@ void gpio_pre_init(void)
if (flags & GPIO_DEFAULT)
continue;
-
/*
* If this is a warm reboot, don't set the output levels or
* we'll shut off the AP.
@@ -552,6 +582,13 @@ void gpio_pre_init(void)
/* Set up GPIO based on flags */
gpio_set_flags_by_mask(g->port, g->mask, flags);
}
+
+ /* Put power button information in bbram */
+ g = gpio_list + GPIO_POWER_BUTTON_L;
+ map = gpio_find_wui_from_io(g->port, g->mask);
+ NPCX_BBRAM(BBRM_DATA_INDEX_PBUTTON) = map->wui_table;
+ NPCX_BBRAM(BBRM_DATA_INDEX_PBUTTON + 1) = map->wui_group;
+ NPCX_BBRAM(BBRM_DATA_INDEX_PBUTTON + 2) = map->wui_mask;
}
/* List of GPIO IRQs to enable. Don't automatically enable interrupts for
diff --git a/chip/npcx/i2c.c b/chip/npcx/i2c.c
index e09bda30b6..33f512cc22 100644
--- a/chip/npcx/i2c.c
+++ b/chip/npcx/i2c.c
@@ -562,6 +562,9 @@ static void i2c_init(void)
/* Enable clock for I2C peripheral */
clock_enable_peripheral(CGC_OFFSET_I2C, CGC_I2C_MASK,
CGC_MODE_RUN | CGC_MODE_SLEEP);
+
+ /* Set I2C freq */
+ i2c_freq_changed();
/*
* initialize smb status and register
*/
@@ -589,4 +592,4 @@ static void i2c_init(void)
task_enable_irq(i2c_irqs[port]);
}
}
-DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_INIT_I2C);
+DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_DEFAULT);
diff --git a/chip/npcx/keyboard_raw.c b/chip/npcx/keyboard_raw.c
index e6599a35e2..f43488a3fa 100644
--- a/chip/npcx/keyboard_raw.c
+++ b/chip/npcx/keyboard_raw.c
@@ -40,6 +40,14 @@ void keyboard_raw_init(void)
NPCX_KBSOUT0 = 0x00;
NPCX_KBSOUT1 = 0x00;
+#ifdef CONFIG_KEYBOARD_COL2_INVERTED
+ /*
+ * When column 2 is inverted, Nuvoton EC KBS outputs only support
+ * open-drain. So we should change this pin to GPIO
+ */
+ SET_BIT(NPCX_DEVALT(ALT_GROUP_8), NPCX_DEVALT8_NO_KSO02_SL);
+#endif
+
/*
* Enable interrupts for the inputs. The top-level interrupt is still
* masked off, so this won't trigger interrupts yet.
@@ -79,14 +87,29 @@ test_mockable void keyboard_raw_drive_column(int col)
uint32_t mask;
/* Drive all lines to high */
- if (col == KEYBOARD_COLUMN_NONE)
+ if (col == KEYBOARD_COLUMN_NONE) {
mask = KB_COL_MASK;
+#ifdef CONFIG_KEYBOARD_COL2_INVERTED
+ gpio_set_level(GPIO_KBD_KSO2, 1);
+#endif
+ }
/* Set KBSOUT to zero to detect key-press */
- else if (col == KEYBOARD_COLUMN_ALL)
+ else if (col == KEYBOARD_COLUMN_ALL) {
mask = 0;
+#ifdef CONFIG_KEYBOARD_COL2_INVERTED
+ gpio_set_level(GPIO_KBD_KSO2, 0);
+#endif
+ }
/* Drive one line for detection */
- else
+ else {
+#ifdef CONFIG_KEYBOARD_COL2_INVERTED
+ if (col == 2)
+ gpio_set_level(GPIO_KBD_KSO2, 1);
+ else
+ gpio_set_level(GPIO_KBD_KSO2, 0);
+#endif
mask = ((~(1 << col)) & KB_COL_MASK);
+ }
/* Set KBSOUT */
NPCX_KBSOUT0 = (mask & 0xFFFF);
diff --git a/chip/npcx/lfw/ec_lfw.c b/chip/npcx/lfw/ec_lfw.c
index 9875681559..e9710398f3 100644
--- a/chip/npcx/lfw/ec_lfw.c
+++ b/chip/npcx/lfw/ec_lfw.c
@@ -9,6 +9,7 @@
#include "registers.h"
#include "config_chip.h"
#include "ec_lfw.h"
+#include "system_chip.h"
/* size of little FW */
#define LFW_SIZE 0x1000
@@ -92,30 +93,9 @@ bin2ram(void)
/* Disable FIU pins to tri-state */
CLEAR_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS);
- /* TODO: (ML) Booter has cleared watchdog flag */
-#ifndef CHIP_NPCX5M5G
- static uint32_t reset_flag;
- /* Check for VCC1 reset */
- if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_STS)) {
- /* Clear flag bit */
- SET_BIT(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_STS);
- reset_flag = 1;
- }
- /* Software debugger reset */
- else if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_DBGRST_STS))
- reset_flag = 1;
- /* Watchdog Reset */
- else if (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS)) {
- reset_flag = 1;
- } else {
- reset_flag = 0;
- }
- if (reset_flag) {
-#else
- /* Workaround method to distinguish reboot or sysjump */
- if (org_sp < 0x200C0000) {
-#endif
+ /* 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"
@@ -149,6 +129,9 @@ entry_lfw(void)
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();
diff --git a/chip/npcx/lpc.c b/chip/npcx/lpc.c
index 55d76f46d0..1622905299 100644
--- a/chip/npcx/lpc.c
+++ b/chip/npcx/lpc.c
@@ -350,8 +350,8 @@ uint32_t lpc_get_host_event_mask(enum lpc_host_event_type type)
int lpc_get_pltrst_asserted(void)
{
- /* TODO: (Simon) need to define GPIO_PLTRST */
- return 0;
+ /* Read PLTRST status*/
+ return (NPCX_MSWCTL1 & 0x04) ? 0 : 1;
}
/**
@@ -573,6 +573,8 @@ static void lpc_init(void)
NPCX_WIN_SIZE = 0x88;
NPCX_WIN_BASE(0) = (uint32_t)shm_mem_host_cmd;
NPCX_WIN_BASE(1) = (uint32_t)shm_memmap;
+ /* Write protect of Share memory */
+ NPCX_WIN_WR_PROT(1) = 0xFF;
/* Turn on PMC2 for Host Command usage */
SET_BIT(NPCX_HIPMCTL(PM_CHAN_2), 0);
diff --git a/chip/npcx/openocd/npcx_cmds.tcl b/chip/npcx/openocd/npcx_cmds.tcl
index 2d5a6c930e..63ed2932bc 100644
--- a/chip/npcx/openocd/npcx_cmds.tcl
+++ b/chip/npcx/openocd/npcx_cmds.tcl
@@ -10,38 +10,42 @@ source [find mem_helper.tcl]
proc flash_npcx {image_path image_offset image_size spifw_image} {
set UPLOAD_FLAG 0x200C4000;
- # Upload program spi image FW to lower 16KB Data RAM
- fast_load_image $spifw_image 0x200C0000
- fast_load
# Clear whole 128KB Code RAM
mwb 0x10088000 0xFF 0x20000
# Upload binary image to Code RAM
fast_load_image $image_path 0x10088000
fast_load
+
+ # Upload program spi image FW to lower 16KB Data RAM
+ fast_load_image $spifw_image 0x200C0000
+ fast_load
+
# Set sp to upper 16KB Data RAM
reg sp 0x200C8000
# Set spi offset address of uploaded image
reg r0 $image_offset
# Set spi program size of uploaded image
reg r1 $image_size
+ # Set pc to start of spi program function
+ reg pc 0x200C0001
# Clear upload flag
mww $UPLOAD_FLAG 0x0
- # Start to program spi flash
- resume 0x200C0001
+
echo "*** Program ... ***"
- sleep 1
+ # Start to program spi flash
+ resume
+
# Wait for any pending flash operations to complete
while {[expr [mrw $UPLOAD_FLAG] & 0x01] == 0} { sleep 1 }
- # Halt CPU
- halt
-
if {[expr [mrw $UPLOAD_FLAG] & 0x02] == 0} {
echo "*** Program Fail ***"
} else {
echo "*** Program Done ***"
}
+ # Halt CPU
+ halt
}
proc flash_npcx_ro {image_offset} {
@@ -64,6 +68,9 @@ proc flash_npcx_ro {image_offset} {
}
proc flash_npcx_evb {image_offset} {
+ set MPU_RNR 0xE000ED98;
+ set MPU_RASR 0xE000EDA0;
+
# 128 KB for RO& RW regions
set fw_size 0x20000
# 4K little FW
@@ -84,21 +91,31 @@ proc flash_npcx_evb {image_offset} {
# Halt CPU first
halt
+
+ # diable MPU for Data RAM first
+ mww $MPU_RNR 0x1
+ mww $MPU_RASR 0x0
+
echo "*** Start to program RO region ***"
# Write to lower 128kB from offset
flash_npcx $ro_image_path $image_offset $fw_size $spifw_image
- echo "*** Finish program RO region ***"
+ echo "*** Finish program RO region ***\r\n"
echo "*** Start to program RW region ***"
# Write to upper 128kB from offset
flash_npcx $rw_image_path $rw_image_offset $fw_size $spifw_image
- echo "*** Finish program RW region ***"
+ 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 ***"
+ echo "*** Finish program LFW region ***\r\n"
# Reset CPU
reset
}
+
+proc halt_npcx_cpu { } {
+ echo "*** Halt CPU first ***"
+ halt
+}
diff --git a/chip/npcx/peci.c b/chip/npcx/peci.c
index d5de9c1e40..2850ce793c 100644
--- a/chip/npcx/peci.c
+++ b/chip/npcx/peci.c
@@ -247,6 +247,12 @@ static void peci_init(void)
{
int i;
+ /* Enable clock for PECI peripheral */
+ clock_enable_peripheral(CGC_OFFSET_PECI, CGC_PECI_MASK,
+ CGC_MODE_RUN | CGC_MODE_SLEEP);
+ /* Set PECI freq */
+ peci_freq_changed();
+
/* make sure PECI_DATA function pin enable */
CLEAR_BIT(NPCX_DEVALT(0x0A), 6);
/* Set initial clock frequency */
diff --git a/chip/npcx/pwm.c b/chip/npcx/pwm.c
index bfbf2090d2..752ffe47fe 100644
--- a/chip/npcx/pwm.c
+++ b/chip/npcx/pwm.c
@@ -57,22 +57,27 @@ void pwm_freq_changed(void)
{
uint32_t prescaler_divider = 0;
+ /* Disable PWM for module configuration */
+ pwm_enable(pwm_init_ch, 0);
+
if (pwm_init_ch == PWM_CH_FAN) {
/*
* Using PWM Frequency and Resolution we calculate
* prescaler for input clock
*/
- /* (Benson_TBD_9) pwm_clock/freq/resolution not confirm */
#ifdef CONFIG_PWM_INPUT_LFCLK
prescaler_divider = (uint32_t)(32768 /
- pwm_channels[pwm_init_ch].freq);
+ (pwm_channels[pwm_init_ch].freq)
+ /(pwm_channels[pwm_init_ch].cycle_pulses));
#else
- prescaler_divider = (uint32_t)(clock_get_apb2_freq()
- / pwm_channels[pwm_init_ch].freq);
+ prescaler_divider = (uint32_t)(
+ clock_get_apb2_freq() / pwm_channels[pwm_init_ch].freq
+ / (pwm_channels[pwm_init_ch].cycle_pulses));
#endif
} else {
- prescaler_divider = (uint32_t)(clock_get_apb2_freq()
- / pwm_channels[pwm_init_ch].freq);
+ prescaler_divider = (uint32_t)(
+ clock_get_apb2_freq() / pwm_channels[pwm_init_ch].freq
+ / (pwm_channels[pwm_init_ch].cycle_pulses));
}
/* Set clock prescalre divider to ADC module*/
if (prescaler_divider >= 1)
@@ -138,8 +143,6 @@ void pwm_set_duty(enum pwm_channel ch, int percent)
if (percent < 0)
percent = 0;
- /* (Benson_TBD_14) if 100% make mft cannot get TCRB,
- * it will need to change to 99% */
else if (percent > 100)
percent = 100;
CPRINTS("pwm1duty=%d", percent);
@@ -149,14 +152,14 @@ void pwm_set_duty(enum pwm_channel ch, int percent)
CPRINTS("freq=0x%x", pwm_channels[ch].freq);
CPRINTS("resolution=%d", resolution);
CPRINTS("duty_cycle=%d", duty_cycle);
-
+ if (percent*resolution > (duty_cycle*100))
+ duty_cycle += 1;
/* Set the duty cycle */
- /* (Benson_TBD_14) Always enable the fan channel or not */
- if (percent) {
+ if (duty_cycle > 0) {
NPCX_DCR(pwm_channels[ch].channel) = (duty_cycle - 1);
pwm_enable(ch, 1);
} else {
- NPCX_DCR(pwm_channels[ch].channel) = 0;
+ NPCX_DCR(pwm_channels[ch].channel) = resolution;
pwm_enable(ch, 0);
}
}
@@ -170,7 +173,8 @@ void pwm_set_duty(enum pwm_channel ch, int percent)
int pwm_get_duty(enum pwm_channel ch)
{
/* Return percent */
- if (0 == pwm_get_enabled(ch))
+ if ((0 == pwm_get_enabled(ch)) || (NPCX_DCR(pwm_channels[ch].channel)
+ > NPCX_CTR(pwm_channels[ch].channel)))
return 0;
else
return (((NPCX_DCR(pwm_channels[ch].channel) + 1) * 100)
@@ -199,8 +203,8 @@ void pwm_config(enum pwm_channel ch)
/* Set PWM heartbeat mode is no heartbeat*/
NPCX_PWMCTL(pwm_channels[ch].channel) =
(NPCX_PWMCTL(pwm_channels[ch].channel)
- &(~(((1<<2)-1)<<NPCX_PWMCTL_HB_DC_CTL)))
- |(NPCX_PWM_HBM_NORMAL<<NPCX_PWMCTL_HB_DC_CTL);
+ & (~(((1<<2)-1) << NPCX_PWMCTL_HB_DC_CTL)))
+ | (NPCX_PWM_HBM_NORMAL << NPCX_PWMCTL_HB_DC_CTL);
/* Set PWM operation frequence */
pwm_freq_changed();
@@ -210,14 +214,11 @@ void pwm_config(enum pwm_channel ch)
(pwm_channels[ch].cycle_pulses - 1);
/* Set the duty cycle */
- NPCX_DCR(pwm_channels[ch].channel) = 0;
+ NPCX_DCR(pwm_channels[ch].channel) = pwm_channels[ch].cycle_pulses;
/* Set PWM polarity is normal*/
CLEAR_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTL_INVP);
- /* Set PWM open drain output is push-pull type*/
- CLEAR_BIT(NPCX_PWMCTL(pwm_channels[ch].channel), NPCX_PWMCTLEX_OD_OUT);
-
/* Select default CLK or LFCLK clock input to PWM module */
NPCX_PWMCTLEX(pwm_channels[ch].channel) =
(NPCX_PWMCTLEX(pwm_channels[ch].channel)
@@ -252,7 +253,6 @@ static void pwm_init(void)
int i;
#ifdef CONFIG_PWM_DSLEEP
-
/* Enable the PWM module and delay a few clocks */
clock_enable_peripheral(CGC_OFFSET_PWM, CGC_PWM_MASK, CGC_MODE_ALL);
#else
diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h
index 1d11770ad1..21a0609d64 100644
--- a/chip/npcx/registers.h
+++ b/chip/npcx/registers.h
@@ -37,7 +37,7 @@
#define I2C_LEVEL_SUPPORT 1
/* Switcher of features */
#define SUPPORT_LCT 1
-#define SUPPORT_WDG 0
+#define SUPPORT_WDG 1
#define SUPPORT_HIB 1
/* Switcher of debugging */
#define DEBUG_I2C 0
@@ -213,7 +213,7 @@
#define NPCX_IRQ_WKINTA_2 NPCX_IRQ_60
#define NPCX_IRQ_WKINTB_2 NPCX_IRQ_61
#define NPCX_IRQ_WKINTC_2 NPCX_IRQ_62
-#define NPCX_IRQ_WKINTD_2 PCX_IRQ_63
+#define NPCX_IRQ_WKINTD_2 NPCX_IRQ_63
#define NPCX_IRQ_COUNT 64
@@ -397,8 +397,12 @@ enum {
/******************************************************************************/
/* MSWC Registers */
#define NPCX_MSWCTL1 REG8(NPCX_MSWC_BASE_ADDR + 0x000)
+#define NPCX_MSWCTL2 REG8(NPCX_MSWC_BASE_ADDR + 0x002)
#define NPCX_HCBAL REG8(NPCX_MSWC_BASE_ADDR + 0x008)
#define NPCX_HCBAH REG8(NPCX_MSWC_BASE_ADDR + 0x00A)
+#define NPCX_SRID_CR REG8(NPCX_MSWC_BASE_ADDR + 0x01C)
+#define NPCX_SID_CR REG8(NPCX_MSWC_BASE_ADDR + 0x020)
+#define NPCX_DEVICE_ID_CR REG8(NPCX_MSWC_BASE_ADDR + 0x022)
/******************************************************************************/
/* System Configuration (SCFG) Registers */
@@ -451,6 +455,7 @@ enum {
#define NPCX_STRPST_SPI_COMP 7
#define NPCX_RSTCTL_VCC1_RST_STS 0
#define NPCX_RSTCTL_DBGRST_STS 1
+#define NPCX_RSTCTL_VCC1_RST_SCRATCH 3
#define NPCX_RSTCTL_LRESET_PLTRST_MODE 5
#define NPCX_RSTCTL_HIPRST_MODE 6
#define NPCX_DEV_CTL4_SPI_SP_SEL 4
@@ -712,6 +717,8 @@ enum {
CGC_OFFSET_PWM = 1,
CGC_OFFSET_I2C = 2,
CGC_OFFSET_ADC = 3,
+ CGC_OFFSET_PECI = 3,
+ CGC_OFFSET_SPI = 3,
CGC_OFFSET_TIMER = 3,
CGC_OFFSET_LPC = 4,
CGC_OFFSET_ESPI = 5,
@@ -721,11 +728,14 @@ enum {
#define CGC_UART_MASK (1 << NPCX_PWDWN_CTL1_UART_PD)
#define CGC_FAN_MASK (1 << NPCX_PWDWN_CTL1_MFT1_PD)
#define CGC_FIU_MASK (1 << NPCX_PWDWN_CTL1_FIU_PD)
-#define CGC_PWM_MASK (1 << NPCX_PWDWN_CTL2_PWM2_PD)
+#define CGC_PWM_MASK ((1 << NPCX_PWDWN_CTL2_PWM0_PD) | \
+ (1 << NPCX_PWDWN_CTL2_PWM1_PD))
#define CGC_I2C_MASK ((1 << NPCX_PWDWN_CTL3_SMB0_PD) | \
(1 << NPCX_PWDWN_CTL3_SMB1_PD) | \
(1 << NPCX_PWDWN_CTL3_SMB2_PD))
#define CGC_ADC_MASK (1 << NPCX_PWDWN_CTL4_ADC_PD)
+#define CGC_PECI_MASK (1 << NPCX_PWDWN_CTL4_PECI_PD)
+#define CGC_SPI_MASK (1 << NPCX_PWDWN_CTL4_SPIP_PD)
#define CGC_TIMER_MASK ((1 << NPCX_PWDWN_CTL4_ITIM1_PD) | \
(1 << NPCX_PWDWN_CTL4_ITIM2_PD) | \
(1 << NPCX_PWDWN_CTL4_ITIM3_PD))
diff --git a/chip/npcx/spi.c b/chip/npcx/spi.c
index c2802fea4f..82a1b31dbb 100644
--- a/chip/npcx/spi.c
+++ b/chip/npcx/spi.c
@@ -63,7 +63,7 @@ void spi_freq_changed(void)
NPCX_SPI_CTL1 = (NPCX_SPI_CTL1&(~(((1<<7)-1)<<NPCX_SPI_CTL1_SCDV)))
|(prescaler_divider<<NPCX_SPI_CTL1_SCDV);
}
-DECLARE_HOOK(HOOK_FREQ_CHANGE, spi_freq_changed, HOOK_PRIO_DEFAULT);
+DECLARE_HOOK(HOOK_FREQ_CHANGE, spi_freq_changed, HOOK_PRIO_FIRST);
/**
* Set SPI enabled.
@@ -169,6 +169,10 @@ int spi_transaction(const uint8_t *txdata, int txlen,
*/
static void spi_init(void)
{
+ /* Enable clock for SPI peripheral */
+ clock_enable_peripheral(CGC_OFFSET_SPI, CGC_SPI_MASK,
+ CGC_MODE_RUN | CGC_MODE_SLEEP);
+
/* Disabling spi module */
spi_enable(0);
diff --git a/chip/npcx/spiflashfw/ec_npcxflash.c b/chip/npcx/spiflashfw/ec_npcxflash.c
index 0a7dc2b2e2..41e833b273 100644
--- a/chip/npcx/spiflashfw/ec_npcxflash.c
+++ b/chip/npcx/spiflashfw/ec_npcxflash.c
@@ -123,7 +123,7 @@ void sspi_flash_burst_write(unsigned int dest_addr, unsigned int bytes,
sspi_flash_cs_level(1);
}
-void sspi_flash_physical_clear_stsreg(void)
+int sspi_flash_physical_clear_stsreg(void)
{
/* Disable tri-state */
sspi_flash_tristate(0);
@@ -139,11 +139,17 @@ void sspi_flash_physical_clear_stsreg(void)
/* Wait writing completed */
sspi_flash_wait_ready();
- /* Read status register 1/2 */
+ /* Read status register 1/2 for checking */
sspi_flash_execute_cmd(CMD_READ_STATUS_REG, MASK_CMD_RD_1BYTE);
+ if (NPCX_UMA_DB0 != 0x00)
+ return 0;
sspi_flash_execute_cmd(CMD_READ_STATUS_REG2, MASK_CMD_RD_1BYTE);
+ if (NPCX_UMA_DB0 != 0x00)
+ return 0;
/* Enable tri-state */
sspi_flash_tristate(1);
+
+ return 1;
}
void sspi_flash_physical_write(int offset, int size, const char *data)
@@ -212,7 +218,7 @@ int sspi_flash_verify(int offset, int size, const char *data)
uint8_t *ptr_flash;
uint8_t *ptr_mram;
- ptr_flash = (uint8_t *)(0x64000000+offset);
+ ptr_flash = (uint8_t *)(CONFIG_FLASH_BASE + offset);
ptr_mram = (uint8_t *)data;
result = 1;
@@ -235,7 +241,7 @@ int sspi_flash_verify(int offset, int size, const char *data)
int sspi_flash_get_image_used(const char *fw_base)
{
const uint8_t *image;
- int size = 0x20000; /* maximum size is 128KB */
+ int size = CONFIG_CDRAM_SIZE; /* maximum size is 128KB */
image = (const uint8_t *)fw_base;
/*
@@ -250,7 +256,7 @@ int sspi_flash_get_image_used(const char *fw_base)
}
-volatile __attribute__((section(".up_flag"))) unsigned int flag_upload;
+volatile __attribute__((section(".up_flag"))) uint32_t flag_upload;
/* Entry function of spi upload function */
void __attribute__ ((section(".startup_text"), noreturn))
@@ -259,9 +265,14 @@ sspi_flash_upload(int spi_offset, int spi_size)
/*
* Flash image has been uploaded to Code RAM
*/
- const char *image_base = (char *)0x10088000;
+ const char *image_base = (const char *)CONFIG_CDRAM_BASE;
uint32_t sz_image = spi_size;
+ /* Unlock & stop watchdog */
+ NPCX_WDSDM = 0x87;
+ NPCX_WDSDM = 0x61;
+ NPCX_WDSDM = 0x63;
+
/* Set pinmux first */
sspi_flash_pinmux(1);
@@ -270,25 +281,25 @@ sspi_flash_upload(int spi_offset, int spi_size)
sz_image = sspi_flash_get_image_used(image_base);
/* Clear status reg of spi flash for protection */
- sspi_flash_physical_clear_stsreg();
-
- /* Start to erase */
- sspi_flash_physical_erase(spi_offset, sz_image);
+ if (sspi_flash_physical_clear_stsreg()) {
+ /* Start to erase */
+ sspi_flash_physical_erase(spi_offset, sz_image);
- /* Start to write */
- sspi_flash_physical_write(spi_offset, sz_image, image_base);
+ /* Start to write */
+ sspi_flash_physical_write(spi_offset, sz_image, image_base);
- /* Verify data */
- if (sspi_flash_verify(spi_offset, sz_image, image_base))
- flag_upload |= 0x02;
+ /* Verify data */
+ if (sspi_flash_verify(spi_offset, sz_image, image_base))
+ flag_upload |= 0x02;
- /* Disable pinmux */
- sspi_flash_pinmux(0);
+ /* Disable pinmux */
+ sspi_flash_pinmux(0);
+ }
/* Mark we have finished upload work */
flag_upload |= 0x01;
- /* Should never reach this*/
+ /* Infinite loop */
for (;;)
;
}
diff --git a/chip/npcx/system.c b/chip/npcx/system.c
index ac6a4ba4d9..44f5c03f64 100644
--- a/chip/npcx/system.c
+++ b/chip/npcx/system.c
@@ -24,16 +24,9 @@
uint32_t base_addr;
#endif
-/* Indices for battery-backed ram (BBRAM) data position */
-enum bbram_data_index {
- BBRM_DATA_INDEX_SCRATCHPAD = 0, /* General-purpose scratchpad */
- BBRM_DATA_INDEX_SAVED_RESET_FLAGS = 4, /* Saved reset flags */
- BBRM_DATA_INDEX_WAKE = 8, /* Wake reasons for hibernate */
-};
-
/* Flags for BBRM_DATA_INDEX_WAKE */
-#define PSLDATA_WAKE_MTC (1 << 0) /* LCT alarm */
-#define PSLDATA_WAKE_PIN (1 << 1) /* Wake pin */
+#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
@@ -47,7 +40,8 @@ enum bbram_data_index {
#define MTC_WUI_GROUP MIWU_GROUP_4
#define MTC_WUI_MASK MASK_PIN7
-uint32_t flag_hibernate;
+/* ROM address of chip revision */
+#define CHIP_REV_ADDR 0x00007FFC
/* Begin address for the .lpram section; defined in linker script */
uintptr_t __lpram_fw_start = CONFIG_LPRAM_BASE;
@@ -259,32 +253,57 @@ void system_set_rtc(uint32_t seconds)
}
/* Check reset cause */
-static void check_reset_cause(void)
+void system_check_reset_cause(void)
{
uint32_t hib_wake_flags = bbram_data_read(BBRM_DATA_INDEX_WAKE);
uint32_t flags = 0;
- /* Check for VCC1 reset */
- if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_STS))
- flags |= RESET_FLAG_POWER_ON;
+ /* Use scratch bit to check power on reset or VCC1_RST reset */
+ if (!IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_SCRATCH)) {
+ /* Check for VCC1 reset */
+ if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_STS))
+ flags |= RESET_FLAG_RESET_PIN;
+ else
+ flags |= RESET_FLAG_POWER_ON;
+ }
+
+ /*
+ * Set scratch bit to distinguish VCC1RST# is asserted again
+ * or not. This bit will be clear automatically when VCC1RST#
+ * is asserted or power-on reset occurs
+ */
+ SET_BIT(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_SCRATCH);
/* Software debugger reset */
- if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_DBGRST_STS))
+ if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_DBGRST_STS)) {
flags |= RESET_FLAG_SOFT;
+ /* Clear debugger reset status initially*/
+ SET_BIT(NPCX_RSTCTL, NPCX_RSTCTL_DBGRST_STS);
+ }
/* 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 & PSLDATA_WAKE_PIN))
+ if ((hib_wake_flags & HIBERNATE_WAKE_PIN))
flags |= RESET_FLAG_WAKE_PIN;
+ else if ((hib_wake_flags & HIBERNATE_WAKE_MTC))
+ flags |= RESET_FLAG_RTC_ALARM;
/* Restore then clear saved reset flags */
flags |= bbram_data_read(BBRM_DATA_INDEX_SAVED_RESET_FLAGS);
bbram_data_write(BBRM_DATA_INDEX_SAVED_RESET_FLAGS, 0);
+ /* Clear saved hibernate wake flag, too */
+ bbram_data_write(BBRM_DATA_INDEX_WAKE, 0);
system_set_reset_flags(flags);
}
@@ -316,6 +335,25 @@ void system_mpu_config(void)
* [0] - ENABLE = 1 (enabled)
*/
CPU_MPU_RASR = 0x03080013;
+
+ /* Create a new MPU Region for data ram */
+ CPU_MPU_RNR = 1; /* Select region number 1 */
+ CPU_MPU_RASR = CPU_MPU_RASR & 0xFFFFFFFE; /* Disable region */
+ CPU_MPU_RBAR = CONFIG_RAM_BASE; /* Set region base address */
+ /*
+ * Set region size & attribute and enable region
+ * [31:29] - Reserved.
+ * [28] - XN (Execute Never) = 1
+ * [27] - Reserved.
+ * [26:24] - AP = 011 (Full access)
+ * [23:22] - Reserved.
+ * [21:19,18,17,16] - TEX,S,C,B = 001000 (Normal memory)
+ * [15:8] - SRD = 0 (Subregions enabled)
+ * [7:6] - Reserved.
+ * [5:1] - SIZE = 01110 (32K)
+ * [0] - ENABLE = 1 (enabled)
+ */
+ CPU_MPU_RASR = 0x1308001D;
}
void __attribute__ ((section(".lowpower_ram")))
@@ -332,9 +370,22 @@ __enter_hibernate_in_lpram(void)
/* Enter deep idle, wake-up by GPIOxx or RTC */
asm("wfi");
- /*TODO: Using POWER_BUTTON_L GPIO02 to wake-up? */
- if (IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_1 , MIWU_GROUP_1), 2))
+ /* POWER_BUTTON_L wake-up */
+ if (NPCX_WKPND(NPCX_BBRAM(BBRM_DATA_INDEX_PBUTTON),
+ NPCX_BBRAM(BBRM_DATA_INDEX_PBUTTON + 1))
+ & NPCX_BBRAM(BBRM_DATA_INDEX_PBUTTON + 2)) {
+ /* Clear WUI pending bit of POWER_BUTTON_L */
+ NPCX_WKPCL(NPCX_BBRAM(BBRM_DATA_INDEX_PBUTTON),
+ NPCX_BBRAM(BBRM_DATA_INDEX_PBUTTON + 1))
+ = NPCX_BBRAM(BBRM_DATA_INDEX_PBUTTON + 2);
+ /*
+ * Mark wake-up reason for hibernate
+ * Do not call bbram_data_write directly cause of
+ * excuting in low-power ram
+ */
+ NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_PIN;
break;
+ }
/* RTC wake-up */
else if (IS_BIT_SET(NPCX_WTC, NPCX_WTC_PTO)) {
/* Clear WUI pending bit of MTC */
@@ -342,6 +393,9 @@ __enter_hibernate_in_lpram(void)
/* Clear interrupt & Disable alarm interrupt */
CLEAR_BIT(NPCX_WTC, NPCX_WTC_WIE);
SET_BIT(NPCX_WTC, NPCX_WTC_PTO);
+
+ /* Mark wake-up reason for hibernate */
+ NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_MTC;
break;
}
}
@@ -388,14 +442,11 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
if (seconds || microseconds)
system_set_rtc_alarm(seconds, microseconds);
- /* Unlock & stop watchdog registers */
+ /* Unlock & stop watchdog */
NPCX_WDSDM = 0x87;
NPCX_WDSDM = 0x61;
NPCX_WDSDM = 0x63;
- /* Configure address LPRAM in the MPU as a regular memory */
- system_mpu_config();
-
/* Enable Low Power RAM */
NPCX_LPRAM_CTRL = 1;
@@ -418,6 +469,13 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
}
+static char system_to_hex(uint8_t x)
+{
+ if (x >= 0 && x <= 9)
+ return '0' + x;
+ return 'a' + x - 10;
+}
+
/*****************************************************************************/
/* IC specific low-level driver */
@@ -491,17 +549,19 @@ void system_pre_init(void)
* EC should be initialized in Booter
*/
-#ifndef CHIP_NPCX5M5G
/* Power-down the modules we don't need */
- NPCX_PWDWN_CTL(0) = 0xFD; /* Skip SDP_PD */
+ NPCX_PWDWN_CTL(0) = 0xF9; /* Skip SDP_PD FIU_PD */
NPCX_PWDWN_CTL(1) = 0xFF;
- NPCX_PWDWN_CTL(2) = 0xFF;
- NPCX_PWDWN_CTL(3) = 0xF0; /*Skip ITIM3/2/1_PD */
+ NPCX_PWDWN_CTL(2) = 0x8F;
+ NPCX_PWDWN_CTL(3) = 0xF4; /* Skip ITIM2/1_PD */
NPCX_PWDWN_CTL(4) = 0xF8;
- NPCX_PWDWN_CTL(5) = 0x87;
-#endif
- /* Check reset cause */
- check_reset_cause();
+ NPCX_PWDWN_CTL(5) = 0x85; /* Skip ITIM5_PD */
+
+ /*
+ * Configure LPRAM in the MPU as a regular memory
+ * and DATA RAM to prevent code execution
+ */
+ system_mpu_config();
}
void system_reset(int flags)
@@ -543,49 +603,59 @@ void system_reset(int flags)
*/
const char *system_get_chip_vendor(void)
{
- uint8_t fam_id = system_sib_read_reg(SIO_OFFSET, INDEX_SID);
+ static char str[15] = "Unknown-";
+ char *p = str + 8;
+
+ /* Read Vendor ID in core register */
+ uint8_t fam_id = NPCX_SID_CR;
switch (fam_id) {
- case 0xFC:
- return "NUC";
+ case 0x20:
+ return "Nuvoton";
default:
- return "Unknown";
+ *p = system_to_hex((fam_id & 0xF0) >> 4);
+ *(p + 1) = system_to_hex(fam_id & 0x0F);
+ *(p + 2) = '\0';
+ return str;
}
}
const char *system_get_chip_name(void)
{
- uint8_t chip_id = system_sib_read_reg(SIO_OFFSET, INDEX_SRID);
+ static char str[15] = "Unknown-";
+ char *p = str + 8;
+
+ /* Read Chip ID in core register */
+ uint8_t chip_id = NPCX_DEVICE_ID_CR;
switch (chip_id) {
- case 0x05:
- return "NPCX5m5G";
+ case 0x12:
+ return "NPCX585G";
+ case 0x13:
+ return "NPCX575G";
default:
- return "Unknown";
+ *p = system_to_hex((chip_id & 0xF0) >> 4);
+ *(p + 1) = system_to_hex(chip_id & 0x0F);
+ *(p + 2) = '\0';
+ return str;
}
}
const char *system_get_chip_revision(void)
{
- static char rev[1];
+ static char rev[4];
+#ifndef CHIP_NPCX5M5G
uint8_t rev_num = system_sib_read_reg(SIO_OFFSET, INDEX_CHPREV);
-
- /* set revision from character '0' */
- rev[0] = '0' + rev_num;
+#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);
+ *(rev + 3) = system_to_hex(rev_num & 0x0F);
return rev;
}
-int system_set_console_force_enabled(int val)
-{
- /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */
- return 0;
-}
-
-int system_get_console_force_enabled(void)
-{
- /* TODO(crosbug.com/p/23575): IMPLEMENT ME ! */
- return 0;
-}
-
/**
* Get/Set VbNvContext in non-volatile storage. The block should be 16 bytes
* long, which is the current size of VbNvContext block.
@@ -595,12 +665,25 @@ int system_get_console_force_enabled(void)
*/
int system_get_vbnvcontext(uint8_t *block)
{
- return EC_ERROR_UNIMPLEMENTED;
+ int i;
+ uint32_t *pblock = (uint32_t *) block;
+ for (i = 0; i < 4; i++)
+ pblock[i] = bbram_data_read(BBRM_DATA_INDEX_VBNVCNTXT + i*4);
+
+ return EC_SUCCESS;
}
int system_set_vbnvcontext(const uint8_t *block)
{
- return EC_ERROR_UNIMPLEMENTED;
+ int i, result;
+ uint32_t *pblock = (uint32_t *) block;
+ for (i = 0; i < 4; i++) {
+ result = bbram_data_write(BBRM_DATA_INDEX_VBNVCNTXT + i*4,
+ pblock[i]);
+ if (result != EC_SUCCESS)
+ return result;
+ }
+ return EC_SUCCESS;
}
/**
diff --git a/chip/npcx/system_chip.h b/chip/npcx/system_chip.h
index 280246c414..135e2f1cd8 100644
--- a/chip/npcx/system_chip.h
+++ b/chip/npcx/system_chip.h
@@ -8,7 +8,22 @@
#ifndef __CROS_EC_NPCX_LPC_H
#define __CROS_EC_NPCX_LPC_H
+/* Indices for battery-backed ram (BBRAM) data position */
+enum bbram_data_index {
+ BBRM_DATA_INDEX_SCRATCHPAD = 0, /* General-purpose scratchpad */
+ BBRM_DATA_INDEX_SAVED_RESET_FLAGS = 4, /* Saved reset flags */
+ BBRM_DATA_INDEX_WAKE = 8, /* Wake reasons for hibernate */
+ BBRM_DATA_INDEX_PBUTTON = 12, /* Power button for hibernate */
+ BBRM_DATA_INDEX_VBNVCNTXT = 16, /* VbNvContext for ARM arch */
+ 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 */
+void system_check_reset_cause(void);
/* End address for the .lpram section; defined in linker script */
extern unsigned int __lpram_fw_end;
diff --git a/chip/npcx/watchdog.c b/chip/npcx/watchdog.c
index 411488877a..f72be3cb7b 100644
--- a/chip/npcx/watchdog.c
+++ b/chip/npcx/watchdog.c
@@ -15,13 +15,13 @@
#include "timer.h"
#include "task.h"
#include "util.h"
+#include "system_chip.h"
#include "watchdog.h"
/* WDCNT value for watchdog period */
#define WDCNT_VALUE ((CONFIG_WATCHDOG_PERIOD_MS*INT_32K_CLOCK) / (1024*1000))
-/* Delay counter time for print watchdog info through UART */
-#define WDCNT_DELAY 0x10
-
+/* Delay time for warning timer to print watchdog info through UART */
+#define WDCNT_DELAY WDCNT_VALUE
void watchdog_init_warning_timer(void)
{
@@ -45,7 +45,6 @@ void watchdog_init_warning_timer(void)
task_enable_irq(ITIM16_INT(ITIM_WDG_NO));
}
-
void watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
{
int wd_cnt;
@@ -55,16 +54,26 @@ void watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
/* Read watchdog counter from TWMWD */
wd_cnt = NPCX_TWMWD;
#if DEBUG_WDG
- ccprintf("WD (%d)\r\n", wd_cnt);
+ panic_printf("WD (%d)\r\n", wd_cnt);
#endif
- if (wd_cnt <= WDCNT_DELAY)
+ if (wd_cnt <= WDCNT_DELAY) {
+ /*
+ * Touch watchdog to let UART have enough time
+ * to print panic info
+ */
+ NPCX_WDSDM = 0x5C;
+ /* Print panic info */
watchdog_trace(excep_lr, excep_sp);
+ cflush();
+ /* Trigger watchdog immediately */
+ system_watchdog_reset();
+ }
}
/* ISR for watchdog warning naked will keep SP & LR */
void IRQ_HANDLER(ITIM16_INT(ITIM_WDG_NO))(void) __attribute__((naked));
void IRQ_HANDLER(ITIM16_INT(ITIM_WDG_NO))(void)
- {
+{
/* Naked call so we can extract raw LR and SP */
asm volatile("mov r0, lr\n"
"mov r1, sp\n"
@@ -75,7 +84,7 @@ void IRQ_HANDLER(ITIM16_INT(ITIM_WDG_NO))(void)
"bl watchdog_check\n"
"pop {r0, lr}\n"
"b task_resched_if_needed\n");
- }
+}
const struct irq_priority IRQ_PRIORITY(ITIM16_INT(ITIM_WDG_NO))
__attribute__((section(".rodata.irqprio")))
= {ITIM16_INT(ITIM_WDG_NO), 0};
diff --git a/common/system.c b/common/system.c
index b257bc8594..d57b1ce9ab 100644
--- a/common/system.c
+++ b/common/system.c
@@ -310,8 +310,8 @@ void system_disable_jump(void)
test_mockable enum system_image_copy_t system_get_image_copy(void)
{
- /* TODO: (ML) return which region is used in Code RAM */
#ifdef CONFIG_CODERAM_ARCH
+ /* Return which region is used in Code RAM */
return system_get_shrspi_image_copy();
#else
uintptr_t my_addr = (uintptr_t)system_get_image_copy -
@@ -477,8 +477,8 @@ int system_run_image_copy(enum system_image_copy_t copy)
if (base == 0xffffffff)
return EC_ERROR_INVAL;
- /* TODO: (ML) jump to little FW for code ram architecture */
#ifdef CONFIG_CODERAM_ARCH
+ /* Jump to little FW for code ram architecture */
init_addr = system_get_lfw_address(base);
#else
/* Make sure the reset vector is inside the destination image */