static int pil_lpass_reset(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); phys_addr_t start_addr = pil_get_entry_addr(pil); int ret; /* Deassert reset to subsystem and wait for propagation */ writel_relaxed(0, drv->restart_reg); mb(); udelay(2); ret = pil_lpass_enable_clks(drv); if (ret) return ret; /* Program Image Address */ writel_relaxed((start_addr >> 4) & 0x0FFFFFF0, drv->reg_base + QDSP6SS_RST_EVB); ret = pil_q6v5_reset(pil); if (ret) { pil_lpass_disable_clks(drv); return ret; } drv->is_booted = true; return 0; }
static int pil_lpass_reset(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); phys_addr_t start_addr = pil_get_entry_addr(pil); int ret; writel_relaxed(0, drv->restart_reg); mb(); udelay(2); ret = pil_lpass_enable_clks(drv); if (ret) return ret; writel_relaxed((start_addr >> 4) & 0x0FFFFFF0, drv->reg_base + QDSP6SS_RST_EVB); ret = pil_q6v5_reset(pil); if (ret) { pil_lpass_disable_clks(drv); return ret; } drv->is_booted = true; return 0; }
static int pil_msa_pbl_reset(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); phys_addr_t start_addr = pil_get_entry_addr(pil); int ret; /* * Bring subsystem out of reset and enable required * regulators and clocks. */ ret = pil_msa_pbl_power_up(drv); if (ret) goto err_power; /* Deassert reset to subsystem and wait for propagation */ writel_relaxed(0, drv->restart_reg); mb(); udelay(2); ret = pil_msa_pbl_enable_clks(drv); if (ret) goto err_clks; /* Program Image Address */ if (drv->self_auth) { writel_relaxed(start_addr, drv->rmb_base + RMB_MBA_IMAGE); /* Ensure write to RMB base occurs before reset is released. */ mb(); } else { writel_relaxed((start_addr >> 4) & 0x0FFFFFF0, drv->reg_base + QDSP6SS_RST_EVB); } ret = pil_q6v5_reset(pil); if (ret) goto err_q6v5_reset; /* Wait for MBA to start. Check for PBL and MBA errors while waiting. */ if (drv->self_auth) { ret = pil_msa_wait_for_mba_ready(drv); if (ret) goto err_q6v5_reset; } drv->is_booted = true; return 0; err_q6v5_reset: pil_msa_pbl_disable_clks(drv); err_clks: writel_relaxed(1, drv->restart_reg); pil_msa_pbl_power_down(drv); err_power: return ret; }
static int pil_msa_pbl_reset(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); phys_addr_t start_addr = pil_get_entry_addr(pil); int ret; ret = pil_msa_pbl_power_up(drv); if (ret) goto err_power; writel_relaxed(0, drv->restart_reg); mb(); udelay(2); ret = pil_msa_pbl_enable_clks(drv); if (ret) goto err_clks; if (drv->self_auth) { writel_relaxed(start_addr, drv->rmb_base + RMB_MBA_IMAGE); mb(); } else { writel_relaxed((start_addr >> 4) & 0x0FFFFFF0, drv->reg_base + QDSP6SS_RST_EVB); } ret = pil_q6v5_reset(pil); if (ret) goto err_q6v5_reset; if (drv->self_auth) { ret = pil_msa_wait_for_mba_ready(drv); if (ret) goto err_q6v5_reset; } drv->is_booted = true; return 0; err_q6v5_reset: pil_msa_pbl_disable_clks(drv); err_clks: writel_relaxed(1, drv->restart_reg); pil_msa_pbl_power_down(drv); err_power: return ret; }
static int pil_q6v3_reset(struct pil_desc *pil) { u32 reg; struct q6v3_data *drv = dev_get_drvdata(pil->dev); phys_addr_t start_addr = pil_get_entry_addr(pil); /* Put Q6 into reset */ reg = readl_relaxed(drv->cbase + LCC_Q6_FUNC); reg |= Q6SS_SS_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES | STOP_CORE | CORE_ARES; reg &= ~CORE_GFM4_CLK_EN; writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC); /* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */ usleep_range(20, 30); /* Turn on Q6 memory */ reg |= CORE_GFM4_CLK_EN | CORE_L1_MEM_CORE_EN | CORE_TCM_MEM_CORE_EN | CORE_TCM_MEM_PERPH_EN; writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC); /* Turn on Q6 core clocks and take core out of reset */ reg &= ~(CLAMP_IO | Q6SS_SS_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES | CORE_ARES); writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC); /* Wait for clocks to be enabled */ mb(); /* Program boot address */ writel_relaxed((start_addr >> 12) & 0xFFFFF, drv->base + QDSP6SS_RST_EVB); writel_relaxed(Q6_STRAP_TCM_CONFIG | Q6_STRAP_TCM_BASE, drv->base + QDSP6SS_STRAP_TCM); writel_relaxed(Q6_STRAP_AHB_UPPER | Q6_STRAP_AHB_LOWER, drv->base + QDSP6SS_STRAP_AHB); /* Wait for addresses to be programmed before starting Q6 */ mb(); /* Start Q6 instruction execution */ reg &= ~STOP_CORE; writel_relaxed(reg, drv->cbase + LCC_Q6_FUNC); return 0; }
static int pil_riva_reset(struct pil_desc *pil) { u32 reg, sel; struct riva_data *drv = dev_get_drvdata(pil->dev); void __iomem *base = drv->base; phys_addr_t start_addr = pil_get_entry_addr(pil); void __iomem *cbase = drv->cbase; bool use_cxo = cxo_is_needed(drv); /* Enable A2XB bridge */ reg = readl_relaxed(base + RIVA_PMU_A2XB_CFG); reg |= RIVA_PMU_A2XB_CFG_EN; writel_relaxed(reg, base + RIVA_PMU_A2XB_CFG); /* Program PLL 13 to 960 MHz */ reg = readl_relaxed(cbase + RIVA_PLL_MODE); reg &= ~(PLL_MODE_BYPASSNL | PLL_MODE_OUTCTRL | PLL_MODE_RESET_N); writel_relaxed(reg, cbase + RIVA_PLL_MODE); if (use_cxo) writel_relaxed(0x40000C00 | 50, cbase + RIVA_PLL_L_VAL); else writel_relaxed(0x40000C00 | 40, cbase + RIVA_PLL_L_VAL); writel_relaxed(0, cbase + RIVA_PLL_M_VAL); writel_relaxed(1, cbase + RIVA_PLL_N_VAL); writel_relaxed(0x01495227, cbase + RIVA_PLL_CONFIG); reg = readl_relaxed(cbase + RIVA_PLL_MODE); reg &= ~(PLL_MODE_REF_XO_SEL); reg |= use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF; writel_relaxed(reg, cbase + RIVA_PLL_MODE); /* Enable PLL 13 */ reg |= PLL_MODE_BYPASSNL; writel_relaxed(reg, cbase + RIVA_PLL_MODE); /* * H/W requires a 5us delay between disabling the bypass and * de-asserting the reset. Delay 10us just to be safe. */ mb(); usleep_range(10, 20); reg |= PLL_MODE_RESET_N; writel_relaxed(reg, cbase + RIVA_PLL_MODE); reg |= PLL_MODE_OUTCTRL; writel_relaxed(reg, cbase + RIVA_PLL_MODE); /* Wait for PLL to settle */ mb(); usleep_range(50, 100); /* Configure cCPU for 240 MHz */ sel = readl_relaxed(base + RIVA_PMU_ROOT_CLK_SEL); reg = readl_relaxed(base + RIVA_PMU_CLK_ROOT3); if (sel & RIVA_PMU_ROOT_CLK_SEL_3) { reg &= ~(RIVA_PMU_CLK_ROOT3_SRC0_SEL | RIVA_PMU_CLK_ROOT3_SRC0_DIV); reg |= RIVA_PMU_CLK_ROOT3_SRC0_SEL_RIVA | RIVA_PMU_CLK_ROOT3_SRC0_DIV_2; } else { reg &= ~(RIVA_PMU_CLK_ROOT3_SRC1_SEL | RIVA_PMU_CLK_ROOT3_SRC1_DIV); reg |= RIVA_PMU_CLK_ROOT3_SRC1_SEL_RIVA | RIVA_PMU_CLK_ROOT3_SRC1_DIV_2; } writel_relaxed(reg, base + RIVA_PMU_CLK_ROOT3); reg |= RIVA_PMU_CLK_ROOT3_ENA; writel_relaxed(reg, base + RIVA_PMU_CLK_ROOT3); reg = readl_relaxed(base + RIVA_PMU_ROOT_CLK_SEL); reg ^= RIVA_PMU_ROOT_CLK_SEL_3; writel_relaxed(reg, base + RIVA_PMU_ROOT_CLK_SEL); /* Use the high vector table */ reg = readl_relaxed(base + RIVA_PMU_CCPU_CTL); reg |= RIVA_PMU_CCPU_CTL_HIGH_IVT | RIVA_PMU_CCPU_CTL_REMAP_EN; writel_relaxed(reg, base + RIVA_PMU_CCPU_CTL); /* Set base memory address */ writel_relaxed(start_addr >> 16, base + RIVA_PMU_CCPU_BOOT_REMAP_ADDR); /* Clear warmboot bit indicating this is a cold boot */ reg = readl_relaxed(base + RIVA_PMU_CFG); reg &= ~(RIVA_PMU_CFG_WARM_BOOT); writel_relaxed(reg, base + RIVA_PMU_CFG); /* Enable the cCPU clock */ reg = readl_relaxed(base + RIVA_PMU_OVRD_VAL); reg |= RIVA_PMU_OVRD_VAL_CCPU_CLK; writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL); /* Take cCPU out of reset */ reg |= RIVA_PMU_OVRD_VAL_CCPU_RESET; writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL); return 0; }
static int modem_reset(struct pil_desc *pil) { u32 reg; const struct modem_data *drv = dev_get_drvdata(pil->dev); unsigned long start_addr = pil_get_entry_addr(pil); /* Put modem AHB0,1,2 clocks into reset */ writel_relaxed(BIT(0) | BIT(1), drv->cbase + MAHB0_SFAB_PORT_RESET); writel_relaxed(BIT(7), drv->cbase + MAHB1_CLK_CTL); writel_relaxed(BIT(7), drv->cbase + MAHB2_CLK_CTL); /* Vote for pll8 on behalf of the modem */ reg = readl_relaxed(drv->cbase + PLL_ENA_MARM); reg |= BIT(8); writel_relaxed(reg, drv->cbase + PLL_ENA_MARM); /* Wait for PLL8 to enable */ while (!(readl_relaxed(drv->cbase + PLL8_STATUS) & BIT(16))) cpu_relax(); /* Set MAHB1 divider to Div-5 to run MAHB1,2 and sfab at 79.8 Mhz*/ writel_relaxed(0x4, drv->cbase + MAHB1_NS); /* Vote for modem AHB1 and 2 clocks to be on on behalf of the modem */ reg = readl_relaxed(drv->cbase + MARM_CLK_BRANCH_ENA_VOTE); reg |= BIT(0) | BIT(1); writel_relaxed(reg, drv->cbase + MARM_CLK_BRANCH_ENA_VOTE); /* Source marm_clk off of PLL8 */ reg = readl_relaxed(drv->cbase + MARM_CLK_SRC_CTL); if ((reg & 0x1) == 0) { writel_relaxed(0x3, drv->cbase + MARM_CLK_SRC1_NS); reg |= 0x1; } else { writel_relaxed(0x3, drv->cbase + MARM_CLK_SRC0_NS); reg &= ~0x1; } writel_relaxed(reg | 0x2, drv->cbase + MARM_CLK_SRC_CTL); /* * Force core on and periph on signals to remain active during halt * for marm_clk and mahb2_clk */ writel_relaxed(0x6F, drv->cbase + MARM_CLK_FS); writel_relaxed(0x6F, drv->cbase + MAHB2_CLK_FS); /* * Enable all of the marm_clk branches, cxo sourced marm branches, * and sleep clock branches */ writel_relaxed(0x10, drv->cbase + MARM_CLK_CTL); writel_relaxed(0x10, drv->cbase + MAHB0_CLK_CTL); writel_relaxed(0x10, drv->cbase + SFAB_MSS_S_HCLK_CTL); writel_relaxed(0x10, drv->cbase + MSS_MODEM_CXO_CLK_CTL); writel_relaxed(0x10, drv->cbase + MSS_SLP_CLK_CTL); writel_relaxed(0x10, drv->cbase + MSS_MARM_SYS_REF_CLK_CTL); /* Wait for above clocks to be turned on */ while (readl_relaxed(drv->cbase + CLK_HALT_MSS_SMPSS_MISC_STATE) & (BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(4) | BIT(6))) cpu_relax(); /* Take MAHB0,1,2 clocks out of reset */ writel_relaxed(0x0, drv->cbase + MAHB2_CLK_CTL); writel_relaxed(0x0, drv->cbase + MAHB1_CLK_CTL); writel_relaxed(0x0, drv->cbase + MAHB0_SFAB_PORT_RESET); mb(); /* Setup exception vector table base address */ writel_relaxed(start_addr | 0x1, drv->base + MARM_BOOT_CONTROL); /* Wait for vector table to be setup */ mb(); /* Bring modem out of reset */ writel_relaxed(0x0, drv->cbase + MARM_RESET); return 0; }
static int pil_pronto_reset(struct pil_desc *pil) { u32 reg; int rc; struct pronto_data *drv = dev_get_drvdata(pil->dev); void __iomem *base = drv->base; phys_addr_t start_addr = pil_get_entry_addr(pil); /* Deassert reset to subsystem and wait for propagation */ reg = readl_relaxed(drv->reset_base); reg &= ~CLK_CTL_WCNSS_RESTART_BIT; writel_relaxed(reg, drv->reset_base); mb(); udelay(2); /* Configure boot address */ writel_relaxed(start_addr >> 16, base + PRONTO_PMU_CCPU_BOOT_REMAP_ADDR); /* Use the high vector table */ reg = readl_relaxed(base + PRONTO_PMU_CCPU_CTL); reg |= PRONTO_PMU_CCPU_CTL_REMAP_EN | PRONTO_PMU_CCPU_CTL_HIGH_IVT; writel_relaxed(reg, base + PRONTO_PMU_CCPU_CTL); /* Turn on AHB clock of common_ss */ reg = readl_relaxed(base + PRONTO_PMU_COMMON_AHB_CBCR); reg |= PRONTO_PMU_COMMON_AHB_CBCR_CLK_EN; writel_relaxed(reg, base + PRONTO_PMU_COMMON_AHB_CBCR); /* Turn on CPU clock of common_ss */ reg = readl_relaxed(base + PRONTO_PMU_COMMON_CPU_CBCR); reg |= PRONTO_PMU_COMMON_CPU_CBCR_CLK_EN; writel_relaxed(reg, base + PRONTO_PMU_COMMON_CPU_CBCR); /* Enable A2XB bridge */ reg = readl_relaxed(base + PRONTO_PMU_COMMON_CSR); reg |= PRONTO_PMU_COMMON_CSR_A2XB_CFG_EN; writel_relaxed(reg, base + PRONTO_PMU_COMMON_CSR); /* Enable common_ss power */ reg = readl_relaxed(base + PRONTO_PMU_COMMON_GDSCR); reg &= ~PRONTO_PMU_COMMON_GDSCR_SW_COLLAPSE; writel_relaxed(reg, base + PRONTO_PMU_COMMON_GDSCR); /* Wait for AHB clock to be on */ rc = readl_tight_poll_timeout(base + PRONTO_PMU_COMMON_AHB_CBCR, reg, !(reg & PRONTO_PMU_COMMON_AHB_CLK_OFF), CLK_UPDATE_TIMEOUT_US); if (rc) { dev_err(pil->dev, "pronto common ahb clk enable timeout\n"); return rc; } /* Wait for CPU clock to be on */ rc = readl_tight_poll_timeout(base + PRONTO_PMU_COMMON_CPU_CBCR, reg, !(reg & PRONTO_PMU_COMMON_CPU_CLK_OFF), CLK_UPDATE_TIMEOUT_US); if (rc) { dev_err(pil->dev, "pronto common cpu clk enable timeout\n"); return rc; } /* Deassert ARM9 software reset */ reg = readl_relaxed(base + PRONTO_PMU_SOFT_RESET); reg &= ~PRONTO_PMU_SOFT_RESET_CRCM_CCPU_SOFT_RESET; writel_relaxed(reg, base + PRONTO_PMU_SOFT_RESET); return 0; }
static int pil_riva_reset(struct pil_desc *pil) { u32 reg, sel; struct riva_data *drv = dev_get_drvdata(pil->dev); void __iomem *base = drv->base; phys_addr_t start_addr = pil_get_entry_addr(pil); void __iomem *cbase = drv->cbase; bool use_cxo = cxo_is_needed(drv); /* */ reg = readl_relaxed(base + RIVA_PMU_A2XB_CFG); reg |= RIVA_PMU_A2XB_CFG_EN; writel_relaxed(reg, base + RIVA_PMU_A2XB_CFG); /* */ reg = readl_relaxed(cbase + RIVA_PLL_MODE); reg &= ~(PLL_MODE_BYPASSNL | PLL_MODE_OUTCTRL | PLL_MODE_RESET_N); writel_relaxed(reg, cbase + RIVA_PLL_MODE); if (use_cxo) writel_relaxed(0x40000C00 | 50, cbase + RIVA_PLL_L_VAL); else writel_relaxed(0x40000C00 | 40, cbase + RIVA_PLL_L_VAL); writel_relaxed(0, cbase + RIVA_PLL_M_VAL); writel_relaxed(1, cbase + RIVA_PLL_N_VAL); writel_relaxed(0x01495227, cbase + RIVA_PLL_CONFIG); reg = readl_relaxed(cbase + RIVA_PLL_MODE); reg &= ~(PLL_MODE_REF_XO_SEL); reg |= use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF; writel_relaxed(reg, cbase + RIVA_PLL_MODE); /* */ reg |= PLL_MODE_BYPASSNL; writel_relaxed(reg, cbase + RIVA_PLL_MODE); /* */ mb(); usleep_range(10, 20); reg |= PLL_MODE_RESET_N; writel_relaxed(reg, cbase + RIVA_PLL_MODE); reg |= PLL_MODE_OUTCTRL; writel_relaxed(reg, cbase + RIVA_PLL_MODE); /* */ mb(); usleep_range(50, 100); /* */ sel = readl_relaxed(base + RIVA_PMU_ROOT_CLK_SEL); reg = readl_relaxed(base + RIVA_PMU_CLK_ROOT3); if (sel & RIVA_PMU_ROOT_CLK_SEL_3) { reg &= ~(RIVA_PMU_CLK_ROOT3_SRC0_SEL | RIVA_PMU_CLK_ROOT3_SRC0_DIV); reg |= RIVA_PMU_CLK_ROOT3_SRC0_SEL_RIVA | RIVA_PMU_CLK_ROOT3_SRC0_DIV_2; } else { reg &= ~(RIVA_PMU_CLK_ROOT3_SRC1_SEL | RIVA_PMU_CLK_ROOT3_SRC1_DIV); reg |= RIVA_PMU_CLK_ROOT3_SRC1_SEL_RIVA | RIVA_PMU_CLK_ROOT3_SRC1_DIV_2; } writel_relaxed(reg, base + RIVA_PMU_CLK_ROOT3); reg |= RIVA_PMU_CLK_ROOT3_ENA; writel_relaxed(reg, base + RIVA_PMU_CLK_ROOT3); reg = readl_relaxed(base + RIVA_PMU_ROOT_CLK_SEL); reg ^= RIVA_PMU_ROOT_CLK_SEL_3; writel_relaxed(reg, base + RIVA_PMU_ROOT_CLK_SEL); /* */ reg = readl_relaxed(base + RIVA_PMU_CCPU_CTL); reg |= RIVA_PMU_CCPU_CTL_HIGH_IVT | RIVA_PMU_CCPU_CTL_REMAP_EN; writel_relaxed(reg, base + RIVA_PMU_CCPU_CTL); /* */ writel_relaxed(start_addr >> 16, base + RIVA_PMU_CCPU_BOOT_REMAP_ADDR); /* */ reg = readl_relaxed(base + RIVA_PMU_CFG); reg &= ~(RIVA_PMU_CFG_WARM_BOOT); writel_relaxed(reg, base + RIVA_PMU_CFG); /* */ reg = readl_relaxed(base + RIVA_PMU_OVRD_VAL); reg |= RIVA_PMU_OVRD_VAL_CCPU_CLK; writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL); /* */ reg |= RIVA_PMU_OVRD_VAL_CCPU_RESET; writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL); return 0; }
static int pil_mss_reset(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); phys_addr_t start_addr = pil_get_entry_addr(pil); int ret; if (drv->mba_phys) start_addr = drv->mba_phys; /* * Bring subsystem out of reset and enable required * regulators and clocks. */ ret = pil_mss_power_up(drv); if (ret) goto err_power; /* Deassert reset to subsystem and wait for propagation */ ret = pil_mss_restart_reg(drv, 0); if (ret) goto err_restart; ret = pil_mss_enable_clks(drv); if (ret) goto err_clks; /* Program Image Address */ if (drv->self_auth) { writel_relaxed(start_addr, drv->rmb_base + RMB_MBA_IMAGE); /* * Ensure write to RMB base occurs before reset * is released. */ mb(); } else { writel_relaxed((start_addr >> 4) & 0x0FFFFFF0, drv->reg_base + QDSP6SS_RST_EVB); } ret = pil_q6v5_reset(pil); if (ret) goto err_q6v5_reset; /* Wait for MBA to start. Check for PBL and MBA errors while waiting. */ if (drv->self_auth) { ret = pil_msa_wait_for_mba_ready(drv); if (ret) goto err_q6v5_reset; } dev_info(pil->dev, "MBA boot done\n"); drv->is_booted = true; return 0; err_q6v5_reset: modem_log_rmb_regs(drv->rmb_base); pil_mss_disable_clks(drv); if (drv->ahb_clk_vote) clk_disable_unprepare(drv->ahb_clk); err_clks: pil_mss_restart_reg(drv, 1); err_restart: pil_mss_power_down(drv); err_power: return ret; }
static int modem_reset(struct pil_desc *pil) { u32 reg; const struct modem_data *drv = dev_get_drvdata(pil->dev); phys_addr_t start_addr = pil_get_entry_addr(pil); writel_relaxed(BIT(0) | BIT(1), drv->cbase + MAHB0_SFAB_PORT_RESET); writel_relaxed(BIT(7), drv->cbase + MAHB1_CLK_CTL); writel_relaxed(BIT(7), drv->cbase + MAHB2_CLK_CTL); reg = readl_relaxed(drv->cbase + PLL_ENA_MARM); reg |= BIT(8); writel_relaxed(reg, drv->cbase + PLL_ENA_MARM); while (!(readl_relaxed(drv->cbase + PLL8_STATUS) & BIT(16))) cpu_relax(); writel_relaxed(0x4, drv->cbase + MAHB1_NS); reg = readl_relaxed(drv->cbase + MARM_CLK_BRANCH_ENA_VOTE); reg |= BIT(0) | BIT(1); writel_relaxed(reg, drv->cbase + MARM_CLK_BRANCH_ENA_VOTE); reg = readl_relaxed(drv->cbase + MARM_CLK_SRC_CTL); if ((reg & 0x1) == 0) { writel_relaxed(0x3, drv->cbase + MARM_CLK_SRC1_NS); reg |= 0x1; } else { writel_relaxed(0x3, drv->cbase + MARM_CLK_SRC0_NS); reg &= ~0x1; } writel_relaxed(reg | 0x2, drv->cbase + MARM_CLK_SRC_CTL); writel_relaxed(0x6F, drv->cbase + MARM_CLK_FS); writel_relaxed(0x6F, drv->cbase + MAHB2_CLK_FS); writel_relaxed(0x10, drv->cbase + MARM_CLK_CTL); writel_relaxed(0x10, drv->cbase + MAHB0_CLK_CTL); writel_relaxed(0x10, drv->cbase + SFAB_MSS_S_HCLK_CTL); writel_relaxed(0x10, drv->cbase + MSS_MODEM_CXO_CLK_CTL); writel_relaxed(0x10, drv->cbase + MSS_SLP_CLK_CTL); writel_relaxed(0x10, drv->cbase + MSS_MARM_SYS_REF_CLK_CTL); while (readl_relaxed(drv->cbase + CLK_HALT_MSS_SMPSS_MISC_STATE) & (BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(4) | BIT(6))) cpu_relax(); writel_relaxed(0x0, drv->cbase + MAHB2_CLK_CTL); writel_relaxed(0x0, drv->cbase + MAHB1_CLK_CTL); writel_relaxed(0x0, drv->cbase + MAHB0_SFAB_PORT_RESET); mb(); writel_relaxed(start_addr | 0x1, drv->base + MARM_BOOT_CONTROL); mb(); writel_relaxed(0x0, drv->cbase + MARM_RESET); return 0; }