From 6a184d5019f0b45fe692da09a14e9ce7c853d68c Mon Sep 17 00:00:00 2001 From: "Hu, Hebo" Date: Fri, 8 Mar 2019 15:34:21 +0800 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/1510518 Commit-Ready: Rushikesh S Kadam Commit-Ready: Hebo Hu Tested-by: Jett Rink Reviewed-by: Jett Rink Reviewed-by: Hebo Hu --- core/minute-ia/init.S | 15 +++++++++++++++ core/minute-ia/interrupts.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ core/minute-ia/interrupts.h | 11 +++++++++++ 3 files changed, 72 insertions(+) (limited to 'core') 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 -- cgit v1.2.1