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_msa_pbl_shutdown(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_Q6_HALT_BASE); pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_MODEM_HALT_BASE); pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_NC_HALT_BASE); writel_relaxed(1, drv->restart_reg); if (drv->is_booted) { pil_msa_pbl_disable_clks(drv); pil_msa_pbl_power_down(drv); drv->is_booted = false; } return 0; }