Message ID | 20241027112557.3866257-1-alice.guo@oss.nxp.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [v1] soc: imx: Add SoC device register for i.MX9 | expand |
Hi Alice, Am 27.10.24 um 12:25 schrieb alice.guo@oss.nxp.com: > From: "alice.guo" <alice.guo@nxp.com> > > i.MX9 SoCs have SoC ID, SoC revision number and chip unique identifier > which are provided by the corresponding ARM trusted firmware API. This > patch intends to use SMC call to obtain these information and then > register i.MX9 SoC as a device. > > Signed-off-by: alice.guo <alice.guo@nxp.com> > --- > drivers/soc/imx/Makefile | 2 +- > drivers/soc/imx/soc-imx9.c | 102 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 103 insertions(+), 1 deletion(-) > create mode 100644 drivers/soc/imx/soc-imx9.c > > diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile > index 3ad321ca608a..ca6a5fa1618f 100644 > --- a/drivers/soc/imx/Makefile > +++ b/drivers/soc/imx/Makefile > @@ -3,4 +3,4 @@ ifeq ($(CONFIG_ARM),y) > obj-$(CONFIG_ARCH_MXC) += soc-imx.o > endif > obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o > -obj-$(CONFIG_SOC_IMX9) += imx93-src.o > +obj-$(CONFIG_SOC_IMX9) += imx93-src.o soc-imx9.o > diff --git a/drivers/soc/imx/soc-imx9.c b/drivers/soc/imx/soc-imx9.c > new file mode 100644 > index 000000000000..7e8a8b2efa61 > --- /dev/null > +++ b/drivers/soc/imx/soc-imx9.c > @@ -0,0 +1,102 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright 2024 NXP > + */ > + > +#include <linux/arm-smccc.h> > +#include <linux/init.h> > +#include <linux/module.h> > +#include <linux/of.h> > +#include <linux/slab.h> > +#include <linux/sys_soc.h> > + > +#define IMX_SIP_GET_SOC_INFO 0xc2000006 > +#define SOC_ID(x) (((x) & 0xFFFF) >> 8) > +#define SOC_REV_MAJOR(x) ((((x) >> 28) & 0xF) - 0x9) > +#define SOC_REV_MINOR(x) (((x) >> 24) & 0xF) > + > +static int imx9_soc_device_register(void) > +{ > + struct soc_device_attribute *attr; > + struct arm_smccc_res res; > + struct soc_device *sdev; > + u32 soc_id, rev_major, rev_minor; > + u64 uid127_64, uid63_0; > + int err; > + > + attr = kzalloc(sizeof(*attr), GFP_KERNEL); > + if (!attr) > + return -ENOMEM; > + > + err = of_property_read_string(of_root, "model", &attr->machine); > + if (err) { > + err = -EINVAL; > + goto attr; > + } > + > + attr->family = kasprintf(GFP_KERNEL, "Freescale i.MX"); > + > + /* > + * Retrieve the soc id, rev & uid info: > + * res.a1[31:16]: soc revision; > + * res.a1[15:0]: soc id; > + * res.a2: uid[127:64]; > + * res.a3: uid[63:0]; > + */ > + arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res); > + if (res.a0 != SMCCC_RET_SUCCESS) { > + err = -EINVAL; > + goto family; Please see my comment below. Does it make sense to print the value of res.a0? I stumbled above this recently on a i.MX93 board with a vendor kernel 6.6.23 and the firmware hadn't it implemented. > + } > + > + soc_id = SOC_ID(res.a1); > + rev_major = SOC_REV_MAJOR(res.a1); > + rev_minor = SOC_REV_MINOR(res.a1); > + > + attr->soc_id = kasprintf(GFP_KERNEL, "i.MX%2x", soc_id); > + attr->revision = kasprintf(GFP_KERNEL, "%d.%d", rev_major, rev_minor); > + > + uid127_64 = res.a2; > + uid63_0 = res.a3; > + attr->serial_number = kasprintf(GFP_KERNEL, "%016llx%016llx", uid127_64, uid63_0); > + > + sdev = soc_device_register(attr); > + if (IS_ERR(sdev)) { > + err = -ENODEV; > + goto soc_id; > + } > + > + return 0; > + > +soc_id: > + kfree(attr->soc_id); > + kfree(attr->serial_number); > + kfree(attr->revision); > +family: > + kfree(attr->family); > +attr: > + kfree(attr); > + return err; > +} > + > +static int __init imx9_soc_init(void) > +{ > + int ret = 0; > + > + if (of_machine_is_compatible("fsl,imx91") || > + of_machine_is_compatible("fsl,imx93") || > + of_machine_is_compatible("fsl,imx95")) { > + ret = imx9_soc_device_register(); > + if (ret) { > + pr_err("%s: imx9_soc_device_register returned %d\n", __func__, ret); Can we please have these kernel logs within imx9_soc_device_register()? Btw we could print the real return code of the function which failed. Thanks > + return ret; > + } > + } > + > + return ret; > +} > +device_initcall(imx9_soc_init); > + > +MODULE_AUTHOR("NXP"); > +MODULE_DESCRIPTION("NXP i.MX9 SoC"); > +MODULE_LICENSE("GPL");
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile index 3ad321ca608a..ca6a5fa1618f 100644 --- a/drivers/soc/imx/Makefile +++ b/drivers/soc/imx/Makefile @@ -3,4 +3,4 @@ ifeq ($(CONFIG_ARM),y) obj-$(CONFIG_ARCH_MXC) += soc-imx.o endif obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o -obj-$(CONFIG_SOC_IMX9) += imx93-src.o +obj-$(CONFIG_SOC_IMX9) += imx93-src.o soc-imx9.o diff --git a/drivers/soc/imx/soc-imx9.c b/drivers/soc/imx/soc-imx9.c new file mode 100644 index 000000000000..7e8a8b2efa61 --- /dev/null +++ b/drivers/soc/imx/soc-imx9.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP + */ + +#include <linux/arm-smccc.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/sys_soc.h> + +#define IMX_SIP_GET_SOC_INFO 0xc2000006 +#define SOC_ID(x) (((x) & 0xFFFF) >> 8) +#define SOC_REV_MAJOR(x) ((((x) >> 28) & 0xF) - 0x9) +#define SOC_REV_MINOR(x) (((x) >> 24) & 0xF) + +static int imx9_soc_device_register(void) +{ + struct soc_device_attribute *attr; + struct arm_smccc_res res; + struct soc_device *sdev; + u32 soc_id, rev_major, rev_minor; + u64 uid127_64, uid63_0; + int err; + + attr = kzalloc(sizeof(*attr), GFP_KERNEL); + if (!attr) + return -ENOMEM; + + err = of_property_read_string(of_root, "model", &attr->machine); + if (err) { + err = -EINVAL; + goto attr; + } + + attr->family = kasprintf(GFP_KERNEL, "Freescale i.MX"); + + /* + * Retrieve the soc id, rev & uid info: + * res.a1[31:16]: soc revision; + * res.a1[15:0]: soc id; + * res.a2: uid[127:64]; + * res.a3: uid[63:0]; + */ + arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res); + if (res.a0 != SMCCC_RET_SUCCESS) { + err = -EINVAL; + goto family; + } + + soc_id = SOC_ID(res.a1); + rev_major = SOC_REV_MAJOR(res.a1); + rev_minor = SOC_REV_MINOR(res.a1); + + attr->soc_id = kasprintf(GFP_KERNEL, "i.MX%2x", soc_id); + attr->revision = kasprintf(GFP_KERNEL, "%d.%d", rev_major, rev_minor); + + uid127_64 = res.a2; + uid63_0 = res.a3; + attr->serial_number = kasprintf(GFP_KERNEL, "%016llx%016llx", uid127_64, uid63_0); + + sdev = soc_device_register(attr); + if (IS_ERR(sdev)) { + err = -ENODEV; + goto soc_id; + } + + return 0; + +soc_id: + kfree(attr->soc_id); + kfree(attr->serial_number); + kfree(attr->revision); +family: + kfree(attr->family); +attr: + kfree(attr); + return err; +} + +static int __init imx9_soc_init(void) +{ + int ret = 0; + + if (of_machine_is_compatible("fsl,imx91") || + of_machine_is_compatible("fsl,imx93") || + of_machine_is_compatible("fsl,imx95")) { + ret = imx9_soc_device_register(); + if (ret) { + pr_err("%s: imx9_soc_device_register returned %d\n", __func__, ret); + return ret; + } + } + + return ret; +} +device_initcall(imx9_soc_init); + +MODULE_AUTHOR("NXP"); +MODULE_DESCRIPTION("NXP i.MX9 SoC"); +MODULE_LICENSE("GPL");