xref: /rk3399_ARM-atf/plat/imx/imx8ulp/apd_context.c (revision 478af8d3c34576793a820733ddba6449c2cf2fac)
1*478af8d3SJacky Bai /*
2*478af8d3SJacky Bai  * Copyright 2021-2024 NXP
3*478af8d3SJacky Bai  *
4*478af8d3SJacky Bai  * SPDX-License-Identifier: BSD-3-Clause
5*478af8d3SJacky Bai  */
6*478af8d3SJacky Bai 
7*478af8d3SJacky Bai #include <assert.h>
8*478af8d3SJacky Bai #include <stdbool.h>
9*478af8d3SJacky Bai 
10*478af8d3SJacky Bai #include <drivers/delay_timer.h>
11*478af8d3SJacky Bai #include <lib/mmio.h>
12*478af8d3SJacky Bai 
13*478af8d3SJacky Bai #include <plat_imx8.h>
14*478af8d3SJacky Bai #include <xrdc.h>
15*478af8d3SJacky Bai 
16*478af8d3SJacky Bai #define PCC_PR	BIT(31)
17*478af8d3SJacky Bai #define PFD_VALID_MASK	U(0x40404040)
18*478af8d3SJacky Bai 
19*478af8d3SJacky Bai #define S400_MU_BASE	U(0x27020000)
20*478af8d3SJacky Bai #define S400_MU_RSR	(S400_MU_BASE + 0x12c)
21*478af8d3SJacky Bai #define S400_MU_TRx(i)	(S400_MU_BASE + 0x200 + (i) * 4)
22*478af8d3SJacky Bai #define S400_MU_RRx(i)	(S400_MU_BASE + 0x280 + (i) * 4)
23*478af8d3SJacky Bai 
24*478af8d3SJacky Bai /*
25*478af8d3SJacky Bai  * need to re-init the PLL, CGC1, PCC, CMC, XRDC, SIM, GPIO etc.
26*478af8d3SJacky Bai  * init the PLL &PFD first, then switch the CA35 clock to PLL for
27*478af8d3SJacky Bai  * performance consideration, restore other bus fabric clock.
28*478af8d3SJacky Bai  */
29*478af8d3SJacky Bai 
30*478af8d3SJacky Bai extern void imx8ulp_caam_init(void);
31*478af8d3SJacky Bai extern void upower_wait_resp(void);
32*478af8d3SJacky Bai extern void dram_enter_retention(void);
33*478af8d3SJacky Bai extern void dram_exit_retention(void);
34*478af8d3SJacky Bai 
35*478af8d3SJacky Bai struct plat_gic_ctx imx_gicv3_ctx;
36*478af8d3SJacky Bai static uint32_t cmc1_pmprot;
37*478af8d3SJacky Bai static uint32_t cmc1_srie;
38*478af8d3SJacky Bai 
39*478af8d3SJacky Bai /* TPM5: global timer */
40*478af8d3SJacky Bai static uint32_t tpm5[3];
41*478af8d3SJacky Bai 
42*478af8d3SJacky Bai static uint32_t wdog3[2];
43*478af8d3SJacky Bai 
44*478af8d3SJacky Bai /* CGC1 PLL2 */
45*478af8d3SJacky Bai uint32_t pll2[][2] = {
46*478af8d3SJacky Bai 	{0x292c0510, 0x0}, {0x292c0518, 0x0}, {0x292c051c, 0x0},
47*478af8d3SJacky Bai 	{0x292c0520, 0x0}, {0x292c0500, 0x0},
48*478af8d3SJacky Bai };
49*478af8d3SJacky Bai 
50*478af8d3SJacky Bai /* CGC1 PLL3 */
51*478af8d3SJacky Bai uint32_t pll3[][2] = {
52*478af8d3SJacky Bai 	{0x292c0604, 0x0}, {0x292c0608, 0x0}, {0x292c060c, 0x0},
53*478af8d3SJacky Bai 	{0x292c0610, 0x0}, {0x292c0618, 0x0}, {0x292c061c, 0x0},
54*478af8d3SJacky Bai 	{0x292c0620, 0x0}, {0x292c0624, 0x0}, {0x292c0600, 0x0},
55*478af8d3SJacky Bai 	{0x292c0614, 0x0},
56*478af8d3SJacky Bai };
57*478af8d3SJacky Bai 
58*478af8d3SJacky Bai /* CGC1 others */
59*478af8d3SJacky Bai uint32_t cgc1[][2] = {
60*478af8d3SJacky Bai 	{0x292c0014, 0x0}, {0x292c0034, 0x0}, {0x292c0038, 0x0},
61*478af8d3SJacky Bai 	{0x292c0108, 0x0}, {0x292c0208, 0x0}, {0x292c0700, 0x0},
62*478af8d3SJacky Bai 	{0x292c0810, 0x0}, {0x292c0900, 0x0}, {0x292c0904, 0x0},
63*478af8d3SJacky Bai 	{0x292c0908, 0x0}, {0x292c090c, 0x0}, {0x292c0a00, 0x0},
64*478af8d3SJacky Bai };
65*478af8d3SJacky Bai 
66*478af8d3SJacky Bai static uint32_t pcc3[61];
67*478af8d3SJacky Bai static uint32_t pcc4[32];
68*478af8d3SJacky Bai 
69*478af8d3SJacky Bai static uint32_t pcc5_0[33];
70*478af8d3SJacky Bai static uint32_t pcc5_1[][2] = {
71*478af8d3SJacky Bai 	{0x2da70084, 0x0}, {0x2da70088, 0x0}, {0x2da7008c, 0x0},
72*478af8d3SJacky Bai 	{0x2da700a0, 0x0}, {0x2da700a4, 0x0}, {0x2da700a8, 0x0},
73*478af8d3SJacky Bai 	{0x2da700ac, 0x0}, {0x2da700b0, 0x0}, {0x2da700b4, 0x0},
74*478af8d3SJacky Bai 	{0x2da700bc, 0x0}, {0x2da700c0, 0x0}, {0x2da700c8, 0x0},
75*478af8d3SJacky Bai 	{0x2da700cc, 0x0}, {0x2da700d0, 0x0}, {0x2da700f0, 0x0},
76*478af8d3SJacky Bai 	{0x2da700f4, 0x0}, {0x2da700f8, 0x0}, {0x2da70108, 0x0},
77*478af8d3SJacky Bai 	{0x2da7010c, 0x0}, {0x2da70110, 0x0}, {0x2da70114, 0x0},
78*478af8d3SJacky Bai };
79*478af8d3SJacky Bai 
80*478af8d3SJacky Bai static uint32_t cgc2[][2] = {
81*478af8d3SJacky Bai 	{0x2da60014, 0x0}, {0x2da60020, 0x0}, {0x2da6003c, 0x0},
82*478af8d3SJacky Bai 	{0x2da60040, 0x0}, {0x2da60108, 0x0}, {0x2da60208, 0x0},
83*478af8d3SJacky Bai 	{0x2da60900, 0x0}, {0x2da60904, 0x0}, {0x2da60908, 0x0},
84*478af8d3SJacky Bai 	{0x2da60910, 0x0}, {0x2da60a00, 0x0},
85*478af8d3SJacky Bai };
86*478af8d3SJacky Bai 
87*478af8d3SJacky Bai static uint32_t pll4[][2] = {
88*478af8d3SJacky Bai 	{0x2da60604, 0x0}, {0x2da60608, 0x0}, {0x2da6060c, 0x0},
89*478af8d3SJacky Bai 	{0x2da60610, 0x0}, {0x2da60618, 0x0}, {0x2da6061c, 0x0},
90*478af8d3SJacky Bai 	{0x2da60620, 0x0}, {0x2da60624, 0x0}, {0x2da60600, 0x0},
91*478af8d3SJacky Bai 	{0x2da60614, 0x0},
92*478af8d3SJacky Bai };
93*478af8d3SJacky Bai 
94*478af8d3SJacky Bai static uint32_t lpav_sim[][2] = {
95*478af8d3SJacky Bai 	{0x2da50000, 0x0}, {0x2da50004, 0x0}, {0x2da50008, 0x0},
96*478af8d3SJacky Bai 	{0x2da5001c, 0x0}, {0x2da50020, 0x0}, {0x2da50024, 0x0},
97*478af8d3SJacky Bai 	{0x2da50034, 0x0},
98*478af8d3SJacky Bai };
99*478af8d3SJacky Bai 
100*478af8d3SJacky Bai #define APD_GPIO_CTRL_NUM		2
101*478af8d3SJacky Bai #define LPAV_GPIO_CTRL_NUM		1
102*478af8d3SJacky Bai #define GPIO_CTRL_REG_NUM		8
103*478af8d3SJacky Bai #define GPIO_PIN_MAX_NUM	32
104*478af8d3SJacky Bai #define GPIO_CTX(addr, num)	\
105*478af8d3SJacky Bai 	{.base = (addr), .pin_num = (num), }
106*478af8d3SJacky Bai 
107*478af8d3SJacky Bai struct gpio_ctx {
108*478af8d3SJacky Bai 	/* gpio base */
109*478af8d3SJacky Bai 	uintptr_t base;
110*478af8d3SJacky Bai 	/* port control */
111*478af8d3SJacky Bai 	uint32_t port_ctrl[GPIO_CTRL_REG_NUM];
112*478af8d3SJacky Bai 	/* GPIO ICR, Max 32 */
113*478af8d3SJacky Bai 	uint32_t pin_num;
114*478af8d3SJacky Bai 	uint32_t gpio_icr[GPIO_PIN_MAX_NUM];
115*478af8d3SJacky Bai };
116*478af8d3SJacky Bai 
117*478af8d3SJacky Bai static uint32_t gpio_ctrl_offset[GPIO_CTRL_REG_NUM] = {
118*478af8d3SJacky Bai 	 0xc, 0x10, 0x14, 0x18, 0x1c, 0x40, 0x54, 0x58
119*478af8d3SJacky Bai };
120*478af8d3SJacky Bai static struct gpio_ctx apd_gpio_ctx[APD_GPIO_CTRL_NUM] = {
121*478af8d3SJacky Bai 	GPIO_CTX(IMX_GPIOE_BASE, 24),
122*478af8d3SJacky Bai 	GPIO_CTX(IMX_GPIOF_BASE, 32),
123*478af8d3SJacky Bai };
124*478af8d3SJacky Bai 
125*478af8d3SJacky Bai static struct gpio_ctx lpav_gpio_ctx = GPIO_CTX(IMX_GPIOD_BASE, 24);
126*478af8d3SJacky Bai /* iomuxc setting */
127*478af8d3SJacky Bai #define IOMUXC_SECTION_NUM	8
128*478af8d3SJacky Bai struct iomuxc_section {
129*478af8d3SJacky Bai 	uint32_t offset;
130*478af8d3SJacky Bai 	uint32_t reg_num;
131*478af8d3SJacky Bai };
132*478af8d3SJacky Bai 
133*478af8d3SJacky Bai struct iomuxc_section iomuxc_sections[IOMUXC_SECTION_NUM] = {
134*478af8d3SJacky Bai 	{.offset = IOMUXC_PTD_PCR_BASE, .reg_num = 24},
135*478af8d3SJacky Bai 	{.offset = IOMUXC_PTE_PCR_BASE, .reg_num = 24},
136*478af8d3SJacky Bai 	{.offset = IOMUXC_PTF_PCR_BASE, .reg_num = 32},
137*478af8d3SJacky Bai 	{.offset = IOMUXC_PSMI_BASE0, .reg_num = 10},
138*478af8d3SJacky Bai 	{.offset = IOMUXC_PSMI_BASE1, .reg_num = 61},
139*478af8d3SJacky Bai 	{.offset = IOMUXC_PSMI_BASE2, .reg_num = 12},
140*478af8d3SJacky Bai 	{.offset = IOMUXC_PSMI_BASE3, .reg_num = 20},
141*478af8d3SJacky Bai 	{.offset = IOMUXC_PSMI_BASE4, .reg_num = 75},
142*478af8d3SJacky Bai };
143*478af8d3SJacky Bai static uint32_t iomuxc_ctx[258];
144*478af8d3SJacky Bai 
145*478af8d3SJacky Bai void iomuxc_save(void)
146*478af8d3SJacky Bai {
147*478af8d3SJacky Bai 	unsigned int i, j;
148*478af8d3SJacky Bai 	unsigned int index = 0U;
149*478af8d3SJacky Bai 
150*478af8d3SJacky Bai 	for (i = 0U; i < IOMUXC_SECTION_NUM; i++) {
151*478af8d3SJacky Bai 		for (j = 0U; j < iomuxc_sections[i].reg_num; j++) {
152*478af8d3SJacky Bai 			iomuxc_ctx[index++] = mmio_read_32(iomuxc_sections[i].offset + j * 4);
153*478af8d3SJacky Bai 		}
154*478af8d3SJacky Bai 	}
155*478af8d3SJacky Bai }
156*478af8d3SJacky Bai 
157*478af8d3SJacky Bai void iomuxc_restore(void)
158*478af8d3SJacky Bai {
159*478af8d3SJacky Bai 	unsigned int i, j;
160*478af8d3SJacky Bai 	unsigned int index = 0U;
161*478af8d3SJacky Bai 
162*478af8d3SJacky Bai 	for (i = 0U; i < IOMUXC_SECTION_NUM; i++) {
163*478af8d3SJacky Bai 		for (j = 0U; j < iomuxc_sections[i].reg_num; j++) {
164*478af8d3SJacky Bai 			mmio_write_32(iomuxc_sections[i].offset + j * 4, iomuxc_ctx[index++]);
165*478af8d3SJacky Bai 		}
166*478af8d3SJacky Bai 	}
167*478af8d3SJacky Bai }
168*478af8d3SJacky Bai 
169*478af8d3SJacky Bai void gpio_save(struct gpio_ctx *ctx, int port_num)
170*478af8d3SJacky Bai {
171*478af8d3SJacky Bai 	unsigned int i, j;
172*478af8d3SJacky Bai 
173*478af8d3SJacky Bai 	for (i = 0U; i < port_num; i++) {
174*478af8d3SJacky Bai 		/* save the port control setting */
175*478af8d3SJacky Bai 		for (j = 0U; j < GPIO_CTRL_REG_NUM; j++) {
176*478af8d3SJacky Bai 			if (j < 4U) {
177*478af8d3SJacky Bai 				ctx->port_ctrl[j] = mmio_read_32(ctx->base + gpio_ctrl_offset[j]);
178*478af8d3SJacky Bai 				/*
179*478af8d3SJacky Bai 				 * clear the permission setting to read the GPIO
180*478af8d3SJacky Bai 				 * non-secure world setting.
181*478af8d3SJacky Bai 				 */
182*478af8d3SJacky Bai 				mmio_write_32(ctx->base + gpio_ctrl_offset[j], 0x0);
183*478af8d3SJacky Bai 			} else {
184*478af8d3SJacky Bai 				ctx->port_ctrl[j] = mmio_read_32(ctx->base + gpio_ctrl_offset[j]);
185*478af8d3SJacky Bai 			}
186*478af8d3SJacky Bai 		}
187*478af8d3SJacky Bai 		/* save the gpio icr setting */
188*478af8d3SJacky Bai 		for (j = 0U; j < ctx->pin_num; j++) {
189*478af8d3SJacky Bai 			ctx->gpio_icr[j] = mmio_read_32(ctx->base + 0x80 + j * 4);
190*478af8d3SJacky Bai 		}
191*478af8d3SJacky Bai 
192*478af8d3SJacky Bai 		ctx++;
193*478af8d3SJacky Bai 	}
194*478af8d3SJacky Bai }
195*478af8d3SJacky Bai 
196*478af8d3SJacky Bai void gpio_restore(struct gpio_ctx *ctx, int port_num)
197*478af8d3SJacky Bai {
198*478af8d3SJacky Bai 	unsigned int i, j;
199*478af8d3SJacky Bai 
200*478af8d3SJacky Bai 	for (i = 0U; i < port_num; i++) {
201*478af8d3SJacky Bai 		for (j = 0U; j < ctx->pin_num; j++)
202*478af8d3SJacky Bai 			mmio_write_32(ctx->base + 0x80 + j * 4, ctx->gpio_icr[j]);
203*478af8d3SJacky Bai 
204*478af8d3SJacky Bai 		for (j = 4U; j < GPIO_CTRL_REG_NUM; j++) {
205*478af8d3SJacky Bai 			mmio_write_32(ctx->base + gpio_ctrl_offset[j], ctx->port_ctrl[j]);
206*478af8d3SJacky Bai 		}
207*478af8d3SJacky Bai 
208*478af8d3SJacky Bai 		/* permission config retore last */
209*478af8d3SJacky Bai 		for (j = 0U; j < 4; j++) {
210*478af8d3SJacky Bai 			mmio_write_32(ctx->base + gpio_ctrl_offset[j], ctx->port_ctrl[j]);
211*478af8d3SJacky Bai 		}
212*478af8d3SJacky Bai 
213*478af8d3SJacky Bai 		ctx++;
214*478af8d3SJacky Bai 	}
215*478af8d3SJacky Bai }
216*478af8d3SJacky Bai 
217*478af8d3SJacky Bai void cgc1_save(void)
218*478af8d3SJacky Bai {
219*478af8d3SJacky Bai 	unsigned int i;
220*478af8d3SJacky Bai 
221*478af8d3SJacky Bai 	/* PLL2 */
222*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pll2); i++) {
223*478af8d3SJacky Bai 		pll2[i][1] = mmio_read_32(pll2[i][0]);
224*478af8d3SJacky Bai 	}
225*478af8d3SJacky Bai 
226*478af8d3SJacky Bai 	/* PLL3 */
227*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pll3); i++) {
228*478af8d3SJacky Bai 		pll3[i][1] = mmio_read_32(pll3[i][0]);
229*478af8d3SJacky Bai 	}
230*478af8d3SJacky Bai 
231*478af8d3SJacky Bai 	/* CGC1 others */
232*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(cgc1); i++) {
233*478af8d3SJacky Bai 		cgc1[i][1] = mmio_read_32(cgc1[i][0]);
234*478af8d3SJacky Bai 	}
235*478af8d3SJacky Bai }
236*478af8d3SJacky Bai 
237*478af8d3SJacky Bai void cgc1_restore(void)
238*478af8d3SJacky Bai {
239*478af8d3SJacky Bai 	unsigned int i;
240*478af8d3SJacky Bai 
241*478af8d3SJacky Bai 	/* PLL2 */
242*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pll2); i++) {
243*478af8d3SJacky Bai 		mmio_write_32(pll2[i][0], pll2[i][1]);
244*478af8d3SJacky Bai 	}
245*478af8d3SJacky Bai 	/* wait for PLL2 lock */
246*478af8d3SJacky Bai 	while (!(mmio_read_32(pll2[4][0]) & BIT(24))) {
247*478af8d3SJacky Bai 		;
248*478af8d3SJacky Bai 	}
249*478af8d3SJacky Bai 
250*478af8d3SJacky Bai 	/* PLL3 */
251*478af8d3SJacky Bai 	for (i = 0U; i < 9U; i++) {
252*478af8d3SJacky Bai 		mmio_write_32(pll3[i][0], pll3[i][1]);
253*478af8d3SJacky Bai 	}
254*478af8d3SJacky Bai 
255*478af8d3SJacky Bai 	/* wait for PLL3 lock */
256*478af8d3SJacky Bai 	while (!(mmio_read_32(pll3[4][0]) & BIT(24))) {
257*478af8d3SJacky Bai 		;
258*478af8d3SJacky Bai 	}
259*478af8d3SJacky Bai 
260*478af8d3SJacky Bai 	/* restore the PFDs */
261*478af8d3SJacky Bai 	mmio_write_32(pll3[9][0], pll3[9][1] & ~(BIT(31) | BIT(23) | BIT(15) | BIT(7)));
262*478af8d3SJacky Bai 	mmio_write_32(pll3[9][0], pll3[9][1]);
263*478af8d3SJacky Bai 
264*478af8d3SJacky Bai 	/* wait for the PFD is stable, only need to check the enabled PFDs */
265*478af8d3SJacky Bai 	while (!(mmio_read_32(pll3[9][0]) & PFD_VALID_MASK)) {
266*478af8d3SJacky Bai 		;
267*478af8d3SJacky Bai 	}
268*478af8d3SJacky Bai 
269*478af8d3SJacky Bai 	/* CGC1 others */
270*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(cgc1); i++) {
271*478af8d3SJacky Bai 		mmio_write_32(cgc1[i][0], cgc1[i][1]);
272*478af8d3SJacky Bai 	}
273*478af8d3SJacky Bai }
274*478af8d3SJacky Bai 
275*478af8d3SJacky Bai void tpm5_save(void)
276*478af8d3SJacky Bai {
277*478af8d3SJacky Bai 	tpm5[0] = mmio_read_32(IMX_TPM5_BASE + 0x10);
278*478af8d3SJacky Bai 	tpm5[1] = mmio_read_32(IMX_TPM5_BASE + 0x18);
279*478af8d3SJacky Bai 	tpm5[2] = mmio_read_32(IMX_TPM5_BASE + 0x20);
280*478af8d3SJacky Bai }
281*478af8d3SJacky Bai 
282*478af8d3SJacky Bai void tpm5_restore(void)
283*478af8d3SJacky Bai {
284*478af8d3SJacky Bai 	mmio_write_32(IMX_TPM5_BASE + 0x10, tpm5[0]);
285*478af8d3SJacky Bai 	mmio_write_32(IMX_TPM5_BASE + 0x18, tpm5[1]);
286*478af8d3SJacky Bai 	mmio_write_32(IMX_TPM5_BASE + 0x20, tpm5[2]);
287*478af8d3SJacky Bai }
288*478af8d3SJacky Bai 
289*478af8d3SJacky Bai void wdog3_save(void)
290*478af8d3SJacky Bai {
291*478af8d3SJacky Bai 	/* enable wdog3 clock */
292*478af8d3SJacky Bai 	mmio_write_32(IMX_PCC3_BASE + 0xa8, 0xd2800000);
293*478af8d3SJacky Bai 
294*478af8d3SJacky Bai 	/* save the CS & TOVAL regiter */
295*478af8d3SJacky Bai 	wdog3[0] = mmio_read_32(IMX_WDOG3_BASE);
296*478af8d3SJacky Bai 	wdog3[1] = mmio_read_32(IMX_WDOG3_BASE + 0x8);
297*478af8d3SJacky Bai }
298*478af8d3SJacky Bai 
299*478af8d3SJacky Bai void wdog3_restore(void)
300*478af8d3SJacky Bai {
301*478af8d3SJacky Bai 	/* enable wdog3 clock */
302*478af8d3SJacky Bai 	mmio_write_32(IMX_PCC3_BASE + 0xa8, 0xd2800000);
303*478af8d3SJacky Bai 
304*478af8d3SJacky Bai 	/* reconfig the CS */
305*478af8d3SJacky Bai 	mmio_write_32(IMX_WDOG3_BASE, wdog3[0]);
306*478af8d3SJacky Bai 	/* set the tiemout value */
307*478af8d3SJacky Bai 	mmio_write_32(IMX_WDOG3_BASE + 0x8, wdog3[1]);
308*478af8d3SJacky Bai 
309*478af8d3SJacky Bai 	/* wait for the lock status */
310*478af8d3SJacky Bai 	while ((mmio_read_32(IMX_WDOG3_BASE) & BIT(11))) {
311*478af8d3SJacky Bai 		;
312*478af8d3SJacky Bai 	}
313*478af8d3SJacky Bai 
314*478af8d3SJacky Bai 	/* wait for the config done */
315*478af8d3SJacky Bai 	while (!(mmio_read_32(IMX_WDOG3_BASE) & BIT(10))) {
316*478af8d3SJacky Bai 		;
317*478af8d3SJacky Bai 	}
318*478af8d3SJacky Bai }
319*478af8d3SJacky Bai 
320*478af8d3SJacky Bai static uint32_t lpuart_regs[4];
321*478af8d3SJacky Bai #define LPUART_BAUD     0x10
322*478af8d3SJacky Bai #define LPUART_CTRL     0x18
323*478af8d3SJacky Bai #define LPUART_FIFO     0x28
324*478af8d3SJacky Bai #define LPUART_WATER    0x2c
325*478af8d3SJacky Bai 
326*478af8d3SJacky Bai void lpuart_save(void)
327*478af8d3SJacky Bai {
328*478af8d3SJacky Bai 	lpuart_regs[0] = mmio_read_32(IMX_LPUART5_BASE + LPUART_BAUD);
329*478af8d3SJacky Bai 	lpuart_regs[1] = mmio_read_32(IMX_LPUART5_BASE + LPUART_FIFO);
330*478af8d3SJacky Bai 	lpuart_regs[2] = mmio_read_32(IMX_LPUART5_BASE + LPUART_WATER);
331*478af8d3SJacky Bai 	lpuart_regs[3] = mmio_read_32(IMX_LPUART5_BASE + LPUART_CTRL);
332*478af8d3SJacky Bai }
333*478af8d3SJacky Bai 
334*478af8d3SJacky Bai void lpuart_restore(void)
335*478af8d3SJacky Bai {
336*478af8d3SJacky Bai 	mmio_write_32(IMX_LPUART5_BASE + LPUART_BAUD, lpuart_regs[0]);
337*478af8d3SJacky Bai 	mmio_write_32(IMX_LPUART5_BASE + LPUART_FIFO, lpuart_regs[1]);
338*478af8d3SJacky Bai 	mmio_write_32(IMX_LPUART5_BASE + LPUART_WATER, lpuart_regs[2]);
339*478af8d3SJacky Bai 	mmio_write_32(IMX_LPUART5_BASE + LPUART_CTRL, lpuart_regs[3]);
340*478af8d3SJacky Bai }
341*478af8d3SJacky Bai 
342*478af8d3SJacky Bai bool is_lpav_owned_by_apd(void)
343*478af8d3SJacky Bai {
344*478af8d3SJacky Bai 	return (mmio_read_32(0x2802b044) & BIT(7)) ? true : false;
345*478af8d3SJacky Bai }
346*478af8d3SJacky Bai 
347*478af8d3SJacky Bai void lpav_ctx_save(void)
348*478af8d3SJacky Bai {
349*478af8d3SJacky Bai 	unsigned int i;
350*478af8d3SJacky Bai 	uint32_t val;
351*478af8d3SJacky Bai 
352*478af8d3SJacky Bai 	/* CGC2 save */
353*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(cgc2); i++) {
354*478af8d3SJacky Bai 		cgc2[i][1] = mmio_read_32(cgc2[i][0]);
355*478af8d3SJacky Bai 	}
356*478af8d3SJacky Bai 
357*478af8d3SJacky Bai 	/* PLL4 */
358*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pll4); i++) {
359*478af8d3SJacky Bai 		pll4[i][1] = mmio_read_32(pll4[i][0]);
360*478af8d3SJacky Bai 	}
361*478af8d3SJacky Bai 
362*478af8d3SJacky Bai 	/* PCC5 save */
363*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc5_0); i++) {
364*478af8d3SJacky Bai 		val = mmio_read_32(IMX_PCC5_BASE + i * 4);
365*478af8d3SJacky Bai 		if (val & PCC_PR) {
366*478af8d3SJacky Bai 			pcc5_0[i] = val;
367*478af8d3SJacky Bai 		}
368*478af8d3SJacky Bai 	}
369*478af8d3SJacky Bai 
370*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc5_1); i++) {
371*478af8d3SJacky Bai 		val = mmio_read_32(pcc5_1[i][0]);
372*478af8d3SJacky Bai 		if (val & PCC_PR) {
373*478af8d3SJacky Bai 			pcc5_1[i][1] = val;
374*478af8d3SJacky Bai 		}
375*478af8d3SJacky Bai 	}
376*478af8d3SJacky Bai 
377*478af8d3SJacky Bai 	/* LPAV SIM save */
378*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(lpav_sim); i++) {
379*478af8d3SJacky Bai 		lpav_sim[i][1] = mmio_read_32(lpav_sim[i][0]);
380*478af8d3SJacky Bai 	}
381*478af8d3SJacky Bai 
382*478af8d3SJacky Bai 	/* Save GPIO port D */
383*478af8d3SJacky Bai 	gpio_save(&lpav_gpio_ctx, LPAV_GPIO_CTRL_NUM);
384*478af8d3SJacky Bai 
385*478af8d3SJacky Bai 	/* put DDR into retention */
386*478af8d3SJacky Bai 	dram_enter_retention();
387*478af8d3SJacky Bai }
388*478af8d3SJacky Bai 
389*478af8d3SJacky Bai void lpav_ctx_restore(void)
390*478af8d3SJacky Bai {
391*478af8d3SJacky Bai 	unsigned int i;
392*478af8d3SJacky Bai 
393*478af8d3SJacky Bai 	/* PLL4 */
394*478af8d3SJacky Bai 	for (i = 0U; i < 9U; i++) {
395*478af8d3SJacky Bai 		mmio_write_32(pll4[i][0], pll4[i][1]);
396*478af8d3SJacky Bai 	}
397*478af8d3SJacky Bai 
398*478af8d3SJacky Bai 	/* wait for PLL4 lock */
399*478af8d3SJacky Bai 	while (!(mmio_read_32(pll4[8][0]) & BIT(24))) {
400*478af8d3SJacky Bai 		;
401*478af8d3SJacky Bai 	}
402*478af8d3SJacky Bai 
403*478af8d3SJacky Bai 	/* restore the PLL4 PFDs */
404*478af8d3SJacky Bai 	mmio_write_32(pll4[9][0], pll4[9][1] & ~(BIT(31) | BIT(23) | BIT(15) | BIT(7)));
405*478af8d3SJacky Bai 	mmio_write_32(pll4[9][0], pll4[9][1]);
406*478af8d3SJacky Bai 
407*478af8d3SJacky Bai 	/* wait for the PFD is stable */
408*478af8d3SJacky Bai 	while (!(mmio_read_32(pll4[9][0]) & PFD_VALID_MASK)) {
409*478af8d3SJacky Bai 		;
410*478af8d3SJacky Bai 	}
411*478af8d3SJacky Bai 
412*478af8d3SJacky Bai 	/* CGC2 restore */
413*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(cgc2); i++) {
414*478af8d3SJacky Bai 		mmio_write_32(cgc2[i][0], cgc2[i][1]);
415*478af8d3SJacky Bai 	}
416*478af8d3SJacky Bai 
417*478af8d3SJacky Bai 	/* PCC5 restore */
418*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc5_0); i++) {
419*478af8d3SJacky Bai 		if (pcc5_0[i] & PCC_PR) {
420*478af8d3SJacky Bai 			mmio_write_32(IMX_PCC5_BASE + i * 4, pcc5_0[i]);
421*478af8d3SJacky Bai 		}
422*478af8d3SJacky Bai 	}
423*478af8d3SJacky Bai 
424*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc5_1); i++) {
425*478af8d3SJacky Bai 		if (pcc5_1[i][1] & PCC_PR) {
426*478af8d3SJacky Bai 			mmio_write_32(pcc5_1[i][0], pcc5_1[i][1]);
427*478af8d3SJacky Bai 		}
428*478af8d3SJacky Bai 	}
429*478af8d3SJacky Bai 
430*478af8d3SJacky Bai 	/* LPAV_SIM */
431*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(lpav_sim); i++) {
432*478af8d3SJacky Bai 		mmio_write_32(lpav_sim[i][0], lpav_sim[i][1]);
433*478af8d3SJacky Bai 	}
434*478af8d3SJacky Bai 
435*478af8d3SJacky Bai 	gpio_restore(&lpav_gpio_ctx, LPAV_GPIO_CTRL_NUM);
436*478af8d3SJacky Bai 	/* DDR retention exit */
437*478af8d3SJacky Bai 	dram_exit_retention();
438*478af8d3SJacky Bai }
439*478af8d3SJacky Bai 
440*478af8d3SJacky Bai void imx_apd_ctx_save(unsigned int proc_num)
441*478af8d3SJacky Bai {
442*478af8d3SJacky Bai 	unsigned int i;
443*478af8d3SJacky Bai 	uint32_t val;
444*478af8d3SJacky Bai 
445*478af8d3SJacky Bai 	/* enable LPUART5's clock by default */
446*478af8d3SJacky Bai 	mmio_setbits_32(IMX_PCC3_BASE + 0xe8, BIT(30));
447*478af8d3SJacky Bai 
448*478af8d3SJacky Bai 	/* save the gic config */
449*478af8d3SJacky Bai 	plat_gic_save(proc_num, &imx_gicv3_ctx);
450*478af8d3SJacky Bai 
451*478af8d3SJacky Bai 	cmc1_pmprot = mmio_read_32(IMX_CMC1_BASE + 0x18);
452*478af8d3SJacky Bai 	cmc1_srie = mmio_read_32(IMX_CMC1_BASE + 0x8c);
453*478af8d3SJacky Bai 
454*478af8d3SJacky Bai 	/* save the PCC3 */
455*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc3); i++) {
456*478af8d3SJacky Bai 		/* save the pcc if it is exist */
457*478af8d3SJacky Bai 		val = mmio_read_32(IMX_PCC3_BASE + i * 4);
458*478af8d3SJacky Bai 		if (val & PCC_PR) {
459*478af8d3SJacky Bai 			pcc3[i] = val;
460*478af8d3SJacky Bai 		}
461*478af8d3SJacky Bai 	}
462*478af8d3SJacky Bai 
463*478af8d3SJacky Bai 	/* save the PCC4 */
464*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc4); i++) {
465*478af8d3SJacky Bai 		/* save the pcc if it is exist */
466*478af8d3SJacky Bai 		val = mmio_read_32(IMX_PCC4_BASE + i * 4);
467*478af8d3SJacky Bai 		if (val & PCC_PR) {
468*478af8d3SJacky Bai 			pcc4[i] = val;
469*478af8d3SJacky Bai 		}
470*478af8d3SJacky Bai 	}
471*478af8d3SJacky Bai 
472*478af8d3SJacky Bai 	/* save the CGC1 */
473*478af8d3SJacky Bai 	cgc1_save();
474*478af8d3SJacky Bai 
475*478af8d3SJacky Bai 	wdog3_save();
476*478af8d3SJacky Bai 
477*478af8d3SJacky Bai 	gpio_save(apd_gpio_ctx, APD_GPIO_CTRL_NUM);
478*478af8d3SJacky Bai 
479*478af8d3SJacky Bai 	iomuxc_save();
480*478af8d3SJacky Bai 
481*478af8d3SJacky Bai 	tpm5_save();
482*478af8d3SJacky Bai 
483*478af8d3SJacky Bai 	lpuart_save();
484*478af8d3SJacky Bai 
485*478af8d3SJacky Bai 	/*
486*478af8d3SJacky Bai 	 * save the lpav ctx & put the ddr into retention
487*478af8d3SJacky Bai 	 * if lpav master is assigned to APD domain.
488*478af8d3SJacky Bai 	 */
489*478af8d3SJacky Bai 	if (is_lpav_owned_by_apd()) {
490*478af8d3SJacky Bai 		lpav_ctx_save();
491*478af8d3SJacky Bai 	}
492*478af8d3SJacky Bai }
493*478af8d3SJacky Bai 
494*478af8d3SJacky Bai void xrdc_reinit(void)
495*478af8d3SJacky Bai {
496*478af8d3SJacky Bai 	xrdc_apply_apd_config();
497*478af8d3SJacky Bai 	xrdc_apply_lpav_config();
498*478af8d3SJacky Bai 
499*478af8d3SJacky Bai 	xrdc_enable();
500*478af8d3SJacky Bai }
501*478af8d3SJacky Bai 
502*478af8d3SJacky Bai void s400_release_caam(void)
503*478af8d3SJacky Bai {
504*478af8d3SJacky Bai 	uint32_t msg, resp;
505*478af8d3SJacky Bai 
506*478af8d3SJacky Bai 	mmio_write_32(S400_MU_TRx(0), 0x17d70206);
507*478af8d3SJacky Bai 	mmio_write_32(S400_MU_TRx(1), 0x7);
508*478af8d3SJacky Bai 
509*478af8d3SJacky Bai 	do {
510*478af8d3SJacky Bai 		resp = mmio_read_32(S400_MU_RSR);
511*478af8d3SJacky Bai 	} while ((resp & 0x3) != 0x3);
512*478af8d3SJacky Bai 
513*478af8d3SJacky Bai 	msg = mmio_read_32(S400_MU_RRx(0));
514*478af8d3SJacky Bai 	resp = mmio_read_32(S400_MU_RRx(1));
515*478af8d3SJacky Bai 
516*478af8d3SJacky Bai 	VERBOSE("resp %x; %x", msg, resp);
517*478af8d3SJacky Bai }
518*478af8d3SJacky Bai 
519*478af8d3SJacky Bai void imx_apd_ctx_restore(unsigned int proc_num)
520*478af8d3SJacky Bai {
521*478af8d3SJacky Bai 	unsigned int i;
522*478af8d3SJacky Bai 
523*478af8d3SJacky Bai 	/* restore the CCG1 */
524*478af8d3SJacky Bai 	cgc1_restore();
525*478af8d3SJacky Bai 
526*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc3); i++) {
527*478af8d3SJacky Bai 		/* save the pcc if it is exist */
528*478af8d3SJacky Bai 		if (pcc3[i] & PCC_PR) {
529*478af8d3SJacky Bai 			mmio_write_32(IMX_PCC3_BASE + i * 4, pcc3[i]);
530*478af8d3SJacky Bai 		}
531*478af8d3SJacky Bai 	}
532*478af8d3SJacky Bai 
533*478af8d3SJacky Bai 	for (i = 0U; i < ARRAY_SIZE(pcc4); i++) {
534*478af8d3SJacky Bai 		if (pcc4[i] & PCC_PR) {
535*478af8d3SJacky Bai 			mmio_write_32(IMX_PCC4_BASE + i * 4, pcc4[i]);
536*478af8d3SJacky Bai 		}
537*478af8d3SJacky Bai 	}
538*478af8d3SJacky Bai 
539*478af8d3SJacky Bai 	wdog3_restore();
540*478af8d3SJacky Bai 
541*478af8d3SJacky Bai 	iomuxc_restore();
542*478af8d3SJacky Bai 
543*478af8d3SJacky Bai 	gpio_restore(apd_gpio_ctx, APD_GPIO_CTRL_NUM);
544*478af8d3SJacky Bai 
545*478af8d3SJacky Bai 	tpm5_restore();
546*478af8d3SJacky Bai 
547*478af8d3SJacky Bai 	xrdc_reinit();
548*478af8d3SJacky Bai 
549*478af8d3SJacky Bai 	/* restore the gic config */
550*478af8d3SJacky Bai 	plat_gic_restore(proc_num, &imx_gicv3_ctx);
551*478af8d3SJacky Bai 
552*478af8d3SJacky Bai 	mmio_write_32(IMX_CMC1_BASE + 0x18, cmc1_pmprot);
553*478af8d3SJacky Bai 	mmio_write_32(IMX_CMC1_BASE + 0x8c, cmc1_srie);
554*478af8d3SJacky Bai 
555*478af8d3SJacky Bai 	/* enable LPUART5's clock by default */
556*478af8d3SJacky Bai 	mmio_setbits_32(IMX_PCC3_BASE + 0xe8, BIT(30));
557*478af8d3SJacky Bai 
558*478af8d3SJacky Bai 	/* restore the console lpuart */
559*478af8d3SJacky Bai 	lpuart_restore();
560*478af8d3SJacky Bai 
561*478af8d3SJacky Bai 	/* FIXME: make uart work for ATF */
562*478af8d3SJacky Bai 	mmio_write_32(IMX_LPUART_BASE + 0x18, 0xc0000);
563*478af8d3SJacky Bai 
564*478af8d3SJacky Bai 	/*
565*478af8d3SJacky Bai 	 * Ask S400 to release caam to APD as it is owned by s400
566*478af8d3SJacky Bai 	 */
567*478af8d3SJacky Bai 	s400_release_caam();
568*478af8d3SJacky Bai 
569*478af8d3SJacky Bai 	/* re-init the caam */
570*478af8d3SJacky Bai 	imx8ulp_caam_init();
571*478af8d3SJacky Bai 
572*478af8d3SJacky Bai 	/*
573*478af8d3SJacky Bai 	 * ack the upower, seems a necessary steps, otherwise the upower can
574*478af8d3SJacky Bai 	 * not response to the new API service call. put this just before the
575*478af8d3SJacky Bai 	 * ddr retention exit because that the dram retention exit flow need to
576*478af8d3SJacky Bai 	 * communicate with upower.
577*478af8d3SJacky Bai 	 */
578*478af8d3SJacky Bai 	upower_wait_resp();
579*478af8d3SJacky Bai 
580*478af8d3SJacky Bai 	/*
581*478af8d3SJacky Bai 	 * restore the lpav ctx & make ddr out of retention
582*478af8d3SJacky Bai 	 * if lpav master is assigned to APD domain.
583*478af8d3SJacky Bai 	 */
584*478af8d3SJacky Bai 	if (is_lpav_owned_by_apd()) {
585*478af8d3SJacky Bai 		lpav_ctx_restore();
586*478af8d3SJacky Bai 	}
587*478af8d3SJacky Bai }
588*478af8d3SJacky Bai 
589*478af8d3SJacky Bai #define DGO_CTRL1	U(0xc)
590*478af8d3SJacky Bai #define USB_WAKEUP	U(0x44)
591*478af8d3SJacky Bai #define USB1_PHY_DPD_WAKEUP_EN	BIT_32(5)
592*478af8d3SJacky Bai #define USB0_PHY_DPD_WAKEUP_EN	BIT_32(4)
593*478af8d3SJacky Bai #define USB1_PHY_WAKEUP_ISO_DISABLE	BIT_32(1)
594*478af8d3SJacky Bai #define USB0_PHY_WAKEUP_ISO_DISABLE	BIT_32(0)
595*478af8d3SJacky Bai 
596*478af8d3SJacky Bai void usb_wakeup_enable(bool enable)
597*478af8d3SJacky Bai {
598*478af8d3SJacky Bai 	if (enable) {
599*478af8d3SJacky Bai 		mmio_setbits_32(IMX_SIM1_BASE + USB_WAKEUP,
600*478af8d3SJacky Bai 				USB1_PHY_WAKEUP_ISO_DISABLE | USB0_PHY_WAKEUP_ISO_DISABLE);
601*478af8d3SJacky Bai 		mmio_setbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
602*478af8d3SJacky Bai 		while (!(mmio_read_32(IMX_SIM1_BASE + DGO_CTRL1) & BIT(1))) {
603*478af8d3SJacky Bai 			;
604*478af8d3SJacky Bai 		}
605*478af8d3SJacky Bai 
606*478af8d3SJacky Bai 		mmio_clrbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
607*478af8d3SJacky Bai 		mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(1));
608*478af8d3SJacky Bai 
609*478af8d3SJacky Bai 		/* Need to delay for a while to make sure the wakeup logic can work */
610*478af8d3SJacky Bai 		udelay(500);
611*478af8d3SJacky Bai 
612*478af8d3SJacky Bai 		mmio_setbits_32(IMX_SIM1_BASE + USB_WAKEUP,
613*478af8d3SJacky Bai 				USB1_PHY_DPD_WAKEUP_EN | USB0_PHY_DPD_WAKEUP_EN);
614*478af8d3SJacky Bai 		mmio_setbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
615*478af8d3SJacky Bai 		while (!(mmio_read_32(IMX_SIM1_BASE + DGO_CTRL1) & BIT(1))) {
616*478af8d3SJacky Bai 			;
617*478af8d3SJacky Bai 		}
618*478af8d3SJacky Bai 
619*478af8d3SJacky Bai 		mmio_clrbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
620*478af8d3SJacky Bai 		mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(1));
621*478af8d3SJacky Bai 	} else {
622*478af8d3SJacky Bai 		/*
623*478af8d3SJacky Bai 		 * USBx_PHY_DPD_WAKEUP_EN should be cleared before USB0_PHY_WAKEUP_ISO_DISABLE
624*478af8d3SJacky Bai 		 * to provide the correct the wake-up functionality.
625*478af8d3SJacky Bai 		 */
626*478af8d3SJacky Bai 		mmio_write_32(IMX_SIM1_BASE + USB_WAKEUP, USB1_PHY_WAKEUP_ISO_DISABLE |
627*478af8d3SJacky Bai 			USB0_PHY_WAKEUP_ISO_DISABLE);
628*478af8d3SJacky Bai 		mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
629*478af8d3SJacky Bai 		while (!(mmio_read_32(IMX_SIM1_BASE + DGO_CTRL1) & BIT(1))) {
630*478af8d3SJacky Bai 			;
631*478af8d3SJacky Bai 		}
632*478af8d3SJacky Bai 
633*478af8d3SJacky Bai 		mmio_clrbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
634*478af8d3SJacky Bai 		mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(1));
635*478af8d3SJacky Bai 	}
636*478af8d3SJacky Bai }
637