xref: /rk3399_ARM-atf/plat/imx/imx8ulp/apd_context.c (revision 1c408d3c40abbe48064c1e2ef5224c1d6edca3cd)
1478af8d3SJacky Bai /*
2478af8d3SJacky Bai  * Copyright 2021-2024 NXP
3478af8d3SJacky Bai  *
4478af8d3SJacky Bai  * SPDX-License-Identifier: BSD-3-Clause
5478af8d3SJacky Bai  */
6478af8d3SJacky Bai 
7478af8d3SJacky Bai #include <assert.h>
8478af8d3SJacky Bai #include <stdbool.h>
9478af8d3SJacky Bai 
10478af8d3SJacky Bai #include <drivers/delay_timer.h>
11478af8d3SJacky Bai #include <lib/mmio.h>
12478af8d3SJacky Bai 
13478af8d3SJacky Bai #include <plat_imx8.h>
14478af8d3SJacky Bai #include <xrdc.h>
15478af8d3SJacky Bai 
16478af8d3SJacky Bai #define PCC_PR	BIT(31)
17478af8d3SJacky Bai #define PFD_VALID_MASK	U(0x40404040)
18478af8d3SJacky Bai 
19478af8d3SJacky Bai #define S400_MU_BASE	U(0x27020000)
20478af8d3SJacky Bai #define S400_MU_RSR	(S400_MU_BASE + 0x12c)
21478af8d3SJacky Bai #define S400_MU_TRx(i)	(S400_MU_BASE + 0x200 + (i) * 4)
22478af8d3SJacky Bai #define S400_MU_RRx(i)	(S400_MU_BASE + 0x280 + (i) * 4)
23478af8d3SJacky Bai 
24478af8d3SJacky Bai /*
25478af8d3SJacky Bai  * need to re-init the PLL, CGC1, PCC, CMC, XRDC, SIM, GPIO etc.
26478af8d3SJacky Bai  * init the PLL &PFD first, then switch the CA35 clock to PLL for
27478af8d3SJacky Bai  * performance consideration, restore other bus fabric clock.
28478af8d3SJacky Bai  */
29478af8d3SJacky Bai 
30478af8d3SJacky Bai extern void imx8ulp_caam_init(void);
31478af8d3SJacky Bai extern void upower_wait_resp(void);
32478af8d3SJacky Bai extern void dram_enter_retention(void);
33478af8d3SJacky Bai extern void dram_exit_retention(void);
34478af8d3SJacky Bai 
35478af8d3SJacky Bai struct plat_gic_ctx imx_gicv3_ctx;
36478af8d3SJacky Bai static uint32_t cmc1_pmprot;
37478af8d3SJacky Bai static uint32_t cmc1_srie;
38478af8d3SJacky Bai 
39478af8d3SJacky Bai /* TPM5: global timer */
40478af8d3SJacky Bai static uint32_t tpm5[3];
41478af8d3SJacky Bai 
42478af8d3SJacky Bai static uint32_t wdog3[2];
43478af8d3SJacky Bai 
44478af8d3SJacky Bai /* CGC1 PLL2 */
45478af8d3SJacky Bai uint32_t pll2[][2] = {
46478af8d3SJacky Bai 	{0x292c0510, 0x0}, {0x292c0518, 0x0}, {0x292c051c, 0x0},
47478af8d3SJacky Bai 	{0x292c0520, 0x0}, {0x292c0500, 0x0},
48478af8d3SJacky Bai };
49478af8d3SJacky Bai 
50478af8d3SJacky Bai /* CGC1 PLL3 */
51478af8d3SJacky Bai uint32_t pll3[][2] = {
52478af8d3SJacky Bai 	{0x292c0604, 0x0}, {0x292c0608, 0x0}, {0x292c060c, 0x0},
53478af8d3SJacky Bai 	{0x292c0610, 0x0}, {0x292c0618, 0x0}, {0x292c061c, 0x0},
54478af8d3SJacky Bai 	{0x292c0620, 0x0}, {0x292c0624, 0x0}, {0x292c0600, 0x0},
55478af8d3SJacky Bai 	{0x292c0614, 0x0},
56478af8d3SJacky Bai };
57478af8d3SJacky Bai 
58478af8d3SJacky Bai /* CGC1 others */
59478af8d3SJacky Bai uint32_t cgc1[][2] = {
60478af8d3SJacky Bai 	{0x292c0014, 0x0}, {0x292c0034, 0x0}, {0x292c0038, 0x0},
61478af8d3SJacky Bai 	{0x292c0108, 0x0}, {0x292c0208, 0x0}, {0x292c0700, 0x0},
62478af8d3SJacky Bai 	{0x292c0810, 0x0}, {0x292c0900, 0x0}, {0x292c0904, 0x0},
63478af8d3SJacky Bai 	{0x292c0908, 0x0}, {0x292c090c, 0x0}, {0x292c0a00, 0x0},
64478af8d3SJacky Bai };
65478af8d3SJacky Bai 
66478af8d3SJacky Bai static uint32_t pcc3[61];
67478af8d3SJacky Bai static uint32_t pcc4[32];
68478af8d3SJacky Bai 
69478af8d3SJacky Bai static uint32_t pcc5_0[33];
70478af8d3SJacky Bai static uint32_t pcc5_1[][2] = {
71478af8d3SJacky Bai 	{0x2da70084, 0x0}, {0x2da70088, 0x0}, {0x2da7008c, 0x0},
72478af8d3SJacky Bai 	{0x2da700a0, 0x0}, {0x2da700a4, 0x0}, {0x2da700a8, 0x0},
73478af8d3SJacky Bai 	{0x2da700ac, 0x0}, {0x2da700b0, 0x0}, {0x2da700b4, 0x0},
74478af8d3SJacky Bai 	{0x2da700bc, 0x0}, {0x2da700c0, 0x0}, {0x2da700c8, 0x0},
75478af8d3SJacky Bai 	{0x2da700cc, 0x0}, {0x2da700d0, 0x0}, {0x2da700f0, 0x0},
76478af8d3SJacky Bai 	{0x2da700f4, 0x0}, {0x2da700f8, 0x0}, {0x2da70108, 0x0},
77478af8d3SJacky Bai 	{0x2da7010c, 0x0}, {0x2da70110, 0x0}, {0x2da70114, 0x0},
78478af8d3SJacky Bai };
79478af8d3SJacky Bai 
80478af8d3SJacky Bai static uint32_t cgc2[][2] = {
81478af8d3SJacky Bai 	{0x2da60014, 0x0}, {0x2da60020, 0x0}, {0x2da6003c, 0x0},
82478af8d3SJacky Bai 	{0x2da60040, 0x0}, {0x2da60108, 0x0}, {0x2da60208, 0x0},
83478af8d3SJacky Bai 	{0x2da60900, 0x0}, {0x2da60904, 0x0}, {0x2da60908, 0x0},
84478af8d3SJacky Bai 	{0x2da60910, 0x0}, {0x2da60a00, 0x0},
85478af8d3SJacky Bai };
86478af8d3SJacky Bai 
87478af8d3SJacky Bai static uint32_t pll4[][2] = {
88478af8d3SJacky Bai 	{0x2da60604, 0x0}, {0x2da60608, 0x0}, {0x2da6060c, 0x0},
89478af8d3SJacky Bai 	{0x2da60610, 0x0}, {0x2da60618, 0x0}, {0x2da6061c, 0x0},
90478af8d3SJacky Bai 	{0x2da60620, 0x0}, {0x2da60624, 0x0}, {0x2da60600, 0x0},
91478af8d3SJacky Bai 	{0x2da60614, 0x0},
92478af8d3SJacky Bai };
93478af8d3SJacky Bai 
94478af8d3SJacky Bai static uint32_t lpav_sim[][2] = {
95478af8d3SJacky Bai 	{0x2da50000, 0x0}, {0x2da50004, 0x0}, {0x2da50008, 0x0},
96478af8d3SJacky Bai 	{0x2da5001c, 0x0}, {0x2da50020, 0x0}, {0x2da50024, 0x0},
97478af8d3SJacky Bai 	{0x2da50034, 0x0},
98478af8d3SJacky Bai };
99478af8d3SJacky Bai 
100478af8d3SJacky Bai #define APD_GPIO_CTRL_NUM		2
101478af8d3SJacky Bai #define LPAV_GPIO_CTRL_NUM		1
102478af8d3SJacky Bai #define GPIO_CTRL_REG_NUM		8
103478af8d3SJacky Bai #define GPIO_PIN_MAX_NUM	32
104478af8d3SJacky Bai #define GPIO_CTX(addr, num)	\
105478af8d3SJacky Bai 	{.base = (addr), .pin_num = (num), }
106478af8d3SJacky Bai 
107478af8d3SJacky Bai struct gpio_ctx {
108478af8d3SJacky Bai 	/* gpio base */
109478af8d3SJacky Bai 	uintptr_t base;
110478af8d3SJacky Bai 	/* port control */
111478af8d3SJacky Bai 	uint32_t port_ctrl[GPIO_CTRL_REG_NUM];
112478af8d3SJacky Bai 	/* GPIO ICR, Max 32 */
113478af8d3SJacky Bai 	uint32_t pin_num;
114478af8d3SJacky Bai 	uint32_t gpio_icr[GPIO_PIN_MAX_NUM];
115478af8d3SJacky Bai };
116478af8d3SJacky Bai 
117478af8d3SJacky Bai static uint32_t gpio_ctrl_offset[GPIO_CTRL_REG_NUM] = {
118478af8d3SJacky Bai 	 0xc, 0x10, 0x14, 0x18, 0x1c, 0x40, 0x54, 0x58
119478af8d3SJacky Bai };
120478af8d3SJacky Bai static struct gpio_ctx apd_gpio_ctx[APD_GPIO_CTRL_NUM] = {
121478af8d3SJacky Bai 	GPIO_CTX(IMX_GPIOE_BASE, 24),
122478af8d3SJacky Bai 	GPIO_CTX(IMX_GPIOF_BASE, 32),
123478af8d3SJacky Bai };
124478af8d3SJacky Bai 
125478af8d3SJacky Bai static struct gpio_ctx lpav_gpio_ctx = GPIO_CTX(IMX_GPIOD_BASE, 24);
126478af8d3SJacky Bai /* iomuxc setting */
127478af8d3SJacky Bai #define IOMUXC_SECTION_NUM	8
128478af8d3SJacky Bai struct iomuxc_section {
129478af8d3SJacky Bai 	uint32_t offset;
130478af8d3SJacky Bai 	uint32_t reg_num;
131478af8d3SJacky Bai };
132478af8d3SJacky Bai 
133478af8d3SJacky Bai struct iomuxc_section iomuxc_sections[IOMUXC_SECTION_NUM] = {
134478af8d3SJacky Bai 	{.offset = IOMUXC_PTD_PCR_BASE, .reg_num = 24},
135478af8d3SJacky Bai 	{.offset = IOMUXC_PTE_PCR_BASE, .reg_num = 24},
136478af8d3SJacky Bai 	{.offset = IOMUXC_PTF_PCR_BASE, .reg_num = 32},
137478af8d3SJacky Bai 	{.offset = IOMUXC_PSMI_BASE0, .reg_num = 10},
138478af8d3SJacky Bai 	{.offset = IOMUXC_PSMI_BASE1, .reg_num = 61},
139478af8d3SJacky Bai 	{.offset = IOMUXC_PSMI_BASE2, .reg_num = 12},
140478af8d3SJacky Bai 	{.offset = IOMUXC_PSMI_BASE3, .reg_num = 20},
141478af8d3SJacky Bai 	{.offset = IOMUXC_PSMI_BASE4, .reg_num = 75},
142478af8d3SJacky Bai };
143478af8d3SJacky Bai static uint32_t iomuxc_ctx[258];
144478af8d3SJacky Bai 
14536af80c2SJacky Bai #define PORTS_NUM		3U
apd_io_pad_off(void)14636af80c2SJacky Bai void apd_io_pad_off(void)
14736af80c2SJacky Bai {
14836af80c2SJacky Bai 	unsigned int i, j;
14936af80c2SJacky Bai 
15036af80c2SJacky Bai 	/* off the PTD/E/F, need to be customized based on actual user case */
15136af80c2SJacky Bai 	for (i = 0; i < PORTS_NUM; i++) {
15236af80c2SJacky Bai 		for (j = 0; j < iomuxc_sections[i].reg_num; j++) {
15336af80c2SJacky Bai 			mmio_write_32(iomuxc_sections[i].offset + j * 4, 0);
15436af80c2SJacky Bai 		}
15536af80c2SJacky Bai 	}
15636af80c2SJacky Bai 
15736af80c2SJacky Bai 	/* disable the PTD compensation */
15836af80c2SJacky Bai 	mmio_write_32(IMX_SIM1_BASE + 0x48, 0x800);
15936af80c2SJacky Bai }
16036af80c2SJacky Bai 
iomuxc_save(void)161478af8d3SJacky Bai void iomuxc_save(void)
162478af8d3SJacky Bai {
163478af8d3SJacky Bai 	unsigned int i, j;
164478af8d3SJacky Bai 	unsigned int index = 0U;
165478af8d3SJacky Bai 
166478af8d3SJacky Bai 	for (i = 0U; i < IOMUXC_SECTION_NUM; i++) {
167478af8d3SJacky Bai 		for (j = 0U; j < iomuxc_sections[i].reg_num; j++) {
168478af8d3SJacky Bai 			iomuxc_ctx[index++] = mmio_read_32(iomuxc_sections[i].offset + j * 4);
169478af8d3SJacky Bai 		}
170478af8d3SJacky Bai 	}
17136af80c2SJacky Bai 
17236af80c2SJacky Bai 	apd_io_pad_off();
173478af8d3SJacky Bai }
174478af8d3SJacky Bai 
iomuxc_restore(void)175478af8d3SJacky Bai void iomuxc_restore(void)
176478af8d3SJacky Bai {
177478af8d3SJacky Bai 	unsigned int i, j;
178478af8d3SJacky Bai 	unsigned int index = 0U;
179478af8d3SJacky Bai 
180478af8d3SJacky Bai 	for (i = 0U; i < IOMUXC_SECTION_NUM; i++) {
181478af8d3SJacky Bai 		for (j = 0U; j < iomuxc_sections[i].reg_num; j++) {
182478af8d3SJacky Bai 			mmio_write_32(iomuxc_sections[i].offset + j * 4, iomuxc_ctx[index++]);
183478af8d3SJacky Bai 		}
184478af8d3SJacky Bai 	}
185478af8d3SJacky Bai }
186478af8d3SJacky Bai 
gpio_save(struct gpio_ctx * ctx,int port_num)187478af8d3SJacky Bai void gpio_save(struct gpio_ctx *ctx, int port_num)
188478af8d3SJacky Bai {
189478af8d3SJacky Bai 	unsigned int i, j;
190478af8d3SJacky Bai 
191478af8d3SJacky Bai 	for (i = 0U; i < port_num; i++) {
192478af8d3SJacky Bai 		/* save the port control setting */
193478af8d3SJacky Bai 		for (j = 0U; j < GPIO_CTRL_REG_NUM; j++) {
194478af8d3SJacky Bai 			if (j < 4U) {
195478af8d3SJacky Bai 				ctx->port_ctrl[j] = mmio_read_32(ctx->base + gpio_ctrl_offset[j]);
196478af8d3SJacky Bai 				/*
197478af8d3SJacky Bai 				 * clear the permission setting to read the GPIO
198478af8d3SJacky Bai 				 * non-secure world setting.
199478af8d3SJacky Bai 				 */
200478af8d3SJacky Bai 				mmio_write_32(ctx->base + gpio_ctrl_offset[j], 0x0);
201478af8d3SJacky Bai 			} else {
202478af8d3SJacky Bai 				ctx->port_ctrl[j] = mmio_read_32(ctx->base + gpio_ctrl_offset[j]);
203478af8d3SJacky Bai 			}
204478af8d3SJacky Bai 		}
205478af8d3SJacky Bai 		/* save the gpio icr setting */
206478af8d3SJacky Bai 		for (j = 0U; j < ctx->pin_num; j++) {
207478af8d3SJacky Bai 			ctx->gpio_icr[j] = mmio_read_32(ctx->base + 0x80 + j * 4);
208478af8d3SJacky Bai 		}
209478af8d3SJacky Bai 
210478af8d3SJacky Bai 		ctx++;
211478af8d3SJacky Bai 	}
212478af8d3SJacky Bai }
213478af8d3SJacky Bai 
gpio_restore(struct gpio_ctx * ctx,int port_num)214478af8d3SJacky Bai void gpio_restore(struct gpio_ctx *ctx, int port_num)
215478af8d3SJacky Bai {
216478af8d3SJacky Bai 	unsigned int i, j;
217478af8d3SJacky Bai 
218478af8d3SJacky Bai 	for (i = 0U; i < port_num; i++) {
219478af8d3SJacky Bai 		for (j = 0U; j < ctx->pin_num; j++)
220478af8d3SJacky Bai 			mmio_write_32(ctx->base + 0x80 + j * 4, ctx->gpio_icr[j]);
221478af8d3SJacky Bai 
222478af8d3SJacky Bai 		for (j = 4U; j < GPIO_CTRL_REG_NUM; j++) {
223478af8d3SJacky Bai 			mmio_write_32(ctx->base + gpio_ctrl_offset[j], ctx->port_ctrl[j]);
224478af8d3SJacky Bai 		}
225478af8d3SJacky Bai 
226478af8d3SJacky Bai 		/* permission config retore last */
227478af8d3SJacky Bai 		for (j = 0U; j < 4; j++) {
228478af8d3SJacky Bai 			mmio_write_32(ctx->base + gpio_ctrl_offset[j], ctx->port_ctrl[j]);
229478af8d3SJacky Bai 		}
230478af8d3SJacky Bai 
231478af8d3SJacky Bai 		ctx++;
232478af8d3SJacky Bai 	}
233478af8d3SJacky Bai }
234478af8d3SJacky Bai 
cgc1_save(void)235478af8d3SJacky Bai void cgc1_save(void)
236478af8d3SJacky Bai {
237478af8d3SJacky Bai 	unsigned int i;
238478af8d3SJacky Bai 
239478af8d3SJacky Bai 	/* PLL2 */
240478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pll2); i++) {
241478af8d3SJacky Bai 		pll2[i][1] = mmio_read_32(pll2[i][0]);
242478af8d3SJacky Bai 	}
243478af8d3SJacky Bai 
244478af8d3SJacky Bai 	/* PLL3 */
245478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pll3); i++) {
246478af8d3SJacky Bai 		pll3[i][1] = mmio_read_32(pll3[i][0]);
247478af8d3SJacky Bai 	}
248478af8d3SJacky Bai 
249478af8d3SJacky Bai 	/* CGC1 others */
250478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(cgc1); i++) {
251478af8d3SJacky Bai 		cgc1[i][1] = mmio_read_32(cgc1[i][0]);
252478af8d3SJacky Bai 	}
253478af8d3SJacky Bai }
254478af8d3SJacky Bai 
cgc1_restore(void)255478af8d3SJacky Bai void cgc1_restore(void)
256478af8d3SJacky Bai {
257478af8d3SJacky Bai 	unsigned int i;
258478af8d3SJacky Bai 
259478af8d3SJacky Bai 	/* PLL2 */
260478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pll2); i++) {
261478af8d3SJacky Bai 		mmio_write_32(pll2[i][0], pll2[i][1]);
262478af8d3SJacky Bai 	}
263478af8d3SJacky Bai 	/* wait for PLL2 lock */
264478af8d3SJacky Bai 	while (!(mmio_read_32(pll2[4][0]) & BIT(24))) {
265478af8d3SJacky Bai 		;
266478af8d3SJacky Bai 	}
267478af8d3SJacky Bai 
268478af8d3SJacky Bai 	/* PLL3 */
269478af8d3SJacky Bai 	for (i = 0U; i < 9U; i++) {
270478af8d3SJacky Bai 		mmio_write_32(pll3[i][0], pll3[i][1]);
271478af8d3SJacky Bai 	}
272478af8d3SJacky Bai 
273478af8d3SJacky Bai 	/* wait for PLL3 lock */
274478af8d3SJacky Bai 	while (!(mmio_read_32(pll3[4][0]) & BIT(24))) {
275478af8d3SJacky Bai 		;
276478af8d3SJacky Bai 	}
277478af8d3SJacky Bai 
278478af8d3SJacky Bai 	/* restore the PFDs */
279478af8d3SJacky Bai 	mmio_write_32(pll3[9][0], pll3[9][1] & ~(BIT(31) | BIT(23) | BIT(15) | BIT(7)));
280478af8d3SJacky Bai 	mmio_write_32(pll3[9][0], pll3[9][1]);
281478af8d3SJacky Bai 
282478af8d3SJacky Bai 	/* wait for the PFD is stable, only need to check the enabled PFDs */
283478af8d3SJacky Bai 	while (!(mmio_read_32(pll3[9][0]) & PFD_VALID_MASK)) {
284478af8d3SJacky Bai 		;
285478af8d3SJacky Bai 	}
286478af8d3SJacky Bai 
287478af8d3SJacky Bai 	/* CGC1 others */
288478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(cgc1); i++) {
289478af8d3SJacky Bai 		mmio_write_32(cgc1[i][0], cgc1[i][1]);
290478af8d3SJacky Bai 	}
291478af8d3SJacky Bai }
292478af8d3SJacky Bai 
tpm5_save(void)293478af8d3SJacky Bai void tpm5_save(void)
294478af8d3SJacky Bai {
295478af8d3SJacky Bai 	tpm5[0] = mmio_read_32(IMX_TPM5_BASE + 0x10);
296478af8d3SJacky Bai 	tpm5[1] = mmio_read_32(IMX_TPM5_BASE + 0x18);
297478af8d3SJacky Bai 	tpm5[2] = mmio_read_32(IMX_TPM5_BASE + 0x20);
298478af8d3SJacky Bai }
299478af8d3SJacky Bai 
tpm5_restore(void)300478af8d3SJacky Bai void tpm5_restore(void)
301478af8d3SJacky Bai {
302478af8d3SJacky Bai 	mmio_write_32(IMX_TPM5_BASE + 0x10, tpm5[0]);
303478af8d3SJacky Bai 	mmio_write_32(IMX_TPM5_BASE + 0x18, tpm5[1]);
304478af8d3SJacky Bai 	mmio_write_32(IMX_TPM5_BASE + 0x20, tpm5[2]);
305478af8d3SJacky Bai }
306478af8d3SJacky Bai 
wdog3_save(void)307478af8d3SJacky Bai void wdog3_save(void)
308478af8d3SJacky Bai {
309478af8d3SJacky Bai 	/* enable wdog3 clock */
310478af8d3SJacky Bai 	mmio_write_32(IMX_PCC3_BASE + 0xa8, 0xd2800000);
311478af8d3SJacky Bai 
312478af8d3SJacky Bai 	/* save the CS & TOVAL regiter */
313478af8d3SJacky Bai 	wdog3[0] = mmio_read_32(IMX_WDOG3_BASE);
314478af8d3SJacky Bai 	wdog3[1] = mmio_read_32(IMX_WDOG3_BASE + 0x8);
315478af8d3SJacky Bai }
316478af8d3SJacky Bai 
wdog3_restore(void)317478af8d3SJacky Bai void wdog3_restore(void)
318478af8d3SJacky Bai {
319478af8d3SJacky Bai 	/* enable wdog3 clock */
320478af8d3SJacky Bai 	mmio_write_32(IMX_PCC3_BASE + 0xa8, 0xd2800000);
321478af8d3SJacky Bai 
322478af8d3SJacky Bai 	/* reconfig the CS */
323478af8d3SJacky Bai 	mmio_write_32(IMX_WDOG3_BASE, wdog3[0]);
324478af8d3SJacky Bai 	/* set the tiemout value */
325478af8d3SJacky Bai 	mmio_write_32(IMX_WDOG3_BASE + 0x8, wdog3[1]);
326478af8d3SJacky Bai 
327478af8d3SJacky Bai 	/* wait for the lock status */
328478af8d3SJacky Bai 	while ((mmio_read_32(IMX_WDOG3_BASE) & BIT(11))) {
329478af8d3SJacky Bai 		;
330478af8d3SJacky Bai 	}
331478af8d3SJacky Bai 
332478af8d3SJacky Bai 	/* wait for the config done */
333478af8d3SJacky Bai 	while (!(mmio_read_32(IMX_WDOG3_BASE) & BIT(10))) {
334478af8d3SJacky Bai 		;
335478af8d3SJacky Bai 	}
336478af8d3SJacky Bai }
337478af8d3SJacky Bai 
338478af8d3SJacky Bai static uint32_t lpuart_regs[4];
339478af8d3SJacky Bai #define LPUART_BAUD     0x10
340478af8d3SJacky Bai #define LPUART_CTRL     0x18
341478af8d3SJacky Bai #define LPUART_FIFO     0x28
342478af8d3SJacky Bai #define LPUART_WATER    0x2c
343478af8d3SJacky Bai 
lpuart_save(void)344478af8d3SJacky Bai void lpuart_save(void)
345478af8d3SJacky Bai {
346478af8d3SJacky Bai 	lpuart_regs[0] = mmio_read_32(IMX_LPUART5_BASE + LPUART_BAUD);
347478af8d3SJacky Bai 	lpuart_regs[1] = mmio_read_32(IMX_LPUART5_BASE + LPUART_FIFO);
348478af8d3SJacky Bai 	lpuart_regs[2] = mmio_read_32(IMX_LPUART5_BASE + LPUART_WATER);
349478af8d3SJacky Bai 	lpuart_regs[3] = mmio_read_32(IMX_LPUART5_BASE + LPUART_CTRL);
350478af8d3SJacky Bai }
351478af8d3SJacky Bai 
lpuart_restore(void)352478af8d3SJacky Bai void lpuart_restore(void)
353478af8d3SJacky Bai {
354478af8d3SJacky Bai 	mmio_write_32(IMX_LPUART5_BASE + LPUART_BAUD, lpuart_regs[0]);
355478af8d3SJacky Bai 	mmio_write_32(IMX_LPUART5_BASE + LPUART_FIFO, lpuart_regs[1]);
356478af8d3SJacky Bai 	mmio_write_32(IMX_LPUART5_BASE + LPUART_WATER, lpuart_regs[2]);
357478af8d3SJacky Bai 	mmio_write_32(IMX_LPUART5_BASE + LPUART_CTRL, lpuart_regs[3]);
358478af8d3SJacky Bai }
359478af8d3SJacky Bai 
is_lpav_owned_by_apd(void)360478af8d3SJacky Bai bool is_lpav_owned_by_apd(void)
361478af8d3SJacky Bai {
362478af8d3SJacky Bai 	return (mmio_read_32(0x2802b044) & BIT(7)) ? true : false;
363478af8d3SJacky Bai }
364478af8d3SJacky Bai 
lpav_ctx_save(void)365478af8d3SJacky Bai void lpav_ctx_save(void)
366478af8d3SJacky Bai {
367478af8d3SJacky Bai 	unsigned int i;
368478af8d3SJacky Bai 	uint32_t val;
369478af8d3SJacky Bai 
370478af8d3SJacky Bai 	/* CGC2 save */
371478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(cgc2); i++) {
372478af8d3SJacky Bai 		cgc2[i][1] = mmio_read_32(cgc2[i][0]);
373478af8d3SJacky Bai 	}
374478af8d3SJacky Bai 
375478af8d3SJacky Bai 	/* PLL4 */
376478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pll4); i++) {
377478af8d3SJacky Bai 		pll4[i][1] = mmio_read_32(pll4[i][0]);
378478af8d3SJacky Bai 	}
379478af8d3SJacky Bai 
380478af8d3SJacky Bai 	/* PCC5 save */
381478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc5_0); i++) {
382478af8d3SJacky Bai 		val = mmio_read_32(IMX_PCC5_BASE + i * 4);
383478af8d3SJacky Bai 		if (val & PCC_PR) {
384478af8d3SJacky Bai 			pcc5_0[i] = val;
385478af8d3SJacky Bai 		}
386478af8d3SJacky Bai 	}
387478af8d3SJacky Bai 
388478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc5_1); i++) {
389478af8d3SJacky Bai 		val = mmio_read_32(pcc5_1[i][0]);
390478af8d3SJacky Bai 		if (val & PCC_PR) {
391478af8d3SJacky Bai 			pcc5_1[i][1] = val;
392478af8d3SJacky Bai 		}
393478af8d3SJacky Bai 	}
394478af8d3SJacky Bai 
395478af8d3SJacky Bai 	/* LPAV SIM save */
396478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(lpav_sim); i++) {
397478af8d3SJacky Bai 		lpav_sim[i][1] = mmio_read_32(lpav_sim[i][0]);
398478af8d3SJacky Bai 	}
399478af8d3SJacky Bai 
400478af8d3SJacky Bai 	/* Save GPIO port D */
401478af8d3SJacky Bai 	gpio_save(&lpav_gpio_ctx, LPAV_GPIO_CTRL_NUM);
402478af8d3SJacky Bai 
403478af8d3SJacky Bai 	/* put DDR into retention */
404478af8d3SJacky Bai 	dram_enter_retention();
405478af8d3SJacky Bai }
406478af8d3SJacky Bai 
lpav_ctx_restore(void)407478af8d3SJacky Bai void lpav_ctx_restore(void)
408478af8d3SJacky Bai {
409478af8d3SJacky Bai 	unsigned int i;
410478af8d3SJacky Bai 
411478af8d3SJacky Bai 	/* PLL4 */
412478af8d3SJacky Bai 	for (i = 0U; i < 9U; i++) {
413478af8d3SJacky Bai 		mmio_write_32(pll4[i][0], pll4[i][1]);
414478af8d3SJacky Bai 	}
415478af8d3SJacky Bai 
416478af8d3SJacky Bai 	/* wait for PLL4 lock */
417478af8d3SJacky Bai 	while (!(mmio_read_32(pll4[8][0]) & BIT(24))) {
418478af8d3SJacky Bai 		;
419478af8d3SJacky Bai 	}
420478af8d3SJacky Bai 
421478af8d3SJacky Bai 	/* restore the PLL4 PFDs */
422478af8d3SJacky Bai 	mmio_write_32(pll4[9][0], pll4[9][1] & ~(BIT(31) | BIT(23) | BIT(15) | BIT(7)));
423478af8d3SJacky Bai 	mmio_write_32(pll4[9][0], pll4[9][1]);
424478af8d3SJacky Bai 
425478af8d3SJacky Bai 	/* wait for the PFD is stable */
426478af8d3SJacky Bai 	while (!(mmio_read_32(pll4[9][0]) & PFD_VALID_MASK)) {
427478af8d3SJacky Bai 		;
428478af8d3SJacky Bai 	}
429478af8d3SJacky Bai 
430478af8d3SJacky Bai 	/* CGC2 restore */
431478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(cgc2); i++) {
432478af8d3SJacky Bai 		mmio_write_32(cgc2[i][0], cgc2[i][1]);
433478af8d3SJacky Bai 	}
434478af8d3SJacky Bai 
435478af8d3SJacky Bai 	/* PCC5 restore */
436478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc5_0); i++) {
437478af8d3SJacky Bai 		if (pcc5_0[i] & PCC_PR) {
438478af8d3SJacky Bai 			mmio_write_32(IMX_PCC5_BASE + i * 4, pcc5_0[i]);
439478af8d3SJacky Bai 		}
440478af8d3SJacky Bai 	}
441478af8d3SJacky Bai 
442478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc5_1); i++) {
443478af8d3SJacky Bai 		if (pcc5_1[i][1] & PCC_PR) {
444478af8d3SJacky Bai 			mmio_write_32(pcc5_1[i][0], pcc5_1[i][1]);
445478af8d3SJacky Bai 		}
446478af8d3SJacky Bai 	}
447478af8d3SJacky Bai 
448478af8d3SJacky Bai 	/* LPAV_SIM */
449478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(lpav_sim); i++) {
450478af8d3SJacky Bai 		mmio_write_32(lpav_sim[i][0], lpav_sim[i][1]);
451478af8d3SJacky Bai 	}
452478af8d3SJacky Bai 
453478af8d3SJacky Bai 	gpio_restore(&lpav_gpio_ctx, LPAV_GPIO_CTRL_NUM);
454478af8d3SJacky Bai 	/* DDR retention exit */
455478af8d3SJacky Bai 	dram_exit_retention();
456478af8d3SJacky Bai }
457478af8d3SJacky Bai 
imx_apd_ctx_save(unsigned int proc_num)458478af8d3SJacky Bai void imx_apd_ctx_save(unsigned int proc_num)
459478af8d3SJacky Bai {
460478af8d3SJacky Bai 	unsigned int i;
461478af8d3SJacky Bai 	uint32_t val;
462478af8d3SJacky Bai 
463478af8d3SJacky Bai 	/* enable LPUART5's clock by default */
464478af8d3SJacky Bai 	mmio_setbits_32(IMX_PCC3_BASE + 0xe8, BIT(30));
465478af8d3SJacky Bai 
466478af8d3SJacky Bai 	/* save the gic config */
467478af8d3SJacky Bai 	plat_gic_save(proc_num, &imx_gicv3_ctx);
468478af8d3SJacky Bai 
469478af8d3SJacky Bai 	cmc1_pmprot = mmio_read_32(IMX_CMC1_BASE + 0x18);
470478af8d3SJacky Bai 	cmc1_srie = mmio_read_32(IMX_CMC1_BASE + 0x8c);
471478af8d3SJacky Bai 
472478af8d3SJacky Bai 	/* save the PCC3 */
473478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc3); i++) {
474478af8d3SJacky Bai 		/* save the pcc if it is exist */
475478af8d3SJacky Bai 		val = mmio_read_32(IMX_PCC3_BASE + i * 4);
476478af8d3SJacky Bai 		if (val & PCC_PR) {
477478af8d3SJacky Bai 			pcc3[i] = val;
478478af8d3SJacky Bai 		}
479478af8d3SJacky Bai 	}
480478af8d3SJacky Bai 
481478af8d3SJacky Bai 	/* save the PCC4 */
482478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc4); i++) {
483478af8d3SJacky Bai 		/* save the pcc if it is exist */
484478af8d3SJacky Bai 		val = mmio_read_32(IMX_PCC4_BASE + i * 4);
485478af8d3SJacky Bai 		if (val & PCC_PR) {
486478af8d3SJacky Bai 			pcc4[i] = val;
487478af8d3SJacky Bai 		}
488478af8d3SJacky Bai 	}
489478af8d3SJacky Bai 
490478af8d3SJacky Bai 	/* save the CGC1 */
491478af8d3SJacky Bai 	cgc1_save();
492478af8d3SJacky Bai 
493478af8d3SJacky Bai 	wdog3_save();
494478af8d3SJacky Bai 
495478af8d3SJacky Bai 	gpio_save(apd_gpio_ctx, APD_GPIO_CTRL_NUM);
496478af8d3SJacky Bai 
497478af8d3SJacky Bai 	iomuxc_save();
498478af8d3SJacky Bai 
499478af8d3SJacky Bai 	tpm5_save();
500478af8d3SJacky Bai 
501478af8d3SJacky Bai 	lpuart_save();
502478af8d3SJacky Bai 
503478af8d3SJacky Bai 	/*
504478af8d3SJacky Bai 	 * save the lpav ctx & put the ddr into retention
505478af8d3SJacky Bai 	 * if lpav master is assigned to APD domain.
506478af8d3SJacky Bai 	 */
507478af8d3SJacky Bai 	if (is_lpav_owned_by_apd()) {
508478af8d3SJacky Bai 		lpav_ctx_save();
509478af8d3SJacky Bai 	}
510478af8d3SJacky Bai }
511478af8d3SJacky Bai 
xrdc_reinit(void)512478af8d3SJacky Bai void xrdc_reinit(void)
513478af8d3SJacky Bai {
514478af8d3SJacky Bai 	xrdc_apply_apd_config();
515478af8d3SJacky Bai 	xrdc_apply_lpav_config();
516478af8d3SJacky Bai 
517478af8d3SJacky Bai 	xrdc_enable();
518478af8d3SJacky Bai }
519478af8d3SJacky Bai 
s400_release_caam(void)520478af8d3SJacky Bai void s400_release_caam(void)
521478af8d3SJacky Bai {
522478af8d3SJacky Bai 	uint32_t msg, resp;
523478af8d3SJacky Bai 
524478af8d3SJacky Bai 	mmio_write_32(S400_MU_TRx(0), 0x17d70206);
525478af8d3SJacky Bai 	mmio_write_32(S400_MU_TRx(1), 0x7);
526478af8d3SJacky Bai 
527478af8d3SJacky Bai 	do {
528478af8d3SJacky Bai 		resp = mmio_read_32(S400_MU_RSR);
529478af8d3SJacky Bai 	} while ((resp & 0x3) != 0x3);
530478af8d3SJacky Bai 
531478af8d3SJacky Bai 	msg = mmio_read_32(S400_MU_RRx(0));
532478af8d3SJacky Bai 	resp = mmio_read_32(S400_MU_RRx(1));
533478af8d3SJacky Bai 
534478af8d3SJacky Bai 	VERBOSE("resp %x; %x", msg, resp);
535478af8d3SJacky Bai }
536478af8d3SJacky Bai 
imx_apd_ctx_restore(unsigned int proc_num)537478af8d3SJacky Bai void imx_apd_ctx_restore(unsigned int proc_num)
538478af8d3SJacky Bai {
539478af8d3SJacky Bai 	unsigned int i;
540478af8d3SJacky Bai 
541478af8d3SJacky Bai 	/* restore the CCG1 */
542478af8d3SJacky Bai 	cgc1_restore();
543478af8d3SJacky Bai 
544478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc3); i++) {
545478af8d3SJacky Bai 		/* save the pcc if it is exist */
546478af8d3SJacky Bai 		if (pcc3[i] & PCC_PR) {
547478af8d3SJacky Bai 			mmio_write_32(IMX_PCC3_BASE + i * 4, pcc3[i]);
548478af8d3SJacky Bai 		}
549478af8d3SJacky Bai 	}
550478af8d3SJacky Bai 
551478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc4); i++) {
552478af8d3SJacky Bai 		if (pcc4[i] & PCC_PR) {
553478af8d3SJacky Bai 			mmio_write_32(IMX_PCC4_BASE + i * 4, pcc4[i]);
554478af8d3SJacky Bai 		}
555478af8d3SJacky Bai 	}
556478af8d3SJacky Bai 
557478af8d3SJacky Bai 	wdog3_restore();
558478af8d3SJacky Bai 
559478af8d3SJacky Bai 	iomuxc_restore();
560478af8d3SJacky Bai 
561478af8d3SJacky Bai 	tpm5_restore();
562478af8d3SJacky Bai 
563478af8d3SJacky Bai 	xrdc_reinit();
564478af8d3SJacky Bai 
565*68f132b8SYe Li 	/* Restore GPIO after xrdc_reinit, otherwise MSCs are invalid */
566*68f132b8SYe Li 	gpio_restore(apd_gpio_ctx, APD_GPIO_CTRL_NUM);
567*68f132b8SYe Li 
568478af8d3SJacky Bai 	/* restore the gic config */
569478af8d3SJacky Bai 	plat_gic_restore(proc_num, &imx_gicv3_ctx);
570478af8d3SJacky Bai 
571478af8d3SJacky Bai 	mmio_write_32(IMX_CMC1_BASE + 0x18, cmc1_pmprot);
572478af8d3SJacky Bai 	mmio_write_32(IMX_CMC1_BASE + 0x8c, cmc1_srie);
573478af8d3SJacky Bai 
574478af8d3SJacky Bai 	/* enable LPUART5's clock by default */
575478af8d3SJacky Bai 	mmio_setbits_32(IMX_PCC3_BASE + 0xe8, BIT(30));
576478af8d3SJacky Bai 
577478af8d3SJacky Bai 	/* restore the console lpuart */
578478af8d3SJacky Bai 	lpuart_restore();
579478af8d3SJacky Bai 
580478af8d3SJacky Bai 	/* FIXME: make uart work for ATF */
581478af8d3SJacky Bai 	mmio_write_32(IMX_LPUART_BASE + 0x18, 0xc0000);
582478af8d3SJacky Bai 
583ea1f7a2eSYe Li 	/* Allow M core to reset A core */
584ea1f7a2eSYe Li 	mmio_clrbits_32(IMX_MU0B_BASE + 0x10, BIT(2));
585478af8d3SJacky Bai 	/*
586478af8d3SJacky Bai 	 * Ask S400 to release caam to APD as it is owned by s400
587478af8d3SJacky Bai 	 */
588478af8d3SJacky Bai 	s400_release_caam();
589478af8d3SJacky Bai 
590478af8d3SJacky Bai 	/* re-init the caam */
591478af8d3SJacky Bai 	imx8ulp_caam_init();
592478af8d3SJacky Bai 
593478af8d3SJacky Bai 	/*
594478af8d3SJacky Bai 	 * ack the upower, seems a necessary steps, otherwise the upower can
595478af8d3SJacky Bai 	 * not response to the new API service call. put this just before the
596478af8d3SJacky Bai 	 * ddr retention exit because that the dram retention exit flow need to
597478af8d3SJacky Bai 	 * communicate with upower.
598478af8d3SJacky Bai 	 */
599478af8d3SJacky Bai 	upower_wait_resp();
600478af8d3SJacky Bai 
601478af8d3SJacky Bai 	/*
602478af8d3SJacky Bai 	 * restore the lpav ctx & make ddr out of retention
603478af8d3SJacky Bai 	 * if lpav master is assigned to APD domain.
604478af8d3SJacky Bai 	 */
605478af8d3SJacky Bai 	if (is_lpav_owned_by_apd()) {
606478af8d3SJacky Bai 		lpav_ctx_restore();
607478af8d3SJacky Bai 	}
608478af8d3SJacky Bai }
609478af8d3SJacky Bai 
610478af8d3SJacky Bai #define DGO_CTRL1	U(0xc)
611478af8d3SJacky Bai #define USB_WAKEUP	U(0x44)
612478af8d3SJacky Bai #define USB1_PHY_DPD_WAKEUP_EN	BIT_32(5)
613478af8d3SJacky Bai #define USB0_PHY_DPD_WAKEUP_EN	BIT_32(4)
614478af8d3SJacky Bai #define USB1_PHY_WAKEUP_ISO_DISABLE	BIT_32(1)
615478af8d3SJacky Bai #define USB0_PHY_WAKEUP_ISO_DISABLE	BIT_32(0)
616478af8d3SJacky Bai 
usb_wakeup_enable(bool enable)617478af8d3SJacky Bai void usb_wakeup_enable(bool enable)
618478af8d3SJacky Bai {
619478af8d3SJacky Bai 	if (enable) {
620478af8d3SJacky Bai 		mmio_setbits_32(IMX_SIM1_BASE + USB_WAKEUP,
621478af8d3SJacky Bai 				USB1_PHY_WAKEUP_ISO_DISABLE | USB0_PHY_WAKEUP_ISO_DISABLE);
622478af8d3SJacky Bai 		mmio_setbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
623478af8d3SJacky Bai 		while (!(mmio_read_32(IMX_SIM1_BASE + DGO_CTRL1) & BIT(1))) {
624478af8d3SJacky Bai 			;
625478af8d3SJacky Bai 		}
626478af8d3SJacky Bai 
627478af8d3SJacky Bai 		mmio_clrbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
628478af8d3SJacky Bai 		mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(1));
629478af8d3SJacky Bai 
630478af8d3SJacky Bai 		/* Need to delay for a while to make sure the wakeup logic can work */
631478af8d3SJacky Bai 		udelay(500);
632478af8d3SJacky Bai 
633478af8d3SJacky Bai 		mmio_setbits_32(IMX_SIM1_BASE + USB_WAKEUP,
634478af8d3SJacky Bai 				USB1_PHY_DPD_WAKEUP_EN | USB0_PHY_DPD_WAKEUP_EN);
635478af8d3SJacky Bai 		mmio_setbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
636478af8d3SJacky Bai 		while (!(mmio_read_32(IMX_SIM1_BASE + DGO_CTRL1) & BIT(1))) {
637478af8d3SJacky Bai 			;
638478af8d3SJacky Bai 		}
639478af8d3SJacky Bai 
640478af8d3SJacky Bai 		mmio_clrbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
641478af8d3SJacky Bai 		mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(1));
642478af8d3SJacky Bai 	} else {
643478af8d3SJacky Bai 		/*
644478af8d3SJacky Bai 		 * USBx_PHY_DPD_WAKEUP_EN should be cleared before USB0_PHY_WAKEUP_ISO_DISABLE
645478af8d3SJacky Bai 		 * to provide the correct the wake-up functionality.
646478af8d3SJacky Bai 		 */
647478af8d3SJacky Bai 		mmio_write_32(IMX_SIM1_BASE + USB_WAKEUP, USB1_PHY_WAKEUP_ISO_DISABLE |
648478af8d3SJacky Bai 			USB0_PHY_WAKEUP_ISO_DISABLE);
649478af8d3SJacky Bai 		mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
650478af8d3SJacky Bai 		while (!(mmio_read_32(IMX_SIM1_BASE + DGO_CTRL1) & BIT(1))) {
651478af8d3SJacky Bai 			;
652478af8d3SJacky Bai 		}
653478af8d3SJacky Bai 
654478af8d3SJacky Bai 		mmio_clrbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
655478af8d3SJacky Bai 		mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(1));
656478af8d3SJacky Bai 	}
657478af8d3SJacky Bai }
658