in qcom_q6v5_adsp.c [182:254]
static int adsp_start(struct rproc *rproc)
{
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
int ret;
unsigned int val;
ret = qcom_q6v5_prepare(&adsp->q6v5);
if (ret)
return ret;
ret = clk_prepare_enable(adsp->xo);
if (ret)
goto disable_irqs;
dev_pm_genpd_set_performance_state(adsp->dev, INT_MAX);
ret = pm_runtime_get_sync(adsp->dev);
if (ret) {
pm_runtime_put_noidle(adsp->dev);
goto disable_xo_clk;
}
ret = clk_bulk_prepare_enable(adsp->num_clks, adsp->clks);
if (ret) {
dev_err(adsp->dev, "adsp clk_enable failed\n");
goto disable_power_domain;
}
/* Enable the XO clock */
writel(1, adsp->qdsp6ss_base + QDSP6SS_XO_CBCR);
/* Enable the QDSP6SS sleep clock */
writel(1, adsp->qdsp6ss_base + QDSP6SS_SLEEP_CBCR);
/* Enable the QDSP6 core clock */
writel(1, adsp->qdsp6ss_base + QDSP6SS_CORE_CBCR);
/* Program boot address */
writel(adsp->mem_phys >> 4, adsp->qdsp6ss_base + RST_EVB_REG);
/* De-assert QDSP6 stop core. QDSP6 will execute after out of reset */
writel(0x1, adsp->qdsp6ss_base + CORE_START_REG);
/* Trigger boot FSM to start QDSP6 */
writel(0x1, adsp->qdsp6ss_base + BOOT_CMD_REG);
/* Wait for core to come out of reset */
ret = readl_poll_timeout(adsp->qdsp6ss_base + BOOT_STATUS_REG,
val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT);
if (ret) {
dev_err(adsp->dev, "failed to bootup adsp\n");
goto disable_adsp_clks;
}
ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5 * HZ));
if (ret == -ETIMEDOUT) {
dev_err(adsp->dev, "start timed out\n");
goto disable_adsp_clks;
}
return 0;
disable_adsp_clks:
clk_bulk_disable_unprepare(adsp->num_clks, adsp->clks);
disable_power_domain:
dev_pm_genpd_set_performance_state(adsp->dev, 0);
pm_runtime_put(adsp->dev);
disable_xo_clk:
clk_disable_unprepare(adsp->xo);
disable_irqs:
qcom_q6v5_unprepare(&adsp->q6v5);
return ret;
}