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