diff options
author | Hu, Hebo <hebo.hu@intel.com> | 2019-03-08 15:34:21 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-04-08 02:51:29 -0700 |
commit | 6a184d5019f0b45fe692da09a14e9ce7c853d68c (patch) | |
tree | 541192356148342f09bacebb75bea95027e98e7d /core | |
parent | d0a350e6691a9d93138051e2aa00e0d6c26151b5 (diff) | |
download | chrome-ec-6a184d5019f0b45fe692da09a14e9ce7c853d68c.tar.gz |
ish/ish5: implement AON low power management framework
AON PM framework including:
1: AON task skeleton
2: task switching between main FW and AON task
3: 'idlestats' console command for D0ix statistic information
4: D0ix entrance in idle task
BUG=b:122364080
BRANCH=none
TEST=tested on arcada
Change-Id: Iefa9e067892d5c42d9f0c795275fe88e5a36115b
Signed-off-by: Hu, Hebo <hebo.hu@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/1510518
Commit-Ready: Rushikesh S Kadam <rushikesh.s.kadam@intel.com>
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 'core')
-rw-r--r-- | core/minute-ia/init.S | 15 | ||||
-rw-r--r-- | core/minute-ia/interrupts.c | 46 | ||||
-rw-r--r-- | core/minute-ia/interrupts.h | 11 |
3 files changed, 72 insertions, 0 deletions
diff --git a/core/minute-ia/init.S b/core/minute-ia/init.S index 8a5ec8e4e2..66154b2c19 100644 --- a/core/minute-ia/init.S +++ b/core/minute-ia/init.S @@ -14,6 +14,8 @@ .global __idt +.global __gdt +.global __gdt_ptr # GDT is loaded by ISH ROM. The FW code retains the same GDT # and hence the same segment selector @@ -307,6 +309,19 @@ __gdt: # Flags: 0x93 (Data R/W, Present, DPL0, Acessed=1) .long GEN_GDT_DESC_LO(0x0, 0xffffffff, GDT_DESC_DATA_FLAGS) .long GEN_GDT_DESC_UP(0x0, 0xffffffff, GDT_DESC_DATA_FLAGS) +#if defined(CONFIG_ISH_PM_AONTASK) + # placeholder entries, will be updated by init_aon_task() + # in power_mgt.c + # Entry 3: placeholder TSS descriptor for main FW + .long 0x0 + .long 0x0 + # Entry 4: placeholder TSS descriptor for aontask + .long 0x0 + .long 0x0 + # Entry 5: placeholder LDT descriptor for aontask + .long 0x0 + .long 0x0 +#endif #.section .data __idt_ptr: diff --git a/core/minute-ia/interrupts.c b/core/minute-ia/interrupts.c index 07ee42713e..36cb77c820 100644 --- a/core/minute-ia/interrupts.c +++ b/core/minute-ia/interrupts.c @@ -46,6 +46,46 @@ void set_ioapic_redtbl_raw(const unsigned irq, const uint32_t val) write_ioapic_reg(redtbl_hi, DEST_APIC_ID); } +/** + * bitmap for current IRQ's mask status + * ISH support max 64 IRQs, 64 bit bitmap value is ok + */ +#define ISH_MAX_IOAPIC_IRQS (64) +uint64_t ioapic_irq_mask_bitmap; + +/** + * disable current all enabled intrrupts + * return current irq mask bitmap + * power management typically use 'disable_all_interrupts' to disable current + * all interrupts and save current interrupts enabling settings before enter + * low power state, and use 'restore_interrupts' to restore the interrupts + * settings after exit low power state. + */ +uint64_t disable_all_interrupts(void) +{ + uint64_t saved_map; + int i; + + saved_map = ioapic_irq_mask_bitmap; + + for (i = 0; i < ISH_MAX_IOAPIC_IRQS; i++) { + if (((uint64_t)0x1 << i) & saved_map) + mask_interrupt(i); + } + + return saved_map; +} + +void restore_interrupts(uint64_t irq_map) +{ + int i; + + for (i = 0; i < ISH_MAX_IOAPIC_IRQS; i++) { + if (((uint64_t)0x1 << i) & irq_map) + unmask_interrupt(i); + } +} + /* * Get lower 32bit of IOAPIC redirection table entry. * @@ -75,6 +115,7 @@ void unmask_interrupt(uint32_t irq) val = read_ioapic_reg(redtbl_lo); val &= ~IOAPIC_REDTBL_MASK; set_ioapic_redtbl_raw(irq, val); + ioapic_irq_mask_bitmap |= ((uint64_t)0x1) << irq; } void mask_interrupt(uint32_t irq) @@ -85,6 +126,8 @@ void mask_interrupt(uint32_t irq) val = read_ioapic_reg(redtbl_lo); val |= IOAPIC_REDTBL_MASK; set_ioapic_redtbl_raw(irq, val); + + ioapic_irq_mask_bitmap &= ~(((uint64_t)0x1) << irq); } /* Maps IRQs to vectors. To be programmed in IOAPIC redirection table */ @@ -100,6 +143,9 @@ static const irq_desc_t system_irqs[] = { LEVEL_INTR(ISH_HPET_TIMER1_IRQ, ISH_HPET_TIMER1_VEC), LEVEL_INTR(ISH_DEBUG_UART_IRQ, ISH_DEBUG_UART_VEC), LEVEL_INTR(ISH_RESET_PREP_IRQ, ISH_RESET_PREP_VEC), +#ifdef CONFIG_ISH_PM_D0I1 + LEVEL_INTR(ISH_PMU_WAKEUP_IRQ, ISH_PMU_WAKEUP_VEC), +#endif }; /** diff --git a/core/minute-ia/interrupts.h b/core/minute-ia/interrupts.h index 1a5e44d1ee..3a951a5ddb 100644 --- a/core/minute-ia/interrupts.h +++ b/core/minute-ia/interrupts.h @@ -51,6 +51,17 @@ void init_interrupts(void); void mask_interrupt(unsigned int irq); void unmask_interrupt(unsigned int irq); +/** + * disable current all enabled intrrupts + * return current irq mask bitmap + * power management typically use 'disable_all_interrupts' to disable current + * all interrupts and save current interrupts enabling settings before enter + * low power state, and use 'restore_interrupts' to restore the interrupts + * settings after exit low power state. + */ +uint64_t disable_all_interrupts(void); +void restore_interrupts(uint64_t irq_map); + /* Only call in interrupt context */ uint32_t get_current_interrupt_vector(void); #endif |