123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657 |
- /*
- * Copyright 2021-2024 NXP
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include <stdbool.h>
- #include <drivers/delay_timer.h>
- #include <lib/mmio.h>
- #include <plat_imx8.h>
- #include <xrdc.h>
- #define PCC_PR BIT(31)
- #define PFD_VALID_MASK U(0x40404040)
- #define S400_MU_BASE U(0x27020000)
- #define S400_MU_RSR (S400_MU_BASE + 0x12c)
- #define S400_MU_TRx(i) (S400_MU_BASE + 0x200 + (i) * 4)
- #define S400_MU_RRx(i) (S400_MU_BASE + 0x280 + (i) * 4)
- /*
- * need to re-init the PLL, CGC1, PCC, CMC, XRDC, SIM, GPIO etc.
- * init the PLL &PFD first, then switch the CA35 clock to PLL for
- * performance consideration, restore other bus fabric clock.
- */
- extern void imx8ulp_caam_init(void);
- extern void upower_wait_resp(void);
- extern void dram_enter_retention(void);
- extern void dram_exit_retention(void);
- struct plat_gic_ctx imx_gicv3_ctx;
- static uint32_t cmc1_pmprot;
- static uint32_t cmc1_srie;
- /* TPM5: global timer */
- static uint32_t tpm5[3];
- static uint32_t wdog3[2];
- /* CGC1 PLL2 */
- uint32_t pll2[][2] = {
- {0x292c0510, 0x0}, {0x292c0518, 0x0}, {0x292c051c, 0x0},
- {0x292c0520, 0x0}, {0x292c0500, 0x0},
- };
- /* CGC1 PLL3 */
- uint32_t pll3[][2] = {
- {0x292c0604, 0x0}, {0x292c0608, 0x0}, {0x292c060c, 0x0},
- {0x292c0610, 0x0}, {0x292c0618, 0x0}, {0x292c061c, 0x0},
- {0x292c0620, 0x0}, {0x292c0624, 0x0}, {0x292c0600, 0x0},
- {0x292c0614, 0x0},
- };
- /* CGC1 others */
- uint32_t cgc1[][2] = {
- {0x292c0014, 0x0}, {0x292c0034, 0x0}, {0x292c0038, 0x0},
- {0x292c0108, 0x0}, {0x292c0208, 0x0}, {0x292c0700, 0x0},
- {0x292c0810, 0x0}, {0x292c0900, 0x0}, {0x292c0904, 0x0},
- {0x292c0908, 0x0}, {0x292c090c, 0x0}, {0x292c0a00, 0x0},
- };
- static uint32_t pcc3[61];
- static uint32_t pcc4[32];
- static uint32_t pcc5_0[33];
- static uint32_t pcc5_1[][2] = {
- {0x2da70084, 0x0}, {0x2da70088, 0x0}, {0x2da7008c, 0x0},
- {0x2da700a0, 0x0}, {0x2da700a4, 0x0}, {0x2da700a8, 0x0},
- {0x2da700ac, 0x0}, {0x2da700b0, 0x0}, {0x2da700b4, 0x0},
- {0x2da700bc, 0x0}, {0x2da700c0, 0x0}, {0x2da700c8, 0x0},
- {0x2da700cc, 0x0}, {0x2da700d0, 0x0}, {0x2da700f0, 0x0},
- {0x2da700f4, 0x0}, {0x2da700f8, 0x0}, {0x2da70108, 0x0},
- {0x2da7010c, 0x0}, {0x2da70110, 0x0}, {0x2da70114, 0x0},
- };
- static uint32_t cgc2[][2] = {
- {0x2da60014, 0x0}, {0x2da60020, 0x0}, {0x2da6003c, 0x0},
- {0x2da60040, 0x0}, {0x2da60108, 0x0}, {0x2da60208, 0x0},
- {0x2da60900, 0x0}, {0x2da60904, 0x0}, {0x2da60908, 0x0},
- {0x2da60910, 0x0}, {0x2da60a00, 0x0},
- };
- static uint32_t pll4[][2] = {
- {0x2da60604, 0x0}, {0x2da60608, 0x0}, {0x2da6060c, 0x0},
- {0x2da60610, 0x0}, {0x2da60618, 0x0}, {0x2da6061c, 0x0},
- {0x2da60620, 0x0}, {0x2da60624, 0x0}, {0x2da60600, 0x0},
- {0x2da60614, 0x0},
- };
- static uint32_t lpav_sim[][2] = {
- {0x2da50000, 0x0}, {0x2da50004, 0x0}, {0x2da50008, 0x0},
- {0x2da5001c, 0x0}, {0x2da50020, 0x0}, {0x2da50024, 0x0},
- {0x2da50034, 0x0},
- };
- #define APD_GPIO_CTRL_NUM 2
- #define LPAV_GPIO_CTRL_NUM 1
- #define GPIO_CTRL_REG_NUM 8
- #define GPIO_PIN_MAX_NUM 32
- #define GPIO_CTX(addr, num) \
- {.base = (addr), .pin_num = (num), }
- struct gpio_ctx {
- /* gpio base */
- uintptr_t base;
- /* port control */
- uint32_t port_ctrl[GPIO_CTRL_REG_NUM];
- /* GPIO ICR, Max 32 */
- uint32_t pin_num;
- uint32_t gpio_icr[GPIO_PIN_MAX_NUM];
- };
- static uint32_t gpio_ctrl_offset[GPIO_CTRL_REG_NUM] = {
- 0xc, 0x10, 0x14, 0x18, 0x1c, 0x40, 0x54, 0x58
- };
- static struct gpio_ctx apd_gpio_ctx[APD_GPIO_CTRL_NUM] = {
- GPIO_CTX(IMX_GPIOE_BASE, 24),
- GPIO_CTX(IMX_GPIOF_BASE, 32),
- };
- static struct gpio_ctx lpav_gpio_ctx = GPIO_CTX(IMX_GPIOD_BASE, 24);
- /* iomuxc setting */
- #define IOMUXC_SECTION_NUM 8
- struct iomuxc_section {
- uint32_t offset;
- uint32_t reg_num;
- };
- struct iomuxc_section iomuxc_sections[IOMUXC_SECTION_NUM] = {
- {.offset = IOMUXC_PTD_PCR_BASE, .reg_num = 24},
- {.offset = IOMUXC_PTE_PCR_BASE, .reg_num = 24},
- {.offset = IOMUXC_PTF_PCR_BASE, .reg_num = 32},
- {.offset = IOMUXC_PSMI_BASE0, .reg_num = 10},
- {.offset = IOMUXC_PSMI_BASE1, .reg_num = 61},
- {.offset = IOMUXC_PSMI_BASE2, .reg_num = 12},
- {.offset = IOMUXC_PSMI_BASE3, .reg_num = 20},
- {.offset = IOMUXC_PSMI_BASE4, .reg_num = 75},
- };
- static uint32_t iomuxc_ctx[258];
- #define PORTS_NUM 3U
- void apd_io_pad_off(void)
- {
- unsigned int i, j;
- /* off the PTD/E/F, need to be customized based on actual user case */
- for (i = 0; i < PORTS_NUM; i++) {
- for (j = 0; j < iomuxc_sections[i].reg_num; j++) {
- mmio_write_32(iomuxc_sections[i].offset + j * 4, 0);
- }
- }
- /* disable the PTD compensation */
- mmio_write_32(IMX_SIM1_BASE + 0x48, 0x800);
- }
- void iomuxc_save(void)
- {
- unsigned int i, j;
- unsigned int index = 0U;
- for (i = 0U; i < IOMUXC_SECTION_NUM; i++) {
- for (j = 0U; j < iomuxc_sections[i].reg_num; j++) {
- iomuxc_ctx[index++] = mmio_read_32(iomuxc_sections[i].offset + j * 4);
- }
- }
- apd_io_pad_off();
- }
- void iomuxc_restore(void)
- {
- unsigned int i, j;
- unsigned int index = 0U;
- for (i = 0U; i < IOMUXC_SECTION_NUM; i++) {
- for (j = 0U; j < iomuxc_sections[i].reg_num; j++) {
- mmio_write_32(iomuxc_sections[i].offset + j * 4, iomuxc_ctx[index++]);
- }
- }
- }
- void gpio_save(struct gpio_ctx *ctx, int port_num)
- {
- unsigned int i, j;
- for (i = 0U; i < port_num; i++) {
- /* save the port control setting */
- for (j = 0U; j < GPIO_CTRL_REG_NUM; j++) {
- if (j < 4U) {
- ctx->port_ctrl[j] = mmio_read_32(ctx->base + gpio_ctrl_offset[j]);
- /*
- * clear the permission setting to read the GPIO
- * non-secure world setting.
- */
- mmio_write_32(ctx->base + gpio_ctrl_offset[j], 0x0);
- } else {
- ctx->port_ctrl[j] = mmio_read_32(ctx->base + gpio_ctrl_offset[j]);
- }
- }
- /* save the gpio icr setting */
- for (j = 0U; j < ctx->pin_num; j++) {
- ctx->gpio_icr[j] = mmio_read_32(ctx->base + 0x80 + j * 4);
- }
- ctx++;
- }
- }
- void gpio_restore(struct gpio_ctx *ctx, int port_num)
- {
- unsigned int i, j;
- for (i = 0U; i < port_num; i++) {
- for (j = 0U; j < ctx->pin_num; j++)
- mmio_write_32(ctx->base + 0x80 + j * 4, ctx->gpio_icr[j]);
- for (j = 4U; j < GPIO_CTRL_REG_NUM; j++) {
- mmio_write_32(ctx->base + gpio_ctrl_offset[j], ctx->port_ctrl[j]);
- }
- /* permission config retore last */
- for (j = 0U; j < 4; j++) {
- mmio_write_32(ctx->base + gpio_ctrl_offset[j], ctx->port_ctrl[j]);
- }
- ctx++;
- }
- }
- void cgc1_save(void)
- {
- unsigned int i;
- /* PLL2 */
- for (i = 0U; i < ARRAY_SIZE(pll2); i++) {
- pll2[i][1] = mmio_read_32(pll2[i][0]);
- }
- /* PLL3 */
- for (i = 0U; i < ARRAY_SIZE(pll3); i++) {
- pll3[i][1] = mmio_read_32(pll3[i][0]);
- }
- /* CGC1 others */
- for (i = 0U; i < ARRAY_SIZE(cgc1); i++) {
- cgc1[i][1] = mmio_read_32(cgc1[i][0]);
- }
- }
- void cgc1_restore(void)
- {
- unsigned int i;
- /* PLL2 */
- for (i = 0U; i < ARRAY_SIZE(pll2); i++) {
- mmio_write_32(pll2[i][0], pll2[i][1]);
- }
- /* wait for PLL2 lock */
- while (!(mmio_read_32(pll2[4][0]) & BIT(24))) {
- ;
- }
- /* PLL3 */
- for (i = 0U; i < 9U; i++) {
- mmio_write_32(pll3[i][0], pll3[i][1]);
- }
- /* wait for PLL3 lock */
- while (!(mmio_read_32(pll3[4][0]) & BIT(24))) {
- ;
- }
- /* restore the PFDs */
- mmio_write_32(pll3[9][0], pll3[9][1] & ~(BIT(31) | BIT(23) | BIT(15) | BIT(7)));
- mmio_write_32(pll3[9][0], pll3[9][1]);
- /* wait for the PFD is stable, only need to check the enabled PFDs */
- while (!(mmio_read_32(pll3[9][0]) & PFD_VALID_MASK)) {
- ;
- }
- /* CGC1 others */
- for (i = 0U; i < ARRAY_SIZE(cgc1); i++) {
- mmio_write_32(cgc1[i][0], cgc1[i][1]);
- }
- }
- void tpm5_save(void)
- {
- tpm5[0] = mmio_read_32(IMX_TPM5_BASE + 0x10);
- tpm5[1] = mmio_read_32(IMX_TPM5_BASE + 0x18);
- tpm5[2] = mmio_read_32(IMX_TPM5_BASE + 0x20);
- }
- void tpm5_restore(void)
- {
- mmio_write_32(IMX_TPM5_BASE + 0x10, tpm5[0]);
- mmio_write_32(IMX_TPM5_BASE + 0x18, tpm5[1]);
- mmio_write_32(IMX_TPM5_BASE + 0x20, tpm5[2]);
- }
- void wdog3_save(void)
- {
- /* enable wdog3 clock */
- mmio_write_32(IMX_PCC3_BASE + 0xa8, 0xd2800000);
- /* save the CS & TOVAL regiter */
- wdog3[0] = mmio_read_32(IMX_WDOG3_BASE);
- wdog3[1] = mmio_read_32(IMX_WDOG3_BASE + 0x8);
- }
- void wdog3_restore(void)
- {
- /* enable wdog3 clock */
- mmio_write_32(IMX_PCC3_BASE + 0xa8, 0xd2800000);
- /* reconfig the CS */
- mmio_write_32(IMX_WDOG3_BASE, wdog3[0]);
- /* set the tiemout value */
- mmio_write_32(IMX_WDOG3_BASE + 0x8, wdog3[1]);
- /* wait for the lock status */
- while ((mmio_read_32(IMX_WDOG3_BASE) & BIT(11))) {
- ;
- }
- /* wait for the config done */
- while (!(mmio_read_32(IMX_WDOG3_BASE) & BIT(10))) {
- ;
- }
- }
- static uint32_t lpuart_regs[4];
- #define LPUART_BAUD 0x10
- #define LPUART_CTRL 0x18
- #define LPUART_FIFO 0x28
- #define LPUART_WATER 0x2c
- void lpuart_save(void)
- {
- lpuart_regs[0] = mmio_read_32(IMX_LPUART5_BASE + LPUART_BAUD);
- lpuart_regs[1] = mmio_read_32(IMX_LPUART5_BASE + LPUART_FIFO);
- lpuart_regs[2] = mmio_read_32(IMX_LPUART5_BASE + LPUART_WATER);
- lpuart_regs[3] = mmio_read_32(IMX_LPUART5_BASE + LPUART_CTRL);
- }
- void lpuart_restore(void)
- {
- mmio_write_32(IMX_LPUART5_BASE + LPUART_BAUD, lpuart_regs[0]);
- mmio_write_32(IMX_LPUART5_BASE + LPUART_FIFO, lpuart_regs[1]);
- mmio_write_32(IMX_LPUART5_BASE + LPUART_WATER, lpuart_regs[2]);
- mmio_write_32(IMX_LPUART5_BASE + LPUART_CTRL, lpuart_regs[3]);
- }
- bool is_lpav_owned_by_apd(void)
- {
- return (mmio_read_32(0x2802b044) & BIT(7)) ? true : false;
- }
- void lpav_ctx_save(void)
- {
- unsigned int i;
- uint32_t val;
- /* CGC2 save */
- for (i = 0U; i < ARRAY_SIZE(cgc2); i++) {
- cgc2[i][1] = mmio_read_32(cgc2[i][0]);
- }
- /* PLL4 */
- for (i = 0U; i < ARRAY_SIZE(pll4); i++) {
- pll4[i][1] = mmio_read_32(pll4[i][0]);
- }
- /* PCC5 save */
- for (i = 0U; i < ARRAY_SIZE(pcc5_0); i++) {
- val = mmio_read_32(IMX_PCC5_BASE + i * 4);
- if (val & PCC_PR) {
- pcc5_0[i] = val;
- }
- }
- for (i = 0U; i < ARRAY_SIZE(pcc5_1); i++) {
- val = mmio_read_32(pcc5_1[i][0]);
- if (val & PCC_PR) {
- pcc5_1[i][1] = val;
- }
- }
- /* LPAV SIM save */
- for (i = 0U; i < ARRAY_SIZE(lpav_sim); i++) {
- lpav_sim[i][1] = mmio_read_32(lpav_sim[i][0]);
- }
- /* Save GPIO port D */
- gpio_save(&lpav_gpio_ctx, LPAV_GPIO_CTRL_NUM);
- /* put DDR into retention */
- dram_enter_retention();
- }
- void lpav_ctx_restore(void)
- {
- unsigned int i;
- /* PLL4 */
- for (i = 0U; i < 9U; i++) {
- mmio_write_32(pll4[i][0], pll4[i][1]);
- }
- /* wait for PLL4 lock */
- while (!(mmio_read_32(pll4[8][0]) & BIT(24))) {
- ;
- }
- /* restore the PLL4 PFDs */
- mmio_write_32(pll4[9][0], pll4[9][1] & ~(BIT(31) | BIT(23) | BIT(15) | BIT(7)));
- mmio_write_32(pll4[9][0], pll4[9][1]);
- /* wait for the PFD is stable */
- while (!(mmio_read_32(pll4[9][0]) & PFD_VALID_MASK)) {
- ;
- }
- /* CGC2 restore */
- for (i = 0U; i < ARRAY_SIZE(cgc2); i++) {
- mmio_write_32(cgc2[i][0], cgc2[i][1]);
- }
- /* PCC5 restore */
- for (i = 0U; i < ARRAY_SIZE(pcc5_0); i++) {
- if (pcc5_0[i] & PCC_PR) {
- mmio_write_32(IMX_PCC5_BASE + i * 4, pcc5_0[i]);
- }
- }
- for (i = 0U; i < ARRAY_SIZE(pcc5_1); i++) {
- if (pcc5_1[i][1] & PCC_PR) {
- mmio_write_32(pcc5_1[i][0], pcc5_1[i][1]);
- }
- }
- /* LPAV_SIM */
- for (i = 0U; i < ARRAY_SIZE(lpav_sim); i++) {
- mmio_write_32(lpav_sim[i][0], lpav_sim[i][1]);
- }
- gpio_restore(&lpav_gpio_ctx, LPAV_GPIO_CTRL_NUM);
- /* DDR retention exit */
- dram_exit_retention();
- }
- void imx_apd_ctx_save(unsigned int proc_num)
- {
- unsigned int i;
- uint32_t val;
- /* enable LPUART5's clock by default */
- mmio_setbits_32(IMX_PCC3_BASE + 0xe8, BIT(30));
- /* save the gic config */
- plat_gic_save(proc_num, &imx_gicv3_ctx);
- cmc1_pmprot = mmio_read_32(IMX_CMC1_BASE + 0x18);
- cmc1_srie = mmio_read_32(IMX_CMC1_BASE + 0x8c);
- /* save the PCC3 */
- for (i = 0U; i < ARRAY_SIZE(pcc3); i++) {
- /* save the pcc if it is exist */
- val = mmio_read_32(IMX_PCC3_BASE + i * 4);
- if (val & PCC_PR) {
- pcc3[i] = val;
- }
- }
- /* save the PCC4 */
- for (i = 0U; i < ARRAY_SIZE(pcc4); i++) {
- /* save the pcc if it is exist */
- val = mmio_read_32(IMX_PCC4_BASE + i * 4);
- if (val & PCC_PR) {
- pcc4[i] = val;
- }
- }
- /* save the CGC1 */
- cgc1_save();
- wdog3_save();
- gpio_save(apd_gpio_ctx, APD_GPIO_CTRL_NUM);
- iomuxc_save();
- tpm5_save();
- lpuart_save();
- /*
- * save the lpav ctx & put the ddr into retention
- * if lpav master is assigned to APD domain.
- */
- if (is_lpav_owned_by_apd()) {
- lpav_ctx_save();
- }
- }
- void xrdc_reinit(void)
- {
- xrdc_apply_apd_config();
- xrdc_apply_lpav_config();
- xrdc_enable();
- }
- void s400_release_caam(void)
- {
- uint32_t msg, resp;
- mmio_write_32(S400_MU_TRx(0), 0x17d70206);
- mmio_write_32(S400_MU_TRx(1), 0x7);
- do {
- resp = mmio_read_32(S400_MU_RSR);
- } while ((resp & 0x3) != 0x3);
- msg = mmio_read_32(S400_MU_RRx(0));
- resp = mmio_read_32(S400_MU_RRx(1));
- VERBOSE("resp %x; %x", msg, resp);
- }
- void imx_apd_ctx_restore(unsigned int proc_num)
- {
- unsigned int i;
- /* restore the CCG1 */
- cgc1_restore();
- for (i = 0U; i < ARRAY_SIZE(pcc3); i++) {
- /* save the pcc if it is exist */
- if (pcc3[i] & PCC_PR) {
- mmio_write_32(IMX_PCC3_BASE + i * 4, pcc3[i]);
- }
- }
- for (i = 0U; i < ARRAY_SIZE(pcc4); i++) {
- if (pcc4[i] & PCC_PR) {
- mmio_write_32(IMX_PCC4_BASE + i * 4, pcc4[i]);
- }
- }
- wdog3_restore();
- iomuxc_restore();
- tpm5_restore();
- xrdc_reinit();
- /* Restore GPIO after xrdc_reinit, otherwise MSCs are invalid */
- gpio_restore(apd_gpio_ctx, APD_GPIO_CTRL_NUM);
- /* restore the gic config */
- plat_gic_restore(proc_num, &imx_gicv3_ctx);
- mmio_write_32(IMX_CMC1_BASE + 0x18, cmc1_pmprot);
- mmio_write_32(IMX_CMC1_BASE + 0x8c, cmc1_srie);
- /* enable LPUART5's clock by default */
- mmio_setbits_32(IMX_PCC3_BASE + 0xe8, BIT(30));
- /* restore the console lpuart */
- lpuart_restore();
- /* FIXME: make uart work for ATF */
- mmio_write_32(IMX_LPUART_BASE + 0x18, 0xc0000);
- /* Allow M core to reset A core */
- mmio_clrbits_32(IMX_MU0B_BASE + 0x10, BIT(2));
- /*
- * Ask S400 to release caam to APD as it is owned by s400
- */
- s400_release_caam();
- /* re-init the caam */
- imx8ulp_caam_init();
- /*
- * ack the upower, seems a necessary steps, otherwise the upower can
- * not response to the new API service call. put this just before the
- * ddr retention exit because that the dram retention exit flow need to
- * communicate with upower.
- */
- upower_wait_resp();
- /*
- * restore the lpav ctx & make ddr out of retention
- * if lpav master is assigned to APD domain.
- */
- if (is_lpav_owned_by_apd()) {
- lpav_ctx_restore();
- }
- }
- #define DGO_CTRL1 U(0xc)
- #define USB_WAKEUP U(0x44)
- #define USB1_PHY_DPD_WAKEUP_EN BIT_32(5)
- #define USB0_PHY_DPD_WAKEUP_EN BIT_32(4)
- #define USB1_PHY_WAKEUP_ISO_DISABLE BIT_32(1)
- #define USB0_PHY_WAKEUP_ISO_DISABLE BIT_32(0)
- void usb_wakeup_enable(bool enable)
- {
- if (enable) {
- mmio_setbits_32(IMX_SIM1_BASE + USB_WAKEUP,
- USB1_PHY_WAKEUP_ISO_DISABLE | USB0_PHY_WAKEUP_ISO_DISABLE);
- mmio_setbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
- while (!(mmio_read_32(IMX_SIM1_BASE + DGO_CTRL1) & BIT(1))) {
- ;
- }
- mmio_clrbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
- mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(1));
- /* Need to delay for a while to make sure the wakeup logic can work */
- udelay(500);
- mmio_setbits_32(IMX_SIM1_BASE + USB_WAKEUP,
- USB1_PHY_DPD_WAKEUP_EN | USB0_PHY_DPD_WAKEUP_EN);
- mmio_setbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
- while (!(mmio_read_32(IMX_SIM1_BASE + DGO_CTRL1) & BIT(1))) {
- ;
- }
- mmio_clrbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
- mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(1));
- } else {
- /*
- * USBx_PHY_DPD_WAKEUP_EN should be cleared before USB0_PHY_WAKEUP_ISO_DISABLE
- * to provide the correct the wake-up functionality.
- */
- mmio_write_32(IMX_SIM1_BASE + USB_WAKEUP, USB1_PHY_WAKEUP_ISO_DISABLE |
- USB0_PHY_WAKEUP_ISO_DISABLE);
- mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
- while (!(mmio_read_32(IMX_SIM1_BASE + DGO_CTRL1) & BIT(1))) {
- ;
- }
- mmio_clrbits_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(0));
- mmio_write_32(IMX_SIM1_BASE + DGO_CTRL1, BIT(1));
- }
- }
|