Skip to content

Commit 25205fe

Browse files
committed
Merge tag 'imx-drivers-6.14' of https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into soc/drivers
i.MX drivers change for 6.14: - Add a SoC driver for i.MX9 (Alice Guo) * tag 'imx-drivers-6.14' of https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux: soc: imx: Add SoC device register for i.MX9 Link: https://lore.kernel.org/r/20250105095139.714590-1-shawnguo2@yeah.net Signed-off-by: Arnd Bergmann <arnd@arndb.de>
2 parents 14ade5a + 0b4dc35 commit 25205fe

2 files changed

Lines changed: 129 additions & 1 deletion

File tree

drivers/soc/imx/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ ifeq ($(CONFIG_ARM),y)
33
obj-$(CONFIG_ARCH_MXC) += soc-imx.o
44
endif
55
obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o
6-
obj-$(CONFIG_SOC_IMX9) += imx93-src.o
6+
obj-$(CONFIG_SOC_IMX9) += imx93-src.o soc-imx9.o

drivers/soc/imx/soc-imx9.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright 2024 NXP
4+
*/
5+
6+
#include <linux/arm-smccc.h>
7+
#include <linux/init.h>
8+
#include <linux/module.h>
9+
#include <linux/of.h>
10+
#include <linux/platform_device.h>
11+
#include <linux/slab.h>
12+
#include <linux/sys_soc.h>
13+
14+
#define IMX_SIP_GET_SOC_INFO 0xc2000006
15+
#define SOC_ID(x) (((x) & 0xFFFF) >> 8)
16+
#define SOC_REV_MAJOR(x) ((((x) >> 28) & 0xF) - 0x9)
17+
#define SOC_REV_MINOR(x) (((x) >> 24) & 0xF)
18+
19+
static int imx9_soc_probe(struct platform_device *pdev)
20+
{
21+
struct soc_device_attribute *attr;
22+
struct arm_smccc_res res;
23+
struct soc_device *sdev;
24+
u32 soc_id, rev_major, rev_minor;
25+
u64 uid127_64, uid63_0;
26+
int err;
27+
28+
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
29+
if (!attr)
30+
return -ENOMEM;
31+
32+
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+
}
37+
38+
attr->family = kasprintf(GFP_KERNEL, "Freescale i.MX");
39+
40+
/*
41+
* Retrieve the soc id, rev & uid info:
42+
* res.a1[31:16]: soc revision;
43+
* res.a1[15:0]: soc id;
44+
* res.a2: uid[127:64];
45+
* res.a3: uid[63:0];
46+
*/
47+
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+
}
53+
54+
soc_id = SOC_ID(res.a1);
55+
rev_major = SOC_REV_MAJOR(res.a1);
56+
rev_minor = SOC_REV_MINOR(res.a1);
57+
58+
attr->soc_id = kasprintf(GFP_KERNEL, "i.MX%2x", soc_id);
59+
attr->revision = kasprintf(GFP_KERNEL, "%d.%d", rev_major, rev_minor);
60+
61+
uid127_64 = res.a2;
62+
uid63_0 = res.a3;
63+
attr->serial_number = kasprintf(GFP_KERNEL, "%016llx%016llx", uid127_64, uid63_0);
64+
65+
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+
}
71+
72+
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;
83+
}
84+
85+
static __maybe_unused const struct of_device_id imx9_soc_match[] = {
86+
{ .compatible = "fsl,imx93", },
87+
{ .compatible = "fsl,imx95", },
88+
{ }
89+
};
90+
91+
#define IMX_SOC_DRIVER "imx9-soc"
92+
93+
static struct platform_driver imx9_soc_driver = {
94+
.probe = imx9_soc_probe,
95+
.driver = {
96+
.name = IMX_SOC_DRIVER,
97+
},
98+
};
99+
100+
static int __init imx9_soc_init(void)
101+
{
102+
int ret;
103+
struct platform_device *pdev;
104+
105+
/* No match means it is not an i.MX 9 series SoC, do nothing. */
106+
if (!of_match_node(imx9_soc_match, of_root))
107+
return 0;
108+
109+
ret = platform_driver_register(&imx9_soc_driver);
110+
if (ret) {
111+
pr_err("failed to register imx9_soc platform driver: %d\n", ret);
112+
return ret;
113+
}
114+
115+
pdev = platform_device_register_simple(IMX_SOC_DRIVER, -1, NULL, 0);
116+
if (IS_ERR(pdev)) {
117+
pr_err("failed to register imx9_soc platform device: %ld\n", PTR_ERR(pdev));
118+
platform_driver_unregister(&imx9_soc_driver);
119+
return PTR_ERR(pdev);
120+
}
121+
122+
return 0;
123+
}
124+
device_initcall(imx9_soc_init);
125+
126+
MODULE_AUTHOR("NXP");
127+
MODULE_DESCRIPTION("NXP i.MX9 SoC");
128+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)