Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright 2020 NXP
0004  */
0005 
0006 #include <linux/mfd/syscon.h>
0007 #include <linux/of.h>
0008 #include <linux/of_address.h>
0009 #include <linux/regmap.h>
0010 #include <linux/slab.h>
0011 #include <linux/sys_soc.h>
0012 
0013 #include <soc/imx/cpu.h>
0014 #include <soc/imx/revision.h>
0015 
0016 #define IIM_UID     0x820
0017 
0018 #define OCOTP_UID_H 0x420
0019 #define OCOTP_UID_L 0x410
0020 
0021 #define OCOTP_ULP_UID_1     0x4b0
0022 #define OCOTP_ULP_UID_2     0x4c0
0023 #define OCOTP_ULP_UID_3     0x4d0
0024 #define OCOTP_ULP_UID_4     0x4e0
0025 
0026 static int __init imx_soc_device_init(void)
0027 {
0028     struct soc_device_attribute *soc_dev_attr;
0029     const char *ocotp_compat = NULL;
0030     struct soc_device *soc_dev;
0031     struct device_node *root;
0032     struct regmap *ocotp = NULL;
0033     const char *soc_id;
0034     u64 soc_uid = 0;
0035     u32 val;
0036     int ret;
0037     int i;
0038 
0039     /* Return early if this is running on devices with different SoCs */
0040     if (!__mxc_cpu_type)
0041         return 0;
0042 
0043     soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
0044     if (!soc_dev_attr)
0045         return -ENOMEM;
0046 
0047     soc_dev_attr->family = "Freescale i.MX";
0048 
0049     root = of_find_node_by_path("/");
0050     ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
0051     of_node_put(root);
0052     if (ret)
0053         goto free_soc;
0054 
0055     switch (__mxc_cpu_type) {
0056     case MXC_CPU_MX1:
0057         soc_id = "i.MX1";
0058         break;
0059     case MXC_CPU_MX21:
0060         soc_id = "i.MX21";
0061         break;
0062     case MXC_CPU_MX25:
0063         soc_id = "i.MX25";
0064         break;
0065     case MXC_CPU_MX27:
0066         soc_id = "i.MX27";
0067         break;
0068     case MXC_CPU_MX31:
0069         soc_id = "i.MX31";
0070         break;
0071     case MXC_CPU_MX35:
0072         soc_id = "i.MX35";
0073         break;
0074     case MXC_CPU_MX50:
0075         soc_id = "i.MX50";
0076         break;
0077     case MXC_CPU_MX51:
0078         ocotp_compat = "fsl,imx51-iim";
0079         soc_id = "i.MX51";
0080         break;
0081     case MXC_CPU_MX53:
0082         ocotp_compat = "fsl,imx53-iim";
0083         soc_id = "i.MX53";
0084         break;
0085     case MXC_CPU_IMX6SL:
0086         ocotp_compat = "fsl,imx6sl-ocotp";
0087         soc_id = "i.MX6SL";
0088         break;
0089     case MXC_CPU_IMX6DL:
0090         ocotp_compat = "fsl,imx6q-ocotp";
0091         soc_id = "i.MX6DL";
0092         break;
0093     case MXC_CPU_IMX6SX:
0094         ocotp_compat = "fsl,imx6sx-ocotp";
0095         soc_id = "i.MX6SX";
0096         break;
0097     case MXC_CPU_IMX6Q:
0098         ocotp_compat = "fsl,imx6q-ocotp";
0099         soc_id = "i.MX6Q";
0100         break;
0101     case MXC_CPU_IMX6UL:
0102         ocotp_compat = "fsl,imx6ul-ocotp";
0103         soc_id = "i.MX6UL";
0104         break;
0105     case MXC_CPU_IMX6ULL:
0106         ocotp_compat = "fsl,imx6ull-ocotp";
0107         soc_id = "i.MX6ULL";
0108         break;
0109     case MXC_CPU_IMX6ULZ:
0110         ocotp_compat = "fsl,imx6ull-ocotp";
0111         soc_id = "i.MX6ULZ";
0112         break;
0113     case MXC_CPU_IMX6SLL:
0114         ocotp_compat = "fsl,imx6sll-ocotp";
0115         soc_id = "i.MX6SLL";
0116         break;
0117     case MXC_CPU_IMX7D:
0118         ocotp_compat = "fsl,imx7d-ocotp";
0119         soc_id = "i.MX7D";
0120         break;
0121     case MXC_CPU_IMX7ULP:
0122         ocotp_compat = "fsl,imx7ulp-ocotp";
0123         soc_id = "i.MX7ULP";
0124         break;
0125     case MXC_CPU_VF500:
0126         ocotp_compat = "fsl,vf610-ocotp";
0127         soc_id = "VF500";
0128         break;
0129     case MXC_CPU_VF510:
0130         ocotp_compat = "fsl,vf610-ocotp";
0131         soc_id = "VF510";
0132         break;
0133     case MXC_CPU_VF600:
0134         ocotp_compat = "fsl,vf610-ocotp";
0135         soc_id = "VF600";
0136         break;
0137     case MXC_CPU_VF610:
0138         ocotp_compat = "fsl,vf610-ocotp";
0139         soc_id = "VF610";
0140         break;
0141     default:
0142         soc_id = "Unknown";
0143     }
0144     soc_dev_attr->soc_id = soc_id;
0145 
0146     if (ocotp_compat) {
0147         ocotp = syscon_regmap_lookup_by_compatible(ocotp_compat);
0148         if (IS_ERR(ocotp))
0149             pr_err("%s: failed to find %s regmap!\n", __func__, ocotp_compat);
0150     }
0151 
0152     if (!IS_ERR_OR_NULL(ocotp)) {
0153         if (__mxc_cpu_type == MXC_CPU_IMX7ULP) {
0154             regmap_read(ocotp, OCOTP_ULP_UID_4, &val);
0155             soc_uid = val & 0xffff;
0156             regmap_read(ocotp, OCOTP_ULP_UID_3, &val);
0157             soc_uid <<= 16;
0158             soc_uid |= val & 0xffff;
0159             regmap_read(ocotp, OCOTP_ULP_UID_2, &val);
0160             soc_uid <<= 16;
0161             soc_uid |= val & 0xffff;
0162             regmap_read(ocotp, OCOTP_ULP_UID_1, &val);
0163             soc_uid <<= 16;
0164             soc_uid |= val & 0xffff;
0165         } else if (__mxc_cpu_type == MXC_CPU_MX51 ||
0166                __mxc_cpu_type == MXC_CPU_MX53) {
0167             for (i=0; i < 8; i++) {
0168                 regmap_read(ocotp, IIM_UID + i*4, &val);
0169                 soc_uid <<= 8;
0170                 soc_uid |= (val & 0xff);
0171             }
0172         } else {
0173             regmap_read(ocotp, OCOTP_UID_H, &val);
0174             soc_uid = val;
0175             regmap_read(ocotp, OCOTP_UID_L, &val);
0176             soc_uid <<= 32;
0177             soc_uid |= val;
0178         }
0179     }
0180 
0181     soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d.%d",
0182                        (imx_get_soc_revision() >> 4) & 0xf,
0183                        imx_get_soc_revision() & 0xf);
0184     if (!soc_dev_attr->revision) {
0185         ret = -ENOMEM;
0186         goto free_soc;
0187     }
0188 
0189     soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid);
0190     if (!soc_dev_attr->serial_number) {
0191         ret = -ENOMEM;
0192         goto free_rev;
0193     }
0194 
0195     soc_dev = soc_device_register(soc_dev_attr);
0196     if (IS_ERR(soc_dev)) {
0197         ret = PTR_ERR(soc_dev);
0198         goto free_serial_number;
0199     }
0200 
0201     return 0;
0202 
0203 free_serial_number:
0204     kfree(soc_dev_attr->serial_number);
0205 free_rev:
0206     kfree(soc_dev_attr->revision);
0207 free_soc:
0208     kfree(soc_dev_attr);
0209     return ret;
0210 }
0211 device_initcall(imx_soc_device_init);