cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

socinfo.c (18273B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
      4 * Copyright (c) 2017-2019, Linaro Ltd.
      5 */
      6
      7#include <linux/debugfs.h>
      8#include <linux/err.h>
      9#include <linux/module.h>
     10#include <linux/platform_device.h>
     11#include <linux/random.h>
     12#include <linux/slab.h>
     13#include <linux/soc/qcom/smem.h>
     14#include <linux/string.h>
     15#include <linux/sys_soc.h>
     16#include <linux/types.h>
     17
     18#include <asm/unaligned.h>
     19
     20/*
     21 * SoC version type with major number in the upper 16 bits and minor
     22 * number in the lower 16 bits.
     23 */
     24#define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff)
     25#define SOCINFO_MINOR(ver) ((ver) & 0xffff)
     26#define SOCINFO_VERSION(maj, min)  ((((maj) & 0xffff) << 16)|((min) & 0xffff))
     27
     28#define SMEM_SOCINFO_BUILD_ID_LENGTH           32
     29#define SMEM_SOCINFO_CHIP_ID_LENGTH            32
     30
     31/*
     32 * SMEM item id, used to acquire handles to respective
     33 * SMEM region.
     34 */
     35#define SMEM_HW_SW_BUILD_ID            137
     36
     37#ifdef CONFIG_DEBUG_FS
     38#define SMEM_IMAGE_VERSION_BLOCKS_COUNT        32
     39#define SMEM_IMAGE_VERSION_SIZE                4096
     40#define SMEM_IMAGE_VERSION_NAME_SIZE           75
     41#define SMEM_IMAGE_VERSION_VARIANT_SIZE        20
     42#define SMEM_IMAGE_VERSION_OEM_SIZE            32
     43
     44/*
     45 * SMEM Image table indices
     46 */
     47#define SMEM_IMAGE_TABLE_BOOT_INDEX     0
     48#define SMEM_IMAGE_TABLE_TZ_INDEX       1
     49#define SMEM_IMAGE_TABLE_RPM_INDEX      3
     50#define SMEM_IMAGE_TABLE_APPS_INDEX     10
     51#define SMEM_IMAGE_TABLE_MPSS_INDEX     11
     52#define SMEM_IMAGE_TABLE_ADSP_INDEX     12
     53#define SMEM_IMAGE_TABLE_CNSS_INDEX     13
     54#define SMEM_IMAGE_TABLE_VIDEO_INDEX    14
     55#define SMEM_IMAGE_VERSION_TABLE       469
     56
     57/*
     58 * SMEM Image table names
     59 */
     60static const char *const socinfo_image_names[] = {
     61	[SMEM_IMAGE_TABLE_ADSP_INDEX] = "adsp",
     62	[SMEM_IMAGE_TABLE_APPS_INDEX] = "apps",
     63	[SMEM_IMAGE_TABLE_BOOT_INDEX] = "boot",
     64	[SMEM_IMAGE_TABLE_CNSS_INDEX] = "cnss",
     65	[SMEM_IMAGE_TABLE_MPSS_INDEX] = "mpss",
     66	[SMEM_IMAGE_TABLE_RPM_INDEX] = "rpm",
     67	[SMEM_IMAGE_TABLE_TZ_INDEX] = "tz",
     68	[SMEM_IMAGE_TABLE_VIDEO_INDEX] = "video",
     69};
     70
     71static const char *const pmic_models[] = {
     72	[0]  = "Unknown PMIC model",
     73	[1]  = "PM8941",
     74	[2]  = "PM8841",
     75	[3]  = "PM8019",
     76	[4]  = "PM8226",
     77	[5]  = "PM8110",
     78	[6]  = "PMA8084",
     79	[7]  = "PMI8962",
     80	[8]  = "PMD9635",
     81	[9]  = "PM8994",
     82	[10] = "PMI8994",
     83	[11] = "PM8916",
     84	[12] = "PM8004",
     85	[13] = "PM8909/PM8058",
     86	[14] = "PM8028",
     87	[15] = "PM8901",
     88	[16] = "PM8950/PM8027",
     89	[17] = "PMI8950/ISL9519",
     90	[18] = "PMK8001/PM8921",
     91	[19] = "PMI8996/PM8018",
     92	[20] = "PM8998/PM8015",
     93	[21] = "PMI8998/PM8014",
     94	[22] = "PM8821",
     95	[23] = "PM8038",
     96	[24] = "PM8005/PM8922",
     97	[25] = "PM8917",
     98	[26] = "PM660L",
     99	[27] = "PM660",
    100	[30] = "PM8150",
    101	[31] = "PM8150L",
    102	[32] = "PM8150B",
    103	[33] = "PMK8002",
    104	[36] = "PM8009",
    105	[38] = "PM8150C",
    106	[41] = "SMB2351",
    107	[47] = "PMK8350",
    108	[48] = "PM8350",
    109	[49] = "PM8350C",
    110	[50] = "PM8350B",
    111	[51] = "PMR735A",
    112	[52] = "PMR735B",
    113	[58] = "PM8450",
    114	[65] = "PM8010",
    115};
    116#endif /* CONFIG_DEBUG_FS */
    117
    118/* Socinfo SMEM item structure */
    119struct socinfo {
    120	__le32 fmt;
    121	__le32 id;
    122	__le32 ver;
    123	char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH];
    124	/* Version 2 */
    125	__le32 raw_id;
    126	__le32 raw_ver;
    127	/* Version 3 */
    128	__le32 hw_plat;
    129	/* Version 4 */
    130	__le32 plat_ver;
    131	/* Version 5 */
    132	__le32 accessory_chip;
    133	/* Version 6 */
    134	__le32 hw_plat_subtype;
    135	/* Version 7 */
    136	__le32 pmic_model;
    137	__le32 pmic_die_rev;
    138	/* Version 8 */
    139	__le32 pmic_model_1;
    140	__le32 pmic_die_rev_1;
    141	__le32 pmic_model_2;
    142	__le32 pmic_die_rev_2;
    143	/* Version 9 */
    144	__le32 foundry_id;
    145	/* Version 10 */
    146	__le32 serial_num;
    147	/* Version 11 */
    148	__le32 num_pmics;
    149	__le32 pmic_array_offset;
    150	/* Version 12 */
    151	__le32 chip_family;
    152	__le32 raw_device_family;
    153	__le32 raw_device_num;
    154	/* Version 13 */
    155	__le32 nproduct_id;
    156	char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH];
    157	/* Version 14 */
    158	__le32 num_clusters;
    159	__le32 ncluster_array_offset;
    160	__le32 num_defective_parts;
    161	__le32 ndefective_parts_array_offset;
    162	/* Version 15 */
    163	__le32 nmodem_supported;
    164};
    165
    166#ifdef CONFIG_DEBUG_FS
    167struct socinfo_params {
    168	u32 raw_device_family;
    169	u32 hw_plat_subtype;
    170	u32 accessory_chip;
    171	u32 raw_device_num;
    172	u32 chip_family;
    173	u32 foundry_id;
    174	u32 plat_ver;
    175	u32 raw_ver;
    176	u32 hw_plat;
    177	u32 fmt;
    178	u32 nproduct_id;
    179	u32 num_clusters;
    180	u32 ncluster_array_offset;
    181	u32 num_defective_parts;
    182	u32 ndefective_parts_array_offset;
    183	u32 nmodem_supported;
    184};
    185
    186struct smem_image_version {
    187	char name[SMEM_IMAGE_VERSION_NAME_SIZE];
    188	char variant[SMEM_IMAGE_VERSION_VARIANT_SIZE];
    189	char pad;
    190	char oem[SMEM_IMAGE_VERSION_OEM_SIZE];
    191};
    192#endif /* CONFIG_DEBUG_FS */
    193
    194struct qcom_socinfo {
    195	struct soc_device *soc_dev;
    196	struct soc_device_attribute attr;
    197#ifdef CONFIG_DEBUG_FS
    198	struct dentry *dbg_root;
    199	struct socinfo_params info;
    200#endif /* CONFIG_DEBUG_FS */
    201};
    202
    203struct soc_id {
    204	unsigned int id;
    205	const char *name;
    206};
    207
    208static const struct soc_id soc_id[] = {
    209	{ 87, "MSM8960" },
    210	{ 109, "APQ8064" },
    211	{ 122, "MSM8660A" },
    212	{ 123, "MSM8260A" },
    213	{ 124, "APQ8060A" },
    214	{ 126, "MSM8974" },
    215	{ 130, "MPQ8064" },
    216	{ 138, "MSM8960AB" },
    217	{ 139, "APQ8060AB" },
    218	{ 140, "MSM8260AB" },
    219	{ 141, "MSM8660AB" },
    220	{ 145, "MSM8626" },
    221	{ 147, "MSM8610" },
    222	{ 153, "APQ8064AB" },
    223	{ 158, "MSM8226" },
    224	{ 159, "MSM8526" },
    225	{ 161, "MSM8110" },
    226	{ 162, "MSM8210" },
    227	{ 163, "MSM8810" },
    228	{ 164, "MSM8212" },
    229	{ 165, "MSM8612" },
    230	{ 166, "MSM8112" },
    231	{ 168, "MSM8225Q" },
    232	{ 169, "MSM8625Q" },
    233	{ 170, "MSM8125Q" },
    234	{ 172, "APQ8064AA" },
    235	{ 178, "APQ8084" },
    236	{ 184, "APQ8074" },
    237	{ 185, "MSM8274" },
    238	{ 186, "MSM8674" },
    239	{ 194, "MSM8974PRO-AC" },
    240	{ 198, "MSM8126" },
    241	{ 199, "APQ8026" },
    242	{ 200, "MSM8926" },
    243	{ 205, "MSM8326" },
    244	{ 206, "MSM8916" },
    245	{ 207, "MSM8994" },
    246	{ 208, "APQ8074PRO-AA" },
    247	{ 209, "APQ8074PRO-AB" },
    248	{ 210, "APQ8074PRO-AC" },
    249	{ 211, "MSM8274PRO-AA" },
    250	{ 212, "MSM8274PRO-AB" },
    251	{ 213, "MSM8274PRO-AC" },
    252	{ 214, "MSM8674PRO-AA" },
    253	{ 215, "MSM8674PRO-AB" },
    254	{ 216, "MSM8674PRO-AC" },
    255	{ 217, "MSM8974PRO-AA" },
    256	{ 218, "MSM8974PRO-AB" },
    257	{ 219, "APQ8028" },
    258	{ 220, "MSM8128" },
    259	{ 221, "MSM8228" },
    260	{ 222, "MSM8528" },
    261	{ 223, "MSM8628" },
    262	{ 224, "MSM8928" },
    263	{ 225, "MSM8510" },
    264	{ 226, "MSM8512" },
    265	{ 233, "MSM8936" },
    266	{ 239, "MSM8939" },
    267	{ 240, "APQ8036" },
    268	{ 241, "APQ8039" },
    269	{ 246, "MSM8996" },
    270	{ 247, "APQ8016" },
    271	{ 248, "MSM8216" },
    272	{ 249, "MSM8116" },
    273	{ 250, "MSM8616" },
    274	{ 251, "MSM8992" },
    275	{ 253, "APQ8094" },
    276	{ 290, "MDM9607" },
    277	{ 291, "APQ8096" },
    278	{ 292, "MSM8998" },
    279	{ 293, "MSM8953" },
    280	{ 296, "MDM8207" },
    281	{ 297, "MDM9207" },
    282	{ 298, "MDM9307" },
    283	{ 299, "MDM9628" },
    284	{ 304, "APQ8053" },
    285	{ 305, "MSM8996SG" },
    286	{ 310, "MSM8996AU" },
    287	{ 311, "APQ8096AU" },
    288	{ 312, "APQ8096SG" },
    289	{ 317, "SDM660" },
    290	{ 318, "SDM630" },
    291	{ 319, "APQ8098" },
    292	{ 321, "SDM845" },
    293	{ 322, "MDM9206" },
    294	{ 323, "IPQ8074" },
    295	{ 324, "SDA660" },
    296	{ 325, "SDM658" },
    297	{ 326, "SDA658" },
    298	{ 327, "SDA630" },
    299	{ 338, "SDM450" },
    300	{ 341, "SDA845" },
    301	{ 342, "IPQ8072" },
    302	{ 343, "IPQ8076" },
    303	{ 344, "IPQ8078" },
    304	{ 345, "SDM636" },
    305	{ 346, "SDA636" },
    306	{ 349, "SDM632" },
    307	{ 350, "SDA632" },
    308	{ 351, "SDA450" },
    309	{ 356, "SM8250" },
    310	{ 375, "IPQ8070" },
    311	{ 376, "IPQ8071" },
    312	{ 389, "IPQ8072A" },
    313	{ 390, "IPQ8074A" },
    314	{ 391, "IPQ8076A" },
    315	{ 392, "IPQ8078A" },
    316	{ 394, "SM6125" },
    317	{ 395, "IPQ8070A" },
    318	{ 396, "IPQ8071A" },
    319	{ 402, "IPQ6018" },
    320	{ 403, "IPQ6028" },
    321	{ 421, "IPQ6000" },
    322	{ 422, "IPQ6010" },
    323	{ 425, "SC7180" },
    324	{ 434, "SM6350" },
    325	{ 439, "SM8350" },
    326	{ 449, "SC8280XP" },
    327	{ 453, "IPQ6005" },
    328	{ 455, "QRB5165" },
    329	{ 457, "SM8450" },
    330	{ 459, "SM7225" },
    331	{ 460, "SA8540P" },
    332	{ 480, "SM8450" },
    333	{ 482, "SM8450" },
    334	{ 487, "SC7280" },
    335};
    336
    337static const char *socinfo_machine(struct device *dev, unsigned int id)
    338{
    339	int idx;
    340
    341	for (idx = 0; idx < ARRAY_SIZE(soc_id); idx++) {
    342		if (soc_id[idx].id == id)
    343			return soc_id[idx].name;
    344	}
    345
    346	return NULL;
    347}
    348
    349#ifdef CONFIG_DEBUG_FS
    350
    351#define QCOM_OPEN(name, _func)						\
    352static int qcom_open_##name(struct inode *inode, struct file *file)	\
    353{									\
    354	return single_open(file, _func, inode->i_private);		\
    355}									\
    356									\
    357static const struct file_operations qcom_ ##name## _ops = {		\
    358	.open = qcom_open_##name,					\
    359	.read = seq_read,						\
    360	.llseek = seq_lseek,						\
    361	.release = single_release,					\
    362}
    363
    364#define DEBUGFS_ADD(info, name)						\
    365	debugfs_create_file(__stringify(name), 0444,			\
    366			    qcom_socinfo->dbg_root,			\
    367			    info, &qcom_ ##name## _ops)
    368
    369
    370static int qcom_show_build_id(struct seq_file *seq, void *p)
    371{
    372	struct socinfo *socinfo = seq->private;
    373
    374	seq_printf(seq, "%s\n", socinfo->build_id);
    375
    376	return 0;
    377}
    378
    379static int qcom_show_pmic_model(struct seq_file *seq, void *p)
    380{
    381	struct socinfo *socinfo = seq->private;
    382	int model = SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_model));
    383
    384	if (model < 0)
    385		return -EINVAL;
    386
    387	if (model < ARRAY_SIZE(pmic_models) && pmic_models[model])
    388		seq_printf(seq, "%s\n", pmic_models[model]);
    389	else
    390		seq_printf(seq, "unknown (%d)\n", model);
    391
    392	return 0;
    393}
    394
    395static int qcom_show_pmic_model_array(struct seq_file *seq, void *p)
    396{
    397	struct socinfo *socinfo = seq->private;
    398	unsigned int num_pmics = le32_to_cpu(socinfo->num_pmics);
    399	unsigned int pmic_array_offset = le32_to_cpu(socinfo->pmic_array_offset);
    400	int i;
    401	void *ptr = socinfo;
    402
    403	ptr += pmic_array_offset;
    404
    405	/* No need for bounds checking, it happened at socinfo_debugfs_init */
    406	for (i = 0; i < num_pmics; i++) {
    407		unsigned int model = SOCINFO_MINOR(get_unaligned_le32(ptr + 2 * i * sizeof(u32)));
    408		unsigned int die_rev = get_unaligned_le32(ptr + (2 * i + 1) * sizeof(u32));
    409
    410		if (model < ARRAY_SIZE(pmic_models) && pmic_models[model])
    411			seq_printf(seq, "%s %u.%u\n", pmic_models[model],
    412				   SOCINFO_MAJOR(die_rev),
    413				   SOCINFO_MINOR(die_rev));
    414		else
    415			seq_printf(seq, "unknown (%d)\n", model);
    416	}
    417
    418	return 0;
    419}
    420
    421static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p)
    422{
    423	struct socinfo *socinfo = seq->private;
    424
    425	seq_printf(seq, "%u.%u\n",
    426		   SOCINFO_MAJOR(le32_to_cpu(socinfo->pmic_die_rev)),
    427		   SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_die_rev)));
    428
    429	return 0;
    430}
    431
    432static int qcom_show_chip_id(struct seq_file *seq, void *p)
    433{
    434	struct socinfo *socinfo = seq->private;
    435
    436	seq_printf(seq, "%s\n", socinfo->chip_id);
    437
    438	return 0;
    439}
    440
    441QCOM_OPEN(build_id, qcom_show_build_id);
    442QCOM_OPEN(pmic_model, qcom_show_pmic_model);
    443QCOM_OPEN(pmic_model_array, qcom_show_pmic_model_array);
    444QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision);
    445QCOM_OPEN(chip_id, qcom_show_chip_id);
    446
    447#define DEFINE_IMAGE_OPS(type)					\
    448static int show_image_##type(struct seq_file *seq, void *p)		  \
    449{								  \
    450	struct smem_image_version *image_version = seq->private;  \
    451	if (image_version->type[0] != '\0')			  \
    452		seq_printf(seq, "%s\n", image_version->type);	  \
    453	return 0;						  \
    454}								  \
    455static int open_image_##type(struct inode *inode, struct file *file)	  \
    456{									  \
    457	return single_open(file, show_image_##type, inode->i_private); \
    458}									  \
    459									  \
    460static const struct file_operations qcom_image_##type##_ops = {	  \
    461	.open = open_image_##type,					  \
    462	.read = seq_read,						  \
    463	.llseek = seq_lseek,						  \
    464	.release = single_release,					  \
    465}
    466
    467DEFINE_IMAGE_OPS(name);
    468DEFINE_IMAGE_OPS(variant);
    469DEFINE_IMAGE_OPS(oem);
    470
    471static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
    472				 struct socinfo *info, size_t info_size)
    473{
    474	struct smem_image_version *versions;
    475	struct dentry *dentry;
    476	size_t size;
    477	int i;
    478	unsigned int num_pmics;
    479	unsigned int pmic_array_offset;
    480
    481	qcom_socinfo->dbg_root = debugfs_create_dir("qcom_socinfo", NULL);
    482
    483	qcom_socinfo->info.fmt = __le32_to_cpu(info->fmt);
    484
    485	debugfs_create_x32("info_fmt", 0444, qcom_socinfo->dbg_root,
    486			   &qcom_socinfo->info.fmt);
    487
    488	switch (qcom_socinfo->info.fmt) {
    489	case SOCINFO_VERSION(0, 15):
    490		qcom_socinfo->info.nmodem_supported = __le32_to_cpu(info->nmodem_supported);
    491
    492		debugfs_create_u32("nmodem_supported", 0444, qcom_socinfo->dbg_root,
    493				   &qcom_socinfo->info.nmodem_supported);
    494		fallthrough;
    495	case SOCINFO_VERSION(0, 14):
    496		qcom_socinfo->info.num_clusters = __le32_to_cpu(info->num_clusters);
    497		qcom_socinfo->info.ncluster_array_offset = __le32_to_cpu(info->ncluster_array_offset);
    498		qcom_socinfo->info.num_defective_parts = __le32_to_cpu(info->num_defective_parts);
    499		qcom_socinfo->info.ndefective_parts_array_offset = __le32_to_cpu(info->ndefective_parts_array_offset);
    500
    501		debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root,
    502				   &qcom_socinfo->info.num_clusters);
    503		debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root,
    504				   &qcom_socinfo->info.ncluster_array_offset);
    505		debugfs_create_u32("num_defective_parts", 0444, qcom_socinfo->dbg_root,
    506				   &qcom_socinfo->info.num_defective_parts);
    507		debugfs_create_u32("ndefective_parts_array_offset", 0444, qcom_socinfo->dbg_root,
    508				   &qcom_socinfo->info.ndefective_parts_array_offset);
    509		fallthrough;
    510	case SOCINFO_VERSION(0, 13):
    511		qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id);
    512
    513		debugfs_create_u32("nproduct_id", 0444, qcom_socinfo->dbg_root,
    514				   &qcom_socinfo->info.nproduct_id);
    515		DEBUGFS_ADD(info, chip_id);
    516		fallthrough;
    517	case SOCINFO_VERSION(0, 12):
    518		qcom_socinfo->info.chip_family =
    519			__le32_to_cpu(info->chip_family);
    520		qcom_socinfo->info.raw_device_family =
    521			__le32_to_cpu(info->raw_device_family);
    522		qcom_socinfo->info.raw_device_num =
    523			__le32_to_cpu(info->raw_device_num);
    524
    525		debugfs_create_x32("chip_family", 0444, qcom_socinfo->dbg_root,
    526				   &qcom_socinfo->info.chip_family);
    527		debugfs_create_x32("raw_device_family", 0444,
    528				   qcom_socinfo->dbg_root,
    529				   &qcom_socinfo->info.raw_device_family);
    530		debugfs_create_x32("raw_device_number", 0444,
    531				   qcom_socinfo->dbg_root,
    532				   &qcom_socinfo->info.raw_device_num);
    533		fallthrough;
    534	case SOCINFO_VERSION(0, 11):
    535		num_pmics = le32_to_cpu(info->num_pmics);
    536		pmic_array_offset = le32_to_cpu(info->pmic_array_offset);
    537		if (pmic_array_offset + 2 * num_pmics * sizeof(u32) <= info_size)
    538			DEBUGFS_ADD(info, pmic_model_array);
    539		fallthrough;
    540	case SOCINFO_VERSION(0, 10):
    541	case SOCINFO_VERSION(0, 9):
    542		qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id);
    543
    544		debugfs_create_u32("foundry_id", 0444, qcom_socinfo->dbg_root,
    545				   &qcom_socinfo->info.foundry_id);
    546		fallthrough;
    547	case SOCINFO_VERSION(0, 8):
    548	case SOCINFO_VERSION(0, 7):
    549		DEBUGFS_ADD(info, pmic_model);
    550		DEBUGFS_ADD(info, pmic_die_rev);
    551		fallthrough;
    552	case SOCINFO_VERSION(0, 6):
    553		qcom_socinfo->info.hw_plat_subtype =
    554			__le32_to_cpu(info->hw_plat_subtype);
    555
    556		debugfs_create_u32("hardware_platform_subtype", 0444,
    557				   qcom_socinfo->dbg_root,
    558				   &qcom_socinfo->info.hw_plat_subtype);
    559		fallthrough;
    560	case SOCINFO_VERSION(0, 5):
    561		qcom_socinfo->info.accessory_chip =
    562			__le32_to_cpu(info->accessory_chip);
    563
    564		debugfs_create_u32("accessory_chip", 0444,
    565				   qcom_socinfo->dbg_root,
    566				   &qcom_socinfo->info.accessory_chip);
    567		fallthrough;
    568	case SOCINFO_VERSION(0, 4):
    569		qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver);
    570
    571		debugfs_create_u32("platform_version", 0444,
    572				   qcom_socinfo->dbg_root,
    573				   &qcom_socinfo->info.plat_ver);
    574		fallthrough;
    575	case SOCINFO_VERSION(0, 3):
    576		qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat);
    577
    578		debugfs_create_u32("hardware_platform", 0444,
    579				   qcom_socinfo->dbg_root,
    580				   &qcom_socinfo->info.hw_plat);
    581		fallthrough;
    582	case SOCINFO_VERSION(0, 2):
    583		qcom_socinfo->info.raw_ver  = __le32_to_cpu(info->raw_ver);
    584
    585		debugfs_create_u32("raw_version", 0444, qcom_socinfo->dbg_root,
    586				   &qcom_socinfo->info.raw_ver);
    587		fallthrough;
    588	case SOCINFO_VERSION(0, 1):
    589		DEBUGFS_ADD(info, build_id);
    590		break;
    591	}
    592
    593	versions = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMAGE_VERSION_TABLE,
    594				 &size);
    595
    596	for (i = 0; i < ARRAY_SIZE(socinfo_image_names); i++) {
    597		if (!socinfo_image_names[i])
    598			continue;
    599
    600		dentry = debugfs_create_dir(socinfo_image_names[i],
    601					    qcom_socinfo->dbg_root);
    602		debugfs_create_file("name", 0444, dentry, &versions[i],
    603				    &qcom_image_name_ops);
    604		debugfs_create_file("variant", 0444, dentry, &versions[i],
    605				    &qcom_image_variant_ops);
    606		debugfs_create_file("oem", 0444, dentry, &versions[i],
    607				    &qcom_image_oem_ops);
    608	}
    609}
    610
    611static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo)
    612{
    613	debugfs_remove_recursive(qcom_socinfo->dbg_root);
    614}
    615#else
    616static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
    617				 struct socinfo *info, size_t info_size)
    618{
    619}
    620static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) {  }
    621#endif /* CONFIG_DEBUG_FS */
    622
    623static int qcom_socinfo_probe(struct platform_device *pdev)
    624{
    625	struct qcom_socinfo *qs;
    626	struct socinfo *info;
    627	size_t item_size;
    628
    629	info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID,
    630			      &item_size);
    631	if (IS_ERR(info)) {
    632		dev_err(&pdev->dev, "Couldn't find socinfo\n");
    633		return PTR_ERR(info);
    634	}
    635
    636	qs = devm_kzalloc(&pdev->dev, sizeof(*qs), GFP_KERNEL);
    637	if (!qs)
    638		return -ENOMEM;
    639
    640	qs->attr.family = "Snapdragon";
    641	qs->attr.machine = socinfo_machine(&pdev->dev,
    642					   le32_to_cpu(info->id));
    643	qs->attr.soc_id = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u",
    644					 le32_to_cpu(info->id));
    645	qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u",
    646					   SOCINFO_MAJOR(le32_to_cpu(info->ver)),
    647					   SOCINFO_MINOR(le32_to_cpu(info->ver)));
    648	if (offsetof(struct socinfo, serial_num) <= item_size)
    649		qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL,
    650							"%u",
    651							le32_to_cpu(info->serial_num));
    652
    653	qs->soc_dev = soc_device_register(&qs->attr);
    654	if (IS_ERR(qs->soc_dev))
    655		return PTR_ERR(qs->soc_dev);
    656
    657	socinfo_debugfs_init(qs, info, item_size);
    658
    659	/* Feed the soc specific unique data into entropy pool */
    660	add_device_randomness(info, item_size);
    661
    662	platform_set_drvdata(pdev, qs);
    663
    664	return 0;
    665}
    666
    667static int qcom_socinfo_remove(struct platform_device *pdev)
    668{
    669	struct qcom_socinfo *qs = platform_get_drvdata(pdev);
    670
    671	soc_device_unregister(qs->soc_dev);
    672
    673	socinfo_debugfs_exit(qs);
    674
    675	return 0;
    676}
    677
    678static struct platform_driver qcom_socinfo_driver = {
    679	.probe = qcom_socinfo_probe,
    680	.remove = qcom_socinfo_remove,
    681	.driver  = {
    682		.name = "qcom-socinfo",
    683	},
    684};
    685
    686module_platform_driver(qcom_socinfo_driver);
    687
    688MODULE_DESCRIPTION("Qualcomm SoCinfo driver");
    689MODULE_LICENSE("GPL v2");
    690MODULE_ALIAS("platform:qcom-socinfo");