diff options
-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 */ |