From ada1682d60ac6017037305166d02eb0cd5ee50fa Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 4 Oct 2023 20:57:32 +0200 Subject: [PATCH 1/7] firmware: qcom: qseecom: add missing include guards The qseecom header does not contain ifdef guards against multiple inclusion. Add them. Fixes: 00b1248606ba ("firmware: qcom_scm: Add support for Qualcomm Secure Execution Environment SCM interface") Signed-off-by: Bartosz Golaszewski Reviewed-by: Maximilian Luz Link: https://lore.kernel.org/r/20231004185732.98621-1-brgl@bgdev.pl Signed-off-by: Bjorn Andersson --- include/linux/firmware/qcom/qcom_qseecom.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/firmware/qcom/qcom_qseecom.h b/include/linux/firmware/qcom/qcom_qseecom.h index b531547e1dc9e..5c28298a98bec 100644 --- a/include/linux/firmware/qcom/qcom_qseecom.h +++ b/include/linux/firmware/qcom/qcom_qseecom.h @@ -5,6 +5,10 @@ * * Copyright (C) 2023 Maximilian Luz */ + +#ifndef __QCOM_QSEECOM_H +#define __QCOM_QSEECOM_H + #include #include @@ -44,3 +48,5 @@ static inline int qcom_qseecom_app_send(struct qseecom_client *client, void *req { return qcom_scm_qseecom_app_send(client->app_id, req, req_size, rsp, rsp_size); } + +#endif /* __QCOM_QSEECOM_H */ From f86955f2b1ff9fbc7ae4f6595112b2f896885366 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 11 Oct 2023 01:52:29 +0300 Subject: [PATCH 2/7] soc: qcom: pmic_glink: fix connector type to be DisplayPort As it was pointed out by Simon Ser, the DRM_MODE_CONNECTOR_USB connector is reserved for the GUD devices. Other drivers (i915, amdgpu) use DRM_MODE_CONNECTOR_DisplayPort even if the DP stream is handled by the USB-C altmode. While we are still working on implementing the proper way to let userspace know that the DP is wrapped into USB-C, change connector type to be DRM_MODE_CONNECTOR_DisplayPort. Fixes: 080b4e24852b ("soc: qcom: pmic_glink: Introduce altmode support") Cc: Simon Ser Signed-off-by: Dmitry Baryshkov Reviewed-by: Neil Armstrong Acked-by: Simon Ser Link: https://lore.kernel.org/r/20231010225229.77027-1-dmitry.baryshkov@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink_altmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 9569d999391d1..6f8b2f7ae3cc1 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -467,7 +467,7 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev, alt_port->bridge.funcs = &pmic_glink_altmode_bridge_funcs; alt_port->bridge.of_node = to_of_node(fwnode); alt_port->bridge.ops = DRM_BRIDGE_OP_HPD; - alt_port->bridge.type = DRM_MODE_CONNECTOR_USB; + alt_port->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; ret = devm_drm_bridge_add(dev, &alt_port->bridge); if (ret) { From ba21d6367cc2cca8f25fff3bc94b1b8df55fc261 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 9 Oct 2023 15:30:17 -0600 Subject: [PATCH 3/7] soc: qcom: apr: Add __counted_by for struct apr_rx_buf and use struct_size() Prepare for the coming implementation by GCC and Clang of the __counted_by attribute. Flexible array members annotated with __counted_by can have their accesses bounds-checked at run-time via CONFIG_UBSAN_BOUNDS (for array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family functions). While there, use struct_size() helper, instead of the open-coded version, to calculate the size for the allocation of the whole flexible structure, including of course, the flexible-array member. This code was found with the help of Coccinelle, and audited and fixed manually. Signed-off-by: "Gustavo A. R. Silva" Reviewed-by: Justin Stitt Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/ZSRw6RNi3Crhd32H@work Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/apr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index 30f81d6d9d9da..1f8b315576a4a 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -41,7 +41,7 @@ struct packet_router { struct apr_rx_buf { struct list_head node; int len; - uint8_t buf[]; + uint8_t buf[] __counted_by(len); }; /** @@ -171,7 +171,7 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf, return -EINVAL; } - abuf = kzalloc(sizeof(*abuf) + len, GFP_ATOMIC); + abuf = kzalloc(struct_size(abuf, buf, len), GFP_ATOMIC); if (!abuf) return -ENOMEM; From bdac188ec3c71800dd8419620224ee74ef37732a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 17 Oct 2023 11:27:18 +0200 Subject: [PATCH 4/7] firmware: qcom: move Qualcomm code into its own directory We're getting more and more qcom specific .c files in drivers/firmware/ and about to get even more. Create a separate directory for Qualcomm firmware drivers and move existing sources in there. Signed-off-by: Bartosz Golaszewski Acked-by: Elliot Berman Reviewed-by: Krzysztof Kozlowski Reviewed-by: Maximilian Luz Tested-by: Andrew Halaney # sc8280xp-lenovo-thinkpad-x13s Link: https://lore.kernel.org/r/20231017092732.19983-2-brgl@bgdev.pl Signed-off-by: Bjorn Andersson --- MAINTAINERS | 4 +- drivers/firmware/Kconfig | 48 +--------------- drivers/firmware/Makefile | 5 +- drivers/firmware/qcom/Kconfig | 56 +++++++++++++++++++ drivers/firmware/qcom/Makefile | 9 +++ drivers/firmware/{ => qcom}/qcom_qseecom.c | 0 .../{ => qcom}/qcom_qseecom_uefisecapp.c | 0 drivers/firmware/{ => qcom}/qcom_scm-legacy.c | 0 drivers/firmware/{ => qcom}/qcom_scm-smc.c | 0 drivers/firmware/{ => qcom}/qcom_scm.c | 0 drivers/firmware/{ => qcom}/qcom_scm.h | 0 11 files changed, 69 insertions(+), 53 deletions(-) create mode 100644 drivers/firmware/qcom/Kconfig create mode 100644 drivers/firmware/qcom/Makefile rename drivers/firmware/{ => qcom}/qcom_qseecom.c (100%) rename drivers/firmware/{ => qcom}/qcom_qseecom_uefisecapp.c (100%) rename drivers/firmware/{ => qcom}/qcom_scm-legacy.c (100%) rename drivers/firmware/{ => qcom}/qcom_scm-smc.c (100%) rename drivers/firmware/{ => qcom}/qcom_scm.c (100%) rename drivers/firmware/{ => qcom}/qcom_scm.h (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 01dde0acebd32..2e28b5efc7fae 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17804,13 +17804,13 @@ QUALCOMM QSEECOM DRIVER M: Maximilian Luz L: linux-arm-msm@vger.kernel.org S: Maintained -F: drivers/firmware/qcom_qseecom.c +F: drivers/firmware/qcom/qcom_qseecom.c QUALCOMM QSEECOM UEFISECAPP DRIVER M: Maximilian Luz L: linux-arm-msm@vger.kernel.org S: Maintained -F: drivers/firmware/qcom_qseecom_uefisecapp.c +F: drivers/firmware/qcom/qcom_qseecom_uefisecapp.c QUALCOMM RMNET DRIVER M: Subash Abhinov Kasiviswanathan diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 8c608be300601..46949e9b748ae 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -212,53 +212,6 @@ config MTK_ADSP_IPC ADSP exists on some mtk processors. Client might use shared memory to exchange information with ADSP. -config QCOM_SCM - tristate - -config QCOM_SCM_DOWNLOAD_MODE_DEFAULT - bool "Qualcomm download mode enabled by default" - depends on QCOM_SCM - help - A device with "download mode" enabled will upon an unexpected - warm-restart enter a special debug mode that allows the user to - "download" memory content over USB for offline postmortem analysis. - The feature can be enabled/disabled on the kernel command line. - - Say Y here to enable "download mode" by default. - -config QCOM_QSEECOM - bool "Qualcomm QSEECOM interface driver" - depends on QCOM_SCM=y - select AUXILIARY_BUS - help - Various Qualcomm SoCs have a Secure Execution Environment (SEE) running - in the Trust Zone. This module provides an interface to that via the - QSEECOM mechanism, using SCM calls. - - The QSEECOM interface allows, among other things, access to applications - running in the SEE. An example of such an application is 'uefisecapp', - which is required to access UEFI variables on certain systems. If - selected, the interface will also attempt to detect and register client - devices for supported applications. - - Select Y here to enable the QSEECOM interface driver. - -config QCOM_QSEECOM_UEFISECAPP - bool "Qualcomm SEE UEFI Secure App client driver" - depends on QCOM_QSEECOM - depends on EFI - help - Various Qualcomm SoCs do not allow direct access to EFI variables. - Instead, these need to be accessed via the UEFI Secure Application - (uefisecapp), residing in the Secure Execution Environment (SEE). - - This module provides a client driver for uefisecapp, installing efivar - operations to allow the kernel accessing EFI variables, and via that also - provide user-space with access to EFI variables via efivarfs. - - Select Y here to provide access to EFI variables on the aforementioned - platforms. - config SYSFB bool select BOOT_VESA_SUPPORT @@ -344,6 +297,7 @@ source "drivers/firmware/efi/Kconfig" source "drivers/firmware/imx/Kconfig" source "drivers/firmware/meson/Kconfig" source "drivers/firmware/psci/Kconfig" +source "drivers/firmware/qcom/Kconfig" source "drivers/firmware/smccc/Kconfig" source "drivers/firmware/tegra/Kconfig" source "drivers/firmware/xilinx/Kconfig" diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index d41b094a5e580..ec454e9521682 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -18,10 +18,6 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o obj-$(CONFIG_MTK_ADSP_IPC) += mtk-adsp-ipc.o obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o -obj-$(CONFIG_QCOM_SCM) += qcom-scm.o -qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o -obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o -obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o obj-$(CONFIG_SYSFB) += sysfb.o obj-$(CONFIG_SYSFB_SIMPLEFB) += sysfb_simplefb.o obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o @@ -37,6 +33,7 @@ obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ obj-y += efi/ obj-y += imx/ obj-y += psci/ +obj-y += qcom/ obj-y += smccc/ obj-y += tegra/ obj-y += xilinx/ diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig new file mode 100644 index 0000000000000..3f05d9854ddf0 --- /dev/null +++ b/drivers/firmware/qcom/Kconfig @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# For a description of the syntax of this configuration file, +# see Documentation/kbuild/kconfig-language.rst. +# + +menu "Qualcomm firmware drivers" + +config QCOM_SCM + tristate + +config QCOM_SCM_DOWNLOAD_MODE_DEFAULT + bool "Qualcomm download mode enabled by default" + depends on QCOM_SCM + help + A device with "download mode" enabled will upon an unexpected + warm-restart enter a special debug mode that allows the user to + "download" memory content over USB for offline postmortem analysis. + The feature can be enabled/disabled on the kernel command line. + + Say Y here to enable "download mode" by default. + +config QCOM_QSEECOM + bool "Qualcomm QSEECOM interface driver" + depends on QCOM_SCM=y + select AUXILIARY_BUS + help + Various Qualcomm SoCs have a Secure Execution Environment (SEE) running + in the Trust Zone. This module provides an interface to that via the + QSEECOM mechanism, using SCM calls. + + The QSEECOM interface allows, among other things, access to applications + running in the SEE. An example of such an application is 'uefisecapp', + which is required to access UEFI variables on certain systems. If + selected, the interface will also attempt to detect and register client + devices for supported applications. + + Select Y here to enable the QSEECOM interface driver. + +config QCOM_QSEECOM_UEFISECAPP + bool "Qualcomm SEE UEFI Secure App client driver" + depends on QCOM_QSEECOM + depends on EFI + help + Various Qualcomm SoCs do not allow direct access to EFI variables. + Instead, these need to be accessed via the UEFI Secure Application + (uefisecapp), residing in the Secure Execution Environment (SEE). + + This module provides a client driver for uefisecapp, installing efivar + operations to allow the kernel accessing EFI variables, and via that also + provide user-space with access to EFI variables via efivarfs. + + Select Y here to provide access to EFI variables on the aforementioned + platforms. + +endmenu diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile new file mode 100644 index 0000000000000..c9f12ee8224a3 --- /dev/null +++ b/drivers/firmware/qcom/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the linux kernel. +# + +obj-$(CONFIG_QCOM_SCM) += qcom-scm.o +qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o +obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o +obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o diff --git a/drivers/firmware/qcom_qseecom.c b/drivers/firmware/qcom/qcom_qseecom.c similarity index 100% rename from drivers/firmware/qcom_qseecom.c rename to drivers/firmware/qcom/qcom_qseecom.c diff --git a/drivers/firmware/qcom_qseecom_uefisecapp.c b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c similarity index 100% rename from drivers/firmware/qcom_qseecom_uefisecapp.c rename to drivers/firmware/qcom/qcom_qseecom_uefisecapp.c diff --git a/drivers/firmware/qcom_scm-legacy.c b/drivers/firmware/qcom/qcom_scm-legacy.c similarity index 100% rename from drivers/firmware/qcom_scm-legacy.c rename to drivers/firmware/qcom/qcom_scm-legacy.c diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom/qcom_scm-smc.c similarity index 100% rename from drivers/firmware/qcom_scm-smc.c rename to drivers/firmware/qcom/qcom_scm-smc.c diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c similarity index 100% rename from drivers/firmware/qcom_scm.c rename to drivers/firmware/qcom/qcom_scm.c diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h similarity index 100% rename from drivers/firmware/qcom_scm.h rename to drivers/firmware/qcom/qcom_scm.h From 3294d01f7a5ddacb796d7f7bf31eb100a8f6d0e0 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 17 Oct 2023 11:27:19 +0200 Subject: [PATCH 5/7] firmware: qcom: scm: add a missing forward declaration for struct device We reference struct device in the private scm header but we neither include linux/device.h nor forward declare it. Fix it. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Tested-by: Andrew Halaney # sc8280xp-lenovo-thinkpad-x13s Link: https://lore.kernel.org/r/20231017092732.19983-3-brgl@bgdev.pl Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h index 7b68fa820495c..c88e29051d20f 100644 --- a/drivers/firmware/qcom/qcom_scm.h +++ b/drivers/firmware/qcom/qcom_scm.h @@ -4,6 +4,8 @@ #ifndef __QCOM_SCM_INT_H #define __QCOM_SCM_INT_H +struct device; + enum qcom_scm_convention { SMC_CONVENTION_UNKNOWN, SMC_CONVENTION_LEGACY, From d79a27ea8e35a2dfc02096d2937267912bcca022 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 17 Oct 2023 11:27:20 +0200 Subject: [PATCH 6/7] firmware: qcom: scm: remove unneeded 'extern' specifiers 'extern' specifiers do nothing for function declarations. Remove them from the private qcom-scm header. Signed-off-by: Bartosz Golaszewski Reviewed-by: Andrew Halaney Tested-by: Andrew Halaney # sc8280xp-lenovo-thinkpad-x13s Link: https://lore.kernel.org/r/20231017092732.19983-4-brgl@bgdev.pl Signed-off-by: Bjorn Andersson --- drivers/firmware/qcom/qcom_scm.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/qcom/qcom_scm.h b/drivers/firmware/qcom/qcom_scm.h index c88e29051d20f..4532907e8489e 100644 --- a/drivers/firmware/qcom/qcom_scm.h +++ b/drivers/firmware/qcom/qcom_scm.h @@ -66,18 +66,17 @@ int qcom_scm_wait_for_wq_completion(u32 wq_ctx); int scm_get_wq_ctx(u32 *wq_ctx, u32 *flags, u32 *more_pending); #define SCM_SMC_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF)) -extern int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc, - enum qcom_scm_convention qcom_convention, - struct qcom_scm_res *res, bool atomic); +int __scm_smc_call(struct device *dev, const struct qcom_scm_desc *desc, + enum qcom_scm_convention qcom_convention, + struct qcom_scm_res *res, bool atomic); #define scm_smc_call(dev, desc, res, atomic) \ __scm_smc_call((dev), (desc), qcom_scm_convention, (res), (atomic)) #define SCM_LEGACY_FNID(s, c) (((s) << 10) | ((c) & 0x3ff)) -extern int scm_legacy_call_atomic(struct device *dev, - const struct qcom_scm_desc *desc, - struct qcom_scm_res *res); -extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, +int scm_legacy_call_atomic(struct device *dev, const struct qcom_scm_desc *desc, struct qcom_scm_res *res); +int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc, + struct qcom_scm_res *res); #define QCOM_SCM_SVC_BOOT 0x01 #define QCOM_SCM_BOOT_SET_ADDR 0x01 From 723d346173e748c4fdb145b84f572b871ab4011a Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Tue, 17 Oct 2023 10:00:23 +0200 Subject: [PATCH 7/7] soc: qcom: pmic_glink_altmode: Print return value on error It can be useful to know with which return value for example the typec_retimer_set call failed, so include this info in the dev_err prints. Signed-off-by: Luca Weiss Link: https://lore.kernel.org/r/20231017-glink-altmode-ret-v2-1-921aa7cfc381@fairphone.com Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/pmic_glink_altmode.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c index 6f8b2f7ae3cc1..b78279e2f54cf 100644 --- a/drivers/soc/qcom/pmic_glink_altmode.c +++ b/drivers/soc/qcom/pmic_glink_altmode.c @@ -160,7 +160,7 @@ 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"); + dev_err(altmode->dev, "failed to switch mux to DP: %d\n", ret); port->retimer_state.alt = &port->dp_alt; port->retimer_state.data = &dp_data; @@ -168,7 +168,7 @@ static void pmic_glink_altmode_enable_dp(struct pmic_glink_altmode *altmode, ret = typec_retimer_set(port->typec_retimer, &port->retimer_state); if (ret) - dev_err(altmode->dev, "failed to setup retimer to DP\n"); + dev_err(altmode->dev, "failed to setup retimer to DP: %d\n", ret); } static void pmic_glink_altmode_enable_usb(struct pmic_glink_altmode *altmode, @@ -182,7 +182,7 @@ 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"); + dev_err(altmode->dev, "failed to switch mux to USB: %d\n", ret); port->retimer_state.alt = NULL; port->retimer_state.data = NULL; @@ -190,7 +190,7 @@ static void pmic_glink_altmode_enable_usb(struct pmic_glink_altmode *altmode, ret = typec_retimer_set(port->typec_retimer, &port->retimer_state); if (ret) - dev_err(altmode->dev, "failed to setup retimer to USB\n"); + dev_err(altmode->dev, "failed to setup retimer to USB: %d\n", ret); } static void pmic_glink_altmode_safe(struct pmic_glink_altmode *altmode, @@ -204,7 +204,7 @@ 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"); + dev_err(altmode->dev, "failed to switch mux to safe mode: %d\n", ret); port->retimer_state.alt = NULL; port->retimer_state.data = NULL; @@ -212,7 +212,7 @@ static void pmic_glink_altmode_safe(struct pmic_glink_altmode *altmode, ret = typec_retimer_set(port->typec_retimer, &port->retimer_state); if (ret) - dev_err(altmode->dev, "failed to setup retimer to USB\n"); + dev_err(altmode->dev, "failed to setup retimer to USB: %d\n", ret); } static void pmic_glink_altmode_worker(struct work_struct *work) @@ -397,7 +397,7 @@ static void pmic_glink_altmode_enable_worker(struct work_struct *work) ret = pmic_glink_altmode_request(altmode, ALTMODE_PAN_EN, 0); if (ret) - dev_err(altmode->dev, "failed to request altmode notifications\n"); + dev_err(altmode->dev, "failed to request altmode notifications: %d\n", ret); } static void pmic_glink_altmode_pdr_notify(void *priv, int state)