From a3b884cef8730ce1c7ad2276961bce46fbce8fd5 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 7 May 2021 16:20:36 -0400 Subject: firmware: arm_scmi: Add clock management to the SCMI power domain Clocks requiring non-atomic contexts are supported by the generic clock PM layer since commit 0bfa0820c274 ("PM: clk: make PM clock layer compatible with clocks that must sleep"). That means we can have SCMI-based clocks be managed by the SCMI power domain now. Link: https://lore.kernel.org/r/5q88n947-pon-4940-3or6-s54o4r361o5s@onlyvoer.pbz Tested-by: Dien Pham Reviewed-by: Gaku Inami Signed-off-by: Nicolas Pitre Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/scmi_pm_domain.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c index 9d36d5c0622d..4371fdcd5a73 100644 --- a/drivers/firmware/arm_scmi/scmi_pm_domain.c +++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -52,6 +53,27 @@ static int scmi_pd_power_off(struct generic_pm_domain *domain) return scmi_pd_power(domain, false); } +static int scmi_pd_attach_dev(struct generic_pm_domain *pd, struct device *dev) +{ + int ret; + + ret = pm_clk_create(dev); + if (ret) + return ret; + + ret = of_pm_clk_add_clks(dev); + if (ret >= 0) + return 0; + + pm_clk_destroy(dev); + return ret; +} + +static void scmi_pd_detach_dev(struct generic_pm_domain *pd, struct device *dev) +{ + pm_clk_destroy(dev); +} + static int scmi_pm_domain_probe(struct scmi_device *sdev) { int num_domains, i; @@ -102,6 +124,10 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev) scmi_pd->genpd.name = scmi_pd->name; scmi_pd->genpd.power_off = scmi_pd_power_off; scmi_pd->genpd.power_on = scmi_pd_power_on; + scmi_pd->genpd.attach_dev = scmi_pd_attach_dev; + scmi_pd->genpd.detach_dev = scmi_pd_detach_dev; + scmi_pd->genpd.flags = GENPD_FLAG_PM_CLK | + GENPD_FLAG_ACTIVE_WAKEUP; pm_genpd_init(&scmi_pd->genpd, NULL, state == SCMI_POWER_STATE_GENERIC_OFF); -- cgit v1.2.3 From c05b07963e965ae34e75ee8c33af1095350cd87e Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Fri, 21 May 2021 15:40:51 +0200 Subject: firmware: arm_scmi: Add SMCCC discovery dependency in Kconfig ARM_SCMI_PROTOCOL depends on either MAILBOX or HAVE_ARM_SMCCC_DISCOVERY, not MAILBOX alone. Fix the depedency in Kconfig file and driver to reflect the same. Link: https://lore.kernel.org/r/20210521134055.24271-1-etienne.carriere@linaro.org Reviewed-by: Cristian Marussi Signed-off-by: Etienne Carriere [sudeep.holla: Minor tweaks to subject and change log] Signed-off-by: Sudeep Holla --- drivers/firmware/Kconfig | 2 +- drivers/firmware/arm_scmi/common.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index db0ea2d2d75a..a9c613c32282 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -9,7 +9,7 @@ menu "Firmware Drivers" config ARM_SCMI_PROTOCOL tristate "ARM System Control and Management Interface (SCMI) Message Protocol" depends on ARM || ARM64 || COMPILE_TEST - depends on MAILBOX + depends on MAILBOX || HAVE_ARM_SMCCC_DISCOVERY help ARM System Control and Management Interface (SCMI) protocol is a set of operating system-independent software interfaces that are diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 228bf4a71d23..8685619d38f9 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -331,7 +331,7 @@ struct scmi_desc { }; extern const struct scmi_desc scmi_mailbox_desc; -#ifdef CONFIG_HAVE_ARM_SMCCC +#ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY extern const struct scmi_desc scmi_smc_desc; #endif -- cgit v1.2.3 From 0cb7af474e0dbb2f500c67aa62b6db9fafa74de2 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Tue, 1 Jun 2021 11:24:17 +0100 Subject: firmware: arm_scmi: Reset Rx buffer to max size during async commands During an async commands execution the Rx buffer length is at first set to max_msg_sz when the synchronous part of the command is first sent. However once the synchronous part completes the transport layer waits for the delayed response which will be processed using the same xfer descriptor initially allocated. Since synchronous response received at the end of the xfer will shrink the Rx buffer length to the effective payload response length, it needs to be reset again. Raise the Rx buffer length again to max_msg_sz before fetching the delayed response to ensure full response is read correctly from the shared memory. Link: https://lore.kernel.org/r/20210601102421.26581-2-cristian.marussi@arm.com Fixes: 58ecdf03dbb9 ("firmware: arm_scmi: Add support for asynchronous commands and delayed response") Signed-off-by: Cristian Marussi [sudeep.holla: moved reset to scmi_handle_response as it could race with do_xfer_with_response] Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 66eb3f0e5daf..5e8e9337adc7 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -335,6 +335,10 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo, return; } + /* rx.len could be shrunk in the sync do_xfer, so reset to maxsz */ + if (msg_type == MSG_TYPE_DELAYED_RESP) + xfer->rx.len = info->desc->max_msg_size; + scmi_dump_header_dbg(dev, &xfer->hdr); info->desc->ops->fetch_response(cinfo, xfer); -- cgit v1.2.3 From ab7766b72855e6a68109b915d071181b93086e29 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 3 Jun 2021 08:26:31 +0100 Subject: firmware: arm_scmi: Fix the build when CONFIG_MAILBOX is not selected 0day CI kernel test robot reported following build error with randconfig aarch64-linux-ld: drivers/firmware/arm_scmi/driver.o:(.rodata+0x1e0): undefined reference to `scmi_mailbox_desc' Fix the error by adding CONFIG_MAILBOX dependency for scmi_mailbox_desc. Link: https://lore.kernel.org/r/20210603072631.1660963-1-sudeep.holla@arm.com Cc: Etienne Carriere Cc: Cristian Marussi Reviewed-by: Etienne Carriere Reviewed-by: Cristian Marussi Tested-by: Cristian Marussi Reported-by: kernel test robot Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 5e8e9337adc7..ca71568c5c41 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1571,7 +1571,9 @@ ATTRIBUTE_GROUPS(versions); /* Each compatible listed below must have descriptor associated with it */ static const struct of_device_id scmi_of_match[] = { +#ifdef CONFIG_MAILBOX { .compatible = "arm,scmi", .data = &scmi_mailbox_desc }, +#endif #ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY { .compatible = "arm,scmi-smc", .data = &scmi_smc_desc}, #endif -- cgit v1.2.3 From ed7ecb8839010150e3adb41800d218ef3d62e269 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 2 Jun 2021 08:38:50 +0100 Subject: firmware: arm_scpi: Add compatibility checks for shmem node The shared memory node used for communication between the firmware and the OS should be compatible with one of the following: - amlogic,meson-gxbb-scp-shmem - amlogic,meson-axg-scp-shmem - arm,juno-scp-shmem - arm,scp-shmem Add the check for the same while parsing the node before fetching the memory regions. Link: https://lore.kernel.org/r/20210602073851.1005607-1-sudeep.holla@arm.com Cc: Rob Herring Cc: Kevin Hilman Cc: Neil Armstrong Cc: Jerome Brunet Reviewed-by: Cristian Marussi Tested-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scpi.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index d0dee37ad522..cc90a11a69c3 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -897,6 +897,14 @@ static const struct of_device_id legacy_scpi_of_match[] = { {}, }; +static const struct of_device_id shmem_of_match[] __maybe_unused = { + { .compatible = "amlogic,meson-gxbb-scp-shmem", }, + { .compatible = "amlogic,meson-axg-scp-shmem", }, + { .compatible = "arm,juno-scp-shmem", }, + { .compatible = "arm,scp-shmem", }, + { } +}; + static int scpi_probe(struct platform_device *pdev) { int count, idx, ret; @@ -933,6 +941,9 @@ static int scpi_probe(struct platform_device *pdev) struct mbox_client *cl = &pchan->cl; struct device_node *shmem = of_parse_phandle(np, "shmem", idx); + if (!of_match_node(shmem_of_match, shmem)) + return -ENXIO; + ret = of_address_to_resource(shmem, 0, &res); of_node_put(shmem); if (ret) { -- cgit v1.2.3 From 507cd4d2c5eb2d647d27b1047e1a8c73c4890cf3 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Wed, 2 Jun 2021 08:38:51 +0100 Subject: firmware: arm_scmi: Add compatibility checks for shmem node The shared memory node used for communication between the firmware and the OS should be compatible with "arm,scmi-shmem". Add the check for the same while parsing the node before fetching the memory regions. Link: https://lore.kernel.org/r/20210602073851.1005607-2-sudeep.holla@arm.com Cc: Rob Herring Cc: Cristian Marussi Cc: Florian Fainelli Cc: Jim Quinlan Cc: Etienne Carriere Reviewed-by: Florian Fainelli Tested-by: Florian Fainelli Reviewed-by: Cristian Marussi Tested-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/mailbox.c | 3 +++ drivers/firmware/arm_scmi/smc.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c index 4626404be541..e3dcb58314ae 100644 --- a/drivers/firmware/arm_scmi/mailbox.c +++ b/drivers/firmware/arm_scmi/mailbox.c @@ -69,6 +69,9 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, return -ENOMEM; shmem = of_parse_phandle(cdev->of_node, "shmem", idx); + if (!of_device_is_compatible(shmem, "arm,scmi-shmem")) + return -ENXIO; + ret = of_address_to_resource(shmem, 0, &res); of_node_put(shmem); if (ret) { diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c index fcbe2677f84b..bed5596c7209 100644 --- a/drivers/firmware/arm_scmi/smc.c +++ b/drivers/firmware/arm_scmi/smc.c @@ -76,6 +76,9 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, return -ENOMEM; np = of_parse_phandle(cdev->of_node, "shmem", 0); + if (!of_device_is_compatible(np, "arm,scmi-shmem")) + return -ENXIO; + ret = of_address_to_resource(np, 0, &res); of_node_put(np); if (ret) { -- cgit v1.2.3 From f1748b1ee1fa0fd1a074504045b530b62f949188 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Tue, 8 Jun 2021 11:30:56 +0100 Subject: firmware: arm_scmi: Add delayed response status check A successfully received delayed response could anyway report a failure at the protocol layer in the message status field. Add a check also for this error condition. Link: https://lore.kernel.org/r/20210608103056.3388-1-cristian.marussi@arm.com Fixes: 58ecdf03dbb9 ("firmware: arm_scmi: Add support for asynchronous commands and delayed response") Signed-off-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index ca71568c5c41..74986bf96656 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -517,8 +517,12 @@ static int do_xfer_with_response(const struct scmi_protocol_handle *ph, xfer->async_done = &async_response; ret = do_xfer(ph, xfer); - if (!ret && !wait_for_completion_timeout(xfer->async_done, timeout)) - ret = -ETIMEDOUT; + if (!ret) { + if (!wait_for_completion_timeout(xfer->async_done, timeout)) + ret = -ETIMEDOUT; + else if (xfer->hdr.status) + ret = scmi_to_linux_errno(xfer->hdr.status); + } xfer->async_done = NULL; return ret; -- cgit v1.2.3 From e30d91d4ffda0b30839bb5e7d2a123654de95045 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Sun, 6 Jun 2021 23:12:24 +0100 Subject: firmware: arm_scmi: Move reinit_completion from scmi_xfer_get to do_xfer Re-using timed out xfers in a loop can lead to issue if completion was not properly reinitialized. Move reinit_completion from scmi_xfer_get to do_xfer to avoid the issue. Link: https://lore.kernel.org/r/20210606221232.33768-3-cristian.marussi@arm.com Signed-off-by: Cristian Marussi [sudeep.holla: moved reinit_completion instead of adding another one] Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 74986bf96656..80010d3f5975 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -241,7 +241,6 @@ static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle, xfer = &minfo->xfer_block[xfer_id]; xfer->hdr.seq = xfer_id; - reinit_completion(&xfer->done); xfer->transfer_id = atomic_inc_return(&transfer_last_id); return xfer; @@ -438,6 +437,7 @@ static int do_xfer(const struct scmi_protocol_handle *ph, * the scmi_xfer structure. */ xfer->hdr.protocol_id = pi->proto->id; + reinit_completion(&xfer->done); cinfo = idr_find(&info->tx_idr, xfer->hdr.protocol_id); if (unlikely(!cinfo)) -- cgit v1.2.3 From 61832b35b4d953b2b4f6c668a3ad2a3013f40532 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Tue, 8 Jun 2021 15:01:40 +0100 Subject: firmware: arm_scmi: Avoid multiple initialisations of hdr->protocol_id Since the hdr->protocol_id is set from the scmi_protocol_instance handle just before the transfer, there is no need to initialise the same in scmi_xfer_get_init. Remove the unnecessary initialisations. Link: https://lore.kernel.org/r/20210608140140.2042257-1-sudeep.holla@arm.com Tested-by: Cristian Marussi Reviewed-by: Cristian Marussi Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/driver.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/firmware') diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 80010d3f5975..66e5e694be7d 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -432,9 +432,9 @@ static int do_xfer(const struct scmi_protocol_handle *ph, struct scmi_chan_info *cinfo; /* - * Re-instate protocol id here from protocol handle so that cannot be + * Initialise protocol id now from protocol handle to avoid it being * overridden by mistake (or malice) by the protocol code mangling with - * the scmi_xfer structure. + * the scmi_xfer structure prior to this. */ xfer->hdr.protocol_id = pi->proto->id; reinit_completion(&xfer->done); @@ -509,11 +509,8 @@ static int do_xfer_with_response(const struct scmi_protocol_handle *ph, struct scmi_xfer *xfer) { int ret, timeout = msecs_to_jiffies(SCMI_MAX_RESPONSE_TIMEOUT); - const struct scmi_protocol_instance *pi = ph_to_pi(ph); DECLARE_COMPLETION_ONSTACK(async_response); - xfer->hdr.protocol_id = pi->proto->id; - xfer->async_done = &async_response; ret = do_xfer(ph, xfer); @@ -569,7 +566,6 @@ static int xfer_get_init(const struct scmi_protocol_handle *ph, xfer->tx.len = tx_size; xfer->rx.len = rx_size ? : info->desc->max_msg_size; xfer->hdr.id = msg_id; - xfer->hdr.protocol_id = pi->proto->id; xfer->hdr.poll_completion = false; *p = xfer; -- cgit v1.2.3