Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+142 -32
+83
drivers/firmware/arm_scmi/vendors/imx/imx-sm-misc.c
··· 28 28 SCMI_IMX_MISC_DISCOVER_BUILD_INFO = 0x6, 29 29 SCMI_IMX_MISC_CTRL_NOTIFY = 0x8, 30 30 SCMI_IMX_MISC_CFG_INFO_GET = 0xC, 31 + SCMI_IMX_MISC_SYSLOG_GET = 0xD, 31 32 SCMI_IMX_MISC_BOARD_INFO = 0xE, 32 33 }; 33 34 ··· 87 86 __le32 msel; 88 87 #define MISC_MAX_CFGNAME 16 89 88 u8 cfgname[MISC_MAX_CFGNAME]; 89 + }; 90 + 91 + struct scmi_imx_misc_syslog_in { 92 + __le32 flags; 93 + __le32 index; 94 + }; 95 + 96 + #define REMAINING(x) le32_get_bits((x), GENMASK(31, 20)) 97 + #define RETURNED(x) le32_get_bits((x), GENMASK(11, 0)) 98 + 99 + struct scmi_imx_misc_syslog_out { 100 + __le32 numlogflags; 101 + __le32 syslog[]; 90 102 }; 91 103 92 104 static int scmi_imx_misc_attributes_get(const struct scmi_protocol_handle *ph, ··· 384 370 return ret; 385 371 } 386 372 373 + struct scmi_imx_misc_syslog_ipriv { 374 + u32 *array; 375 + u16 *size; 376 + }; 377 + 378 + static void iter_misc_syslog_prepare_message(void *message, u32 desc_index, 379 + const void *priv) 380 + { 381 + struct scmi_imx_misc_syslog_in *msg = message; 382 + 383 + msg->flags = cpu_to_le32(0); 384 + msg->index = cpu_to_le32(desc_index); 385 + } 386 + 387 + static int iter_misc_syslog_update_state(struct scmi_iterator_state *st, 388 + const void *response, void *priv) 389 + { 390 + const struct scmi_imx_misc_syslog_out *r = response; 391 + struct scmi_imx_misc_syslog_ipriv *p = priv; 392 + 393 + st->num_returned = RETURNED(r->numlogflags); 394 + st->num_remaining = REMAINING(r->numlogflags); 395 + *p->size = st->num_returned + st->num_remaining; 396 + 397 + return 0; 398 + } 399 + 400 + static int 401 + iter_misc_syslog_process_response(const struct scmi_protocol_handle *ph, 402 + const void *response, 403 + struct scmi_iterator_state *st, void *priv) 404 + { 405 + const struct scmi_imx_misc_syslog_out *r = response; 406 + struct scmi_imx_misc_syslog_ipriv *p = priv; 407 + 408 + p->array[st->desc_index + st->loop_idx] = 409 + le32_to_cpu(r->syslog[st->loop_idx]); 410 + 411 + return 0; 412 + } 413 + 414 + static int scmi_imx_misc_syslog_get(const struct scmi_protocol_handle *ph, u16 *size, 415 + void *array) 416 + { 417 + struct scmi_iterator_ops ops = { 418 + .prepare_message = iter_misc_syslog_prepare_message, 419 + .update_state = iter_misc_syslog_update_state, 420 + .process_response = iter_misc_syslog_process_response, 421 + }; 422 + struct scmi_imx_misc_syslog_ipriv ipriv = { 423 + .array = array, 424 + .size = size, 425 + }; 426 + void *iter; 427 + 428 + if (!array || !size || !*size) 429 + return -EINVAL; 430 + 431 + iter = ph->hops->iter_response_init(ph, &ops, *size, SCMI_IMX_MISC_SYSLOG_GET, 432 + sizeof(struct scmi_imx_misc_syslog_in), 433 + &ipriv); 434 + if (IS_ERR(iter)) 435 + return PTR_ERR(iter); 436 + 437 + /* If firmware return NOT SUPPORTED, propagate value to caller */ 438 + return ph->hops->iter_response_run(iter); 439 + } 440 + 387 441 static const struct scmi_imx_misc_proto_ops scmi_imx_misc_proto_ops = { 388 442 .misc_ctrl_set = scmi_imx_misc_ctrl_set, 389 443 .misc_ctrl_get = scmi_imx_misc_ctrl_get, 390 444 .misc_ctrl_req_notify = scmi_imx_misc_ctrl_notify, 445 + .misc_syslog = scmi_imx_misc_syslog_get, 391 446 }; 392 447 393 448 static int scmi_imx_misc_protocol_init(const struct scmi_protocol_handle *ph)
+36 -1
drivers/firmware/imx/sm-misc.c
··· 3 3 * Copyright 2024 NXP 4 4 */ 5 5 6 + #include <linux/debugfs.h> 7 + #include <linux/device/devres.h> 6 8 #include <linux/firmware/imx/sm.h> 7 9 #include <linux/module.h> 8 10 #include <linux/of.h> 9 11 #include <linux/platform_device.h> 10 12 #include <linux/scmi_protocol.h> 11 13 #include <linux/scmi_imx_protocol.h> 14 + #include <linux/seq_file.h> 15 + #include <linux/sizes.h> 12 16 13 17 static const struct scmi_imx_misc_proto_ops *imx_misc_ctrl_ops; 14 18 static struct scmi_protocol_handle *ph; ··· 48 44 return 0; 49 45 } 50 46 47 + static int syslog_show(struct seq_file *file, void *priv) 48 + { 49 + /* 4KB is large enough for syslog */ 50 + void *syslog __free(kfree) = kmalloc(SZ_4K, GFP_KERNEL); 51 + /* syslog API use num words, not num bytes */ 52 + u16 size = SZ_4K / 4; 53 + int ret; 54 + 55 + if (!ph) 56 + return -ENODEV; 57 + 58 + ret = imx_misc_ctrl_ops->misc_syslog(ph, &size, syslog); 59 + if (ret) 60 + return ret; 61 + 62 + seq_hex_dump(file, " ", DUMP_PREFIX_NONE, 16, sizeof(u32), syslog, size * 4, false); 63 + seq_putc(file, '\n'); 64 + 65 + return 0; 66 + } 67 + DEFINE_SHOW_ATTRIBUTE(syslog); 68 + 69 + static void scmi_imx_misc_put(void *p) 70 + { 71 + debugfs_remove((struct dentry *)p); 72 + } 73 + 51 74 static int scmi_imx_misc_ctrl_probe(struct scmi_device *sdev) 52 75 { 53 76 const struct scmi_handle *handle = sdev->handle; 54 77 struct device_node *np = sdev->dev.of_node; 78 + struct dentry *scmi_imx_dentry; 55 79 u32 src_id, flags; 56 80 int ret, i, num; 57 81 ··· 130 98 } 131 99 } 132 100 133 - return 0; 101 + scmi_imx_dentry = debugfs_create_dir("scmi_imx", NULL); 102 + debugfs_create_file("syslog", 0444, scmi_imx_dentry, &sdev->dev, &syslog_fops); 103 + 104 + return devm_add_action_or_reset(&sdev->dev, scmi_imx_misc_put, scmi_imx_dentry); 134 105 } 135 106 136 107 static const struct scmi_device_id scmi_id_table[] = {
+5 -1
drivers/soc/imx/soc-imx8m.c
··· 148 148 goto err_clk; 149 149 } 150 150 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; 152 156 153 157 err_clk: 154 158 iounmap(drvdata->ocotp_base);
+16 -30
drivers/soc/imx/soc-imx9.c
··· 12 12 #include <linux/sys_soc.h> 13 13 14 14 #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) 16 16 #define SOC_REV_MAJOR(x) ((((x) >> 28) & 0xF) - 0x9) 17 17 #define SOC_REV_MINOR(x) (((x) >> 24) & 0xF) 18 18 19 19 static int imx9_soc_probe(struct platform_device *pdev) 20 20 { 21 + struct device *dev = &pdev->dev; 21 22 struct soc_device_attribute *attr; 22 23 struct arm_smccc_res res; 23 24 struct soc_device *sdev; ··· 26 25 u64 uid127_64, uid63_0; 27 26 int err; 28 27 29 - attr = kzalloc(sizeof(*attr), GFP_KERNEL); 28 + attr = devm_kzalloc(dev, sizeof(*attr), GFP_KERNEL); 30 29 if (!attr) 31 30 return -ENOMEM; 32 31 33 32 err = of_property_read_string(of_root, "model", &attr->machine); 34 - if (err) { 35 - pr_err("%s: missing model property: %d\n", __func__, err); 36 - goto attr; 37 - } 33 + if (err) 34 + return dev_err_probe(dev, err, "%s: missing model property\n", __func__); 38 35 39 - attr->family = kasprintf(GFP_KERNEL, "Freescale i.MX"); 36 + attr->family = devm_kasprintf(dev, GFP_KERNEL, "Freescale i.MX"); 40 37 41 38 /* 42 39 * Retrieve the soc id, rev & uid info: ··· 44 45 * res.a3: uid[63:0]; 45 46 */ 46 47 arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res); 47 - if (res.a0 != SMCCC_RET_SUCCESS) { 48 - pr_err("%s: SMC failed: 0x%lx\n", __func__, res.a0); 49 - err = -EINVAL; 50 - goto family; 51 - } 48 + if (res.a0 != SMCCC_RET_SUCCESS) 49 + return dev_err_probe(dev, -EINVAL, "%s: SMC failed: 0x%lx\n", __func__, res.a0); 52 50 53 51 soc_id = SOC_ID(res.a1); 54 52 rev_major = SOC_REV_MAJOR(res.a1); 55 53 rev_minor = SOC_REV_MINOR(res.a1); 56 54 57 - attr->soc_id = kasprintf(GFP_KERNEL, "i.MX%2x", soc_id); 58 - attr->revision = kasprintf(GFP_KERNEL, "%d.%d", rev_major, rev_minor); 55 + attr->soc_id = devm_kasprintf(dev, GFP_KERNEL, "i.MX%2x", soc_id); 56 + attr->revision = devm_kasprintf(dev, GFP_KERNEL, "%d.%d", rev_major, rev_minor); 59 57 60 58 uid127_64 = res.a2; 61 59 uid63_0 = res.a3; 62 - attr->serial_number = kasprintf(GFP_KERNEL, "%016llx%016llx", uid127_64, uid63_0); 60 + attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llx%016llx", uid127_64, uid63_0); 63 61 64 62 sdev = soc_device_register(attr); 65 - if (IS_ERR(sdev)) { 66 - err = PTR_ERR(sdev); 67 - pr_err("%s failed to register SoC as a device: %d\n", __func__, err); 68 - goto serial_number; 69 - } 63 + if (IS_ERR(sdev)) 64 + return dev_err_probe(dev, PTR_ERR(sdev), 65 + "%s failed to register SoC as a device\n", __func__); 70 66 71 67 return 0; 72 - 73 - serial_number: 74 - kfree(attr->serial_number); 75 - kfree(attr->revision); 76 - kfree(attr->soc_id); 77 - family: 78 - kfree(attr->family); 79 - attr: 80 - kfree(attr); 81 - return err; 82 68 } 83 69 84 70 static __maybe_unused const struct of_device_id imx9_soc_match[] = { 85 71 { .compatible = "fsl,imx93", }, 72 + { .compatible = "fsl,imx94", }, 86 73 { .compatible = "fsl,imx95", }, 74 + { .compatible = "fsl,imx952", }, 87 75 { } 88 76 }; 89 77
+2
include/linux/scmi_imx_protocol.h
··· 59 59 u32 *num, u32 *val); 60 60 int (*misc_ctrl_req_notify)(const struct scmi_protocol_handle *ph, 61 61 u32 ctrl_id, u32 evt_id, u32 flags); 62 + int (*misc_syslog)(const struct scmi_protocol_handle *ph, u16 *size, 63 + void *array); 62 64 }; 63 65 64 66 /* See LMM_ATTRIBUTES in imx95.rst */