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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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