diff options
author | Arnd Bergmann | 2022-07-12 23:01:24 +0200 |
---|---|---|
committer | Arnd Bergmann | 2022-07-12 23:01:25 +0200 |
commit | 3c37074f0d581b6c73f066b2ffab0c3d4826d623 (patch) | |
tree | 7b56f3c3cad2f24af32be21bb6228e8baef27562 /drivers/firmware | |
parent | 9bc697091a475901526c43d195cb04944cfd1e6f (diff) | |
parent | b9c2ae6cac403dee3195fda9eb28d8ee733b225b (diff) |
Merge tag 'qcom-drivers-for-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/drivers
Qualcomm driver updates for v5.20
This introduces a new driver that requests interconnect bandwidth based
on throughput measurements of the bwmon hardware blocks found associated
with, among other things, the CPU subsystem on many Qualcomm platforms.
It introduces support for the SCM wrapper driver to vote for
interconnect bandwidth for operations that needs bandwidth to the crypto
engine. This ensures both performance and guards against issues caused
by lacking votes for this path.
The socinfo driver gains knowledge about the SC7180P SoC.
It contains a range of fixes for spelling mistakes, refcount leaks in
various drivers and removes some redundant code from the apr remove
path.
The SCM DT bindings are updated to declare support for QCS404, SM6125
and SDX65.
The command db driver has a strncpy() converted to strscpy_pad() and
then back again with proper documentation to why this was the right API.
* tag 'qcom-drivers-for-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux:
soc: qcom: icc-bwmon: Add bandwidth monitoring driver
dt-bindings: interconnect: qcom,msm8998-cpu-bwmon: add BWMON device
soc/qcom: Make QCOM_RPMPD select PM_GENERIC_DOMAINS/_OF
soc: qcom: aoss: Fix refcount leak in qmp_cooling_devices_register
soc: qcom: llcc: Fix syntax errors in comments
soc: qcom: ocmem: Fix refcount leak in of_get_ocmem
dt-bindings: soc: qcom,wcnss: remove unneeded ref for names
firmware: qcom_scm: Add bw voting support to the SCM interface
dt-bindings: firmware: qcom-scm: Add interconnects property
soc: qcom: cmd-db: replace strscpy_pad() with strncpy()
dt-bindings: firmware: scm: Add compatible for SDX65
dt-bindings: arm: qcom: switch maintainer to Bjorn
soc: qcom: rpmhpd: fix typos in comment
soc: qcom: correct kerneldoc
soc: qcom: cmd-db: replace strncpy() with strscpy_pad()
firmware: qcom_scm-legacy: correct kerneldoc
dt-bindings: firmware: document Qualcomm QCS404 and SM6125 SCM
soc: qcom: apr: Drop redundant check in .remove()
firmware: qcom_scm: drop unexpected word "the"
soc: qcom: socinfo: Add an ID for sc7180P
Link: https://lore.kernel.org/r/20220712021830.1271398-1-bjorn.andersson@linaro.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/qcom_scm-legacy.c | 4 | ||||
-rw-r--r-- | drivers/firmware/qcom_scm.c | 71 |
2 files changed, 74 insertions, 1 deletions
diff --git a/drivers/firmware/qcom_scm-legacy.c b/drivers/firmware/qcom_scm-legacy.c index 1829ba220576..9f918b9e6f8f 100644 --- a/drivers/firmware/qcom_scm-legacy.c +++ b/drivers/firmware/qcom_scm-legacy.c @@ -120,6 +120,9 @@ static void __scm_legacy_do(const struct arm_smccc_args *smc, /** * scm_legacy_call() - Sends a command to the SCM and waits for the command to * finish processing. + * @dev: device + * @desc: descriptor structure containing arguments and return values + * @res: results from SMC call * * A note on cache maintenance: * Note that any buffers that are expected to be accessed by the secure world @@ -211,6 +214,7 @@ out: /** * scm_legacy_call_atomic() - Send an atomic SCM command with up to 5 arguments * and 3 return values + * @unused: device, legacy argument, not used, can be NULL * @desc: SCM call descriptor containing arguments * @res: SCM call return values * diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 3163660fa8e2..cdbfe54c8146 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -7,6 +7,7 @@ #include <linux/cpumask.h> #include <linux/export.h> #include <linux/dma-mapping.h> +#include <linux/interconnect.h> #include <linux/module.h> #include <linux/types.h> #include <linux/qcom_scm.h> @@ -31,8 +32,13 @@ struct qcom_scm { struct clk *core_clk; struct clk *iface_clk; struct clk *bus_clk; + struct icc_path *path; struct reset_controller_dev reset; + /* control access to the interconnect path */ + struct mutex scm_bw_lock; + int scm_vote_count; + u64 dload_mode_addr; }; @@ -99,6 +105,42 @@ static void qcom_scm_clk_disable(void) clk_disable_unprepare(__scm->bus_clk); } +static int qcom_scm_bw_enable(void) +{ + int ret = 0; + + if (!__scm->path) + return 0; + + if (IS_ERR(__scm->path)) + return -EINVAL; + + mutex_lock(&__scm->scm_bw_lock); + if (!__scm->scm_vote_count) { + ret = icc_set_bw(__scm->path, 0, UINT_MAX); + if (ret < 0) { + dev_err(__scm->dev, "failed to set bandwidth request\n"); + goto err_bw; + } + } + __scm->scm_vote_count++; +err_bw: + mutex_unlock(&__scm->scm_bw_lock); + + return ret; +} + +static void qcom_scm_bw_disable(void) +{ + if (IS_ERR_OR_NULL(__scm->path)) + return; + + mutex_lock(&__scm->scm_bw_lock); + if (__scm->scm_vote_count-- == 1) + icc_set_bw(__scm->path, 0, 0); + mutex_unlock(&__scm->scm_bw_lock); +} + enum qcom_scm_convention qcom_scm_convention = SMC_CONVENTION_UNKNOWN; static DEFINE_SPINLOCK(scm_query_lock); @@ -444,10 +486,15 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size, if (ret) goto out; + ret = qcom_scm_bw_enable(); + if (ret) + return ret; + desc.args[1] = mdata_phys; ret = qcom_scm_call(__scm->dev, &desc, &res); + qcom_scm_bw_disable(); qcom_scm_clk_disable(); out: @@ -507,7 +554,12 @@ int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size) if (ret) return ret; + ret = qcom_scm_bw_enable(); + if (ret) + return ret; + ret = qcom_scm_call(__scm->dev, &desc, &res); + qcom_scm_bw_disable(); qcom_scm_clk_disable(); return ret ? : res.result[0]; @@ -537,7 +589,12 @@ int qcom_scm_pas_auth_and_reset(u32 peripheral) if (ret) return ret; + ret = qcom_scm_bw_enable(); + if (ret) + return ret; + ret = qcom_scm_call(__scm->dev, &desc, &res); + qcom_scm_bw_disable(); qcom_scm_clk_disable(); return ret ? : res.result[0]; @@ -566,8 +623,13 @@ int qcom_scm_pas_shutdown(u32 peripheral) if (ret) return ret; + ret = qcom_scm_bw_enable(); + if (ret) + return ret; + ret = qcom_scm_call(__scm->dev, &desc, &res); + qcom_scm_bw_disable(); qcom_scm_clk_disable(); return ret ? : res.result[0]; @@ -1277,8 +1339,15 @@ static int qcom_scm_probe(struct platform_device *pdev) if (ret < 0) return ret; + mutex_init(&scm->scm_bw_lock); + clks = (unsigned long)of_device_get_match_data(&pdev->dev); + scm->path = devm_of_icc_get(&pdev->dev, NULL); + if (IS_ERR(scm->path)) + return dev_err_probe(&pdev->dev, PTR_ERR(scm->path), + "failed to acquire interconnect path\n"); + scm->core_clk = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(scm->core_clk)) { if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER) @@ -1337,7 +1406,7 @@ static int qcom_scm_probe(struct platform_device *pdev) /* * If requested enable "download mode", from this point on warmboot - * will cause the the boot stages to enter download mode, unless + * will cause the boot stages to enter download mode, unless * disabled below by a clean shutdown/reboot. */ if (download_mode) |