diff options
Diffstat (limited to 'drivers/remoteproc/qcom_q6v5_mss.c')
-rw-r--r-- | drivers/remoteproc/qcom_q6v5_mss.c | 124 |
1 files changed, 89 insertions, 35 deletions
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index eb3457a6c3b7..66106ba25ba3 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -132,6 +132,7 @@ struct qcom_mss_reg_res { struct rproc_hexagon_res { const char *hexagon_mba_image; struct qcom_mss_reg_res *proxy_supply; + struct qcom_mss_reg_res *fallback_proxy_supply; struct qcom_mss_reg_res *active_supply; char **proxy_clk_names; char **reset_clk_names; @@ -177,16 +178,17 @@ struct q6v5 { int proxy_pd_count; struct reg_info active_regs[1]; - struct reg_info proxy_regs[3]; + struct reg_info proxy_regs[1]; + struct reg_info fallback_proxy_regs[2]; int active_reg_count; int proxy_reg_count; + int fallback_proxy_reg_count; bool dump_mba_loaded; size_t current_dump_size; size_t total_dump_size; phys_addr_t mba_phys; - void *mba_region; size_t mba_size; size_t dp_size; @@ -349,8 +351,11 @@ static int q6v5_pds_enable(struct q6v5 *qproc, struct device **pds, for (i = 0; i < pd_count; i++) { dev_pm_genpd_set_performance_state(pds[i], INT_MAX); ret = pm_runtime_get_sync(pds[i]); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(pds[i]); + dev_pm_genpd_set_performance_state(pds[i], 0); goto unroll_pd_votes; + } } return 0; @@ -405,7 +410,7 @@ static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm, current_perm, next, perms); } -static void q6v5_debug_policy_load(struct q6v5 *qproc) +static void q6v5_debug_policy_load(struct q6v5 *qproc, void *mba_region) { const struct firmware *dp_fw; @@ -413,7 +418,7 @@ static void q6v5_debug_policy_load(struct q6v5 *qproc) return; if (SZ_1M + dp_fw->size <= qproc->mba_size) { - memcpy(qproc->mba_region + SZ_1M, dp_fw->data, dp_fw->size); + memcpy(mba_region + SZ_1M, dp_fw->data, dp_fw->size); qproc->dp_size = dp_fw->size; } @@ -423,6 +428,7 @@ static void q6v5_debug_policy_load(struct q6v5 *qproc) static int q6v5_load(struct rproc *rproc, const struct firmware *fw) { struct q6v5 *qproc = rproc->priv; + void *mba_region; /* MBA is restricted to a maximum size of 1M */ if (fw->size > qproc->mba_size || fw->size > SZ_1M) { @@ -430,8 +436,16 @@ static int q6v5_load(struct rproc *rproc, const struct firmware *fw) return -EINVAL; } - memcpy(qproc->mba_region, fw->data, fw->size); - q6v5_debug_policy_load(qproc); + mba_region = memremap(qproc->mba_phys, qproc->mba_size, MEMREMAP_WC); + if (!mba_region) { + dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n", + &qproc->mba_phys, qproc->mba_size); + return -EBUSY; + } + + memcpy(mba_region, fw->data, fw->size); + q6v5_debug_policy_load(qproc, mba_region); + memunmap(mba_region); return 0; } @@ -538,6 +552,7 @@ static void q6v5_dump_mba_logs(struct q6v5 *qproc) { struct rproc *rproc = qproc->rproc; void *data; + void *mba_region; if (!qproc->has_mba_logs) return; @@ -546,12 +561,16 @@ static void q6v5_dump_mba_logs(struct q6v5 *qproc) qproc->mba_size)) return; - data = vmalloc(MBA_LOG_SIZE); - if (!data) + mba_region = memremap(qproc->mba_phys, qproc->mba_size, MEMREMAP_WC); + if (!mba_region) return; - memcpy(data, qproc->mba_region, MBA_LOG_SIZE); - dev_coredumpv(&rproc->dev, data, MBA_LOG_SIZE, GFP_KERNEL); + data = vmalloc(MBA_LOG_SIZE); + if (data) { + memcpy(data, mba_region, MBA_LOG_SIZE); + dev_coredumpv(&rproc->dev, data, MBA_LOG_SIZE, GFP_KERNEL); + } + memunmap(mba_region); } static int q6v5proc_reset(struct q6v5 *qproc) @@ -890,11 +909,18 @@ static int q6v5_mba_load(struct q6v5 *qproc) goto disable_active_pds; } + ret = q6v5_regulator_enable(qproc, qproc->fallback_proxy_regs, + qproc->fallback_proxy_reg_count); + if (ret) { + dev_err(qproc->dev, "failed to enable fallback proxy supplies\n"); + goto disable_proxy_pds; + } + ret = q6v5_regulator_enable(qproc, qproc->proxy_regs, qproc->proxy_reg_count); if (ret) { dev_err(qproc->dev, "failed to enable proxy supplies\n"); - goto disable_proxy_pds; + goto disable_fallback_proxy_reg; } ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks, @@ -1008,6 +1034,9 @@ disable_proxy_clk: disable_proxy_reg: q6v5_regulator_disable(qproc, qproc->proxy_regs, qproc->proxy_reg_count); +disable_fallback_proxy_reg: + q6v5_regulator_disable(qproc, qproc->fallback_proxy_regs, + qproc->fallback_proxy_reg_count); disable_proxy_pds: q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count); disable_active_pds: @@ -1063,6 +1092,8 @@ static void q6v5_mba_reclaim(struct q6v5 *qproc) qproc->proxy_pd_count); q6v5_clk_disable(qproc->dev, qproc->proxy_clks, qproc->proxy_clk_count); + q6v5_regulator_disable(qproc, qproc->fallback_proxy_regs, + qproc->fallback_proxy_reg_count); q6v5_regulator_disable(qproc, qproc->proxy_regs, qproc->proxy_reg_count); } @@ -1179,7 +1210,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc) goto release_firmware; } - ptr = ioremap_wc(qproc->mpss_phys + offset, phdr->p_memsz); + ptr = memremap(qproc->mpss_phys + offset, phdr->p_memsz, MEMREMAP_WC); if (!ptr) { dev_err(qproc->dev, "unable to map memory region: %pa+%zx-%x\n", @@ -1194,7 +1225,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc) "failed to load segment %d from truncated file %s\n", i, fw_name); ret = -EINVAL; - iounmap(ptr); + memunmap(ptr); goto release_firmware; } @@ -1206,7 +1237,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc) ptr, phdr->p_filesz); if (ret) { dev_err(qproc->dev, "failed to load %s\n", fw_name); - iounmap(ptr); + memunmap(ptr); goto release_firmware; } @@ -1217,7 +1248,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc) memset(ptr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); } - iounmap(ptr); + memunmap(ptr); size += phdr->p_memsz; code_length = readl(qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG); @@ -1284,11 +1315,11 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc, } if (!ret) - ptr = ioremap_wc(qproc->mpss_phys + offset + cp_offset, size); + ptr = memremap(qproc->mpss_phys + offset + cp_offset, size, MEMREMAP_WC); if (ptr) { memcpy(dest, ptr, size); - iounmap(ptr); + memunmap(ptr); } else { memset(dest, 0xff, size); } @@ -1355,7 +1386,7 @@ static int q6v5_stop(struct rproc *rproc) struct q6v5 *qproc = (struct q6v5 *)rproc->priv; int ret; - ret = qcom_q6v5_request_stop(&qproc->q6v5); + ret = qcom_q6v5_request_stop(&qproc->q6v5, qproc->sysmon); if (ret == -ETIMEDOUT) dev_err(qproc->dev, "timed out on wait\n"); @@ -1423,6 +1454,8 @@ static void qcom_msa_handover(struct qcom_q6v5 *q6v5) qproc->proxy_clk_count); q6v5_regulator_disable(qproc, qproc->proxy_regs, qproc->proxy_reg_count); + q6v5_regulator_disable(qproc, qproc->fallback_proxy_regs, + qproc->fallback_proxy_reg_count); q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count); } @@ -1588,12 +1621,6 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc) qproc->mba_phys = r.start; qproc->mba_size = resource_size(&r); - qproc->mba_region = devm_ioremap_wc(qproc->dev, qproc->mba_phys, qproc->mba_size); - if (!qproc->mba_region) { - dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n", - &r.start, qproc->mba_size); - return -EBUSY; - } if (!child) { node = of_parse_phandle(qproc->dev->of_node, @@ -1717,11 +1744,22 @@ static int q6v5_probe(struct platform_device *pdev) ret = q6v5_pds_attach(&pdev->dev, qproc->proxy_pds, desc->proxy_pd_names); - if (ret < 0) { + /* Fallback to regulators for old device trees */ + if (ret == -ENODATA && desc->fallback_proxy_supply) { + ret = q6v5_regulator_init(&pdev->dev, + qproc->fallback_proxy_regs, + desc->fallback_proxy_supply); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to get fallback proxy regulators.\n"); + goto detach_active_pds; + } + qproc->fallback_proxy_reg_count = ret; + } else if (ret < 0) { dev_err(&pdev->dev, "Failed to init power domains\n"); goto detach_active_pds; + } else { + qproc->proxy_pd_count = ret; } - qproc->proxy_pd_count = ret; qproc->has_alt_reset = desc->has_alt_reset; ret = q6v5_init_reset(qproc); @@ -1923,6 +1961,13 @@ static const struct rproc_hexagon_res msm8916_mss = { .hexagon_mba_image = "mba.mbn", .proxy_supply = (struct qcom_mss_reg_res[]) { { + .supply = "pll", + .uA = 100000, + }, + {} + }, + .fallback_proxy_supply = (struct qcom_mss_reg_res[]) { + { .supply = "mx", .uV = 1050000, }, @@ -1930,10 +1975,6 @@ static const struct rproc_hexagon_res msm8916_mss = { .supply = "cx", .uA = 100000, }, - { - .supply = "pll", - .uA = 100000, - }, {} }, .proxy_clk_names = (char*[]){ @@ -1946,6 +1987,11 @@ static const struct rproc_hexagon_res msm8916_mss = { "mem", NULL }, + .proxy_pd_names = (char*[]){ + "mx", + "cx", + NULL + }, .need_mem_protection = false, .has_alt_reset = false, .has_mba_logs = false, @@ -1957,6 +2003,13 @@ static const struct rproc_hexagon_res msm8974_mss = { .hexagon_mba_image = "mba.b00", .proxy_supply = (struct qcom_mss_reg_res[]) { { + .supply = "pll", + .uA = 100000, + }, + {} + }, + .fallback_proxy_supply = (struct qcom_mss_reg_res[]) { + { .supply = "mx", .uV = 1050000, }, @@ -1964,10 +2017,6 @@ static const struct rproc_hexagon_res msm8974_mss = { .supply = "cx", .uA = 100000, }, - { - .supply = "pll", - .uA = 100000, - }, {} }, .active_supply = (struct qcom_mss_reg_res[]) { @@ -1988,6 +2037,11 @@ static const struct rproc_hexagon_res msm8974_mss = { "mem", NULL }, + .proxy_pd_names = (char*[]){ + "mx", + "cx", + NULL + }, .need_mem_protection = false, .has_alt_reset = false, .has_mba_logs = false, |