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