1 // SPDX-License-Identifier: GPL-2.0
6 #include <dt-bindings/firmware/imx/rsrc.h>
7 #include <linux/firmware/imx/sci.h>
8 #include <linux/slab.h>
9 #include <linux/sys_soc.h>
10 #include <linux/platform_device.h>
13 #define IMX_SCU_SOC_DRIVER_NAME "imx-scu-soc"
15 static struct imx_sc_ipc
*soc_ipc_handle
;
17 struct imx_sc_msg_misc_get_soc_id
{
18 struct imx_sc_rpc_msg hdr
;
30 struct imx_sc_msg_misc_get_soc_uid
{
31 struct imx_sc_rpc_msg hdr
;
36 static int imx_scu_soc_uid(u64
*soc_uid
)
38 struct imx_sc_msg_misc_get_soc_uid msg
;
39 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
42 hdr
->ver
= IMX_SC_RPC_VERSION
;
43 hdr
->svc
= IMX_SC_RPC_SVC_MISC
;
44 hdr
->func
= IMX_SC_MISC_FUNC_UNIQUE_ID
;
47 ret
= imx_scu_call_rpc(soc_ipc_handle
, &msg
, true);
49 pr_err("%s: get soc uid failed, ret %d\n", __func__
, ret
);
53 *soc_uid
= msg
.uid_high
;
55 *soc_uid
|= msg
.uid_low
;
60 static int imx_scu_soc_id(void)
62 struct imx_sc_msg_misc_get_soc_id msg
;
63 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
66 hdr
->ver
= IMX_SC_RPC_VERSION
;
67 hdr
->svc
= IMX_SC_RPC_SVC_MISC
;
68 hdr
->func
= IMX_SC_MISC_FUNC_GET_CONTROL
;
71 msg
.data
.req
.control
= IMX_SC_C_ID
;
72 msg
.data
.req
.resource
= IMX_SC_R_SYSTEM
;
74 ret
= imx_scu_call_rpc(soc_ipc_handle
, &msg
, true);
76 pr_err("%s: get soc info failed, ret %d\n", __func__
, ret
);
80 return msg
.data
.resp
.id
;
83 static int imx_scu_soc_probe(struct platform_device
*pdev
)
85 struct soc_device_attribute
*soc_dev_attr
;
86 struct soc_device
*soc_dev
;
91 ret
= imx_scu_get_handle(&soc_ipc_handle
);
95 soc_dev_attr
= devm_kzalloc(&pdev
->dev
, sizeof(*soc_dev_attr
),
100 soc_dev_attr
->family
= "Freescale i.MX";
102 ret
= of_property_read_string(of_root
,
104 &soc_dev_attr
->machine
);
108 id
= imx_scu_soc_id();
112 ret
= imx_scu_soc_uid(&uid
);
116 /* format soc_id value passed from SCU firmware */
118 soc_dev_attr
->soc_id
= kasprintf(GFP_KERNEL
, "0x%x", val
);
119 if (!soc_dev_attr
->soc_id
)
122 /* format revision value passed from SCU firmware */
123 val
= (id
>> 5) & 0xf;
124 val
= (((val
>> 2) + 1) << 4) | (val
& 0x3);
125 soc_dev_attr
->revision
= kasprintf(GFP_KERNEL
,
129 if (!soc_dev_attr
->revision
) {
134 soc_dev_attr
->serial_number
= kasprintf(GFP_KERNEL
, "%016llX", uid
);
135 if (!soc_dev_attr
->serial_number
) {
140 soc_dev
= soc_device_register(soc_dev_attr
);
141 if (IS_ERR(soc_dev
)) {
142 ret
= PTR_ERR(soc_dev
);
143 goto free_serial_number
;
149 kfree(soc_dev_attr
->serial_number
);
151 kfree(soc_dev_attr
->revision
);
153 kfree(soc_dev_attr
->soc_id
);
157 static struct platform_driver imx_scu_soc_driver
= {
159 .name
= IMX_SCU_SOC_DRIVER_NAME
,
161 .probe
= imx_scu_soc_probe
,
164 static int __init
imx_scu_soc_init(void)
166 struct platform_device
*pdev
;
167 struct device_node
*np
;
170 np
= of_find_compatible_node(NULL
, NULL
, "fsl,imx-scu");
176 ret
= platform_driver_register(&imx_scu_soc_driver
);
180 pdev
= platform_device_register_simple(IMX_SCU_SOC_DRIVER_NAME
,
183 platform_driver_unregister(&imx_scu_soc_driver
);
185 return PTR_ERR_OR_ZERO(pdev
);
187 device_initcall(imx_scu_soc_init
);