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