1 /*
2 * Copyright (c) 2019 Microchip Technology Inc.
3 * Copyright (c) 2016 Intel Corporation.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr.h>
9 #include <sys/sys_io.h>
10 #include <sys/__assert.h>
11 #include <pm/pm.h>
12 #include <soc.h>
13
14 /*
15 * CPU will spin up to DEEP_SLEEP_WAIT_SPIN_CLK_REQ times
16 * waiting for PCR CLK_REQ bits to clear except for the
17 * CPU bit itself. This is not necessary as the sleep hardware
18 * will wait for all CLK_REQ to clear once WFI has executed.
19 * Once all CLK_REQ signals are clear the hardware will transition
20 * to the low power state.
21 */
22 /* #define DEEP_SLEEP_WAIT_ON_CLK_REQ_ENABLE */
23 #define DEEP_SLEEP_WAIT_SPIN_CLK_REQ 1000
24
25
26 /*
27 * Some peripherals if enabled always assert their CLK_REQ bits.
28 * For example, any peripheral with a clock generator such as
29 * timers, counters, UART, etc. We save the enables for these
30 * peripherals, disable them, and restore the enabled state upon
31 * wake.
32 */
33 #define DEEP_SLEEP_PERIPH_SAVE_RESTORE
34
35
36 /*
37 * Light sleep: PLL remains on. Fastest wake latency.
38 */
soc_lite_sleep_enable(void)39 void soc_lite_sleep_enable(void)
40 {
41 SCB->SCR &= ~(1ul << 2);
42 PCR_REGS->SYS_SLP_CTRL = MCHP_PCR_SYS_SLP_LIGHT;
43 }
44
45 /*
46 * Deep sleep: PLL is turned off. Wake is fast. PLL requires
47 * a minimum of 3ms to lock. During this time the main clock
48 * will be ramping up from ~16 to 24 MHz.
49 */
soc_deep_sleep_enable(void)50 void soc_deep_sleep_enable(void)
51 {
52 SCB->SCR = (1ul << 2); /* Cortex-M4 SLEEPDEEP */
53 PCR_REGS->SYS_SLP_CTRL = MCHP_PCR_SYS_SLP_HEAVY;
54 }
55
56 /*
57 * Clear PCR Sleep control sleep all causing HW to de-assert all peripheral
58 * SLP_EN signals. HW will does this automatically only if it vectors to an
59 * ISR after wake. We are masking ISR's from running until we restore
60 * peripheral state therefore we force HW to de-assert the SLP_EN signals.
61 */
soc_deep_sleep_disable(void)62 void soc_deep_sleep_disable(void)
63 {
64 PCR_REGS->SYS_SLP_CTRL = 0U;
65 SCB->SCR &= ~(1ul << 2); /* disable Cortex-M4 SLEEPDEEP */
66 }
67
68
soc_deep_sleep_wait_clk_idle(void)69 void soc_deep_sleep_wait_clk_idle(void)
70 {
71 #ifdef DEEP_SLEEP_WAIT_ON_CLK_REQ_ENABLE
72 uint32_t clkreq, cnt;
73
74 cnt = DEEP_SLEEP_WAIT_CLK_REQ;
75 do {
76 clkreq = PCR_REGS->CLK_REQ0 | PCR_REGS->CLK_REQ1
77 | PCR_REGS->CLK_REQ2 | PCR_REGS->CLK_REQ3
78 | PCR_REGS->CLK_REQ4;
79 } while ((clkreq != (1ul << MCHP_PCR1_CPU_POS)) && (cnt-- != 0));
80 #endif
81 }
82
83
84 /*
85 * Allow peripherals connected to external masters to wake the PLL but not
86 * the EC. Once the peripheral has serviced the external master the PLL
87 * will be turned back off. For example, if the eSPI master requests eSPI
88 * configuration information or state of virtual wires the EC doesn't need
89 * to be involved. The hardware can power on the PLL long enough to service
90 * the request and then turn the PLL back off. The SMBus and I2C peripherals
91 * in slave mode can also make use of this feature.
92 */
soc_deep_sleep_non_wake_en(void)93 void soc_deep_sleep_non_wake_en(void)
94 {
95 #ifdef CONFIG_ESPI_XEC
96 GIRQ22_REGS->SRC = 0xfffffffful;
97 GIRQ22_REGS->EN_SET = (1ul << 9);
98 #endif
99 }
100
soc_deep_sleep_non_wake_dis(void)101 void soc_deep_sleep_non_wake_dis(void)
102 {
103 #ifdef CONFIG_ESPI_XEC
104 GIRQ22_REGS->EN_CLR = 0xfffffffful;
105 GIRQ22_REGS->SRC = 0xfffffffful;
106 #endif
107 }
108
109 /* Variables used to save various HW state */
110 #ifdef DEEP_SLEEP_PERIPH_SAVE_RESTORE
111
112 static uint32_t ecs[1];
113
deep_sleep_save_ecs(void)114 static void deep_sleep_save_ecs(void)
115 {
116 ecs[0] = ECS_REGS->ETM_CTRL;
117 ECS_REGS->ETM_CTRL = 0;
118 }
119
120 struct ds_timer_info {
121 uintptr_t addr;
122 uint32_t restore_mask;
123 };
124
125 const struct ds_timer_info ds_timer_tbl[] = {
126 {
127 (uintptr_t)&B16TMR0_REGS->CTRL, 0
128 },
129 {
130 (uintptr_t)&B16TMR1_REGS->CTRL, 0
131 },
132 {
133 (uintptr_t)&B32TMR0_REGS->CTRL, 0
134 },
135 {
136 (uintptr_t)&B32TMR1_REGS->CTRL, 0
137 },
138 {
139 (uintptr_t)&CCT_REGS->CTRL,
140 (MCHP_CCT_CTRL_COMP1_SET | MCHP_CCT_CTRL_COMP0_SET),
141 },
142 };
143 #define NUM_DS_TIMER_ENTRIES \
144 (sizeof(ds_timer_tbl) / sizeof(struct ds_timer_info))
145
146
147 static uint32_t timers[NUM_DS_TIMER_ENTRIES];
148 static uint8_t uart_activate[3];
149
deep_sleep_save_uarts(void)150 static void deep_sleep_save_uarts(void)
151 {
152 uart_activate[0] = UART0_REGS->ACTV;
153 if (uart_activate[0]) {
154 while ((UART0_REGS->LSR & MCHP_UART_LSR_TEMT) == 0) {
155 }
156 }
157 UART0_REGS->ACTV = 0;
158 uart_activate[1] = UART1_REGS->ACTV;
159 if (uart_activate[1]) {
160 while ((UART1_REGS->LSR & MCHP_UART_LSR_TEMT) == 0) {
161 }
162 }
163 UART1_REGS->ACTV = 0;
164 uart_activate[2] = UART2_REGS->ACTV;
165 if (uart_activate[2]) {
166 while ((UART2_REGS->LSR & MCHP_UART_LSR_TEMT) == 0) {
167 }
168 }
169 UART2_REGS->ACTV = 0;
170 }
171
deep_sleep_save_timers(void)172 static void deep_sleep_save_timers(void)
173 {
174 const struct ds_timer_info *p;
175 uint32_t i;
176
177 p = &ds_timer_tbl[0];
178 for (i = 0; i < NUM_DS_TIMER_ENTRIES; i++) {
179 timers[i] = REG32(p->addr);
180 REG32(p->addr) = 0;
181 p++;
182 }
183 }
184
deep_sleep_restore_ecs(void)185 static void deep_sleep_restore_ecs(void)
186 {
187 ECS_REGS->ETM_CTRL = ecs[0];
188 }
189
deep_sleep_restore_uarts(void)190 static void deep_sleep_restore_uarts(void)
191 {
192 UART0_REGS->ACTV = uart_activate[0];
193 UART1_REGS->ACTV = uart_activate[1];
194 UART2_REGS->ACTV = uart_activate[2];
195 }
196
deep_sleep_restore_timers(void)197 static void deep_sleep_restore_timers(void)
198 {
199 const struct ds_timer_info *p;
200 uint32_t i;
201
202 p = &ds_timer_tbl[0];
203 for (i = 0; i < NUM_DS_TIMER_ENTRIES; i++) {
204 REG32(p->addr) = timers[i] & ~p->restore_mask;
205 p++;
206 }
207 }
208
soc_deep_sleep_periph_save(void)209 void soc_deep_sleep_periph_save(void)
210 {
211 deep_sleep_save_uarts();
212 deep_sleep_save_ecs();
213 deep_sleep_save_timers();
214 }
215
soc_deep_sleep_periph_restore(void)216 void soc_deep_sleep_periph_restore(void)
217 {
218 deep_sleep_restore_ecs();
219 deep_sleep_restore_uarts();
220 deep_sleep_restore_timers();
221 }
222
223 #else
224
soc_deep_sleep_periph_save(void)225 void soc_deep_sleep_periph_save(void)
226 {
227 }
228
soc_deep_sleep_periph_restore(void)229 void soc_deep_sleep_periph_restore(void)
230 {
231 }
232
233 #endif /* DEEP_SLEEP_PERIPH_SAVE_RESTORE */
234