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