diff options
author | Randall Spangler <rspangler@chromium.org> | 2015-02-11 11:12:58 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-02-25 03:33:08 +0000 |
commit | c3cd10937e321f04c4b2dfc4786ec146e785e5cb (patch) | |
tree | 44d9221a5d39875b123af1a9ed60749007676445 | |
parent | 3227f921e74d0d03424aa16b8ce2c246b7afcb6f (diff) | |
download | chrome-ec-c3cd10937e321f04c4b2dfc4786ec146e785e5cb.tar.gz |
WIP - Nuvoton 30-Jan patch
Issues fixed on 0216:
1.Modified CONFIG_KEYBOARD_COL2_INVERTED support in keyboard_raw.c
2.Modified warm_reset checking in gpio.c
3.Modified system_get_chip_name in system.c for package info.
4.Modified fan.c and pwm.c for:
● If the DCRn value is greater than the CTRn value, the PWM_n signal is always low.
● Fan stall condition event:
If the measured fan speed is lower than the lowLimit value (unless the Fan Speed Low Limit value is 0) or in case of erroneous measurement, the userCallback is called.
5. Change cycle_pluses to 480 in board.c
Issues fixed:
1. Jump data at top of RAM is getting corrupted. Changed the flag to
RESET_FLAG_RESET_PIN. Added a workaround method to fix VCC1_RST
issue.
2. Hibernate wake need to report whether wake reason was GPIO or RTC
3. Hibernate wake must be distinguishable from watchdog reset. The
booter will log reset reason in Code RAM. I copy the log data to
battery-backup RAM in little FW. And system driver will refer this
data to distinguish if it's watchdog reset or not.
4. Watchdog reset flag is not set. Same fix as 3.
5. Should return error if unable to clear SPI flash status register.
6. Remove chip_temp_sensor.c
7. Remove use of pstate from flash driver
8. Remove support for watchdog warm reset
9. Keyboard raw driver must support COL2 inverted
10. LPC memory mapped data must be read-only from host
11. LPC should support PLTRST# signal
12. Problems reading chip type/version. Use core registers and ROM data to read IDs.
13. When chip type/version is unknown, report hex value.
14. Watchdog does not consistently print panic information.
15. Remove console force enable logic.
16. Enable only the peripheral clocks that are needed. Please notice
user should add bit mask in CGC_XXX_MASK if they want to enable
additional module. For example, if user wants to enable PWM3, he must
add PWDWN_CTL2_PWM3_PD bit in CGC_PWM_MASK.
Please see HOOK_FREQ_CHANGE and HOOK_INIT these two hook functions.
If I turn off all I2C modules in system_pre_init and turn on the
modules I need in i2c_init, I found its freq is not correct. The root
cause is hook_notify(HOOK_FREQ_CHANGE) is executed first (in
clock_init) before i2c_init. At this time, i2c modules are power-down
and writing to freq register is useless. I re-execute freq-changed
hook function after turning on modules again.
17. MPU properly configured to prevent code execution from data RAM
18. Partial nvcontext implementation. Copy these 16 bytes in our battery-backup RAM.
Additional items we also modified:
1. pwm.c: Support open-drain IO type of PWM. (PWM IO-Type cannot by
determined by GPIO, we use bit 1 & 2 of function byte of gpio_alt_func
array to support it)
2. ec_npcxflash.c: Use definition to replace constant value. Stop
watchdog during flash programing.
3. npcx_cmds.tcl: Adjust script sequence for robustness. Add unlock
MPU commands for Data RAM.
BUG=chrome-os-partner:34346
BRANCH=none
TEST=manually verify changes
Change-Id: I722a77d29e7543b054819480c7b7477af4263119
Signed-off-by: Ian Chao <mlchao@nuvoton.com>
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/248670
-rw-r--r-- | board/npcx_evb/board.c | 30 | ||||
-rw-r--r-- | board/npcx_evb/board.h | 2 | ||||
-rw-r--r-- | board/npcx_evb/gpio.inc | 10 | ||||
-rw-r--r-- | chip/npcx/adc.c | 11 | ||||
-rw-r--r-- | chip/npcx/build.mk | 2 | ||||
-rw-r--r-- | chip/npcx/chip_temp_sensor.c | 32 | ||||
-rw-r--r-- | chip/npcx/clock.c | 2 | ||||
-rw-r--r-- | chip/npcx/config_chip.h | 4 | ||||
-rw-r--r-- | chip/npcx/fan.c | 25 | ||||
-rw-r--r-- | chip/npcx/flash.c | 11 | ||||
-rw-r--r-- | chip/npcx/gpio.c | 69 | ||||
-rw-r--r-- | chip/npcx/i2c.c | 5 | ||||
-rw-r--r-- | chip/npcx/keyboard_raw.c | 29 | ||||
-rw-r--r-- | chip/npcx/lfw/ec_lfw.c | 29 | ||||
-rw-r--r-- | chip/npcx/lpc.c | 6 | ||||
-rw-r--r-- | chip/npcx/openocd/npcx_cmds.tcl | 41 | ||||
-rw-r--r-- | chip/npcx/peci.c | 6 | ||||
-rw-r--r-- | chip/npcx/pwm.c | 40 | ||||
-rw-r--r-- | chip/npcx/registers.h | 16 | ||||
-rw-r--r-- | chip/npcx/spi.c | 6 | ||||
-rw-r--r-- | chip/npcx/spiflashfw/ec_npcxflash.c | 47 | ||||
-rw-r--r-- | chip/npcx/system.c | 195 | ||||
-rw-r--r-- | chip/npcx/system_chip.h | 15 | ||||
-rw-r--r-- | chip/npcx/watchdog.c | 25 | ||||
-rw-r--r-- | common/system.c | 4 |
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 */ |