diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-04-26 12:11:52 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-04-26 12:11:52 -0700 |
commit | 37f00ab4a003f371f81e0eae76cf372f06dec780 (patch) | |
tree | c6217483f22a0fac876f12af53f4b8948200f2fd /drivers/firmware/qcom_scm.c | |
parent | 2b90506a8186df5f7c81ad1ebd250103d8469e27 (diff) | |
parent | 5ffa828534036348fa90fb3079ccc0972d202c4a (diff) |
Merge tag 'arm-drivers-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC driver updates from Arnd Bergmann:
"Updates for SoC specific drivers include a few subsystems that have
their own maintainers but send them through the soc tree:
TEE/OP-TEE:
- Add tracepoints around calls to secure world
Memory controller drivers:
- Minor fixes for Renesas, Exynos, Mediatek and Tegra platforms
- Add debug statistics to Tegra20 memory controller
- Update Tegra bindings and convert to dtschema
ARM SCMI Firmware:
- Support for modular SCMI protocols and vendor specific extensions
- New SCMI IIO driver
- Per-cpu DVFS
The other driver changes are all from the platform maintainers
directly and reflect the drivers that don't fit into any other
subsystem as well as treewide changes for a particular platform.
SoCFPGA:
- Various cleanups contributed by Krzysztof Kozlowski
Mediatek:
- add MT8183 support to mutex driver
- MMSYS: use per SoC array to describe the possible routing
- add MMSYS support for MT8183 and MT8167
- add support for PMIC wrapper with integrated arbiter
- add support for MT8192/MT6873
Tegra:
- Bug fixes to PMC and clock drivers
NXP/i.MX:
- Update SCU power domain driver to keep console domain power on.
- Add missing ADC1 power domain to SCU power domain driver.
- Update comments for single global power domain in SCU power domain
driver.
- Add i.MX51/i.MX53 unique id support to i.MX SoC driver.
NXP/FSL SoC driver updates for v5.13
- Add ACPI support for RCPM driver
- Use generic io{read,write} for QE drivers after performance
optimized for PowerPC
- Fix QBMAN probe to cleanup HW states correctly for kexec
- Various cleanup and style fix for QBMAN/QE/GUTS drivers
OMAP:
- Preparation to use devicetree for genpd
- ti-sysc needs iorange check improved when the interconnect target
module has no control registers listed
- ti-sysc needs to probe l4_wkup and l4_cfg interconnects first to
avoid issues with missing resources and unnecessary deferred probe
- ti-sysc debug option can now detect more devices
- ti-sysc now warns if an old incomplete devicetree data is found as
we now rely on it being complete for am3 and 4
- soc init code needs to check for prcm and prm nodes for omap4/5 and
dra7
- omap-prm driver needs to enable autoidle retention support for
omap4
- omap5 clocks are missing gpmc and ocmc clock registers
- pci-dra7xx now needs to use builtin_platform_driver instead of
using builtin_platform_driver_probe for deferred probe to work
Raspberry Pi:
- Fix-up all RPi firmware drivers so as for unbind to happen in an
orderly fashion
- Support for RPi's PoE hat PWM bus
Qualcomm
- Improved detection for SCM calling conventions
- Support for OEM specific wifi firmware path
- Added drivers for SC7280/SM8350: RPMH, LLCC< AOSS QMP"
* tag 'arm-drivers-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (165 commits)
soc: aspeed: fix a ternary sign expansion bug
memory: mtk-smi: Add device-link between smi-larb and smi-common
memory: samsung: exynos5422-dmc: handle clk_set_parent() failure
memory: renesas-rpc-if: fix possible NULL pointer dereference of resource
clk: socfpga: fix iomem pointer cast on 64-bit
soc: aspeed: Adapt to new LPC device tree layout
pinctrl: aspeed-g5: Adapt to new LPC device tree layout
ipmi: kcs: aspeed: Adapt to new LPC DTS layout
ARM: dts: Remove LPC BMC and Host partitions
dt-bindings: aspeed-lpc: Remove LPC partitioning
soc: fsl: enable acpi support in RCPM driver
soc: qcom: mdt_loader: Detect truncated read of segments
soc: qcom: mdt_loader: Validate that p_filesz < p_memsz
soc: qcom: pdr: Fix error return code in pdr_register_listener
firmware: qcom_scm: Fix kernel-doc function names to match
firmware: qcom_scm: Suppress sysfs bind attributes
firmware: qcom_scm: Workaround lack of "is available" call on SC7180
firmware: qcom_scm: Reduce locking section for __get_convention()
firmware: qcom_scm: Make __qcom_scm_is_call_available() return bool
Revert "soc: fsl: qe: introduce qe_io{read,write}* wrappers"
...
Diffstat (limited to 'drivers/firmware/qcom_scm.c')
-rw-r--r-- | drivers/firmware/qcom_scm.c | 89 |
1 files changed, 50 insertions, 39 deletions
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index f57779fc7ee9..ee9cb545e73b 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -113,14 +113,10 @@ static void qcom_scm_clk_disable(void) clk_disable_unprepare(__scm->bus_clk); } -static int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, - u32 cmd_id); +enum qcom_scm_convention qcom_scm_convention = SMC_CONVENTION_UNKNOWN; +static DEFINE_SPINLOCK(scm_query_lock); -enum qcom_scm_convention qcom_scm_convention; -static bool has_queried __read_mostly; -static DEFINE_SPINLOCK(query_lock); - -static void __query_convention(void) +static enum qcom_scm_convention __get_convention(void) { unsigned long flags; struct qcom_scm_desc desc = { @@ -133,36 +129,50 @@ static void __query_convention(void) .owner = ARM_SMCCC_OWNER_SIP, }; struct qcom_scm_res res; + enum qcom_scm_convention probed_convention; int ret; + bool forced = false; - spin_lock_irqsave(&query_lock, flags); - if (has_queried) - goto out; + if (likely(qcom_scm_convention != SMC_CONVENTION_UNKNOWN)) + return qcom_scm_convention; - qcom_scm_convention = SMC_CONVENTION_ARM_64; - // Device isn't required as there is only one argument - no device - // needed to dma_map_single to secure world - ret = scm_smc_call(NULL, &desc, &res, true); + /* + * Device isn't required as there is only one argument - no device + * needed to dma_map_single to secure world + */ + probed_convention = SMC_CONVENTION_ARM_64; + ret = __scm_smc_call(NULL, &desc, probed_convention, &res, true); if (!ret && res.result[0] == 1) - goto out; + goto found; + + /* + * Some SC7180 firmwares didn't implement the + * QCOM_SCM_INFO_IS_CALL_AVAIL call, so we fallback to forcing ARM_64 + * calling conventions on these firmwares. Luckily we don't make any + * early calls into the firmware on these SoCs so the device pointer + * will be valid here to check if the compatible matches. + */ + if (of_device_is_compatible(__scm ? __scm->dev->of_node : NULL, "qcom,scm-sc7180")) { + forced = true; + goto found; + } - qcom_scm_convention = SMC_CONVENTION_ARM_32; - ret = scm_smc_call(NULL, &desc, &res, true); + probed_convention = SMC_CONVENTION_ARM_32; + ret = __scm_smc_call(NULL, &desc, probed_convention, &res, true); if (!ret && res.result[0] == 1) - goto out; - - qcom_scm_convention = SMC_CONVENTION_LEGACY; -out: - has_queried = true; - spin_unlock_irqrestore(&query_lock, flags); - pr_info("qcom_scm: convention: %s\n", - qcom_scm_convention_names[qcom_scm_convention]); -} + goto found; + + probed_convention = SMC_CONVENTION_LEGACY; +found: + spin_lock_irqsave(&scm_query_lock, flags); + if (probed_convention != qcom_scm_convention) { + qcom_scm_convention = probed_convention; + pr_info("qcom_scm: convention: %s%s\n", + qcom_scm_convention_names[qcom_scm_convention], + forced ? " (forced)" : ""); + } + spin_unlock_irqrestore(&scm_query_lock, flags); -static inline enum qcom_scm_convention __get_convention(void) -{ - if (unlikely(!has_queried)) - __query_convention(); return qcom_scm_convention; } @@ -219,8 +229,8 @@ static int qcom_scm_call_atomic(struct device *dev, } } -static int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, - u32 cmd_id) +static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id, + u32 cmd_id) { int ret; struct qcom_scm_desc desc = { @@ -247,7 +257,7 @@ static int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, ret = qcom_scm_call(dev, &desc, &res); - return ret ? : res.result[0]; + return ret ? false : !!res.result[0]; } /** @@ -585,9 +595,8 @@ bool qcom_scm_pas_supported(u32 peripheral) }; struct qcom_scm_res res; - ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL, - QCOM_SCM_PIL_PAS_IS_SUPPORTED); - if (ret <= 0) + if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL, + QCOM_SCM_PIL_PAS_IS_SUPPORTED)) return false; ret = qcom_scm_call(__scm->dev, &desc, &res); @@ -1060,17 +1069,18 @@ EXPORT_SYMBOL(qcom_scm_ice_set_key); */ bool qcom_scm_hdcp_available(void) { + bool avail; int ret = qcom_scm_clk_enable(); if (ret) return ret; - ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP, + avail = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_HDCP_INVOKE); qcom_scm_clk_disable(); - return ret > 0; + return avail; } EXPORT_SYMBOL(qcom_scm_hdcp_available); @@ -1242,7 +1252,7 @@ static int qcom_scm_probe(struct platform_device *pdev) __scm = scm; __scm->dev = &pdev->dev; - __query_convention(); + __get_convention(); /* * If requested enable "download mode", from this point on warmboot @@ -1291,6 +1301,7 @@ static struct platform_driver qcom_scm_driver = { .driver = { .name = "qcom_scm", .of_match_table = qcom_scm_dt_match, + .suppress_bind_attrs = true, }, .probe = qcom_scm_probe, .shutdown = qcom_scm_shutdown, |