brintos

brintos / linux-shallow public Read only

0
0
Text · 4.6 KiB · fab668c Raw
212 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright 2020 NXP4 */5 6#include <linux/mfd/syscon.h>7#include <linux/of.h>8#include <linux/of_address.h>9#include <linux/regmap.h>10#include <linux/slab.h>11#include <linux/sys_soc.h>12 13#include <soc/imx/cpu.h>14#include <soc/imx/revision.h>15 16#define IIM_UID		0x82017 18#define OCOTP_UID_H	0x42019#define OCOTP_UID_L	0x41020 21#define OCOTP_ULP_UID_1		0x4b022#define OCOTP_ULP_UID_2		0x4c023#define OCOTP_ULP_UID_3		0x4d024#define OCOTP_ULP_UID_4		0x4e025 26static int __init imx_soc_device_init(void)27{28	struct soc_device_attribute *soc_dev_attr;29	const char *ocotp_compat = NULL;30	struct soc_device *soc_dev;31	struct device_node *root;32	struct regmap *ocotp = NULL;33	const char *soc_id;34	u64 soc_uid = 0;35	u32 val;36	int ret;37	int i;38 39	/* Return early if this is running on devices with different SoCs */40	if (!__mxc_cpu_type)41		return 0;42 43	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);44	if (!soc_dev_attr)45		return -ENOMEM;46 47	soc_dev_attr->family = "Freescale i.MX";48 49	root = of_find_node_by_path("/");50	ret = of_property_read_string(root, "model", &soc_dev_attr->machine);51	of_node_put(root);52	if (ret)53		goto free_soc;54 55	switch (__mxc_cpu_type) {56	case MXC_CPU_MX1:57		soc_id = "i.MX1";58		break;59	case MXC_CPU_MX21:60		soc_id = "i.MX21";61		break;62	case MXC_CPU_MX25:63		soc_id = "i.MX25";64		break;65	case MXC_CPU_MX27:66		soc_id = "i.MX27";67		break;68	case MXC_CPU_MX31:69		soc_id = "i.MX31";70		break;71	case MXC_CPU_MX35:72		soc_id = "i.MX35";73		break;74	case MXC_CPU_MX50:75		soc_id = "i.MX50";76		break;77	case MXC_CPU_MX51:78		ocotp_compat = "fsl,imx51-iim";79		soc_id = "i.MX51";80		break;81	case MXC_CPU_MX53:82		ocotp_compat = "fsl,imx53-iim";83		soc_id = "i.MX53";84		break;85	case MXC_CPU_IMX6SL:86		ocotp_compat = "fsl,imx6sl-ocotp";87		soc_id = "i.MX6SL";88		break;89	case MXC_CPU_IMX6DL:90		ocotp_compat = "fsl,imx6q-ocotp";91		soc_id = "i.MX6DL";92		break;93	case MXC_CPU_IMX6SX:94		ocotp_compat = "fsl,imx6sx-ocotp";95		soc_id = "i.MX6SX";96		break;97	case MXC_CPU_IMX6Q:98		ocotp_compat = "fsl,imx6q-ocotp";99		soc_id = "i.MX6Q";100		break;101	case MXC_CPU_IMX6UL:102		ocotp_compat = "fsl,imx6ul-ocotp";103		soc_id = "i.MX6UL";104		break;105	case MXC_CPU_IMX6ULL:106		ocotp_compat = "fsl,imx6ull-ocotp";107		soc_id = "i.MX6ULL";108		break;109	case MXC_CPU_IMX6ULZ:110		ocotp_compat = "fsl,imx6ull-ocotp";111		soc_id = "i.MX6ULZ";112		break;113	case MXC_CPU_IMX6SLL:114		ocotp_compat = "fsl,imx6sll-ocotp";115		soc_id = "i.MX6SLL";116		break;117	case MXC_CPU_IMX7D:118		ocotp_compat = "fsl,imx7d-ocotp";119		soc_id = "i.MX7D";120		break;121	case MXC_CPU_IMX7ULP:122		ocotp_compat = "fsl,imx7ulp-ocotp";123		soc_id = "i.MX7ULP";124		break;125	case MXC_CPU_VF500:126		ocotp_compat = "fsl,vf610-ocotp";127		soc_id = "VF500";128		break;129	case MXC_CPU_VF510:130		ocotp_compat = "fsl,vf610-ocotp";131		soc_id = "VF510";132		break;133	case MXC_CPU_VF600:134		ocotp_compat = "fsl,vf610-ocotp";135		soc_id = "VF600";136		break;137	case MXC_CPU_VF610:138		ocotp_compat = "fsl,vf610-ocotp";139		soc_id = "VF610";140		break;141	default:142		soc_id = "Unknown";143	}144	soc_dev_attr->soc_id = soc_id;145 146	if (ocotp_compat) {147		ocotp = syscon_regmap_lookup_by_compatible(ocotp_compat);148		if (IS_ERR(ocotp))149			pr_err("%s: failed to find %s regmap!\n", __func__, ocotp_compat);150	}151 152	if (!IS_ERR_OR_NULL(ocotp)) {153		if (__mxc_cpu_type == MXC_CPU_IMX7ULP) {154			regmap_read(ocotp, OCOTP_ULP_UID_4, &val);155			soc_uid = val & 0xffff;156			regmap_read(ocotp, OCOTP_ULP_UID_3, &val);157			soc_uid <<= 16;158			soc_uid |= val & 0xffff;159			regmap_read(ocotp, OCOTP_ULP_UID_2, &val);160			soc_uid <<= 16;161			soc_uid |= val & 0xffff;162			regmap_read(ocotp, OCOTP_ULP_UID_1, &val);163			soc_uid <<= 16;164			soc_uid |= val & 0xffff;165		} else if (__mxc_cpu_type == MXC_CPU_MX51 ||166			   __mxc_cpu_type == MXC_CPU_MX53) {167			for (i=0; i < 8; i++) {168				regmap_read(ocotp, IIM_UID + i*4, &val);169				soc_uid <<= 8;170				soc_uid |= (val & 0xff);171			}172		} else {173			regmap_read(ocotp, OCOTP_UID_H, &val);174			soc_uid = val;175			regmap_read(ocotp, OCOTP_UID_L, &val);176			soc_uid <<= 32;177			soc_uid |= val;178		}179	}180 181	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d.%d",182					   (imx_get_soc_revision() >> 4) & 0xf,183					   imx_get_soc_revision() & 0xf);184	if (!soc_dev_attr->revision) {185		ret = -ENOMEM;186		goto free_soc;187	}188 189	soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid);190	if (!soc_dev_attr->serial_number) {191		ret = -ENOMEM;192		goto free_rev;193	}194 195	soc_dev = soc_device_register(soc_dev_attr);196	if (IS_ERR(soc_dev)) {197		ret = PTR_ERR(soc_dev);198		goto free_serial_number;199	}200 201	return 0;202 203free_serial_number:204	kfree(soc_dev_attr->serial_number);205free_rev:206	kfree(soc_dev_attr->revision);207free_soc:208	kfree(soc_dev_attr);209	return ret;210}211device_initcall(imx_soc_device_init);212