|
5 | 5 | * |
6 | 6 | */ |
7 | 7 |
|
| 8 | +#include <arch/riscv/csr.h> |
8 | 9 | #include <kernel.h> |
9 | 10 | #include <device.h> |
10 | 11 | #include <init.h> |
@@ -51,9 +52,15 @@ static const struct pll_config_t pll_configuration[] = { |
51 | 52 |
|
52 | 53 | void __intc_ram_code chip_pll_ctrl(enum chip_pll_mode mode) |
53 | 54 | { |
| 55 | + volatile uint8_t _pll_ctrl __unused; |
| 56 | + |
54 | 57 | IT8XXX2_ECPM_PLLCTRL = mode; |
55 | | - /* for deep doze / sleep mode */ |
56 | | - IT8XXX2_ECPM_PLLCTRL = mode; |
| 58 | + /* |
| 59 | + * for deep doze / sleep mode |
| 60 | + * This load operation will ensure PLL setting is taken into |
| 61 | + * control register before wait for interrupt instruction. |
| 62 | + */ |
| 63 | + _pll_ctrl = IT8XXX2_ECPM_PLLCTRL; |
57 | 64 | } |
58 | 65 |
|
59 | 66 | void __intc_ram_code chip_run_pll_sequence(const struct pll_config_t *pll) |
@@ -132,6 +139,48 @@ static int chip_change_pll(const struct device *dev) |
132 | 139 | SYS_INIT(chip_change_pll, POST_KERNEL, 0); |
133 | 140 | #endif /* CONFIG_SOC_IT8XXX2_PLL_FLASH_48M */ |
134 | 141 |
|
| 142 | +extern volatile int wait_interrupt_fired; |
| 143 | + |
| 144 | +static ALWAYS_INLINE void riscv_idle(unsigned int key) |
| 145 | +{ |
| 146 | + /* Disable M-mode external interrupt */ |
| 147 | + csr_clear(mie, MIP_MEIP); |
| 148 | + |
| 149 | + sys_trace_idle(); |
| 150 | + /* Chip doze after wfi instruction */ |
| 151 | + chip_pll_ctrl(CHIP_PLL_DOZE); |
| 152 | + /* Set flag before entering low power mode. */ |
| 153 | + wait_interrupt_fired = 1; |
| 154 | + /* unlock interrupts */ |
| 155 | + irq_unlock(key); |
| 156 | + /* Wait for interrupt */ |
| 157 | + __asm__ volatile ("wfi"); |
| 158 | + |
| 159 | + /* Enable M-mode external interrupt */ |
| 160 | + csr_set(mie, MIP_MEIP); |
| 161 | + /* |
| 162 | + * Sometimes wfi instruction may fail due to CPU's MTIP@mip |
| 163 | + * register is non-zero. |
| 164 | + * If the wait_interrupt_fired flag is true at this point, |
| 165 | + * it means that EC waked-up by the above issue not an |
| 166 | + * interrupt. Hence we loop running wfi instruction here until |
| 167 | + * wfi success. |
| 168 | + */ |
| 169 | + while (wait_interrupt_fired) { |
| 170 | + __asm__ volatile ("wfi"); |
| 171 | + } |
| 172 | +} |
| 173 | + |
| 174 | +void arch_cpu_idle(void) |
| 175 | +{ |
| 176 | + riscv_idle(MSTATUS_IEN); |
| 177 | +} |
| 178 | + |
| 179 | +void arch_cpu_atomic_idle(unsigned int key) |
| 180 | +{ |
| 181 | + riscv_idle(key); |
| 182 | +} |
| 183 | + |
135 | 184 | static int ite_it8xxx2_init(const struct device *arg) |
136 | 185 | { |
137 | 186 | ARG_UNUSED(arg); |
|
0 commit comments