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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
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;

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