diff options
author | Hu, Hebo <hebo.hu@intel.com> | 2019-03-25 15:27:06 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-04-08 02:51:30 -0700 |
commit | 6beb629714ce05108399cefc621b098fc58f03ce (patch) | |
tree | 684dbf362a7f57f58e7d93939bdb555154d665f2 /chip | |
parent | 014b6c86dfd1aa9ec9ffaba2647d4ca89baf1ef4 (diff) | |
download | chrome-ec-6beb629714ce05108399cefc621b098fc58f03ce.tar.gz |
ish/ish5: implement reset, reset_prep and D3 flow
1: reset and reset_prep implemented
2: D3 flow implemented
BUG=b:122364080
BRANCH=none
TEST=tested on arcada
Change-Id: Ie6bacd89e2363578d85157dfb1dd8b56e2828d05
Signed-off-by: Hu, Hebo <hebo.hu@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/1536486
Commit-Ready: Hebo Hu <hebo.hu@intel.corp-partner.google.com>
Tested-by: Jett Rink <jettrink@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Reviewed-by: Hebo Hu <hebo.hu@intel.corp-partner.google.com>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/ish/aontaskfw/ish_aontask.c | 55 | ||||
-rw-r--r-- | chip/ish/build.mk | 1 | ||||
-rw-r--r-- | chip/ish/power_mgt.c | 193 | ||||
-rw-r--r-- | chip/ish/power_mgt.h | 39 | ||||
-rw-r--r-- | chip/ish/registers.h | 27 | ||||
-rw-r--r-- | chip/ish/reset_prep_wr.c | 51 | ||||
-rw-r--r-- | chip/ish/system.c | 13 |
7 files changed, 301 insertions, 78 deletions
diff --git a/chip/ish/aontaskfw/ish_aontask.c b/chip/ish/aontaskfw/ish_aontask.c index e9992ae904..3426622357 100644 --- a/chip/ish/aontaskfw/ish_aontask.c +++ b/chip/ish/aontaskfw/ish_aontask.c @@ -76,7 +76,7 @@ #define AON_IDT_ENTRY_VEC_LAST ISH_PMU_WAKEUP_VEC #endif -static void handle_reset(void); +static void handle_reset(int pm_state); /* ISR for PMU wakeup interrupt */ static void pmu_wakeup_isr(void) @@ -108,7 +108,7 @@ static void reset_prep_isr(void) REG32(IOAPIC_EOI_REG) = ISH_RESET_PREP_VEC; REG32(LAPIC_EOI_REG) = 0x0; - handle_reset(); + handle_reset(ISH_PM_STATE_RESET_PREP); __builtin_unreachable(); } @@ -488,7 +488,7 @@ static void handle_d0i2(void) /* delay some cycles before halt */ delay(SRAM_RETENTION_CYCLES_DELAY); - ish_halt(); + ish_mia_halt(); /* wakeup from PMU interrupt */ /* set main SRAM intto normal mode */ @@ -516,7 +516,7 @@ static void handle_d0i3(void) /* power off main SRAM */ sram_power(0); - ish_halt(); + ish_mia_halt(); /* wakeup from PMU interrupt */ /* power on main SRAM */ @@ -527,22 +527,43 @@ static void handle_d0i3(void) if (ret != AON_SUCCESS) { /* we can't switch back to main FW now, reset ISH */ - handle_reset(); + handle_reset(ISH_PM_STATE_RESET); } } static void handle_d3(void) { - /* TODO store main FW 's context to IMR DDR from main sram */ - /* TODO power off main SRAM */ - - /* TODO handle D3 */ + /* handle D3 */ + handle_reset(ISH_PM_STATE_RESET); } -static void handle_reset(void) +static void handle_reset(int pm_state) { - /* TODO power off main SRAM */ - /* TODO handle reset */ + /* disable CSME CSR irq */ + REG32(IPC_PIMR) &= ~IPC_PIMR_CSME_CSR_BIT; + + /* power off main SRAM */ + sram_power(0); + + while (1) { + + /* check if host ish driver already set the DMA enable flag */ + if (REG32(IPC_ISH_RMP2) & DMA_ENABLED_MASK) { + + /* clear ISH2HOST doorbell register */ + REG32(IPC_ISH2HOST_DOORBELL) = 0; + + /* clear error register in MISC space */ + MISC_ISH_ECC_ERR_SRESP = 1; + + /* reset ISH minute-ia cpu core, will goto ISH ROM */ + ish_mia_reset(); + } + + ish_mia_halt(); + } + + __builtin_unreachable(); } static void handle_unknown_state(void) @@ -600,14 +621,22 @@ void ish_aon_main(void) case ISH_PM_STATE_D3: handle_d3(); break; + case ISH_PM_STATE_RESET: case ISH_PM_STATE_RESET_PREP: - handle_reset(); + handle_reset(aon_share.pm_state); break; default: handle_unknown_state(); break; } + /* check if D3 rising status */ + if (PMU_D3_STATUS & + (PMU_D3_BIT_RISING_EDGE_STATUS | PMU_D3_BIT_SET)) { + aon_share.pm_state = ISH_PM_STATE_D3; + handle_d3(); + } + /* restore main FW's IDT and switch back to main FW */ __asm__ volatile( "lidtl %0;\n" diff --git a/chip/ish/build.mk b/chip/ish/build.mk index 20c0ad9e6b..4e7fdaa26a 100644 --- a/chip/ish/build.mk +++ b/chip/ish/build.mk @@ -18,7 +18,6 @@ endif # Required chip modules chip-y+=clock.o gpio.o system.o hwtimer.o uart.o flash.o -chip-y+=reset_prep_wr.o chip-$(CONFIG_I2C)+=i2c.o chip-$(CONFIG_WATCHDOG)+=watchdog.o chip-$(CONFIG_HOSTCMD_HECI)+=host_command_heci.o diff --git a/chip/ish/power_mgt.c b/chip/ish/power_mgt.c index 7cf2cdc383..4d2fe51ddd 100644 --- a/chip/ish/power_mgt.c +++ b/chip/ish/power_mgt.c @@ -228,6 +228,30 @@ static void switch_to_aontask(void) interrupt_enable(); } +__attribute__ ((noreturn)) +static void handle_reset_in_aontask(int pm_state) +{ + pm_ctx.aon_share->pm_state = pm_state; + + /* only enable PMU wakeup interrupt */ + disable_all_interrupts(); + task_enable_irq(ISH_PMU_WAKEUP_IRQ); + +#ifdef CONFIG_ISH_PM_RESET_PREP + task_enable_irq(ISH_RESET_PREP_IRQ); +#endif + + /* enable Trunk Clock Gating (TCG) of ISH */ + CCU_TCG_EN = 1; + + /* enable power gating of RF(Cache) and ROMs */ + PMU_RF_ROM_PWR_CTRL = 1; + + switch_to_aontask(); + + __builtin_unreachable(); +} + #endif static void enter_d0i0(void) @@ -239,7 +263,7 @@ static void enter_d0i0(void) pm_ctx.aon_share->pm_state = ISH_PM_STATE_D0I0; /* halt ISH cpu, will wakeup from any interrupt */ - ish_halt(); + ish_mia_halt(); t1 = get_time(); @@ -264,11 +288,15 @@ static void enter_d0i1(void) current_irq_map = disable_all_interrupts(); task_enable_irq(ISH_PMU_WAKEUP_IRQ); +#ifdef CONFIG_ISH_PM_RESET_PREP + task_enable_irq(ISH_RESET_PREP_IRQ); +#endif + /* enable Trunk Clock Gating (TCG) of ISH */ CCU_TCG_EN = 1; /* halt ISH cpu, will wakeup from PMU wakeup interrupt */ - ish_halt(); + ish_mia_halt(); /* disable Trunk Clock Gating (TCG) of ISH */ CCU_TCG_EN = 0; @@ -301,6 +329,10 @@ static void enter_d0i2(void) current_irq_map = disable_all_interrupts(); task_enable_irq(ISH_PMU_WAKEUP_IRQ); +#ifdef CONFIG_ISH_PM_RESET_PREP + task_enable_irq(ISH_RESET_PREP_IRQ); +#endif + /* enable Trunk Clock Gating (TCG) of ISH */ CCU_TCG_EN = 1; @@ -346,6 +378,10 @@ static void enter_d0i3(void) current_irq_map = disable_all_interrupts(); task_enable_irq(ISH_PMU_WAKEUP_IRQ); +#ifdef CONFIG_ISH_PM_RESET_PREP + task_enable_irq(ISH_RESET_PREP_IRQ); +#endif + /* enable Trunk Clock Gating (TCG) of ISH */ CCU_TCG_EN = 1; @@ -444,6 +480,15 @@ static void pm_process(uint32_t idle_us) void ish_pm_init(void) { + /* clear reset bit */ + ISH_RST_REG = 0; + + /* clear reset history register in CCU */ + CCU_RST_HST = CCU_RST_HST; + + /* disable TCG and disable BCG */ + CCU_TCG_EN = 0; + CCU_BCG_EN = 0; #ifdef CONFIG_ISH_PM_AONTASK init_aon_task(); @@ -451,6 +496,48 @@ void ish_pm_init(void) /* unmask all wake up events */ PMU_MASK_EVENT = ~PMU_MASK_EVENT_BIT_ALL; + +#ifdef CONFIG_ISH_PM_RESET_PREP + /* unmask reset prep avail interrupt */ + PMU_RST_PREP = 0; + + task_enable_irq(ISH_RESET_PREP_IRQ); +#endif + +#ifdef CONFIG_ISH_PM_D3 + + /* unmask D3 and BME interrupts */ + PMU_D3_STATUS &= (PMU_D3_BIT_SET | PMU_BME_BIT_SET); + + if ((!(PMU_D3_STATUS & PMU_D3_BIT_SET)) && + (PMU_D3_STATUS & PMU_BME_BIT_SET)) { + PMU_D3_STATUS = PMU_D3_STATUS; + } + + task_enable_irq(ISH_D3_RISE_IRQ); + task_enable_irq(ISH_D3_FALL_IRQ); + task_enable_irq(ISH_BME_RISE_IRQ); + task_enable_irq(ISH_BME_FALL_IRQ); + +#endif + +} + +__attribute__ ((noreturn)) +void ish_pm_reset(void) +{ + +#ifdef CONFIG_ISH_PM_AONTASK + if (pm_ctx.aon_valid) { + handle_reset_in_aontask(ISH_PM_STATE_RESET_PREP); + } else { + ish_mia_reset(); + } +#else + ish_mia_reset(); +#endif + + __builtin_unreachable(); } void __idle(void) @@ -535,3 +622,105 @@ static void pmu_wakeup_isr(void) DECLARE_IRQ(ISH_PMU_WAKEUP_IRQ, pmu_wakeup_isr); #endif + +#ifdef CONFIG_ISH_PM_RESET_PREP + +/** + * from ISH5.0, when system doing S0->Sx transition, will receive reset prep + * interrupt, will switch to aontask for handling + * + */ + +__attribute__ ((noreturn)) +static void reset_prep_isr(void) +{ + /* mask reset prep avail interrupt */ + PMU_RST_PREP = PMU_RST_PREP_INT_MASK; + + /** + * Indicate completion of servicing the interrupt to IOAPIC first + * then indicate completion of servicing the interrupt to LAPIC + */ + REG32(IOAPIC_EOI_REG) = ISH_RESET_PREP_VEC; + REG32(LAPIC_EOI_REG) = 0x0; + + if (pm_ctx.aon_valid) { + handle_reset_in_aontask(ISH_PM_STATE_RESET_PREP); + } else { + ish_mia_reset(); + } + + __builtin_unreachable(); +} + +DECLARE_IRQ(ISH_RESET_PREP_IRQ, reset_prep_isr); + +#endif + +#ifdef CONFIG_ISH_PM_D3 + +static void handle_d3(uint32_t irq_vec) +{ + PMU_D3_STATUS = PMU_D3_STATUS; + + if (PMU_D3_STATUS & (PMU_D3_BIT_RISING_EDGE_STATUS | PMU_D3_BIT_SET)) { + + if (!pm_ctx.aon_valid) + ish_mia_reset(); + + /** + * Indicate completion of servicing the interrupt to IOAPIC + * first then indicate completion of servicing the interrupt + * to LAPIC + */ + REG32(IOAPIC_EOI_REG) = irq_vec; + REG32(LAPIC_EOI_REG) = 0x0; + + pm_ctx.aon_share->pm_state = ISH_PM_STATE_D3; + + /* only enable PMU wakeup interrupt */ + disable_all_interrupts(); + task_enable_irq(ISH_PMU_WAKEUP_IRQ); + +#ifdef CONFIG_ISH_PM_RESET_PREP + task_enable_irq(ISH_RESET_PREP_IRQ); +#endif + + /* enable Trunk Clock Gating (TCG) of ISH */ + CCU_TCG_EN = 1; + + /* enable power gating of RF(Cache) and ROMs */ + PMU_RF_ROM_PWR_CTRL = 1; + + switch_to_aontask(); + + __builtin_unreachable(); + } +} + +static void d3_rise_isr(void) +{ + handle_d3(ISH_D3_RISE_VEC); +} + +static void d3_fall_isr(void) +{ + handle_d3(ISH_D3_FALL_VEC); +} + +static void bme_rise_isr(void) +{ + handle_d3(ISH_BME_RISE_VEC); +} + +static void bme_fall_isr(void) +{ + handle_d3(ISH_BME_FALL_VEC); +} + +DECLARE_IRQ(ISH_D3_RISE_IRQ, d3_rise_isr); +DECLARE_IRQ(ISH_D3_FALL_IRQ, d3_fall_isr); +DECLARE_IRQ(ISH_BME_RISE_IRQ, bme_rise_isr); +DECLARE_IRQ(ISH_BME_FALL_IRQ, bme_fall_isr); + +#endif diff --git a/chip/ish/power_mgt.h b/chip/ish/power_mgt.h index fe0c1b4539..2921e0534e 100644 --- a/chip/ish/power_mgt.h +++ b/chip/ish/power_mgt.h @@ -18,26 +18,55 @@ enum { ISH_PM_STATE_D0I2, /* deep sleep state 3: TCG, SRAM power off, cpu halt*/ ISH_PM_STATE_D0I3, - /* D3 state: power off state, on ISH5.0, can't do real power off, + /** + * D3 state: power off state, on ISH5.0, can't do real power off, * similar to D0I3, but will reset ISH */ ISH_PM_STATE_D3, - /* ISH received reset_prep interrupt during S0->Sx transition */ + /** + * reset ISH, main FW received 'reboot' command + */ + ISH_PM_STATE_RESET, + /** + * reset ISH, main FW received reset_prep interrupt during + * S0->Sx transition. + */ ISH_PM_STATE_RESET_PREP, ISH_PM_STATE_NUM }; -/* halt ISH cpu */ -static inline void ish_halt(void) +/* halt ISH minute-ia cpu core */ +static inline void ish_mia_halt(void) { /* make sure interrupts are enabled before halting */ __asm__ volatile("sti;\n" "hlt;"); } -/* ish low power management initialization, +/* reset ISH mintue-ia cpu core */ +__attribute__((noreturn)) +static inline void ish_mia_reset(void) +{ + /** + * ISH HW looks at the rising edge of this bit to + * trigger a MIA reset. + */ + ISH_RST_REG = 0; + ISH_RST_REG = 1; + + __builtin_unreachable(); +} + + +/** + * ish low power management initialization, * should be called at system init stage before RTOS task scheduling start */ void ish_pm_init(void); +/** + * reset ISH (reset minute-ia cpu core, and power off main SRAM) + */ +void ish_pm_reset(void) __attribute__((noreturn)); + #endif /* __CROS_EC_POWER_MGT_H */ diff --git a/chip/ish/registers.h b/chip/ish/registers.h index fad24b7778..f6e1a292fa 100644 --- a/chip/ish/registers.h +++ b/chip/ish/registers.h @@ -58,11 +58,15 @@ enum ish_i2c_port { #define ISH_HPET_TIMER1_IRQ 8 #define ISH_HPET_TIMER2_IRQ 11 #define ISH_IPC_HOST2ISH_IRQ 12 +#define ISH_PMU_WAKEUP_IRQ 18 +#define ISH_D3_RISE_IRQ 19 +#define ISH_D3_FALL_IRQ 29 +#define ISH_BME_RISE_IRQ 50 +#define ISH_BME_FALL_IRQ 51 #define ISH_IPC_ISH2HOST_CLR_IRQ 24 #define ISH_UART0_IRQ 34 #define ISH_UART1_IRQ 35 #define ISH_RESET_PREP_IRQ 62 -#define ISH_PMU_WAKEUP_IRQ 18 /* Interrupt vectors 0-31 are architecture reserved. * Vectors 32-255 are user-defined. @@ -107,6 +111,10 @@ enum ish_i2c_port { #define ISH_IPC_VEC IRQ_TO_VEC(ISH_IPC_HOST2ISH_IRQ) #define ISH_RESET_PREP_VEC IRQ_TO_VEC(ISH_RESET_PREP_IRQ) #define ISH_PMU_WAKEUP_VEC IRQ_TO_VEC(ISH_PMU_WAKEUP_IRQ) +#define ISH_D3_RISE_VEC IRQ_TO_VEC(ISH_D3_RISE_IRQ) +#define ISH_D3_FALL_VEC IRQ_TO_VEC(ISH_D3_FALL_IRQ) +#define ISH_BME_RISE_VEC IRQ_TO_VEC(ISH_BME_RISE_IRQ) +#define ISH_BME_FALL_VEC IRQ_TO_VEC(ISH_BME_FALL_IRQ) #ifdef CONFIG_ISH_UART_0 #define ISH_DEBUG_UART UART_PORT_0 @@ -121,6 +129,7 @@ enum ish_i2c_port { /* IPC_Registers */ #define IPC_PISR (ISH_IPC_BASE + 0x0) #define IPC_PIMR (ISH_IPC_BASE + 0x4) +#define IPC_PIMR_CSME_CSR_BIT (0x1 << 23) #define IPC_ISH2HOST_MSG_REGS (ISH_IPC_BASE + 0x60) #define IPC_ISH_FWSTS (ISH_IPC_BASE + 0x34) #define IPC_HOST2ISH_DOORBELL (ISH_IPC_BASE + 0x48) @@ -128,6 +137,10 @@ enum ish_i2c_port { #define IPC_ISH2HOST_DOORBELL (ISH_IPC_BASE + 0x54) #define IPC_ISH2PMC_DOORBELL (ISH_IPC_BASE + 0x58) #define IPC_ISH2PMC_MSG_REGS (ISH_IPC_BASE + 0x260) +#define IPC_ISH_RMP0 (ISH_IPC_BASE + 0x360) +#define IPC_ISH_RMP1 (ISH_IPC_BASE + 0x364) +#define IPC_ISH_RMP2 (ISH_IPC_BASE + 0x368) +#define DMA_ENABLED_MASK (0x1 << 0) #define IPC_BUSY_CLEAR (ISH_IPC_BASE + 0x378) #define IPC_UMA_RANGE_LOWER_0 REG32(ISH_IPC_BASE + 0x380) #define IPC_UMA_RANGE_LOWER_1 REG32(ISH_IPC_BASE + 0x384) @@ -136,6 +149,17 @@ enum ish_i2c_port { /* PMU Registers */ #define PMU_SRAM_PG_EN REG32(ISH_PMU_BASE + 0x0) +#define PMU_D3_STATUS REG32(ISH_PMU_BASE + 0x4) +#define PMU_D3_BIT_SET (0x1 << 0) +#define PMU_D3_BIT_RISING_EDGE_STATUS (0x1 << 1) +#define PMU_D3_BIT_FALLING_EDGE_STATUS (0x1 << 2) +#define PMU_D3_BIT_RISING_EDGE_MASK (0x1 << 3) +#define PMU_D3_BIT_FALLING_EDGE_MASK (0x1 << 4) +#define PMU_BME_BIT_SET (0x1 << 5) +#define PMU_BME_BIT_RISING_EDGE_STATUS (0x1 << 6) +#define PMU_BME_BIT_FALLING_EDGE_STATUS (0x1 << 7) +#define PMU_BME_BIT_RISING_EDGE_MASK (0x1 << 8) +#define PMU_BME_BIT_FALLING_EDGE_MASK (0x1 << 9) #define PMU_VNN_REQ REG32(ISH_PMU_BASE + 0x3c) #define VNN_REQ_IPC_HOST_WRITE BIT(3) /* Power for IPC host write */ @@ -161,6 +185,7 @@ enum ish_i2c_port { #define MISC_DMA_CTL_REG(ch) REG32(MISC_REG_BASE + (4 * (ch))) #define MISC_SRC_FILLIN_DMA(ch) REG32(MISC_REG_BASE + 0x20 + (4 * (ch))) #define MISC_DST_FILLIN_DMA(ch) REG32(MISC_REG_BASE + 0x80 + (4 * (ch))) +#define MISC_ISH_ECC_ERR_SRESP REG32(MISC_REG_BASE + 0x94) /* DMA registers */ #define DMA_REG_BASE ISH_DMA_BASE diff --git a/chip/ish/reset_prep_wr.c b/chip/ish/reset_prep_wr.c deleted file mode 100644 index c6524b9f49..0000000000 --- a/chip/ish/reset_prep_wr.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright 2019 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. - */ - -/* Power managerment module for ISH */ -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "interrupts.h" -#include "registers.h" -#include "system.h" -#include "task.h" - -#ifdef PM_DEBUG -#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#else -#define CPUTS(outstr) -#define CPRINTS(format, args...) -#define CPRINTF(format, args...) -#endif - -/* - * IRQ fires when we receive a RESET_PREP message from AP. This happens at S0 - * entry. - */ -static void reset_prep_wr_isr(void) -{ - system_reset(SYSTEM_RESET_HARD); -} -DECLARE_IRQ(ISH_RESET_PREP_IRQ, reset_prep_wr_isr); - -void reset_prep_init(void) -{ - /* Clear reset bit */ - ISH_RST_REG = 0; - - /* Clear reset history register from previous boot. */ - CCU_RST_HST = CCU_RST_HST; - /* Unmask reset prep avail interrupt mask */ - PMU_RST_PREP = 0; - /* Clear TCG Enable, no trunk level clock gating*/ - CCU_TCG_ENABLE = 0; - /* Clear BCG Enable, no block level clock gating*/ - CCU_BCG_ENABLE = 0; - - task_enable_irq(ISH_RESET_PREP_IRQ); -} -DECLARE_HOOK(HOOK_INIT, reset_prep_init, HOOK_PRIO_DEFAULT); diff --git a/chip/ish/system.c b/chip/ish/system.c index fad46aa5cc..6c6ce75828 100644 --- a/chip/ish/system.c +++ b/chip/ish/system.c @@ -50,12 +50,15 @@ uint32_t chip_read_reset_flags(void) void _system_reset(int flags, int wake_from_hibernate) { - /* - * ISH HW looks at the rising edge of this bit to - * trigger a MIA reset. +#ifdef CONFIG_LOW_POWER_IDLE + /** + * ish_pm_reset() do more (poweroff main SRAM etc) than + * ish_mia_reset() which just reset the ISH minute-ia cpu core */ - ISH_RST_REG = 0; - ISH_RST_REG = 1; + ish_pm_reset(); +#else + ish_mia_reset(); +#endif } void system_reset(int flags) |