xref: /rk3399_ARM-atf/plat/imx/imx8m/imx8mn/gpc.c (revision 44dea5444b087acd758b1c8370999be635e17e43)
158fdd608SJacky Bai /*
2*44dea544SJacky Bai  * Copyright 2019-2022 NXP
358fdd608SJacky Bai  *
458fdd608SJacky Bai  * SPDX-License-Identifier: BSD-3-Clause
558fdd608SJacky Bai  */
658fdd608SJacky Bai 
758fdd608SJacky Bai #include <stdbool.h>
858fdd608SJacky Bai #include <stdint.h>
958fdd608SJacky Bai #include <stdlib.h>
1058fdd608SJacky Bai 
1158fdd608SJacky Bai #include <common/debug.h>
1258fdd608SJacky Bai #include <drivers/delay_timer.h>
1358fdd608SJacky Bai #include <lib/mmio.h>
1458fdd608SJacky Bai #include <lib/psci/psci.h>
1558fdd608SJacky Bai #include <lib/smccc.h>
1658fdd608SJacky Bai #include <services/std_svc.h>
1758fdd608SJacky Bai 
1858fdd608SJacky Bai #include <gpc.h>
1958fdd608SJacky Bai #include <imx_sip_svc.h>
2058fdd608SJacky Bai #include <platform_def.h>
2158fdd608SJacky Bai 
2258fdd608SJacky Bai #define CCGR(x)		(0x4000 + (x) * 0x10)
2358fdd608SJacky Bai 
24*44dea544SJacky Bai #define MIPI_PWR_REQ		BIT(0)
25*44dea544SJacky Bai #define OTG1_PWR_REQ		BIT(2)
26*44dea544SJacky Bai #define HSIOMIX_PWR_REQ		BIT(4)
27*44dea544SJacky Bai #define GPUMIX_PWR_REQ		BIT(7)
28*44dea544SJacky Bai #define DISPMIX_PWR_REQ		BIT(10)
29*44dea544SJacky Bai 
30*44dea544SJacky Bai #define HSIOMIX_ADB400_SYNC	BIT(5)
31*44dea544SJacky Bai #define DISPMIX_ADB400_SYNC	BIT(7)
32*44dea544SJacky Bai #define GPUMIX_ADB400_SYNC	(0x5 << 9)
33*44dea544SJacky Bai #define HSIOMIX_ADB400_ACK	BIT(23)
34*44dea544SJacky Bai #define DISPMIX_ADB400_ACK	BIT(25)
35*44dea544SJacky Bai #define GPUMIX_ADB400_ACK	(0x5 << 27)
36*44dea544SJacky Bai 
37*44dea544SJacky Bai #define MIPI_PGC		0xc00
38*44dea544SJacky Bai #define OTG1_PGC		0xc80
39*44dea544SJacky Bai #define HSIOMIX_PGC	        0xd00
40*44dea544SJacky Bai #define GPUMIX_PGC		0xdc0
41*44dea544SJacky Bai #define DISPMIX_PGC		0xe80
42*44dea544SJacky Bai 
43*44dea544SJacky Bai enum pu_domain_id {
44*44dea544SJacky Bai 	HSIOMIX,
45*44dea544SJacky Bai 	OTG1 = 2,
46*44dea544SJacky Bai 	GPUMIX = 4,
47*44dea544SJacky Bai 	DISPMIX = 9,
48*44dea544SJacky Bai 	MIPI,
49*44dea544SJacky Bai };
50*44dea544SJacky Bai 
51*44dea544SJacky Bai /* PU domain, add some hole to minimize the uboot change */
52*44dea544SJacky Bai static struct imx_pwr_domain pu_domains[11] = {
53*44dea544SJacky Bai 	[HSIOMIX] = IMX_MIX_DOMAIN(HSIOMIX, false),
54*44dea544SJacky Bai 	[OTG1] = IMX_PD_DOMAIN(OTG1, true),
55*44dea544SJacky Bai 	[GPUMIX] = IMX_MIX_DOMAIN(GPUMIX, false),
56*44dea544SJacky Bai 	[DISPMIX] = IMX_MIX_DOMAIN(DISPMIX, false),
57*44dea544SJacky Bai 	[MIPI] = IMX_PD_DOMAIN(MIPI, true),
58*44dea544SJacky Bai };
59*44dea544SJacky Bai 
60*44dea544SJacky Bai static unsigned int pu_domain_status;
61*44dea544SJacky Bai 
62*44dea544SJacky Bai void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
63*44dea544SJacky Bai {
64*44dea544SJacky Bai 	if (domain_id > MIPI) {
65*44dea544SJacky Bai 		return;
66*44dea544SJacky Bai 	}
67*44dea544SJacky Bai 
68*44dea544SJacky Bai 	struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
69*44dea544SJacky Bai 
70*44dea544SJacky Bai 	if (on) {
71*44dea544SJacky Bai 		if (pwr_domain->need_sync) {
72*44dea544SJacky Bai 			pu_domain_status |= (1 << domain_id);
73*44dea544SJacky Bai 		}
74*44dea544SJacky Bai 
75*44dea544SJacky Bai 		/* HSIOMIX has no PU bit, so skip for it */
76*44dea544SJacky Bai 		if (domain_id != HSIOMIX) {
77*44dea544SJacky Bai 			/* clear the PGC bit */
78*44dea544SJacky Bai 			mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
79*44dea544SJacky Bai 
80*44dea544SJacky Bai 			/* power up the domain */
81*44dea544SJacky Bai 			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
82*44dea544SJacky Bai 
83*44dea544SJacky Bai 			/* wait for power request done */
84*44dea544SJacky Bai 			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req) {
85*44dea544SJacky Bai 				;
86*44dea544SJacky Bai 			}
87*44dea544SJacky Bai 		}
88*44dea544SJacky Bai 
89*44dea544SJacky Bai 		if (domain_id == DISPMIX) {
90*44dea544SJacky Bai 			/* de-reset bus_blk clk and
91*44dea544SJacky Bai 			 * enable bus_blk clk
92*44dea544SJacky Bai 			 */
93*44dea544SJacky Bai 			mmio_write_32(0x32e28000, 0x100);
94*44dea544SJacky Bai 			mmio_write_32(0x32e28004, 0x100);
95*44dea544SJacky Bai 		}
96*44dea544SJacky Bai 
97*44dea544SJacky Bai 		/* handle the ADB400 sync */
98*44dea544SJacky Bai 		if (pwr_domain->need_sync) {
99*44dea544SJacky Bai 			/* clear adb power down request */
100*44dea544SJacky Bai 			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
101*44dea544SJacky Bai 
102*44dea544SJacky Bai 			/* wait for adb power request ack */
103*44dea544SJacky Bai 			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
104*44dea544SJacky Bai 				;
105*44dea544SJacky Bai 			}
106*44dea544SJacky Bai 		}
107*44dea544SJacky Bai 	} else {
108*44dea544SJacky Bai 		pu_domain_status &= ~(1 << domain_id);
109*44dea544SJacky Bai 
110*44dea544SJacky Bai 		if (domain_id == OTG1) {
111*44dea544SJacky Bai 			return;
112*44dea544SJacky Bai 		}
113*44dea544SJacky Bai 
114*44dea544SJacky Bai 		/* handle the ADB400 sync */
115*44dea544SJacky Bai 		if (pwr_domain->need_sync) {
116*44dea544SJacky Bai 
117*44dea544SJacky Bai 			/* set adb power down request */
118*44dea544SJacky Bai 			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
119*44dea544SJacky Bai 
120*44dea544SJacky Bai 			/* wait for adb power request ack */
121*44dea544SJacky Bai 			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack)) {
122*44dea544SJacky Bai 				;
123*44dea544SJacky Bai 			}
124*44dea544SJacky Bai 		}
125*44dea544SJacky Bai 
126*44dea544SJacky Bai 		/* HSIOMIX has no PU bit, so skip for it */
127*44dea544SJacky Bai 		if (domain_id != HSIOMIX) {
128*44dea544SJacky Bai 			/* set the PGC bit */
129*44dea544SJacky Bai 			mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
130*44dea544SJacky Bai 
131*44dea544SJacky Bai 			/* power down the domain */
132*44dea544SJacky Bai 			mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
133*44dea544SJacky Bai 
134*44dea544SJacky Bai 			/* wait for power request done */
135*44dea544SJacky Bai 			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req) {
136*44dea544SJacky Bai 				;
137*44dea544SJacky Bai 			}
138*44dea544SJacky Bai 		}
139*44dea544SJacky Bai 	}
140*44dea544SJacky Bai }
141*44dea544SJacky Bai 
14258fdd608SJacky Bai void imx_gpc_init(void)
14358fdd608SJacky Bai {
14458fdd608SJacky Bai 	unsigned int val;
14558fdd608SJacky Bai 	int i;
14658fdd608SJacky Bai 
14758fdd608SJacky Bai 	/* mask all the wakeup irq by default */
14858fdd608SJacky Bai 	for (i = 0; i < 4; i++) {
14958fdd608SJacky Bai 		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
15058fdd608SJacky Bai 		mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
15158fdd608SJacky Bai 		mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
15258fdd608SJacky Bai 		mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
15358fdd608SJacky Bai 		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
15458fdd608SJacky Bai 	}
15558fdd608SJacky Bai 
15658fdd608SJacky Bai 	val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
15758fdd608SJacky Bai 	/* use GIC wake_request to wakeup C0~C3 from LPM */
15858fdd608SJacky Bai 	val |= CORE_WKUP_FROM_GIC;
15958fdd608SJacky Bai 	/* clear the MASTER0 LPM handshake */
16058fdd608SJacky Bai 	val &= ~MASTER0_LPM_HSK;
16158fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
16258fdd608SJacky Bai 
16358fdd608SJacky Bai 	/* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
16458fdd608SJacky Bai 	mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
16558fdd608SJacky Bai 		MASTER2_MAPPING));
16658fdd608SJacky Bai 
16758fdd608SJacky Bai 	/* set all mix/PU in A53 domain */
16858fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xffff);
16958fdd608SJacky Bai 
17058fdd608SJacky Bai 	/*
17158fdd608SJacky Bai 	 * Set the CORE & SCU power up timing:
17258fdd608SJacky Bai 	 * SW = 0x1, SW2ISO = 0x1;
17358fdd608SJacky Bai 	 * the CPU CORE and SCU power up timming counter
17458fdd608SJacky Bai 	 * is drived  by 32K OSC, each domain's power up
17558fdd608SJacky Bai 	 * latency is (SW + SW2ISO) / 32768
17658fdd608SJacky Bai 	 */
17758fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401);
17858fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401);
17958fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401);
18058fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401);
18158fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401);
18258fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
18358fdd608SJacky Bai 		      (0x59 << TMC_TMR_SHIFT) | 0x5B | (0x2 << TRC1_TMC_SHIFT));
18458fdd608SJacky Bai 
18558fdd608SJacky Bai 	/* set DUMMY PDN/PUP ACK by default for A53 domain */
18658fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
18758fdd608SJacky Bai 		      A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
18858fdd608SJacky Bai 
18958fdd608SJacky Bai 	/* clear DSM by default */
19058fdd608SJacky Bai 	val = mmio_read_32(IMX_GPC_BASE + SLPCR);
19158fdd608SJacky Bai 	val &= ~SLPCR_EN_DSM;
19258fdd608SJacky Bai 	/* enable the fast wakeup wait mode */
19358fdd608SJacky Bai 	val |= SLPCR_A53_FASTWUP_WAIT_MODE;
19458fdd608SJacky Bai 	/* clear the RBC */
19558fdd608SJacky Bai 	val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
19658fdd608SJacky Bai 	/* set the STBY_COUNT to 0x5, (128 * 30)us */
19758fdd608SJacky Bai 	val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
19858fdd608SJacky Bai 	val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
19958fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + SLPCR, val);
20058fdd608SJacky Bai 
20158fdd608SJacky Bai 	/*
20258fdd608SJacky Bai 	 * USB PHY power up needs to make sure RESET bit in SRC is clear,
20358fdd608SJacky Bai 	 * otherwise, the PU power up bit in GPC will NOT self-cleared.
20458fdd608SJacky Bai 	 * only need to do it once.
20558fdd608SJacky Bai 	 */
20658fdd608SJacky Bai 	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
20758fdd608SJacky Bai 
20858fdd608SJacky Bai 	/* enable all the power domain by default */
20958fdd608SJacky Bai 	for (i = 0; i < 103; i++)
21058fdd608SJacky Bai 		mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3);
21158fdd608SJacky Bai 	mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x485);
21258fdd608SJacky Bai }
213