Example #1
0
static int pil_q6v4_modem_boot(struct pil_desc *pil)
{
	struct q6v4_data *drv = pil_to_q6v4_data(pil);
	struct q6v4_modem *mdm = dev_get_drvdata(pil->dev);
	int err;

	err = pil_q6v4_power_up(drv);
	if (err)
		return err;

	pil_q6v4_init_modem(mdm->modem_base, drv->jtag_clk_reg);
	return pil_q6v4_boot(pil);
}
Example #2
0
static int pil_q6v4_reset_trusted(struct pil_desc *pil)
{
	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
	int err;

	err = pil_q6v4_power_up(pil->dev);
	if (err)
		return err;

	/* Unhalt bus port */
	err = msm_bus_axi_portunhalt(pdata->bus_port);
	if (err)
		dev_err(pil->dev, "Failed to unhalt bus port\n");
	return pas_auth_and_reset(pdata->pas_id);
}
Example #3
0
static int pil_q6v4_reset(struct pil_desc *pil)
{
	u32 reg, err;
	const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;

	err = pil_q6v4_power_up(pil->dev);
	if (err)
		return err;
	/* Enable Q6 ACLK */
	writel_relaxed(0x10, pdata->aclk_reg);

	if (drv->modem_base)
		pil_q6v4_init_modem(drv->modem_base, pdata->jtag_clk_reg);

	/* Unhalt bus port */
	err = msm_bus_axi_portunhalt(pdata->bus_port);
	if (err)
		dev_err(pil->dev, "Failed to unhalt bus port\n");

	/* Deassert Q6SS_SS_ARES */
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg &= ~(Q6SS_SS_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	/* Program boot address */
	writel_relaxed((drv->start_addr >> 8) & 0xFFFFFF,
			drv->base + QDSP6SS_RST_EVB);

	/* Program TCM and AHB address ranges */
	writel_relaxed(pdata->strap_tcm_base, drv->base + QDSP6SS_STRAP_TCM);
	writel_relaxed(pdata->strap_ahb_upper | pdata->strap_ahb_lower,
		       drv->base + QDSP6SS_STRAP_AHB);

	/* Turn off Q6 core clock */
	writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
		       drv->base + QDSP6SS_GFMUX_CTL);

	/* Put memories to sleep */
	writel_relaxed(Q6SS_CLAMP_IO, drv->base + QDSP6SS_PWR_CTL);

	/* Assert resets */
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg |= (Q6SS_CORE_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES
	    | Q6SS_STOP_CORE_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	/* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */
	mb();
	usleep_range(20, 30);

	/* Turn on Q6 memories */
	reg = Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N | Q6SS_L1TCM_SLP_NRET_N
	    | Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLEEP_NRET_N | Q6SS_ARR_STBY_N
	    | Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	/* Turn on Q6 core clock */
	reg = Q6SS_CLK_ENA | Q6SS_SRC_SWITCH_CLK_OVR;
	writel_relaxed(reg, drv->base + QDSP6SS_GFMUX_CTL);

	/* Remove Q6SS_CLAMP_IO */
	reg = readl_relaxed(drv->base + QDSP6SS_PWR_CTL);
	reg &= ~Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	/* Bring Q6 core out of reset and start execution. */
	writel_relaxed(0x0, drv->base + QDSP6SS_RESET);

	return 0;
}
static int pil_q6v4_reset(struct pil_desc *pil)
{
	u32 reg, err;
	const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;

	err = pil_q6v4_power_up(pil->dev);
	if (err)
		return err;
	
	writel_relaxed(0x10, pdata->aclk_reg);

	if (drv->modem_base)
		pil_q6v4_init_modem(drv->modem_base, pdata->jtag_clk_reg);

	
	err = msm_bus_axi_portunhalt(pdata->bus_port);
	if (err)
		dev_err(pil->dev, "Failed to unhalt bus port\n");

	
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg &= ~(Q6SS_SS_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	
	writel_relaxed((drv->start_addr >> 8) & 0xFFFFFF,
			drv->base + QDSP6SS_RST_EVB);

	
	writel_relaxed(pdata->strap_tcm_base, drv->base + QDSP6SS_STRAP_TCM);
	writel_relaxed(pdata->strap_ahb_upper | pdata->strap_ahb_lower,
		       drv->base + QDSP6SS_STRAP_AHB);

	
	writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
		       drv->base + QDSP6SS_GFMUX_CTL);

	
	writel_relaxed(Q6SS_CLAMP_IO, drv->base + QDSP6SS_PWR_CTL);

	
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg |= (Q6SS_CORE_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES
	    | Q6SS_STOP_CORE_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	
	mb();
	usleep_range(20, 30);

	
	reg = Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N | Q6SS_L1TCM_SLP_NRET_N
	    | Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLEEP_NRET_N | Q6SS_ARR_STBY_N
	    | Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	
	reg = Q6SS_CLK_ENA | Q6SS_SRC_SWITCH_CLK_OVR;
	writel_relaxed(reg, drv->base + QDSP6SS_GFMUX_CTL);

	
	reg = readl_relaxed(drv->base + QDSP6SS_PWR_CTL);
	reg &= ~Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	
	writel_relaxed(0x0, drv->base + QDSP6SS_RESET);

	return 0;
}
Example #5
0
static int pil_q6v4_reset(struct pil_desc *pil)
{
	u32 reg, err = 0;
	const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;

	pil_q6v4_make_xo_proxy_votes(pil->dev);

	err = pil_q6v4_power_up(pil->dev);
	if (err)
		return err;
	/* Enable Q6 ACLK */
	writel_relaxed(0x10, pdata->aclk_reg);

	if (drv->modem_base)
		pil_q6v4_init_modem(drv->modem_base, pdata->jtag_clk_reg);

	/* Unhalt bus port */
	err = msm_bus_axi_portunhalt(pdata->bus_port);
	if (err)
		dev_err(pil->dev, "Failed to unhalt bus port\n");

	/*
	 * Assert AXIS_ACLK_EN override to allow for correct updating of the
	 * QDSP6_CORE_STATE status bit. This is mandatory only for the SW Q6
	 * in 8960v1 and optional elsewhere.
	 */
	reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
	reg |= Q6SS_AXIS_ACLK_EN;
	writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);

	/* Deassert Q6SS_SS_ARES */
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg &= ~(Q6SS_SS_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	/* Program boot address */
	writel_relaxed((drv->start_addr >> 8) & 0xFFFFFF,
			drv->base + QDSP6SS_RST_EVB);

	/* Program TCM and AHB address ranges */
	writel_relaxed(pdata->strap_tcm_base, drv->base + QDSP6SS_STRAP_TCM);
	writel_relaxed(pdata->strap_ahb_upper | pdata->strap_ahb_lower,
		       drv->base + QDSP6SS_STRAP_AHB);

	/* Turn off Q6 core clock */
	writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
		       drv->base + QDSP6SS_GFMUX_CTL);

	/* Put memories to sleep */
	writel_relaxed(Q6SS_CLAMP_IO, drv->base + QDSP6SS_PWR_CTL);

	/* Assert resets */
	reg = readl_relaxed(drv->base + QDSP6SS_RESET);
	reg |= (Q6SS_CORE_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES
	    | Q6SS_STOP_CORE_ARES);
	writel_relaxed(reg, drv->base + QDSP6SS_RESET);

	/* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */
	mb();
	usleep_range(20, 30);

	/* Turn on Q6 memories */
	reg = Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N | Q6SS_L1TCM_SLP_NRET_N
	    | Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLEEP_NRET_N | Q6SS_ARR_STBY_N
	    | Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	/* Turn on Q6 core clock */
	reg = Q6SS_CLK_ENA | Q6SS_SRC_SWITCH_CLK_OVR;
	writel_relaxed(reg, drv->base + QDSP6SS_GFMUX_CTL);

	/* Remove Q6SS_CLAMP_IO */
	reg = readl_relaxed(drv->base + QDSP6SS_PWR_CTL);
	reg &= ~Q6SS_CLAMP_IO;
	writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);

	/* Bring Q6 core out of reset and start execution. */
	writel_relaxed(0x0, drv->base + QDSP6SS_RESET);

	/*
	 * Re-enable auto-gating of AXIS_ACLK at lease one AXI clock cycle
	 * after resets are de-asserted.
	 */
	mb();
	usleep_range(1, 10);
	reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
	reg &= ~Q6SS_AXIS_ACLK_EN;
	writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);

	return 0;
}