From c3cd10937e321f04c4b2dfc4786ec146e785e5cb Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Wed, 11 Feb 2015 11:12:58 -0800 Subject: WIP - Nuvoton 30-Jan patch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Randall Spangler Reviewed-on: https://chromium-review.googlesource.com/248670 --- board/npcx_evb/board.c | 30 ++++-- board/npcx_evb/board.h | 2 +- board/npcx_evb/gpio.inc | 10 +- chip/npcx/adc.c | 11 +- chip/npcx/build.mk | 2 +- chip/npcx/chip_temp_sensor.c | 32 ------ chip/npcx/clock.c | 2 +- chip/npcx/config_chip.h | 4 +- chip/npcx/fan.c | 25 +++-- chip/npcx/flash.c | 11 +- chip/npcx/gpio.c | 69 ++++++++++--- chip/npcx/i2c.c | 5 +- chip/npcx/keyboard_raw.c | 29 +++++- chip/npcx/lfw/ec_lfw.c | 29 ++---- chip/npcx/lpc.c | 6 +- chip/npcx/openocd/npcx_cmds.tcl | 41 +++++--- chip/npcx/peci.c | 6 ++ chip/npcx/pwm.c | 40 ++++---- chip/npcx/registers.h | 16 ++- chip/npcx/spi.c | 6 +- chip/npcx/spiflashfw/ec_npcxflash.c | 47 +++++---- chip/npcx/system.c | 195 +++++++++++++++++++++++++----------- chip/npcx/system_chip.h | 15 +++ chip/npcx/watchdog.c | 25 +++-- common/system.c | 4 +- 25 files changed, 419 insertions(+), 243 deletions(-) delete mode 100644 chip/npcx/chip_temp_sensor.c 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<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)<= 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 */ -- cgit v1.2.1