diff --git a/drivers/interrupt_controller/intc_ite_it8xxx2.c b/drivers/interrupt_controller/intc_ite_it8xxx2.c index bc8379dbfe4e..ab73c86ee763 100644 --- a/drivers/interrupt_controller/intc_ite_it8xxx2.c +++ b/drivers/interrupt_controller/intc_ite_it8xxx2.c @@ -179,6 +179,11 @@ uint8_t ite_intc_get_irq_num(void) return intc_irq; } +bool ite_intc_no_irq(void) +{ + return (IVECT == IVECT_OFFSET_WITH_IRQ); +} + uint8_t get_irq(void *arg) { ARG_UNUSED(arg); @@ -197,8 +202,6 @@ uint8_t get_irq(void *arg) intc_irq -= IVECT_OFFSET_WITH_IRQ; /* clear interrupt status */ ite_intc_isr_clear(intc_irq); - /* Clear flag on each interrupt. */ - wait_interrupt_fired = 0; /* return interrupt number */ return intc_irq; } diff --git a/drivers/interrupt_controller/intc_ite_it8xxx2.h b/drivers/interrupt_controller/intc_ite_it8xxx2.h index d64ed93fc864..8cef428b9e24 100644 --- a/drivers/interrupt_controller/intc_ite_it8xxx2.h +++ b/drivers/interrupt_controller/intc_ite_it8xxx2.h @@ -9,7 +9,4 @@ #include #include -/* use data type int here not bool to get better instruction number. */ -volatile int wait_interrupt_fired; - #endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_ITE_IT8XXX2_H_ */ diff --git a/soc/riscv/riscv-ite/common/soc_common.h b/soc/riscv/riscv-ite/common/soc_common.h index 55f106143118..4b35f6964690 100644 --- a/soc/riscv/riscv-ite/common/soc_common.h +++ b/soc/riscv/riscv-ite/common/soc_common.h @@ -46,6 +46,7 @@ extern int ite_intc_irq_is_enable(unsigned int irq); extern void ite_intc_irq_polarity_set(unsigned int irq, unsigned int flags); extern void ite_intc_isr_clear(unsigned int irq); void ite_intc_init(void); +bool ite_intc_no_irq(void); #endif /* CONFIG_ITE_IT8XXX2_INTC */ #ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M diff --git a/soc/riscv/riscv-ite/it8xxx2/soc.c b/soc/riscv/riscv-ite/it8xxx2/soc.c index d5564da831ca..d12197874992 100644 --- a/soc/riscv/riscv-ite/it8xxx2/soc.c +++ b/soc/riscv/riscv-ite/it8xxx2/soc.c @@ -176,36 +176,40 @@ BUILD_ASSERT(CONFIG_FLASH_INIT_PRIORITY < CONFIG_IT8XXX2_PLL_SEQUENCE_PRIORITY, "CONFIG_FLASH_INIT_PRIORITY must be less than CONFIG_IT8XXX2_PLL_SEQUENCE_PRIORITY"); #endif /* CONFIG_SOC_IT8XXX2_PLL_FLASH_48M */ -extern volatile int wait_interrupt_fired; - +/* The routine must be called with interrupts locked */ void riscv_idle(enum chip_pll_mode mode, unsigned int key) { - /* Disable M-mode external interrupt */ + /* + * The routine is called with interrupts locked (in kernel/idle()). + * But on kernel/context test_kernel_cpu_idle test, the routine will be + * called without interrupts locked. Hence we disable M-mode external + * interrupt here to protect the below content. + */ csr_clear(mie, MIP_MEIP); - sys_trace_idle(); /* Chip doze after wfi instruction */ chip_pll_ctrl(mode); - /* Set flag before entering low power mode. */ - wait_interrupt_fired = 1; - /* unlock interrupts */ - irq_unlock(key); - /* Wait for interrupt */ - __asm__ volatile ("wfi"); - /* Enable M-mode external interrupt */ - csr_set(mie, MIP_MEIP); + do { + /* Wait for interrupt */ + __asm__ volatile ("wfi"); + /* + * Sometimes wfi instruction may fail due to CPU's MTIP@mip + * register is non-zero. + * If the ite_intc_no_irq() is true at this point, + * it means that EC waked-up by the above issue not an + * interrupt. Hence we loop running wfi instruction here until + * wfi success. + */ + } while (ite_intc_no_irq()); + /* - * Sometimes wfi instruction may fail due to CPU's MTIP@mip - * register is non-zero. - * If the wait_interrupt_fired flag is true at this point, - * it means that EC waked-up by the above issue not an - * interrupt. Hence we loop running wfi instruction here until - * wfi success. + * Enable M-mode external interrupt + * An interrupt can not be fired yet until we enable global interrupt */ - while (wait_interrupt_fired) { - __asm__ volatile ("wfi"); - } + csr_set(mie, MIP_MEIP); + /* Restore global interrupt lockout state */ + irq_unlock(key); } void arch_cpu_idle(void)