int pil_mss_shutdown(struct pil_desc *pil) { struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc); int ret = 0; if (drv->axi_halt_base) { 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); } if (drv->axi_halt_q6) pil_q6v5_halt_axi_port(pil, drv->axi_halt_q6); if (drv->axi_halt_mss) pil_q6v5_halt_axi_port(pil, drv->axi_halt_mss); if (drv->axi_halt_nc) pil_q6v5_halt_axi_port(pil, drv->axi_halt_nc); ret = pil_mss_restart_reg(drv, 1); if (drv->is_booted) { pil_mss_disable_clks(drv); pil_mss_power_down(drv); drv->is_booted = false; } return ret; }
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; } pr_info("pil: 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); err_clks: pil_mss_restart_reg(drv, 1); err_restart: pil_mss_power_down(drv); err_power: return ret; }
static int qproc_start(struct rproc *rproc) { struct qproc *qproc = (struct qproc *)rproc->priv; unsigned long timeout; int ret; u32 val; printk("DEBUG::: pill................... %s \n", __func__); // ret = regulator_enable(qproc->vdd); // if (ret) { // dev_err(qproc->dev, "failed to enable mss vdd\n"); // return ret; // } ret = regulator_enable(qproc->pll); if (ret) { dev_err(qproc->dev, "failed to enable mss vdd pll\n"); return ret; } ret = pil_mss_restart_reg(qproc, 0); //FIXME //ret = reset_control_deassert(qproc->mss_restart); if (ret) { dev_err(qproc->dev, "failed to deassert mss restart\n"); goto disable_vdd; } ret = clk_prepare_enable(qproc->ahb_clk); if (ret) goto assert_reset; ret = clk_prepare_enable(qproc->axi_clk); if (ret) goto disable_ahb_clk; ret = clk_prepare_enable(qproc->rom_clk); if (ret) goto disable_axi_clk; writel_relaxed(qproc->mba_da, qproc->rmb_base + RMB_MBA_IMAGE); /* Ensure order of data/entry point and the following reset release */ wmb(); q6v5proc_reset(qproc); timeout = jiffies + HZ; for (;;) { msleep(1); val = readl(qproc->rmb_base + RMB_PBL_STATUS); if (val || time_after(jiffies, timeout)) break; } if (val == 0) { dev_err(qproc->dev, "PBL boot timed out\n"); ret = -ETIMEDOUT; goto halt_axi_ports; } else if (val != STATUS_PBL_SUCCESS) { dev_err(qproc->dev, "PBL returned unexpected status %d\n", val); ret = -EINVAL; goto halt_axi_ports; } timeout = jiffies + HZ; for (;;) { msleep(1); val = readl(qproc->rmb_base + RMB_MBA_STATUS); if (val || time_after(jiffies, timeout)) break; } if (val == 0) { dev_err(qproc->dev, "MBA boot timed out\n"); ret = -ETIMEDOUT; goto halt_axi_ports; } else if (val != STATUS_XPU_UNLOCKED && val != STATUS_XPU_UNLOCKED_SCRIBBLED) { dev_err(qproc->dev, "MBA returned unexpected status %d\n", val); ret = -EINVAL; goto halt_axi_ports; } dev_info(qproc->dev, "MBA boot done\n"); ret = qproc_load_modem(qproc); if (ret) goto halt_axi_ports; return 0; halt_axi_ports: q6v5proc_halt_axi_port(qproc, qproc->halt_base + MSS_Q6_HALT_BASE); q6v5proc_halt_axi_port(qproc, qproc->halt_base + MSS_MODEM_HALT_BASE); q6v5proc_halt_axi_port(qproc, qproc->halt_base + MSS_NC_HALT_BASE); disable_axi_clk: clk_disable_unprepare(qproc->axi_clk); disable_ahb_clk: clk_disable_unprepare(qproc->ahb_clk); assert_reset: reset_control_assert(qproc->mss_restart); disable_vdd: // regulator_disable(qproc->vdd); dma_free_attrs(qproc->dev, qproc->mba_size, qproc->mba_va, qproc->mba_da, &qproc->mba_attrs); return ret; }
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; if (modem_dbg_cfg) writel_relaxed(modem_dbg_cfg, drv->reg_base + QDSP6SS_DBG_CFG); /* 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); } /* Program DP Address */ if (drv->dp_virt) { writel_relaxed(drv->dp_phys, drv->rmb_base + RMB_PMI_CODE_START); writel_relaxed(drv->dp_size, drv->rmb_base + RMB_PMI_CODE_LENGTH); } else { writel_relaxed(0, drv->rmb_base + RMB_PMI_CODE_START); writel_relaxed(0, drv->rmb_base + RMB_PMI_CODE_LENGTH); } /* Make sure RMB regs are written before bringing modem out of reset */ mb(); 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; }