From 0276f69f13e23b828a149d765d5712e214182ee7 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 14 Jun 2023 15:39:59 +0200 Subject: soc: qcom: icc-bwmon: Set default thresholds dynamically Currently we use predefined initial threshold values. This works, but does not really scale well with more and more SoCs gaining bwmon support, as the necessary kickoff values may differ between platforms due to memory type and/or controller setup. All of the data we need for that is already provided in the device tree, anyway. Change the thresholds to: * low = 0 (as we've been doing up until now) * med = high = BW_MIN Throughput going below the med threshold nudges bwmon into signaling that we should slow down (e.g. if we inherited too high bandwidth from the bootloader). Throughput going above the high threshold nudges bwmon into signaling that we should speed up so as not to choke the bus traffic due to insufficient transfer rates. F_MIN is a perfect initial value for both of these cases - if we go above it (and there's a 99.99% chance it'll happen at boot time), we should definitely make the memory go faster, whereas if we go below it, we should slow down, no matter what performance state we were at before (it's only possible for them to be >= FMIN). This only changes the values programmed at probe time, as high and med thresholds are updated at interrupt, also based on the OPP table from DT. Signed-off-by: Konrad Dybcio Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230610-topic-bwmon_opp-v2-1-0d25c1ce7dca@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/icc-bwmon.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 40068a285913..8daf0eb03279 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -165,9 +165,6 @@ enum bwmon_fields { struct icc_bwmon_data { unsigned int sample_ms; unsigned int count_unit_kb; /* kbytes */ - unsigned int default_highbw_kbps; - unsigned int default_medbw_kbps; - unsigned int default_lowbw_kbps; u8 zone1_thres_count; u8 zone3_thres_count; unsigned int quirks; @@ -564,20 +561,21 @@ static void bwmon_set_threshold(struct icc_bwmon *bwmon, static void bwmon_start(struct icc_bwmon *bwmon) { const struct icc_bwmon_data *data = bwmon->data; + u32 bw_low = 0; int window; + /* No need to check for errors, as this must have succeeded before. */ + dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_low, 0); + bwmon_clear_counters(bwmon, true); window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC); /* Maximum sampling window: 0xffffff for v4 and 0xfffff for v5 */ regmap_field_write(bwmon->regs[F_SAMPLE_WINDOW], window); - bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH], - data->default_highbw_kbps); - bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED], - data->default_medbw_kbps); - bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_LOW], - data->default_lowbw_kbps); + bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH], bw_low); + bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED], bw_low); + bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_LOW], 0); regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE0], BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT); @@ -807,9 +805,6 @@ static int bwmon_remove(struct platform_device *pdev) static const struct icc_bwmon_data msm8998_bwmon_data = { .sample_ms = 4, .count_unit_kb = 1024, - .default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */ - .default_medbw_kbps = 512 * 1024, /* 512 MBps */ - .default_lowbw_kbps = 0, .zone1_thres_count = 16, .zone3_thres_count = 1, .quirks = BWMON_HAS_GLOBAL_IRQ, @@ -822,9 +817,6 @@ static const struct icc_bwmon_data msm8998_bwmon_data = { static const struct icc_bwmon_data sdm845_cpu_bwmon_data = { .sample_ms = 4, .count_unit_kb = 64, - .default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */ - .default_medbw_kbps = 512 * 1024, /* 512 MBps */ - .default_lowbw_kbps = 0, .zone1_thres_count = 16, .zone3_thres_count = 1, .quirks = BWMON_HAS_GLOBAL_IRQ, @@ -835,9 +827,6 @@ static const struct icc_bwmon_data sdm845_cpu_bwmon_data = { static const struct icc_bwmon_data sdm845_llcc_bwmon_data = { .sample_ms = 4, .count_unit_kb = 1024, - .default_highbw_kbps = 800 * 1024, /* 800 MBps */ - .default_medbw_kbps = 256 * 1024, /* 256 MBps */ - .default_lowbw_kbps = 0, .zone1_thres_count = 16, .zone3_thres_count = 1, .regmap_fields = sdm845_llcc_bwmon_reg_fields, @@ -847,9 +836,6 @@ static const struct icc_bwmon_data sdm845_llcc_bwmon_data = { static const struct icc_bwmon_data sc7280_llcc_bwmon_data = { .sample_ms = 4, .count_unit_kb = 64, - .default_highbw_kbps = 800 * 1024, /* 800 MBps */ - .default_medbw_kbps = 256 * 1024, /* 256 MBps */ - .default_lowbw_kbps = 0, .zone1_thres_count = 16, .zone3_thres_count = 1, .quirks = BWMON_NEEDS_FORCE_CLEAR, -- cgit v1.2.3 From a7b484b1c9332a1ee12e8799d62a11ee3f8e0801 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Wed, 14 Jun 2023 18:35:47 +0200 Subject: soc: qcom: ocmem: Fix NUM_PORTS & NUM_MACROS macros Since we're using these two macros to read a value from a register, we need to use the FIELD_GET instead of the FIELD_PREP macro, otherwise we're getting wrong values. So instead of: [ 3.111779] ocmem fdd00000.sram: 2 ports, 1 regions, 512 macros, not interleaved we now get the correct value of: [ 3.129672] ocmem fdd00000.sram: 2 ports, 1 regions, 2 macros, not interleaved Fixes: 88c1e9404f1d ("soc: qcom: add OCMEM driver") Reviewed-by: Caleb Connolly Reviewed-by: Konrad Dybcio Signed-off-by: Luca Weiss Link: https://lore.kernel.org/r/20230506-msm8226-ocmem-v3-1-79da95a2581f@z3ntu.xyz Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ocmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index aaddc3cc53b7..ef7c1748242a 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -80,8 +80,8 @@ struct ocmem { #define OCMEM_HW_VERSION_MINOR(val) FIELD_GET(GENMASK(27, 16), val) #define OCMEM_HW_VERSION_STEP(val) FIELD_GET(GENMASK(15, 0), val) -#define OCMEM_HW_PROFILE_NUM_PORTS(val) FIELD_PREP(0x0000000f, (val)) -#define OCMEM_HW_PROFILE_NUM_MACROS(val) FIELD_PREP(0x00003f00, (val)) +#define OCMEM_HW_PROFILE_NUM_PORTS(val) FIELD_GET(0x0000000f, (val)) +#define OCMEM_HW_PROFILE_NUM_MACROS(val) FIELD_GET(0x00003f00, (val)) #define OCMEM_HW_PROFILE_LAST_REGN_HALFSIZE 0x00010000 #define OCMEM_HW_PROFILE_INTERLEAVING 0x00020000 -- cgit v1.2.3 From 7a2fcba1f4031fa472f069fcd856f19d367b5808 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Wed, 14 Jun 2023 18:35:48 +0200 Subject: soc: qcom: ocmem: Use dev_err_probe where appropriate Use dev_err_probe in the driver probe function where useful, to simplify getting PTR_ERR and to ensure the underlying errors are included in the error message. Reviewed-by: Caleb Connolly Reviewed-by: Konrad Dybcio Signed-off-by: Luca Weiss Link: https://lore.kernel.org/r/20230506-msm8226-ocmem-v3-2-79da95a2581f@z3ntu.xyz Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ocmem.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index ef7c1748242a..462514dfd9e3 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -321,18 +321,13 @@ static int ocmem_dev_probe(struct platform_device *pdev) ocmem->config = device_get_match_data(dev); ret = devm_clk_bulk_get(dev, ARRAY_SIZE(ocmem_clks), ocmem_clks); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "Unable to get clocks\n"); - - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Unable to get clocks\n"); ocmem->mmio = devm_platform_ioremap_resource_byname(pdev, "ctrl"); - if (IS_ERR(ocmem->mmio)) { - dev_err(&pdev->dev, "Failed to ioremap ocmem_ctrl resource\n"); - return PTR_ERR(ocmem->mmio); - } + if (IS_ERR(ocmem->mmio)) + return dev_err_probe(&pdev->dev, PTR_ERR(ocmem->mmio), + "Failed to ioremap ocmem_ctrl resource\n"); ocmem->memory = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem"); @@ -345,16 +340,14 @@ static int ocmem_dev_probe(struct platform_device *pdev) WARN_ON(clk_set_rate(ocmem_clks[OCMEM_CLK_CORE_IDX].clk, 1000) < 0); ret = clk_bulk_prepare_enable(ARRAY_SIZE(ocmem_clks), ocmem_clks); - if (ret) { - dev_info(ocmem->dev, "Failed to enable clocks\n"); - return ret; - } + if (ret) + return dev_err_probe(ocmem->dev, ret, "Failed to enable clocks\n"); if (qcom_scm_restore_sec_cfg_available()) { dev_dbg(dev, "configuring scm\n"); ret = qcom_scm_restore_sec_cfg(QCOM_SCM_OCMEM_DEV_ID, 0); if (ret) { - dev_err(dev, "Could not enable secure configuration\n"); + dev_err_probe(dev, ret, "Could not enable secure configuration\n"); goto err_clk_disable; } } -- cgit v1.2.3 From a7e12e7bda08c367460eed0e4aea5c3694959df1 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Wed, 14 Jun 2023 18:35:49 +0200 Subject: soc: qcom: ocmem: make iface clock optional Some platforms such as msm8226 do not have an iface clk. Since clk_bulk APIs don't offer to a way to treat some clocks as optional simply add core_clk and iface_clk members to our drvdata. Reviewed-by: Konrad Dybcio Signed-off-by: Luca Weiss Link: https://lore.kernel.org/r/20230506-msm8226-ocmem-v3-3-79da95a2581f@z3ntu.xyz Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ocmem.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index 462514dfd9e3..ff8d01b0ac68 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -54,6 +54,8 @@ struct ocmem { const struct ocmem_config *config; struct resource *memory; void __iomem *mmio; + struct clk *core_clk; + struct clk *iface_clk; unsigned int num_ports; unsigned int num_macros; bool interleaved; @@ -95,16 +97,6 @@ struct ocmem { #define OCMEM_PSGSC_CTL_MACRO2_MODE(val) FIELD_PREP(0x00000700, (val)) #define OCMEM_PSGSC_CTL_MACRO3_MODE(val) FIELD_PREP(0x00007000, (val)) -#define OCMEM_CLK_CORE_IDX 0 -static struct clk_bulk_data ocmem_clks[] = { - { - .id = "core", - }, - { - .id = "iface", - }, -}; - static inline void ocmem_write(struct ocmem *ocmem, u32 reg, u32 data) { writel(data, ocmem->mmio + reg); @@ -320,9 +312,15 @@ static int ocmem_dev_probe(struct platform_device *pdev) ocmem->dev = dev; ocmem->config = device_get_match_data(dev); - ret = devm_clk_bulk_get(dev, ARRAY_SIZE(ocmem_clks), ocmem_clks); - if (ret) - return dev_err_probe(dev, ret, "Unable to get clocks\n"); + ocmem->core_clk = devm_clk_get(dev, "core"); + if (IS_ERR(ocmem->core_clk)) + return dev_err_probe(dev, PTR_ERR(ocmem->core_clk), + "Unable to get core clock\n"); + + ocmem->iface_clk = devm_clk_get_optional(dev, "iface"); + if (IS_ERR(ocmem->iface_clk)) + return dev_err_probe(dev, PTR_ERR(ocmem->iface_clk), + "Unable to get iface clock\n"); ocmem->mmio = devm_platform_ioremap_resource_byname(pdev, "ctrl"); if (IS_ERR(ocmem->mmio)) @@ -337,11 +335,15 @@ static int ocmem_dev_probe(struct platform_device *pdev) } /* The core clock is synchronous with graphics */ - WARN_ON(clk_set_rate(ocmem_clks[OCMEM_CLK_CORE_IDX].clk, 1000) < 0); + WARN_ON(clk_set_rate(ocmem->core_clk, 1000) < 0); + + ret = clk_prepare_enable(ocmem->core_clk); + if (ret) + return dev_err_probe(ocmem->dev, ret, "Failed to enable core clock\n"); - ret = clk_bulk_prepare_enable(ARRAY_SIZE(ocmem_clks), ocmem_clks); + ret = clk_prepare_enable(ocmem->iface_clk); if (ret) - return dev_err_probe(ocmem->dev, ret, "Failed to enable clocks\n"); + return dev_err_probe(ocmem->dev, ret, "Failed to enable iface clock\n"); if (qcom_scm_restore_sec_cfg_available()) { dev_dbg(dev, "configuring scm\n"); @@ -406,13 +408,17 @@ static int ocmem_dev_probe(struct platform_device *pdev) return 0; err_clk_disable: - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); + clk_disable_unprepare(ocmem->core_clk); + clk_disable_unprepare(ocmem->iface_clk); return ret; } static int ocmem_dev_remove(struct platform_device *pdev) { - clk_bulk_disable_unprepare(ARRAY_SIZE(ocmem_clks), ocmem_clks); + struct ocmem *ocmem = platform_get_drvdata(pdev); + + clk_disable_unprepare(ocmem->core_clk); + clk_disable_unprepare(ocmem->iface_clk); return 0; } -- cgit v1.2.3 From 2976eec238dcd89475664795f54d4a4d3d05e0f9 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Wed, 14 Jun 2023 18:35:51 +0200 Subject: soc: qcom: ocmem: Add support for msm8226 The msm8226 SoC also contains OCMEM but with one region only. Reviewed-by: Konrad Dybcio Signed-off-by: Luca Weiss Link: https://lore.kernel.org/r/20230506-msm8226-ocmem-v3-5-79da95a2581f@z3ntu.xyz Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ocmem.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index ff8d01b0ac68..2064e9512301 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -423,12 +423,18 @@ static int ocmem_dev_remove(struct platform_device *pdev) return 0; } +static const struct ocmem_config ocmem_8226_config = { + .num_regions = 1, + .macro_size = SZ_128K, +}; + static const struct ocmem_config ocmem_8974_config = { .num_regions = 3, .macro_size = SZ_128K, }; static const struct of_device_id ocmem_of_match[] = { + { .compatible = "qcom,msm8226-ocmem", .data = &ocmem_8226_config }, { .compatible = "qcom,msm8974-ocmem", .data = &ocmem_8974_config }, { } }; -- cgit v1.2.3 From 98c8b3efacaec61287a096dd37ca3c197f298b70 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 19 Jun 2023 14:32:26 +0200 Subject: soc: qcom: rpmpd: Add sync_state Add a sync_state implementation, very similar to the one already present in the RPMhPD driver. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230619-topic-rpmpd_syncstate-v1-1-54f986cf9444@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmpd.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index 99b017fd76b7..fa58c04214ee 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -58,6 +58,7 @@ struct rpmpd { struct qcom_smd_rpm *rpm; unsigned int max_state; __le32 key; + bool state_synced; }; struct rpmpd_desc { @@ -823,7 +824,11 @@ static int rpmpd_aggregate_corner(struct rpmpd *pd) unsigned int this_active_corner = 0, this_sleep_corner = 0; unsigned int peer_active_corner = 0, peer_sleep_corner = 0; - to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner); + /* Clamp to the highest corner/level if sync_state isn't done yet */ + if (!pd->state_synced) + this_active_corner = this_sleep_corner = pd->max_state - 1; + else + to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner); if (peer && peer->enabled) to_active_sleep(peer, peer->corner, &peer_active_corner, @@ -973,11 +978,38 @@ static int rpmpd_probe(struct platform_device *pdev) return of_genpd_add_provider_onecell(pdev->dev.of_node, data); } +static void rpmpd_sync_state(struct device *dev) +{ + const struct rpmpd_desc *desc = of_device_get_match_data(dev); + struct rpmpd **rpmpds = desc->rpmpds; + struct rpmpd *pd; + unsigned int i; + int ret; + + mutex_lock(&rpmpd_lock); + for (i = 0; i < desc->num_pds; i++) { + pd = rpmpds[i]; + if (!pd) + continue; + + pd->state_synced = true; + + if (!pd->enabled) + pd->corner = 0; + + ret = rpmpd_aggregate_corner(pd); + if (ret) + dev_err(dev, "failed to sync %s: %d\n", pd->pd.name, ret); + } + mutex_unlock(&rpmpd_lock); +} + static struct platform_driver rpmpd_driver = { .driver = { .name = "qcom-rpmpd", .of_match_table = rpmpd_match_table, .suppress_bind_attrs = true, + .sync_state = rpmpd_sync_state, }, .probe = rpmpd_probe, }; -- cgit v1.2.3 From d4600cbd5bcbaa2b296b5cf9a5c04408eedb4ef3 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 20 Jun 2023 14:37:03 -0700 Subject: soc: qcom: cmd-db: Drop NUL bytes from debugfs output The debugfs dump of Command DB relies uses %*pEp to print the resource identifiers, with escaping of non-printable characters. But p (ESCAPE_NP) does not escape NUL characters, so for identifiers less than 8 bytes in length the output will retain these. This does not cause an issue while looking at the dump in the terminal (no known complaints at least), but when programmatically consuming the debugfs output the extra characters are unwanted. Change the fixed 8-byte sizeof() to a dynamic strnlen() to avoid printing these NUL characters. Signed-off-by: Bjorn Andersson Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230620213703.283583-1-quic_bjorande@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/cmd-db.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c index 33856abd560c..34c40368d5b5 100644 --- a/drivers/soc/qcom/cmd-db.c +++ b/drivers/soc/qcom/cmd-db.c @@ -284,7 +284,7 @@ static int cmd_db_debugfs_dump(struct seq_file *seq, void *p) ent = rsc_to_entry_header(rsc); for (j = 0; j < le16_to_cpu(rsc->cnt); j++, ent++) { seq_printf(seq, "0x%05x: %*pEp", le32_to_cpu(ent->addr), - (int)sizeof(ent->id), ent->id); + (int)strnlen(ent->id, sizeof(ent->id)), ent->id); len = le16_to_cpu(ent->len); if (len) { -- cgit v1.2.3 From 1b06d8ca087a8fd9b395b577048636926db22f0e Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 20 Jun 2023 16:00:58 -0700 Subject: soc: qcom: rpmh-rsc: Include state in trace event When tracing messages written to the RSC it's very useful to know the type of TCS being targeted, in particular if/when the code borrows a WAKE TCS for ACTIVE votes. Add the "state" of the message to the traced information. While at it, drop the "send-msg:" substring, as this is already captured by the trace event itself. Signed-off-by: Bjorn Andersson Acked-by: Manivannan Sadhasivam Acked-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230620230058.428833-1-quic_bjorande@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmh-rsc.c | 2 +- drivers/soc/qcom/trace-rpmh.h | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index 0dd4363ebac8..a021dc71807b 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -516,7 +516,7 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_MSGID], tcs_id, j, msgid); write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], tcs_id, j, cmd->addr); write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, cmd->data); - trace_rpmh_send_msg(drv, tcs_id, j, msgid, cmd); + trace_rpmh_send_msg(drv, tcs_id, msg->state, j, msgid, cmd); } cmd_enable |= read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id); diff --git a/drivers/soc/qcom/trace-rpmh.h b/drivers/soc/qcom/trace-rpmh.h index 12b676b20cb2..be6b42ecc1f8 100644 --- a/drivers/soc/qcom/trace-rpmh.h +++ b/drivers/soc/qcom/trace-rpmh.h @@ -38,14 +38,15 @@ TRACE_EVENT(rpmh_tx_done, TRACE_EVENT(rpmh_send_msg, - TP_PROTO(struct rsc_drv *d, int m, int n, u32 h, + TP_PROTO(struct rsc_drv *d, int m, enum rpmh_state state, int n, u32 h, const struct tcs_cmd *c), - TP_ARGS(d, m, n, h, c), + TP_ARGS(d, m, state, n, h, c), TP_STRUCT__entry( __string(name, d->name) __field(int, m) + __field(u32, state) __field(int, n) __field(u32, hdr) __field(u32, addr) @@ -56,6 +57,7 @@ TRACE_EVENT(rpmh_send_msg, TP_fast_assign( __assign_str(name, d->name); __entry->m = m; + __entry->state = state; __entry->n = n; __entry->hdr = h; __entry->addr = c->addr; @@ -63,8 +65,14 @@ TRACE_EVENT(rpmh_send_msg, __entry->wait = c->wait; ), - TP_printk("%s: send-msg: tcs(m): %d cmd(n): %d msgid: %#x addr: %#x data: %#x complete: %d", - __get_str(name), __entry->m, __entry->n, __entry->hdr, + TP_printk("%s: tcs(m): %d [%s] cmd(n): %d msgid: %#x addr: %#x data: %#x complete: %d", + __get_str(name), __entry->m, + __print_symbolic(__entry->state, + { RPMH_SLEEP_STATE, "sleep" }, + { RPMH_WAKE_ONLY_STATE, "wake" }, + { RPMH_ACTIVE_ONLY_STATE, "active" }), + __entry->n, + __entry->hdr, __entry->addr, __entry->data, __entry->wait) ); -- cgit v1.2.3 From 7bc1cfaee1f03008e8b1fd29e621cb50a9512263 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Wed, 5 Jul 2023 20:26:41 +0800 Subject: soc: qcom: spm: Convert to devm_platform_ioremap_resource() Use devm_platform_ioremap_resource() to simplify code. Signed-off-by: Yangtao Li Link: https://lore.kernel.org/r/20230705122644.32236-3-frank.li@vivo.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/spm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c index a6cbeb40831b..bab4897267b9 100644 --- a/drivers/soc/qcom/spm.c +++ b/drivers/soc/qcom/spm.c @@ -275,15 +275,13 @@ static int spm_dev_probe(struct platform_device *pdev) { const struct of_device_id *match_id; struct spm_driver_data *drv; - struct resource *res; void __iomem *addr; drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); if (!drv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drv->reg_base = devm_ioremap_resource(&pdev->dev, res); + drv->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(drv->reg_base)) return PTR_ERR(drv->reg_base); -- cgit v1.2.3 From cbdd13bfea785667f9c9df4c6ec46fc841ef6c4a Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Wed, 12 Jul 2023 22:42:15 +0200 Subject: soc: qcom: smem: Use struct_size() Use struct_size() instead of hand-writing it, when allocating a structure with a flex array. This is less verbose. Signed-off-by: Christophe JAILLET Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/f74328551cfab0262ba353f37d047ac74bf616e1.1689194490.git.christophe.jaillet@wanadoo.fr Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index b0d59e815c3b..776096b2e965 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -1059,7 +1059,6 @@ static int qcom_smem_probe(struct platform_device *pdev) struct reserved_mem *rmem; struct qcom_smem *smem; unsigned long flags; - size_t array_size; int num_regions; int hwlock_id; u32 version; @@ -1071,8 +1070,8 @@ static int qcom_smem_probe(struct platform_device *pdev) if (of_property_present(pdev->dev.of_node, "qcom,rpm-msg-ram")) num_regions++; - array_size = num_regions * sizeof(struct smem_region); - smem = devm_kzalloc(&pdev->dev, sizeof(*smem) + array_size, GFP_KERNEL); + smem = devm_kzalloc(&pdev->dev, struct_size(smem, regions, num_regions), + GFP_KERNEL); if (!smem) return -ENOMEM; -- cgit v1.2.3 From bcabe1e09135cd4fc1f5cddc6d4a45a221a768cc Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Thu, 15 Jun 2023 18:50:37 +0200 Subject: soc: qcom: smd-rpm: Match rpmsg channel instead of compatible There is an ever growing list of compatibles in the smd-rpm.c driver. A fallback compatible would help here but would still require keeping the current list around for backwards compatibility. As an alternative, let's switch the driver to match the rpmsg_device_id instead, which is always "rpm_requests" on all platforms. Add a check to ensure that there is a device tree node defined for the device since otherwise the of_platform_populate() call will operate on the root node (/). Similar approaches with matching rpmsg_device_id are already used in qcom_sysmon, qcom_glink_ssr, qrtr, and rpmsg_wwan_ctrl. Tested-by: Konrad Dybcio # SM6375 (G-Link) Reviewed-by: Konrad Dybcio Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20230531-rpm-rproc-v3-4-a07dcdefd918@gerhold.net Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smd-rpm.c | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c index 0c1aa809cc4e..13d8c52330d0 100644 --- a/drivers/soc/qcom/smd-rpm.c +++ b/drivers/soc/qcom/smd-rpm.c @@ -199,6 +199,9 @@ static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev) struct qcom_smd_rpm *rpm; int ret; + if (!rpdev->dev.of_node) + return -EINVAL; + rpm = devm_kzalloc(&rpdev->dev, sizeof(*rpm), GFP_KERNEL); if (!rpm) return -ENOMEM; @@ -230,38 +233,18 @@ static void qcom_smd_rpm_remove(struct rpmsg_device *rpdev) of_platform_depopulate(&rpdev->dev); } -static const struct of_device_id qcom_smd_rpm_of_match[] = { - { .compatible = "qcom,rpm-apq8084" }, - { .compatible = "qcom,rpm-ipq6018" }, - { .compatible = "qcom,rpm-ipq9574" }, - { .compatible = "qcom,rpm-msm8226" }, - { .compatible = "qcom,rpm-msm8909" }, - { .compatible = "qcom,rpm-msm8916" }, - { .compatible = "qcom,rpm-msm8936" }, - { .compatible = "qcom,rpm-msm8953" }, - { .compatible = "qcom,rpm-msm8974" }, - { .compatible = "qcom,rpm-msm8976" }, - { .compatible = "qcom,rpm-msm8994" }, - { .compatible = "qcom,rpm-msm8996" }, - { .compatible = "qcom,rpm-msm8998" }, - { .compatible = "qcom,rpm-sdm660" }, - { .compatible = "qcom,rpm-sm6115" }, - { .compatible = "qcom,rpm-sm6125" }, - { .compatible = "qcom,rpm-sm6375" }, - { .compatible = "qcom,rpm-qcm2290" }, - { .compatible = "qcom,rpm-qcs404" }, - {} +static const struct rpmsg_device_id qcom_smd_rpm_id_table[] = { + { .name = "rpm_requests", }, + { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match); +MODULE_DEVICE_TABLE(rpmsg, qcom_smd_rpm_id_table); static struct rpmsg_driver qcom_smd_rpm_driver = { .probe = qcom_smd_rpm_probe, .remove = qcom_smd_rpm_remove, .callback = qcom_smd_rpm_callback, - .drv = { - .name = "qcom_smd_rpm", - .of_match_table = qcom_smd_rpm_of_match, - }, + .id_table = qcom_smd_rpm_id_table, + .drv.name = "qcom_smd_rpm", }; static int __init qcom_smd_rpm_init(void) -- cgit v1.2.3 From 4dbb9e2322a3a9c912ce796c20c27045ae8dae22 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Thu, 15 Jun 2023 18:50:40 +0200 Subject: soc: qcom: smem: Add qcom_smem_is_available() Avoid having to look up a dummy item from SMEM to detect if it is already available or if we need to defer probing. Reviewed-by: Konrad Dybcio Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20230531-rpm-rproc-v3-7-a07dcdefd918@gerhold.net Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index 776096b2e965..aa4a199efefb 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -359,6 +359,17 @@ static struct qcom_smem *__smem; /* Timeout (ms) for the trylock of remote spinlocks */ #define HWSPINLOCK_TIMEOUT 1000 +/** + * qcom_smem_is_available() - Check if SMEM is available + * + * Return: true if SMEM is available, false otherwise. + */ +bool qcom_smem_is_available(void) +{ + return !!__smem; +} +EXPORT_SYMBOL(qcom_smem_is_available); + static int qcom_smem_alloc_private(struct qcom_smem *smem, struct smem_partition *part, unsigned item, -- cgit v1.2.3 From 8ddfa81d090c71fd6cb3cb8ca1d420c0da33a575 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Thu, 15 Jun 2023 18:50:42 +0200 Subject: soc: qcom: Add RPM processor/subsystem driver Add a simple driver for the qcom,rpm-proc compatible that registers the "smd-edge" and populates other children defined in the device tree. Note that the DT schema belongs to the remoteproc subsystem while this driver is added inside soc/qcom. I argue that the RPM *is* a remoteproc, but as an implementation detail in Linux it can currently not benefit from anything provided by the remoteproc subsystem. The RPM firmware is usually already loaded and started by earlier components in the boot chain and is not meant to be ever restarted. To avoid breaking existing kernel configurations the driver is always built when smd-rpm.c is also built. They belong closely together anyway. To avoid build errors CONFIG_RPMSG_QCOM_SMD must be also built-in if rpm-proc is. Reviewed-by: Konrad Dybcio Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20230531-rpm-rproc-v3-9-a07dcdefd918@gerhold.net Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/Kconfig | 1 + drivers/soc/qcom/Makefile | 2 +- drivers/soc/qcom/rpm-proc.c | 77 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/qcom/rpm-proc.c (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index e597799e8121..715348869d04 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -191,6 +191,7 @@ config QCOM_SMD_RPM tristate "Qualcomm Resource Power Manager (RPM) over SMD" depends on ARCH_QCOM || COMPILE_TEST depends on RPMSG + depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n help If you say yes to this option, support will be included for the Resource Power Manager system found in the Qualcomm 8974 based diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 99114c71092b..113b9ff2ad43 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_QCOM_RPM_MASTER_STATS) += rpm_master_stats.o obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o qcom_rpmh-y += rpmh-rsc.o qcom_rpmh-y += rpmh.o -obj-$(CONFIG_QCOM_SMD_RPM) += smd-rpm.o +obj-$(CONFIG_QCOM_SMD_RPM) += rpm-proc.o smd-rpm.o obj-$(CONFIG_QCOM_SMEM) += smem.o obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o obj-$(CONFIG_QCOM_SMP2P) += smp2p.o diff --git a/drivers/soc/qcom/rpm-proc.c b/drivers/soc/qcom/rpm-proc.c new file mode 100644 index 000000000000..2995d9b90190 --- /dev/null +++ b/drivers/soc/qcom/rpm-proc.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2021-2023, Stephan Gerhold */ + +#include +#include +#include +#include +#include + +static int rpm_proc_probe(struct platform_device *pdev) +{ + struct qcom_smd_edge *edge = NULL; + struct device *dev = &pdev->dev; + struct device_node *edge_node; + int ret; + + edge_node = of_get_child_by_name(dev->of_node, "smd-edge"); + if (edge_node) { + edge = qcom_smd_register_edge(dev, edge_node); + of_node_put(edge_node); + if (IS_ERR(edge)) + return dev_err_probe(dev, PTR_ERR(edge), + "Failed to register smd-edge\n"); + } + + ret = devm_of_platform_populate(dev); + if (ret) { + dev_err(dev, "Failed to populate child devices: %d\n", ret); + goto err; + } + + platform_set_drvdata(pdev, edge); + return 0; +err: + if (edge) + qcom_smd_unregister_edge(edge); + return ret; +} + +static void rpm_proc_remove(struct platform_device *pdev) +{ + struct qcom_smd_edge *edge = platform_get_drvdata(pdev); + + if (edge) + qcom_smd_unregister_edge(edge); +} + +static const struct of_device_id rpm_proc_of_match[] = { + { .compatible = "qcom,rpm-proc", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, rpm_proc_of_match); + +static struct platform_driver rpm_proc_driver = { + .probe = rpm_proc_probe, + .remove_new = rpm_proc_remove, + .driver = { + .name = "qcom-rpm-proc", + .of_match_table = rpm_proc_of_match, + }, +}; + +static int __init rpm_proc_init(void) +{ + return platform_driver_register(&rpm_proc_driver); +} +arch_initcall(rpm_proc_init); + +static void __exit rpm_proc_exit(void) +{ + platform_driver_unregister(&rpm_proc_driver); +} +module_exit(rpm_proc_exit); + +MODULE_DESCRIPTION("Qualcomm RPM processor/subsystem driver"); +MODULE_AUTHOR("Stephan Gerhold "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 6484be9dd109bded43953ae7883bd69b5d841a0b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 14 Jul 2023 11:51:41 -0600 Subject: soc: qcom: Explicitly include correct DT includes The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20230714175142.4067795-1-robh@kernel.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/cpr.c | 1 - drivers/soc/qcom/icc-bwmon.c | 2 +- drivers/soc/qcom/ice.c | 2 ++ drivers/soc/qcom/llcc-qcom.c | 1 - drivers/soc/qcom/ocmem.c | 3 ++- drivers/soc/qcom/pmic_glink.c | 2 +- drivers/soc/qcom/pmic_glink_altmode.c | 1 + drivers/soc/qcom/rpmhpd.c | 1 - drivers/soc/qcom/rpmpd.c | 1 - drivers/soc/qcom/spm.c | 2 -- drivers/soc/qcom/wcnss_ctrl.c | 1 + 11 files changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/cpr.c b/drivers/soc/qcom/cpr.c index 144ea68e0920..94a3f0977212 100644 --- a/drivers/soc/qcom/cpr.c +++ b/drivers/soc/qcom/cpr.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c index 8daf0eb03279..adf2d523f103 100644 --- a/drivers/soc/qcom/icc-bwmon.c +++ b/drivers/soc/qcom/icc-bwmon.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c index a6123ea96272..fbab7fe5c652 100644 --- a/drivers/soc/qcom/ice.c +++ b/drivers/soc/qcom/ice.c @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 67c19ed2219a..e32a4161a8d0 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index 2064e9512301..6edc18b211aa 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -14,7 +14,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index c87056769ebd..264e63493bfe 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -4,8 +4,8 @@ * Copyright (c) 2022, Linaro Ltd */ #include -#include #include +#include #include #include #include diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index df48fbea4b68..1dedacc52aea 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c index 63c35a32065b..2cae1d0aef48 100644 --- a/drivers/soc/qcom/rpmhpd.c +++ b/drivers/soc/qcom/rpmhpd.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index fa58c04214ee..3135dd1dafe0 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c index bab4897267b9..2f0b1bfe7658 100644 --- a/drivers/soc/qcom/spm.c +++ b/drivers/soc/qcom/spm.c @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/drivers/soc/qcom/wcnss_ctrl.c b/drivers/soc/qcom/wcnss_ctrl.c index 2a06d631e415..ad9942412c58 100644 --- a/drivers/soc/qcom/wcnss_ctrl.c +++ b/drivers/soc/qcom/wcnss_ctrl.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From de3acb7af908ef4fa9fda19cdfce1cc30cb48388 Mon Sep 17 00:00:00 2001 From: Rohit Agarwal Date: Wed, 19 Jul 2023 10:52:42 +0530 Subject: soc: qcom: rpmhpd: Use the newly created generic RPMHPD bindings Update the SoC SM8[2345]50 entries to use the new generic RPMHPD bindings. Signed-off-by: Rohit Agarwal Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/1689744162-9421-3-git-send-email-quic_rohiagar@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmhpd.c | 101 +++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 50 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c index 2cae1d0aef48..6641d5228bc6 100644 --- a/drivers/soc/qcom/rpmhpd.c +++ b/drivers/soc/qcom/rpmhpd.c @@ -14,6 +14,7 @@ #include #include #include +#include #define domain_to_rpmhpd(domain) container_of(domain, struct rpmhpd, pd) @@ -358,16 +359,16 @@ static const struct rpmhpd_desc sa8155p_desc = { /* SM8250 RPMH powerdomains */ static struct rpmhpd *sm8250_rpmhpds[] = { - [SM8250_CX] = &cx_w_mx_parent, - [SM8250_CX_AO] = &cx_ao_w_mx_parent, - [SM8250_EBI] = &ebi, - [SM8250_GFX] = &gfx, - [SM8250_LCX] = &lcx, - [SM8250_LMX] = &lmx, - [SM8250_MMCX] = &mmcx, - [SM8250_MMCX_AO] = &mmcx_ao, - [SM8250_MX] = &mx, - [SM8250_MX_AO] = &mx_ao, + [RPMHPD_CX] = &cx_w_mx_parent, + [RPMHPD_CX_AO] = &cx_ao_w_mx_parent, + [RPMHPD_EBI] = &ebi, + [RPMHPD_GFX] = &gfx, + [RPMHPD_LCX] = &lcx, + [RPMHPD_LMX] = &lmx, + [RPMHPD_MMCX] = &mmcx, + [RPMHPD_MMCX_AO] = &mmcx_ao, + [RPMHPD_MX] = &mx, + [RPMHPD_MX_AO] = &mx_ao, }; static const struct rpmhpd_desc sm8250_desc = { @@ -377,19 +378,19 @@ static const struct rpmhpd_desc sm8250_desc = { /* SM8350 Power domains */ static struct rpmhpd *sm8350_rpmhpds[] = { - [SM8350_CX] = &cx_w_mx_parent, - [SM8350_CX_AO] = &cx_ao_w_mx_parent, - [SM8350_EBI] = &ebi, - [SM8350_GFX] = &gfx, - [SM8350_LCX] = &lcx, - [SM8350_LMX] = &lmx, - [SM8350_MMCX] = &mmcx, - [SM8350_MMCX_AO] = &mmcx_ao, - [SM8350_MSS] = &mss, - [SM8350_MX] = &mx, - [SM8350_MX_AO] = &mx_ao, - [SM8350_MXC] = &mxc, - [SM8350_MXC_AO] = &mxc_ao, + [RPMHPD_CX] = &cx_w_mx_parent, + [RPMHPD_CX_AO] = &cx_ao_w_mx_parent, + [RPMHPD_EBI] = &ebi, + [RPMHPD_GFX] = &gfx, + [RPMHPD_LCX] = &lcx, + [RPMHPD_LMX] = &lmx, + [RPMHPD_MMCX] = &mmcx, + [RPMHPD_MMCX_AO] = &mmcx_ao, + [RPMHPD_MSS] = &mss, + [RPMHPD_MX] = &mx, + [RPMHPD_MX_AO] = &mx_ao, + [RPMHPD_MXC] = &mxc, + [RPMHPD_MXC_AO] = &mxc_ao, }; static const struct rpmhpd_desc sm8350_desc = { @@ -399,19 +400,19 @@ static const struct rpmhpd_desc sm8350_desc = { /* SM8450 RPMH powerdomains */ static struct rpmhpd *sm8450_rpmhpds[] = { - [SM8450_CX] = &cx, - [SM8450_CX_AO] = &cx_ao, - [SM8450_EBI] = &ebi, - [SM8450_GFX] = &gfx, - [SM8450_LCX] = &lcx, - [SM8450_LMX] = &lmx, - [SM8450_MMCX] = &mmcx_w_cx_parent, - [SM8450_MMCX_AO] = &mmcx_ao_w_cx_parent, - [SM8450_MSS] = &mss, - [SM8450_MX] = &mx, - [SM8450_MX_AO] = &mx_ao, - [SM8450_MXC] = &mxc, - [SM8450_MXC_AO] = &mxc_ao, + [RPMHPD_CX] = &cx, + [RPMHPD_CX_AO] = &cx_ao, + [RPMHPD_EBI] = &ebi, + [RPMHPD_GFX] = &gfx, + [RPMHPD_LCX] = &lcx, + [RPMHPD_LMX] = &lmx, + [RPMHPD_MMCX] = &mmcx_w_cx_parent, + [RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent, + [RPMHPD_MSS] = &mss, + [RPMHPD_MX] = &mx, + [RPMHPD_MX_AO] = &mx_ao, + [RPMHPD_MXC] = &mxc, + [RPMHPD_MXC_AO] = &mxc_ao, }; static const struct rpmhpd_desc sm8450_desc = { @@ -421,20 +422,20 @@ static const struct rpmhpd_desc sm8450_desc = { /* SM8550 RPMH powerdomains */ static struct rpmhpd *sm8550_rpmhpds[] = { - [SM8550_CX] = &cx, - [SM8550_CX_AO] = &cx_ao, - [SM8550_EBI] = &ebi, - [SM8550_GFX] = &gfx, - [SM8550_LCX] = &lcx, - [SM8550_LMX] = &lmx, - [SM8550_MMCX] = &mmcx_w_cx_parent, - [SM8550_MMCX_AO] = &mmcx_ao_w_cx_parent, - [SM8550_MSS] = &mss, - [SM8550_MX] = &mx, - [SM8550_MX_AO] = &mx_ao, - [SM8550_MXC] = &mxc, - [SM8550_MXC_AO] = &mxc_ao, - [SM8550_NSP] = &nsp, + [RPMHPD_CX] = &cx, + [RPMHPD_CX_AO] = &cx_ao, + [RPMHPD_EBI] = &ebi, + [RPMHPD_GFX] = &gfx, + [RPMHPD_LCX] = &lcx, + [RPMHPD_LMX] = &lmx, + [RPMHPD_MMCX] = &mmcx_w_cx_parent, + [RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent, + [RPMHPD_MSS] = &mss, + [RPMHPD_MX] = &mx, + [RPMHPD_MX_AO] = &mx_ao, + [RPMHPD_MXC] = &mxc, + [RPMHPD_MXC_AO] = &mxc_ao, + [RPMHPD_NSP] = &nsp, }; static const struct rpmhpd_desc sm8550_desc = { -- cgit v1.2.3 From 489d7a8cc286f37f52156100b95751b10e240941 Mon Sep 17 00:00:00 2001 From: Yuanjun Gong Date: Thu, 20 Jul 2023 22:08:34 +0800 Subject: soc: qcom: use devm_clk_get_enabled() in gsbi_probe() in gsbi_probe(), the return value of function clk_prepare_enable() should be checked, since it may fail. using devm_clk_get_enabled() instead of devm_clk_get() and clk_prepare_enable() can avoid this problem. Signed-off-by: Yuanjun Gong Link: https://lore.kernel.org/r/20230720140834.33557-1-ruc_gongyuanjun@163.com [bjorn: Dropped unnecessary "ret" variable] Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_gsbi.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/qcom_gsbi.c b/drivers/soc/qcom/qcom_gsbi.c index f1742e5bddb9..df7907a83aa8 100644 --- a/drivers/soc/qcom/qcom_gsbi.c +++ b/drivers/soc/qcom/qcom_gsbi.c @@ -129,7 +129,7 @@ static int gsbi_probe(struct platform_device *pdev) const struct of_device_id *match; void __iomem *base; struct gsbi_info *gsbi; - int i, ret; + int i; u32 mask, gsbi_num; const struct crci_config *config = NULL; @@ -178,12 +178,10 @@ static int gsbi_probe(struct platform_device *pdev) dev_info(&pdev->dev, "GSBI port protocol: %d crci: %d\n", gsbi->mode, gsbi->crci); - gsbi->hclk = devm_clk_get(&pdev->dev, "iface"); + gsbi->hclk = devm_clk_get_enabled(&pdev->dev, "iface"); if (IS_ERR(gsbi->hclk)) return PTR_ERR(gsbi->hclk); - clk_prepare_enable(gsbi->hclk); - writel_relaxed((gsbi->mode << GSBI_PROTOCOL_SHIFT) | gsbi->crci, base + GSBI_CTRL_REG); @@ -211,10 +209,7 @@ static int gsbi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gsbi); - ret = of_platform_populate(node, NULL, NULL, &pdev->dev); - if (ret) - clk_disable_unprepare(gsbi->hclk); - return ret; + return of_platform_populate(node, NULL, NULL, &pdev->dev); } static int gsbi_remove(struct platform_device *pdev) -- cgit v1.2.3 From 668e08c2e7b02124da573e29a67e013627ebf9ea Mon Sep 17 00:00:00 2001 From: Rohit Agarwal Date: Mon, 31 Jul 2023 17:00:07 +0530 Subject: soc: qcom: rpmhpd: Add SDX75 power domains Add the power domains exposed by RPMH in the Qualcomm SDX75 platform. Signed-off-by: Rohit Agarwal Link: https://lore.kernel.org/r/1690803007-8640-3-git-send-email-quic_rohiagar@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/rpmhpd.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c index 6641d5228bc6..a87e336d5e33 100644 --- a/drivers/soc/qcom/rpmhpd.c +++ b/drivers/soc/qcom/rpmhpd.c @@ -307,6 +307,21 @@ static const struct rpmhpd_desc sdx65_desc = { .num_pds = ARRAY_SIZE(sdx65_rpmhpds), }; +/* SDX75 RPMH powerdomains */ +static struct rpmhpd *sdx75_rpmhpds[] = { + [RPMHPD_CX] = &cx, + [RPMHPD_CX_AO] = &cx_ao, + [RPMHPD_MSS] = &mss, + [RPMHPD_MX] = &mx, + [RPMHPD_MX_AO] = &mx_ao, + [RPMHPD_MXC] = &mxc, +}; + +static const struct rpmhpd_desc sdx75_desc = { + .rpmhpds = sdx75_rpmhpds, + .num_pds = ARRAY_SIZE(sdx75_rpmhpds), +}; + /* SM6350 RPMH powerdomains */ static struct rpmhpd *sm6350_rpmhpds[] = { [SM6350_CX] = &cx_w_mx_parent, @@ -545,6 +560,7 @@ static const struct of_device_id rpmhpd_match_table[] = { { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc }, { .compatible = "qcom,sdx55-rpmhpd", .data = &sdx55_desc}, { .compatible = "qcom,sdx65-rpmhpd", .data = &sdx65_desc}, + { .compatible = "qcom,sdx75-rpmhpd", .data = &sdx75_desc}, { .compatible = "qcom,sm6350-rpmhpd", .data = &sm6350_desc }, { .compatible = "qcom,sm8150-rpmhpd", .data = &sm8150_desc }, { .compatible = "qcom,sm8250-rpmhpd", .data = &sm8250_desc }, -- cgit v1.2.3 From 1beecfe68f802e5d4218bb7c5a728f2f38c979c7 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 19 Jun 2023 10:07:13 +0200 Subject: soc: qcom: pmic_glink_altmode: handle safe mode when disconnect On some Qcom SoCs, the Altmode event mode is set to 0xff when the Type-C port is disconnected. Handle this specific mode and translate it as the SAFE mode. Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20230601-topic-sm8550-upstream-type-c-v5-1-9221cd300903@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink_altmode.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 1dedacc52aea..297d5821c784 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -174,6 +174,20 @@ static void pmic_glink_altmode_enable_usb(struct pmic_glink_altmode *altmode, dev_err(altmode->dev, "failed to switch mux to USB\n"); } +static void pmic_glink_altmode_safe(struct pmic_glink_altmode *altmode, + struct pmic_glink_altmode_port *port) +{ + int ret; + + port->state.alt = NULL; + port->state.data = NULL; + port->state.mode = TYPEC_STATE_SAFE; + + ret = typec_mux_set(port->typec_mux, &port->state); + if (ret) + dev_err(altmode->dev, "failed to switch mux to safe mode\n"); +} + static void pmic_glink_altmode_worker(struct work_struct *work) { struct pmic_glink_altmode_port *alt_port = work_to_altmode_port(work); @@ -181,7 +195,9 @@ static void pmic_glink_altmode_worker(struct work_struct *work) typec_switch_set(alt_port->typec_switch, alt_port->orientation); - if (alt_port->svid == USB_TYPEC_DP_SID) + if (alt_port->svid == USB_TYPEC_DP_SID && alt_port->mode == 0xff) + pmic_glink_altmode_safe(altmode, alt_port); + else if (alt_port->svid == USB_TYPEC_DP_SID) pmic_glink_altmode_enable_dp(altmode, alt_port, alt_port->mode, alt_port->hpd_state, alt_port->hpd_irq); else -- cgit v1.2.3 From 0549bc385f3534c380acbd7722cb6e14cca8c580 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 19 Jun 2023 10:07:14 +0200 Subject: soc: qcom: pmic_glink_altmode: add retimer-switch support Some boards have a retimer/redriver between the SuperSpeed PHY and the USB-C connector to compensates signal integrity losses mainly due to PCB & transmission cables. Add support for an optional retimer-switch in the USB-C connector graph. Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20230601-topic-sm8550-upstream-type-c-v5-2-9221cd300903@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink_altmode.c | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 297d5821c784..d05e0d6edf49 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -69,6 +70,8 @@ struct pmic_glink_altmode_port { struct typec_switch *typec_switch; struct typec_mux *typec_mux; struct typec_mux_state state; + struct typec_retimer *typec_retimer; + struct typec_retimer_state retimer_state; struct typec_altmode dp_alt; struct work_struct work; @@ -158,6 +161,14 @@ static void pmic_glink_altmode_enable_dp(struct pmic_glink_altmode *altmode, ret = typec_mux_set(port->typec_mux, &port->state); if (ret) dev_err(altmode->dev, "failed to switch mux to DP\n"); + + port->retimer_state.alt = &port->dp_alt; + port->retimer_state.data = &dp_data; + port->retimer_state.mode = TYPEC_MODAL_STATE(mode); + + ret = typec_retimer_set(port->typec_retimer, &port->retimer_state); + if (ret) + dev_err(altmode->dev, "failed to setup retimer to DP\n"); } static void pmic_glink_altmode_enable_usb(struct pmic_glink_altmode *altmode, @@ -172,6 +183,14 @@ static void pmic_glink_altmode_enable_usb(struct pmic_glink_altmode *altmode, ret = typec_mux_set(port->typec_mux, &port->state); if (ret) dev_err(altmode->dev, "failed to switch mux to USB\n"); + + port->retimer_state.alt = NULL; + port->retimer_state.data = NULL; + port->retimer_state.mode = TYPEC_STATE_USB; + + ret = typec_retimer_set(port->typec_retimer, &port->retimer_state); + if (ret) + dev_err(altmode->dev, "failed to setup retimer to USB\n"); } static void pmic_glink_altmode_safe(struct pmic_glink_altmode *altmode, @@ -186,6 +205,14 @@ static void pmic_glink_altmode_safe(struct pmic_glink_altmode *altmode, ret = typec_mux_set(port->typec_mux, &port->state); if (ret) dev_err(altmode->dev, "failed to switch mux to safe mode\n"); + + port->retimer_state.alt = NULL; + port->retimer_state.data = NULL; + port->retimer_state.mode = TYPEC_STATE_SAFE; + + ret = typec_retimer_set(port->typec_retimer, &port->retimer_state); + if (ret) + dev_err(altmode->dev, "failed to setup retimer to USB\n"); } static void pmic_glink_altmode_worker(struct work_struct *work) @@ -348,6 +375,11 @@ static const struct drm_bridge_funcs pmic_glink_altmode_bridge_funcs = { .attach = pmic_glink_altmode_attach, }; +static void pmic_glink_altmode_put_retimer(void *data) +{ + typec_retimer_put(data); +} + static void pmic_glink_altmode_put_mux(void *data) { typec_mux_put(data); @@ -454,6 +486,17 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev, if (ret) return ret; + alt_port->typec_retimer = fwnode_typec_retimer_get(fwnode); + if (IS_ERR(alt_port->typec_retimer)) + return dev_err_probe(dev, PTR_ERR(alt_port->typec_retimer), + "failed to acquire retimer-switch for port: %d\n", + port); + + ret = devm_add_action_or_reset(dev, pmic_glink_altmode_put_retimer, + alt_port->typec_retimer); + if (ret) + return ret; + alt_port->typec_switch = fwnode_typec_switch_get(fwnode); if (IS_ERR(alt_port->typec_switch)) return dev_err_probe(dev, PTR_ERR(alt_port->typec_switch), -- cgit v1.2.3 From 7daada8630eb49cd841c0fd022fadd52da100bce Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 19 Jun 2023 10:07:15 +0200 Subject: soc: qcom: pmic_glink: enable altmode for SM8550 Altmode is also supported for SM8550, allow it. Reviewed-by: Konrad Dybcio Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20230601-topic-sm8550-upstream-type-c-v5-3-9221cd300903@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index 264e63493bfe..61c89ddfc75b 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -342,13 +342,9 @@ static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT BIT(PMIC_GLINK_CLIENT_ALTMODE) | BIT(PMIC_GLINK_CLIENT_UCSI); -/* Do not handle altmode for now on those platforms */ -static const unsigned long pmic_glink_sm8550_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) | - BIT(PMIC_GLINK_CLIENT_UCSI); - static const struct of_device_id pmic_glink_of_match[] = { { .compatible = "qcom,sm8450-pmic-glink", .data = &pmic_glink_sm8450_client_mask }, - { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8550_client_mask }, + { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8450_client_mask }, { .compatible = "qcom,pmic-glink" }, {} }; -- cgit v1.2.3 From 42618de085cc305a5a03bb16a5965f8413944843 Mon Sep 17 00:00:00 2001 From: Tengfei Fan Date: Mon, 31 Jul 2023 16:00:43 +0800 Subject: soc: qcom: socinfo: add SM4450 ID Add the ID for the Qualcomm SM4450 SoC. Signed-off-by: Tengfei Fan Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230731080043.38552-7-quic_tengfan@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 4d49945b3a35..441a40f58838 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -405,6 +405,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(SA8775P) }, { qcom_board_id(QRU1000) }, { qcom_board_id(QDU1000) }, + { qcom_board_id(SM4450) }, { qcom_board_id(QDU1010) }, { qcom_board_id(IPQ5019) }, { qcom_board_id(QRU1032) }, -- cgit v1.2.3 From 90158bc118f6f09fd5cd412c5954a40fd032aeff Mon Sep 17 00:00:00 2001 From: Kathiravan T Date: Mon, 24 Jul 2023 14:07:44 +0530 Subject: soc: qcom: socinfo: drop the IPQ5019 SoC ID IPQ5019 SoC is never productized. So lets drop it. Signed-off-by: Kathiravan T Link: https://lore.kernel.org/r/20230724083745.1015321-2-quic_kathirav@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 441a40f58838..1055b2e0bf96 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -407,7 +407,6 @@ static const struct soc_id soc_id[] = { { qcom_board_id(QDU1000) }, { qcom_board_id(SM4450) }, { qcom_board_id(QDU1010) }, - { qcom_board_id(IPQ5019) }, { qcom_board_id(QRU1032) }, { qcom_board_id(QRU1052) }, { qcom_board_id(QRU1062) }, -- cgit v1.2.3 From 23b45f8aab49f97b0c32bdc6331c0baf7337c48a Mon Sep 17 00:00:00 2001 From: David Wronek Date: Sun, 23 Jul 2023 21:05:05 +0200 Subject: soc: qcom: socinfo: Add SoC ID for SM7125 Add the SoC ID entry for Qualcomm SM7125. Signed-off-by: David Wronek Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230723190725.1619193-5-davidwronek@gmail.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/socinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 1055b2e0bf96..497cfb720fcb 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -371,6 +371,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(SDA429W) }, { qcom_board_id(SM8350) }, { qcom_board_id(QCM2290) }, + { qcom_board_id(SM7125) }, { qcom_board_id(SM6115) }, { qcom_board_id(IPQ5010) }, { qcom_board_id(IPQ5018) }, -- cgit v1.2.3 From 4d6e0a1bf8f7a6b44d20162e29a87d0bd9526bb0 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Wed, 2 Aug 2023 10:48:55 +0800 Subject: soc: qcom: ocmem: add missing clk_disable_unprepare() in ocmem_dev_probe() Add clk_disable_unprepare(core_clk) when enable iface_clk failed. Fixes: a7e12e7bda08 ("soc: qcom: ocmem: make iface clock optional") Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20230802024855.2521895-1-yangyingliang@huawei.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/ocmem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c index 6edc18b211aa..20f5461d46b9 100644 --- a/drivers/soc/qcom/ocmem.c +++ b/drivers/soc/qcom/ocmem.c @@ -343,8 +343,10 @@ static int ocmem_dev_probe(struct platform_device *pdev) return dev_err_probe(ocmem->dev, ret, "Failed to enable core clock\n"); ret = clk_prepare_enable(ocmem->iface_clk); - if (ret) + if (ret) { + clk_disable_unprepare(ocmem->core_clk); return dev_err_probe(ocmem->dev, ret, "Failed to enable iface clock\n"); + } if (qcom_scm_restore_sec_cfg_available()) { dev_dbg(dev, "configuring scm\n"); -- cgit v1.2.3 From 5f908786cf44fcb397cfe0f322ef2f41b0909e2a Mon Sep 17 00:00:00 2001 From: Chen Jiahao Date: Tue, 1 Aug 2023 17:48:07 +0800 Subject: soc: qcom: smem: Fix incompatible types in comparison This patch fixes the following sparse error: drivers/soc/qcom/smem.c:738:30: error: incompatible types in comparison expression (different add ress spaces): drivers/soc/qcom/smem.c:738:30: void * drivers/soc/qcom/smem.c:738:30: void [noderef] __iomem * In addr_in_range(), "base" is of type void __iomem *, converting void *addr to the same type to fix above sparse error. Fixes: 20bb6c9de1b7 ("soc: qcom: smem: map only partitions used by local HOST") Signed-off-by: Chen Jiahao Link: https://lore.kernel.org/r/20230801094807.4146779-1-chenjiahao16@huawei.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/smem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index aa4a199efefb..d4a89d2bb43b 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -735,7 +735,7 @@ EXPORT_SYMBOL_GPL(qcom_smem_get_free_space); static bool addr_in_range(void __iomem *base, size_t size, void *addr) { - return base && (addr >= base && addr < base + size); + return base && ((void __iomem *)addr >= base && (void __iomem *)addr < base + size); } /** -- cgit v1.2.3 From 8d207400fd6b79c92aeb2f33bb79f62dff904ea2 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Tue, 1 Aug 2023 12:17:12 +0530 Subject: soc: qcom: qmi_encdec: Restrict string length in decode The QMI TLV value for strings in a lot of qmi element info structures account for null terminated strings with MAX_LEN + 1. If a string is actually MAX_LEN + 1 length, this will cause an out of bounds access when the NULL character is appended in decoding. Fixes: 9b8a11e82615 ("soc: qcom: Introduce QMI encoder/decoder") Cc: stable@vger.kernel.org Signed-off-by: Chris Lew Signed-off-by: Praveenkumar I Link: https://lore.kernel.org/r/20230801064712.3590128-1-quic_ipkumar@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qmi_encdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/qmi_encdec.c b/drivers/soc/qcom/qmi_encdec.c index b7158e3c3a0b..5c7161b18b72 100644 --- a/drivers/soc/qcom/qmi_encdec.c +++ b/drivers/soc/qcom/qmi_encdec.c @@ -534,8 +534,8 @@ static int qmi_decode_string_elem(const struct qmi_elem_info *ei_array, decoded_bytes += rc; } - if (string_len > temp_ei->elem_len) { - pr_err("%s: String len %d > Max Len %d\n", + if (string_len >= temp_ei->elem_len) { + pr_err("%s: String len %d >= Max Len %d\n", __func__, string_len, temp_ei->elem_len); return -ETOOSMALL; } else if (string_len > tlv_len) { -- cgit v1.2.3 From 59e09100836fdb618b107c37189d6001b5825872 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 11 Aug 2023 13:58:36 -0700 Subject: soc: qcom: aoss: Move length requirements from caller The existing implementation of qmp_send() requires the caller to provide a buffer which is of word-aligned. The underlying reason for this is that message ram only supports word accesses, but pushing this requirement onto the clients results in the same boiler plate code sprinkled in every call site. By using a temporary buffer in qmp_send() we can hide the underlying hardware limitations from the clients and allow them to pass their NUL-terminates C string directly. Signed-off-by: Bjorn Andersson Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20230811205839.727373-2-quic_bjorande@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index e376c32cc16e..880fe234ca0a 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -206,36 +206,35 @@ static bool qmp_message_empty(struct qmp *qmp) * qmp_send() - send a message to the AOSS * @qmp: qmp context * @data: message to be sent - * @len: length of the message * * Transmit @data to AOSS and wait for the AOSS to acknowledge the message. - * @len must be a multiple of 4 and not longer than the mailbox size. Access is - * synchronized by this implementation. + * data must not be longer than the mailbox size. Access is synchronized by + * this implementation. * * Return: 0 on success, negative errno on failure */ -int qmp_send(struct qmp *qmp, const void *data, size_t len) +int qmp_send(struct qmp *qmp, const void *data) { + char buf[QMP_MSG_LEN]; long time_left; int ret; if (WARN_ON(IS_ERR_OR_NULL(qmp) || !data)) return -EINVAL; - if (WARN_ON(len + sizeof(u32) > qmp->size)) + if (WARN_ON(strlen(data) >= sizeof(buf))) return -EINVAL; - if (WARN_ON(len % sizeof(u32))) - return -EINVAL; + strscpy_pad(buf, data, sizeof(buf)); mutex_lock(&qmp->tx_lock); /* The message RAM only implements 32-bit accesses */ __iowrite32_copy(qmp->msgram + qmp->offset + sizeof(u32), - data, len / sizeof(u32)); - writel(len, qmp->msgram + qmp->offset); + buf, sizeof(buf) / sizeof(u32)); + writel(sizeof(buf), qmp->msgram + qmp->offset); - /* Read back len to confirm data written in message RAM */ + /* Read back length to confirm data written in message RAM */ readl(qmp->msgram + qmp->offset); qmp_kick(qmp); @@ -262,7 +261,7 @@ static int qmp_qdss_clk_prepare(struct clk_hw *hw) static const char buf[QMP_MSG_LEN] = "{class: clock, res: qdss, val: 1}"; struct qmp *qmp = container_of(hw, struct qmp, qdss_clk); - return qmp_send(qmp, buf, sizeof(buf)); + return qmp_send(qmp, buf); } static void qmp_qdss_clk_unprepare(struct clk_hw *hw) @@ -270,7 +269,7 @@ static void qmp_qdss_clk_unprepare(struct clk_hw *hw) static const char buf[QMP_MSG_LEN] = "{class: clock, res: qdss, val: 0}"; struct qmp *qmp = container_of(hw, struct qmp, qdss_clk); - qmp_send(qmp, buf, sizeof(buf)); + qmp_send(qmp, buf); } static const struct clk_ops qmp_qdss_clk_ops = { @@ -344,7 +343,7 @@ static int qmp_cdev_set_cur_state(struct thermal_cooling_device *cdev, qmp_cdev->name, cdev_state ? "on" : "off"); - ret = qmp_send(qmp_cdev->qmp, buf, sizeof(buf)); + ret = qmp_send(qmp_cdev->qmp, buf); if (!ret) qmp_cdev->state = cdev_state; -- cgit v1.2.3 From 8873d1e2f88afbe89c99d8f49f88934a2da2991f Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 11 Aug 2023 13:58:38 -0700 Subject: soc: qcom: aoss: Format string in qmp_send() The majority of callers to qmp_send() composes the message dynamically using some form of sprintf(), resulting in unnecessary complication and stack usage. By changing the interface of qmp_send() to take a format string and arguments, the duplicated composition of the commands can be moved to a single location. Reviewed-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230811205839.727373-4-quic_bjorande@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 880fe234ca0a..8424d1da4db9 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -205,27 +205,33 @@ static bool qmp_message_empty(struct qmp *qmp) /** * qmp_send() - send a message to the AOSS * @qmp: qmp context - * @data: message to be sent + * @fmt: format string for message to be sent + * @...: arguments for the format string * - * Transmit @data to AOSS and wait for the AOSS to acknowledge the message. + * Transmit message to AOSS and wait for the AOSS to acknowledge the message. * data must not be longer than the mailbox size. Access is synchronized by * this implementation. * * Return: 0 on success, negative errno on failure */ -int qmp_send(struct qmp *qmp, const void *data) +int qmp_send(struct qmp *qmp, const char *fmt, ...) { char buf[QMP_MSG_LEN]; long time_left; + va_list args; + int len; int ret; - if (WARN_ON(IS_ERR_OR_NULL(qmp) || !data)) + if (WARN_ON(IS_ERR_OR_NULL(qmp) || !fmt)) return -EINVAL; - if (WARN_ON(strlen(data) >= sizeof(buf))) - return -EINVAL; + memset(buf, 0, sizeof(buf)); + va_start(args, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); - strscpy_pad(buf, data, sizeof(buf)); + if (WARN_ON(len >= sizeof(buf))) + return -EINVAL; mutex_lock(&qmp->tx_lock); -- cgit v1.2.3 From b4f63bbff96e4510676b1e78b00d14baaee9ad29 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 11 Aug 2023 13:58:39 -0700 Subject: soc: qcom: aoss: Tidy up qmp_send() callers With qmp_send() handling variable length messages and string formatting he callers of qmp_send() can be cleaned up to not care about these things. Drop the QMP_MSG_LEN sized buffers and use the message formatting, as appropriate. Reviewed-by: Konrad Dybcio Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20230811205839.727373-5-quic_bjorande@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom_aoss.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c index 8424d1da4db9..77f0cf126629 100644 --- a/drivers/soc/qcom/qcom_aoss.c +++ b/drivers/soc/qcom/qcom_aoss.c @@ -264,7 +264,7 @@ EXPORT_SYMBOL(qmp_send); static int qmp_qdss_clk_prepare(struct clk_hw *hw) { - static const char buf[QMP_MSG_LEN] = "{class: clock, res: qdss, val: 1}"; + static const char *buf = "{class: clock, res: qdss, val: 1}"; struct qmp *qmp = container_of(hw, struct qmp, qdss_clk); return qmp_send(qmp, buf); @@ -272,7 +272,7 @@ static int qmp_qdss_clk_prepare(struct clk_hw *hw) static void qmp_qdss_clk_unprepare(struct clk_hw *hw) { - static const char buf[QMP_MSG_LEN] = "{class: clock, res: qdss, val: 0}"; + static const char *buf = "{class: clock, res: qdss, val: 0}"; struct qmp *qmp = container_of(hw, struct qmp, qdss_clk); qmp_send(qmp, buf); @@ -334,7 +334,6 @@ static int qmp_cdev_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { struct qmp_cooling_device *qmp_cdev = cdev->devdata; - char buf[QMP_MSG_LEN] = {}; bool cdev_state; int ret; @@ -344,13 +343,8 @@ static int qmp_cdev_set_cur_state(struct thermal_cooling_device *cdev, if (qmp_cdev->state == state) return 0; - snprintf(buf, sizeof(buf), - "{class: volt_flr, event:zero_temp, res:%s, value:%s}", - qmp_cdev->name, - cdev_state ? "on" : "off"); - - ret = qmp_send(qmp_cdev->qmp, buf); - + ret = qmp_send(qmp_cdev->qmp, "{class: volt_flr, event:zero_temp, res:%s, value:%s}", + qmp_cdev->name, cdev_state ? "on" : "off"); if (!ret) qmp_cdev->state = cdev_state; -- cgit v1.2.3