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

    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;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 7
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;
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
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;
}