summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorHu, Hebo <hebo.hu@intel.com>2019-03-08 15:34:21 +0800
committerchrome-bot <chrome-bot@chromium.org>2019-04-08 02:51:29 -0700
commit6a184d5019f0b45fe692da09a14e9ce7c853d68c (patch)
tree541192356148342f09bacebb75bea95027e98e7d /core
parentd0a350e6691a9d93138051e2aa00e0d6c26151b5 (diff)
downloadchrome-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.S15
-rw-r--r--core/minute-ia/interrupts.c46
-rw-r--r--core/minute-ia/interrupts.h11
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