Skip to content

Commit 6d9e4c7

Browse files
committed
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>
2 parents 419a620 + f6ef3d9 commit 6d9e4c7

5 files changed

Lines changed: 142 additions & 32 deletions

File tree

drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ enum scmi_imx_misc_protocol_cmd {
2828
SCMI_IMX_MISC_DISCOVER_BUILD_INFO = 0x6,
2929
SCMI_IMX_MISC_CTRL_NOTIFY = 0x8,
3030
SCMI_IMX_MISC_CFG_INFO_GET = 0xC,
31+
SCMI_IMX_MISC_SYSLOG_GET = 0xD,
3132
SCMI_IMX_MISC_BOARD_INFO = 0xE,
3233
};
3334

@@ -88,6 +89,19 @@ struct scmi_imx_misc_cfg_info_out {
8889
u8 cfgname[MISC_MAX_CFGNAME];
8990
};
9091

92+
struct scmi_imx_misc_syslog_in {
93+
__le32 flags;
94+
__le32 index;
95+
};
96+
97+
#define REMAINING(x) le32_get_bits((x), GENMASK(31, 20))
98+
#define RETURNED(x) le32_get_bits((x), GENMASK(11, 0))
99+
100+
struct scmi_imx_misc_syslog_out {
101+
__le32 numlogflags;
102+
__le32 syslog[];
103+
};
104+
91105
static int scmi_imx_misc_attributes_get(const struct scmi_protocol_handle *ph,
92106
struct scmi_imx_misc_info *mi)
93107
{
@@ -370,10 +384,79 @@ static int scmi_imx_misc_cfg_info_get(const struct scmi_protocol_handle *ph)
370384
return ret;
371385
}
372386

387+
struct scmi_imx_misc_syslog_ipriv {
388+
u32 *array;
389+
u16 *size;
390+
};
391+
392+
static void iter_misc_syslog_prepare_message(void *message, u32 desc_index,
393+
const void *priv)
394+
{
395+
struct scmi_imx_misc_syslog_in *msg = message;
396+
397+
msg->flags = cpu_to_le32(0);
398+
msg->index = cpu_to_le32(desc_index);
399+
}
400+
401+
static int iter_misc_syslog_update_state(struct scmi_iterator_state *st,
402+
const void *response, void *priv)
403+
{
404+
const struct scmi_imx_misc_syslog_out *r = response;
405+
struct scmi_imx_misc_syslog_ipriv *p = priv;
406+
407+
st->num_returned = RETURNED(r->numlogflags);
408+
st->num_remaining = REMAINING(r->numlogflags);
409+
*p->size = st->num_returned + st->num_remaining;
410+
411+
return 0;
412+
}
413+
414+
static int
415+
iter_misc_syslog_process_response(const struct scmi_protocol_handle *ph,
416+
const void *response,
417+
struct scmi_iterator_state *st, void *priv)
418+
{
419+
const struct scmi_imx_misc_syslog_out *r = response;
420+
struct scmi_imx_misc_syslog_ipriv *p = priv;
421+
422+
p->array[st->desc_index + st->loop_idx] =
423+
le32_to_cpu(r->syslog[st->loop_idx]);
424+
425+
return 0;
426+
}
427+
428+
static int scmi_imx_misc_syslog_get(const struct scmi_protocol_handle *ph, u16 *size,
429+
void *array)
430+
{
431+
struct scmi_iterator_ops ops = {
432+
.prepare_message = iter_misc_syslog_prepare_message,
433+
.update_state = iter_misc_syslog_update_state,
434+
.process_response = iter_misc_syslog_process_response,
435+
};
436+
struct scmi_imx_misc_syslog_ipriv ipriv = {
437+
.array = array,
438+
.size = size,
439+
};
440+
void *iter;
441+
442+
if (!array || !size || !*size)
443+
return -EINVAL;
444+
445+
iter = ph->hops->iter_response_init(ph, &ops, *size, SCMI_IMX_MISC_SYSLOG_GET,
446+
sizeof(struct scmi_imx_misc_syslog_in),
447+
&ipriv);
448+
if (IS_ERR(iter))
449+
return PTR_ERR(iter);
450+
451+
/* If firmware return NOT SUPPORTED, propagate value to caller */
452+
return ph->hops->iter_response_run(iter);
453+
}
454+
373455
static const struct scmi_imx_misc_proto_ops scmi_imx_misc_proto_ops = {
374456
.misc_ctrl_set = scmi_imx_misc_ctrl_set,
375457
.misc_ctrl_get = scmi_imx_misc_ctrl_get,
376458
.misc_ctrl_req_notify = scmi_imx_misc_ctrl_notify,
459+
.misc_syslog = scmi_imx_misc_syslog_get,
377460
};
378461

379462
static int scmi_imx_misc_protocol_init(const struct scmi_protocol_handle *ph)

drivers/firmware/imx/sm-misc.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
* Copyright 2024 NXP
44
*/
55

6+
#include <linux/debugfs.h>
7+
#include <linux/device/devres.h>
68
#include <linux/firmware/imx/sm.h>
79
#include <linux/module.h>
810
#include <linux/of.h>
911
#include <linux/platform_device.h>
1012
#include <linux/scmi_protocol.h>
1113
#include <linux/scmi_imx_protocol.h>
14+
#include <linux/seq_file.h>
15+
#include <linux/sizes.h>
1216

1317
static const struct scmi_imx_misc_proto_ops *imx_misc_ctrl_ops;
1418
static struct scmi_protocol_handle *ph;
@@ -44,10 +48,38 @@ static int scmi_imx_misc_ctrl_notifier(struct notifier_block *nb,
4448
return 0;
4549
}
4650

51+
static int syslog_show(struct seq_file *file, void *priv)
52+
{
53+
/* 4KB is large enough for syslog */
54+
void *syslog __free(kfree) = kmalloc(SZ_4K, GFP_KERNEL);
55+
/* syslog API use num words, not num bytes */
56+
u16 size = SZ_4K / 4;
57+
int ret;
58+
59+
if (!ph)
60+
return -ENODEV;
61+
62+
ret = imx_misc_ctrl_ops->misc_syslog(ph, &size, syslog);
63+
if (ret)
64+
return ret;
65+
66+
seq_hex_dump(file, " ", DUMP_PREFIX_NONE, 16, sizeof(u32), syslog, size * 4, false);
67+
seq_putc(file, '\n');
68+
69+
return 0;
70+
}
71+
DEFINE_SHOW_ATTRIBUTE(syslog);
72+
73+
static void scmi_imx_misc_put(void *p)
74+
{
75+
debugfs_remove((struct dentry *)p);
76+
}
77+
4778
static int scmi_imx_misc_ctrl_probe(struct scmi_device *sdev)
4879
{
4980
const struct scmi_handle *handle = sdev->handle;
5081
struct device_node *np = sdev->dev.of_node;
82+
struct dentry *scmi_imx_dentry;
5183
u32 src_id, flags;
5284
int ret, i, num;
5385

@@ -98,7 +130,10 @@ static int scmi_imx_misc_ctrl_probe(struct scmi_device *sdev)
98130
}
99131
}
100132

101-
return 0;
133+
scmi_imx_dentry = debugfs_create_dir("scmi_imx", NULL);
134+
debugfs_create_file("syslog", 0444, scmi_imx_dentry, &sdev->dev, &syslog_fops);
135+
136+
return devm_add_action_or_reset(&sdev->dev, scmi_imx_misc_put, scmi_imx_dentry);
102137
}
103138

104139
static const struct scmi_device_id scmi_id_table[] = {

drivers/soc/imx/soc-imx8m.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,11 @@ static int imx8m_soc_prepare(struct platform_device *pdev, const char *ocotp_com
148148
goto err_clk;
149149
}
150150

151-
return clk_prepare_enable(drvdata->clk);
151+
ret = clk_prepare_enable(drvdata->clk);
152+
if (ret)
153+
goto err_clk;
154+
155+
return 0;
152156

153157
err_clk:
154158
iounmap(drvdata->ocotp_base);

drivers/soc/imx/soc-imx9.c

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,29 @@
1212
#include <linux/sys_soc.h>
1313

1414
#define IMX_SIP_GET_SOC_INFO 0xc2000006
15-
#define SOC_ID(x) (((x) & 0xFFFF) >> 8)
15+
#define SOC_ID(x) (((x) & 0xFF) ? ((x) & 0xFFFF) >> 4 : ((x) & 0xFFFF) >> 8)
1616
#define SOC_REV_MAJOR(x) ((((x) >> 28) & 0xF) - 0x9)
1717
#define SOC_REV_MINOR(x) (((x) >> 24) & 0xF)
1818

1919
static int imx9_soc_probe(struct platform_device *pdev)
2020
{
21+
struct device *dev = &pdev->dev;
2122
struct soc_device_attribute *attr;
2223
struct arm_smccc_res res;
2324
struct soc_device *sdev;
2425
u32 soc_id, rev_major, rev_minor;
2526
u64 uid127_64, uid63_0;
2627
int err;
2728

28-
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
29+
attr = devm_kzalloc(dev, sizeof(*attr), GFP_KERNEL);
2930
if (!attr)
3031
return -ENOMEM;
3132

3233
err = of_property_read_string(of_root, "model", &attr->machine);
33-
if (err) {
34-
pr_err("%s: missing model property: %d\n", __func__, err);
35-
goto attr;
36-
}
34+
if (err)
35+
return dev_err_probe(dev, err, "%s: missing model property\n", __func__);
3736

38-
attr->family = kasprintf(GFP_KERNEL, "Freescale i.MX");
37+
attr->family = devm_kasprintf(dev, GFP_KERNEL, "Freescale i.MX");
3938

4039
/*
4140
* Retrieve the soc id, rev & uid info:
@@ -45,46 +44,33 @@ static int imx9_soc_probe(struct platform_device *pdev)
4544
* res.a3: uid[63:0];
4645
*/
4746
arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res);
48-
if (res.a0 != SMCCC_RET_SUCCESS) {
49-
pr_err("%s: SMC failed: 0x%lx\n", __func__, res.a0);
50-
err = -EINVAL;
51-
goto family;
52-
}
47+
if (res.a0 != SMCCC_RET_SUCCESS)
48+
return dev_err_probe(dev, -EINVAL, "%s: SMC failed: 0x%lx\n", __func__, res.a0);
5349

5450
soc_id = SOC_ID(res.a1);
5551
rev_major = SOC_REV_MAJOR(res.a1);
5652
rev_minor = SOC_REV_MINOR(res.a1);
5753

58-
attr->soc_id = kasprintf(GFP_KERNEL, "i.MX%2x", soc_id);
59-
attr->revision = kasprintf(GFP_KERNEL, "%d.%d", rev_major, rev_minor);
54+
attr->soc_id = devm_kasprintf(dev, GFP_KERNEL, "i.MX%2x", soc_id);
55+
attr->revision = devm_kasprintf(dev, GFP_KERNEL, "%d.%d", rev_major, rev_minor);
6056

6157
uid127_64 = res.a2;
6258
uid63_0 = res.a3;
63-
attr->serial_number = kasprintf(GFP_KERNEL, "%016llx%016llx", uid127_64, uid63_0);
59+
attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llx%016llx", uid127_64, uid63_0);
6460

6561
sdev = soc_device_register(attr);
66-
if (IS_ERR(sdev)) {
67-
err = PTR_ERR(sdev);
68-
pr_err("%s failed to register SoC as a device: %d\n", __func__, err);
69-
goto serial_number;
70-
}
62+
if (IS_ERR(sdev))
63+
return dev_err_probe(dev, PTR_ERR(sdev),
64+
"%s failed to register SoC as a device\n", __func__);
7165

7266
return 0;
73-
74-
serial_number:
75-
kfree(attr->serial_number);
76-
kfree(attr->revision);
77-
kfree(attr->soc_id);
78-
family:
79-
kfree(attr->family);
80-
attr:
81-
kfree(attr);
82-
return err;
8367
}
8468

8569
static __maybe_unused const struct of_device_id imx9_soc_match[] = {
8670
{ .compatible = "fsl,imx93", },
71+
{ .compatible = "fsl,imx94", },
8772
{ .compatible = "fsl,imx95", },
73+
{ .compatible = "fsl,imx952", },
8874
{ }
8975
};
9076

include/linux/scmi_imx_protocol.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ struct scmi_imx_misc_proto_ops {
5959
u32 *num, u32 *val);
6060
int (*misc_ctrl_req_notify)(const struct scmi_protocol_handle *ph,
6161
u32 ctrl_id, u32 evt_id, u32 flags);
62+
int (*misc_syslog)(const struct scmi_protocol_handle *ph, u16 *size,
63+
void *array);
6264
};
6365

6466
/* See LMM_ATTRIBUTES in imx95.rst */

0 commit comments

Comments
 (0)