diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2026-01-21 16:39:29 +0100 |
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2026-01-21 16:39:29 +0100 |
| commit | 6d9e4c74372bd08c75d7c2dbdccc4d713caabbd9 (patch) | |
| tree | 5507f0c9317fc4eb7317fb7192ac745cd0a69644 /drivers/firmware | |
| parent | 419a620dc452b9cd6aa684d99bcff352f7ab7f13 (diff) | |
| parent | f6ef3d9ff81240e9bcc030f2da132eb0f8a761d7 (diff) | |
Merge tag 'imx-drivers-6.20' of https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into soc/drivers
i.MX drivers changes for 6.20:
- A few changes from Peng Fan adding dump syslog support for i.MX
System Manager firmware driver, cleaning up soc-imx9 driver, fixing
error handling for soc-imx8m driver
* tag 'imx-drivers-6.20' of https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux:
soc: imx8m: Fix error handling for clk_prepare_enable()
soc: imx: Spport i.MX9[4,52]
soc: imx: Use dev_err_probe() for i.MX9
soc: imx: Use device-managed APIs for i.MX9
firmware: imx: sm-misc: Dump syslog info
firmware: arm_scmi: imx: Support getting syslog of MISC protocol
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/firmware')
| -rw-r--r-- | drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c | 83 | ||||
| -rw-r--r-- | drivers/firmware/imx/sm-misc.c | 37 |
2 files changed, 119 insertions, 1 deletions
diff --git a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c index 73d80f221b9d..0ada753367ef 100644 --- a/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c +++ b/drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c @@ -28,6 +28,7 @@ enum scmi_imx_misc_protocol_cmd { SCMI_IMX_MISC_DISCOVER_BUILD_INFO = 0x6, SCMI_IMX_MISC_CTRL_NOTIFY = 0x8, SCMI_IMX_MISC_CFG_INFO_GET = 0xC, + SCMI_IMX_MISC_SYSLOG_GET = 0xD, SCMI_IMX_MISC_BOARD_INFO = 0xE, }; @@ -88,6 +89,19 @@ struct scmi_imx_misc_cfg_info_out { u8 cfgname[MISC_MAX_CFGNAME]; }; +struct scmi_imx_misc_syslog_in { + __le32 flags; + __le32 index; +}; + +#define REMAINING(x) le32_get_bits((x), GENMASK(31, 20)) +#define RETURNED(x) le32_get_bits((x), GENMASK(11, 0)) + +struct scmi_imx_misc_syslog_out { + __le32 numlogflags; + __le32 syslog[]; +}; + static int scmi_imx_misc_attributes_get(const struct scmi_protocol_handle *ph, struct scmi_imx_misc_info *mi) { @@ -370,10 +384,79 @@ static int scmi_imx_misc_cfg_info_get(const struct scmi_protocol_handle *ph) return ret; } +struct scmi_imx_misc_syslog_ipriv { + u32 *array; + u16 *size; +}; + +static void iter_misc_syslog_prepare_message(void *message, u32 desc_index, + const void *priv) +{ + struct scmi_imx_misc_syslog_in *msg = message; + + msg->flags = cpu_to_le32(0); + msg->index = cpu_to_le32(desc_index); +} + +static int iter_misc_syslog_update_state(struct scmi_iterator_state *st, + const void *response, void *priv) +{ + const struct scmi_imx_misc_syslog_out *r = response; + struct scmi_imx_misc_syslog_ipriv *p = priv; + + st->num_returned = RETURNED(r->numlogflags); + st->num_remaining = REMAINING(r->numlogflags); + *p->size = st->num_returned + st->num_remaining; + + return 0; +} + +static int +iter_misc_syslog_process_response(const struct scmi_protocol_handle *ph, + const void *response, + struct scmi_iterator_state *st, void *priv) +{ + const struct scmi_imx_misc_syslog_out *r = response; + struct scmi_imx_misc_syslog_ipriv *p = priv; + + p->array[st->desc_index + st->loop_idx] = + le32_to_cpu(r->syslog[st->loop_idx]); + + return 0; +} + +static int scmi_imx_misc_syslog_get(const struct scmi_protocol_handle *ph, u16 *size, + void *array) +{ + struct scmi_iterator_ops ops = { + .prepare_message = iter_misc_syslog_prepare_message, + .update_state = iter_misc_syslog_update_state, + .process_response = iter_misc_syslog_process_response, + }; + struct scmi_imx_misc_syslog_ipriv ipriv = { + .array = array, + .size = size, + }; + void *iter; + + if (!array || !size || !*size) + return -EINVAL; + + iter = ph->hops->iter_response_init(ph, &ops, *size, SCMI_IMX_MISC_SYSLOG_GET, + sizeof(struct scmi_imx_misc_syslog_in), + &ipriv); + if (IS_ERR(iter)) + return PTR_ERR(iter); + + /* If firmware return NOT SUPPORTED, propagate value to caller */ + return ph->hops->iter_response_run(iter); +} + static const struct scmi_imx_misc_proto_ops scmi_imx_misc_proto_ops = { .misc_ctrl_set = scmi_imx_misc_ctrl_set, .misc_ctrl_get = scmi_imx_misc_ctrl_get, .misc_ctrl_req_notify = scmi_imx_misc_ctrl_notify, + .misc_syslog = scmi_imx_misc_syslog_get, }; static int scmi_imx_misc_protocol_init(const struct scmi_protocol_handle *ph) diff --git a/drivers/firmware/imx/sm-misc.c b/drivers/firmware/imx/sm-misc.c index fc3ee12c2be8..0a8ada329c9d 100644 --- a/drivers/firmware/imx/sm-misc.c +++ b/drivers/firmware/imx/sm-misc.c @@ -3,12 +3,16 @@ * Copyright 2024 NXP */ +#include <linux/debugfs.h> +#include <linux/device/devres.h> #include <linux/firmware/imx/sm.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/scmi_protocol.h> #include <linux/scmi_imx_protocol.h> +#include <linux/seq_file.h> +#include <linux/sizes.h> static const struct scmi_imx_misc_proto_ops *imx_misc_ctrl_ops; static struct scmi_protocol_handle *ph; @@ -44,10 +48,38 @@ static int scmi_imx_misc_ctrl_notifier(struct notifier_block *nb, return 0; } +static int syslog_show(struct seq_file *file, void *priv) +{ + /* 4KB is large enough for syslog */ + void *syslog __free(kfree) = kmalloc(SZ_4K, GFP_KERNEL); + /* syslog API use num words, not num bytes */ + u16 size = SZ_4K / 4; + int ret; + + if (!ph) + return -ENODEV; + + ret = imx_misc_ctrl_ops->misc_syslog(ph, &size, syslog); + if (ret) + return ret; + + seq_hex_dump(file, " ", DUMP_PREFIX_NONE, 16, sizeof(u32), syslog, size * 4, false); + seq_putc(file, '\n'); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(syslog); + +static void scmi_imx_misc_put(void *p) +{ + debugfs_remove((struct dentry *)p); +} + static int scmi_imx_misc_ctrl_probe(struct scmi_device *sdev) { const struct scmi_handle *handle = sdev->handle; struct device_node *np = sdev->dev.of_node; + struct dentry *scmi_imx_dentry; u32 src_id, flags; int ret, i, num; @@ -98,7 +130,10 @@ static int scmi_imx_misc_ctrl_probe(struct scmi_device *sdev) } } - return 0; + scmi_imx_dentry = debugfs_create_dir("scmi_imx", NULL); + debugfs_create_file("syslog", 0444, scmi_imx_dentry, &sdev->dev, &syslog_fops); + + return devm_add_action_or_reset(&sdev->dev, scmi_imx_misc_put, scmi_imx_dentry); } static const struct scmi_device_id scmi_id_table[] = { |
