From 15d0a17a18bd9ead50a9949575ec524d09ac9b5c Mon Sep 17 00:00:00 2001 From: Huang Yiwei Date: Wed, 6 Apr 2022 17:12:02 +0800 Subject: [PATCH] soc: qcom: Add snapshot of socinfo driver This is a snapshot of the socinfo driver as of msm-5.15 commit <908a517b050d> ("Merge "sched/walt: remove duplicate definitions of rt_task_arrival_time""). Change-Id: Ib969b851ccbfc5651259aba5872575d0fa3994db Signed-off-by: Huang Yiwei --- drivers/soc/qcom/socinfo.c | 1153 +++++++++++++++++++++++++++++++++++- include/soc/qcom/socinfo.h | 32 + 2 files changed, 1155 insertions(+), 30 deletions(-) create mode 100644 include/soc/qcom/socinfo.h diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 6dc0f39c0ec3..d3d70fbbd92c 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2009-2017, 2021 The Linux Foundation. All rights reserved. * Copyright (c) 2017-2019, Linaro Ltd. */ @@ -14,7 +14,8 @@ #include #include #include - +#include +#include #include /* @@ -33,14 +34,21 @@ * SMEM region. */ #define SMEM_HW_SW_BUILD_ID 137 +#define SMEM_IMAGE_VERSION_TABLE 469 + +#define BUILD_ID_LENGTH 32 +#define CHIP_ID_LENGTH 32 +#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 +#define SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE 128 +#define SMEM_IMAGE_VERSION_SIZE 4096 +#define SMEM_IMAGE_VERSION_NAME_SIZE 75 +#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20 +#define SMEM_IMAGE_VERSION_VARIANT_OFFSET 75 +#define SMEM_IMAGE_VERSION_OEM_SIZE 33 +#define SMEM_IMAGE_VERSION_OEM_OFFSET 95 +#define SMEM_IMAGE_VERSION_PARTITION_APPS 10 #ifdef CONFIG_DEBUG_FS -#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 -#define SMEM_IMAGE_VERSION_SIZE 4096 -#define SMEM_IMAGE_VERSION_NAME_SIZE 75 -#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20 -#define SMEM_IMAGE_VERSION_OEM_SIZE 32 - /* * SMEM Image table indices */ @@ -52,7 +60,6 @@ #define SMEM_IMAGE_TABLE_ADSP_INDEX 12 #define SMEM_IMAGE_TABLE_CNSS_INDEX 13 #define SMEM_IMAGE_TABLE_VIDEO_INDEX 14 -#define SMEM_IMAGE_VERSION_TABLE 469 /* * SMEM Image table names @@ -102,11 +109,91 @@ static const char *const pmic_models[] = { [32] = "PM8150B", [33] = "PMK8002", [36] = "PM8009", - [38] = "PM8150C", - [41] = "SMB2351", }; #endif /* CONFIG_DEBUG_FS */ +static uint32_t socinfo_format; + +enum { + HW_PLATFORM_UNKNOWN = 0, + HW_PLATFORM_SURF = 1, + HW_PLATFORM_FFA = 2, + HW_PLATFORM_FLUID = 3, + HW_PLATFORM_SVLTE_FFA = 4, + HW_PLATFORM_SVLTE_SURF = 5, + HW_PLATFORM_MTP_MDM = 7, + HW_PLATFORM_MTP = 8, + HW_PLATFORM_LIQUID = 9, + /* Dragonboard platform id is assigned as 10 in CDT */ + HW_PLATFORM_DRAGON = 10, + HW_PLATFORM_QRD = 11, + HW_PLATFORM_HRD = 13, + HW_PLATFORM_DTV = 14, + HW_PLATFORM_RCM = 21, + HW_PLATFORM_STP = 23, + HW_PLATFORM_SBC = 24, + HW_PLATFORM_HDK = 31, + HW_PLATFORM_ATP = 33, + HW_PLATFORM_IDP = 34, + HW_PLATFORM_INVALID +}; + +static const char * const hw_platform[] = { + [HW_PLATFORM_UNKNOWN] = "Unknown", + [HW_PLATFORM_SURF] = "Surf", + [HW_PLATFORM_FFA] = "FFA", + [HW_PLATFORM_FLUID] = "Fluid", + [HW_PLATFORM_SVLTE_FFA] = "SVLTE_FFA", + [HW_PLATFORM_SVLTE_SURF] = "SLVTE_SURF", + [HW_PLATFORM_MTP_MDM] = "MDM_MTP_NO_DISPLAY", + [HW_PLATFORM_MTP] = "MTP", + [HW_PLATFORM_RCM] = "RCM", + [HW_PLATFORM_LIQUID] = "Liquid", + [HW_PLATFORM_DRAGON] = "Dragon", + [HW_PLATFORM_QRD] = "QRD", + [HW_PLATFORM_HRD] = "HRD", + [HW_PLATFORM_DTV] = "DTV", + [HW_PLATFORM_STP] = "STP", + [HW_PLATFORM_SBC] = "SBC", + [HW_PLATFORM_HDK] = "HDK", + [HW_PLATFORM_ATP] = "ATP", + [HW_PLATFORM_IDP] = "IDP", +}; + +enum { + PLATFORM_SUBTYPE_QRD = 0x0, + PLATFORM_SUBTYPE_SKUAA = 0x1, + PLATFORM_SUBTYPE_SKUF = 0x2, + PLATFORM_SUBTYPE_SKUAB = 0x3, + PLATFORM_SUBTYPE_SKUG = 0x5, + PLATFORM_SUBTYPE_QRD_INVALID, +}; + +static const char * const qrd_hw_platform_subtype[] = { + [PLATFORM_SUBTYPE_QRD] = "QRD", + [PLATFORM_SUBTYPE_SKUAA] = "SKUAA", + [PLATFORM_SUBTYPE_SKUF] = "SKUF", + [PLATFORM_SUBTYPE_SKUAB] = "SKUAB", + [PLATFORM_SUBTYPE_SKUG] = "SKUG", + [PLATFORM_SUBTYPE_QRD_INVALID] = "INVALID", +}; + +enum { + PLATFORM_SUBTYPE_UNKNOWN = 0x0, + PLATFORM_SUBTYPE_CHARM = 0x1, + PLATFORM_SUBTYPE_STRANGE = 0x2, + PLATFORM_SUBTYPE_STRANGE_2A = 0x3, + PLATFORM_SUBTYPE_INVALID, +}; + +static const char * const hw_platform_subtype[] = { + [PLATFORM_SUBTYPE_UNKNOWN] = "Unknown", + [PLATFORM_SUBTYPE_CHARM] = "charm", + [PLATFORM_SUBTYPE_STRANGE] = "strange", + [PLATFORM_SUBTYPE_STRANGE_2A] = "strange_2a", + [PLATFORM_SUBTYPE_INVALID] = "Invalid", +}; + /* Socinfo SMEM item structure */ struct socinfo { __le32 fmt; @@ -153,7 +240,7 @@ struct socinfo { __le32 ndefective_parts_array_offset; /* Version 15 */ __le32 nmodem_supported; -}; +} *socinfo; #ifdef CONFIG_DEBUG_FS struct socinfo_params { @@ -183,9 +270,415 @@ struct smem_image_version { }; #endif /* CONFIG_DEBUG_FS */ +/* sysfs attributes */ +#define ATTR_DEFINE(param) \ + static DEVICE_ATTR(param, (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH ), \ + msm_get_##param, \ + NULL) + +/* Version 2 */ +static uint32_t socinfo_get_raw_id(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 2) ? + le32_to_cpu(socinfo->raw_id) : 0) + : 0; +} + +static uint32_t socinfo_get_raw_version(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 2) ? + le32_to_cpu(socinfo->raw_ver) : 0) + : 0; +} + +/* Version 3 */ +static uint32_t socinfo_get_platform_type(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 3) ? + le32_to_cpu(socinfo->hw_plat) : 0) + : 0; +} + +/* Version 4 */ +static uint32_t socinfo_get_platform_version(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 4) ? + le32_to_cpu(socinfo->plat_ver) : 0) + : 0; +} +/* Version 5 */ +static uint32_t socinfo_get_accessory_chip(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 5) ? + le32_to_cpu(socinfo->accessory_chip) : 0) + : 0; +} + +/* Version 6 */ +static uint32_t socinfo_get_platform_subtype(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 6) ? + le32_to_cpu(socinfo->hw_plat_subtype) : 0) + : 0; +} + +/* Version 7 */ +static int socinfo_get_pmic_model(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 7) ? + le32_to_cpu(socinfo->pmic_model) : 0xFFFFFFFF) + : 0xFFFFFFFF; +} + +static uint32_t socinfo_get_pmic_die_revision(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 7) ? + le32_to_cpu(socinfo->pmic_die_rev) : 0) + : 0; +} + +/* Version 9 */ +static uint32_t socinfo_get_foundry_id(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 9) ? + le32_to_cpu(socinfo->foundry_id) : 0) + : 0; +} + +/* Version 12 */ +static uint32_t socinfo_get_chip_family(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 12) ? + le32_to_cpu(socinfo->chip_family) : 0) + : 0; +} + +static uint32_t socinfo_get_raw_device_family(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 12) ? + le32_to_cpu(socinfo->raw_device_family) : 0) + : 0; +} + +static uint32_t socinfo_get_raw_device_number(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 12) ? + le32_to_cpu(socinfo->raw_device_num) : 0) + : 0; +} + +/* Version 13 */ +static uint32_t socinfo_get_nproduct_id(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 13) ? + le32_to_cpu(socinfo->nproduct_id) : 0) + : 0; +} + +static char *socinfo_get_chip_name(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 13) ? + socinfo->chip_id : "N/A") + : "N/A"; +} + +/* Version 14 */ +static uint32_t socinfo_get_num_clusters(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 14) ? + le32_to_cpu(socinfo->num_clusters) : 0) + : 0; +} + +static uint32_t socinfo_get_ncluster_array_offset(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 14) ? + le32_to_cpu(socinfo->ncluster_array_offset) : 0) + : 0; +} + +static uint32_t socinfo_get_num_defective_parts(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 14) ? + le32_to_cpu(socinfo->num_defective_parts) : 0) + : 0; +} + +static uint32_t socinfo_get_ndefective_parts_array_offset(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 14) ? + le32_to_cpu(socinfo->ndefective_parts_array_offset) : 0) + : 0; +} + +/* Version 15 */ +static uint32_t socinfo_get_nmodem_supported(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 15) ? + le32_to_cpu(socinfo->nmodem_supported) : 0) + : 0; +} + +/* Version 2 */ +static ssize_t +msm_get_raw_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_raw_id()); +} +ATTR_DEFINE(raw_id); + +static ssize_t +msm_get_raw_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_raw_version()); +} +ATTR_DEFINE(raw_version); + +/* Version 3 */ +static ssize_t +msm_get_hw_platform(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + uint32_t hw_type; + + hw_type = socinfo_get_platform_type(); + + return scnprintf(buf, PAGE_SIZE, "%-.32s\n", + hw_platform[hw_type]); +} +ATTR_DEFINE(hw_platform); + +/* Version 4 */ +static ssize_t +msm_get_platform_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_platform_version()); +} +ATTR_DEFINE(platform_version); + +/* Version 5 */ +static ssize_t +msm_get_accessory_chip(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_accessory_chip()); +} +ATTR_DEFINE(accessory_chip); + +/* Version 6 */ +static ssize_t +msm_get_platform_subtype_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + uint32_t hw_subtype; + + hw_subtype = socinfo_get_platform_subtype(); + return scnprintf(buf, PAGE_SIZE, "%u\n", + hw_subtype); +} +ATTR_DEFINE(platform_subtype_id); + +static ssize_t +msm_get_platform_subtype(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + uint32_t hw_subtype; + + hw_subtype = socinfo_get_platform_subtype(); + if (socinfo_get_platform_type() == HW_PLATFORM_QRD) { + if (hw_subtype >= PLATFORM_SUBTYPE_QRD_INVALID) { + pr_err("Invalid hardware platform sub type for qrd found\n"); + hw_subtype = PLATFORM_SUBTYPE_QRD_INVALID; + } + return scnprintf(buf, PAGE_SIZE, "%-.32s\n", + qrd_hw_platform_subtype[hw_subtype]); + } else { + if (hw_subtype >= PLATFORM_SUBTYPE_INVALID) { + pr_err("Invalid hardware platform subtype\n"); + hw_subtype = PLATFORM_SUBTYPE_INVALID; + } + return scnprintf(buf, PAGE_SIZE, "%-.32s\n", + hw_platform_subtype[hw_subtype]); + } +} +ATTR_DEFINE(platform_subtype); + +/* Version 7 */ +static ssize_t +msm_get_pmic_model(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_pmic_model()); +} +ATTR_DEFINE(pmic_model); + +static ssize_t +msm_get_pmic_die_revision(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_pmic_die_revision()); +} +ATTR_DEFINE(pmic_die_revision); + +/* Version 8 (skip) */ +/* Version 9 */ +static ssize_t +msm_get_foundry_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_foundry_id()); +} +ATTR_DEFINE(foundry_id); + +/* Version 11 (skip) */ +/* Version 12 */ +static ssize_t +msm_get_chip_family(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_chip_family()); +} +ATTR_DEFINE(chip_family); + +static ssize_t +msm_get_raw_device_family(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_raw_device_family()); +} +ATTR_DEFINE(raw_device_family); + +static ssize_t +msm_get_raw_device_number(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_raw_device_number()); +} +ATTR_DEFINE(raw_device_number); + +/* Version 13 */ +static ssize_t +msm_get_nproduct_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_nproduct_id()); +} +ATTR_DEFINE(nproduct_id); + +static ssize_t +msm_get_chip_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%-.32s\n", + socinfo_get_chip_name()); +} +ATTR_DEFINE(chip_id); + +/* Version 14 */ +static ssize_t +msm_get_num_clusters(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_num_clusters()); +} +ATTR_DEFINE(num_clusters); + +static ssize_t +msm_get_ncluster_array_offset(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_ncluster_array_offset()); +} +ATTR_DEFINE(ncluster_array_offset); + +static ssize_t +msm_get_num_defective_parts(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_num_defective_parts()); +} +ATTR_DEFINE(num_defective_parts); + +static ssize_t +msm_get_ndefective_parts_array_offset(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_ndefective_parts_array_offset()); +} +ATTR_DEFINE(ndefective_parts_array_offset); + +/* Version 15 */ +static ssize_t +msm_get_nmodem_supported(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_nmodem_supported()); +} +ATTR_DEFINE(nmodem_supported); + struct qcom_socinfo { struct soc_device *soc_dev; struct soc_device_attribute attr; + uint32_t current_image; + struct rw_semaphore current_image_rwsem; #ifdef CONFIG_DEBUG_FS struct dentry *dbg_root; struct socinfo_params info; @@ -283,43 +776,616 @@ static const struct soc_id soc_id[] = { { 319, "APQ8098" }, { 321, "SDM845" }, { 322, "MDM9206" }, - { 323, "IPQ8074" }, { 324, "SDA660" }, { 325, "SDM658" }, { 326, "SDA658" }, { 327, "SDA630" }, { 338, "SDM450" }, { 341, "SDA845" }, - { 342, "IPQ8072" }, - { 343, "IPQ8076" }, - { 344, "IPQ8078" }, { 345, "SDM636" }, { 346, "SDA636" }, { 349, "SDM632" }, { 350, "SDA632" }, { 351, "SDA450" }, { 356, "SM8250" }, - { 375, "IPQ8070" }, - { 376, "IPQ8071" }, - { 389, "IPQ8072A" }, - { 390, "IPQ8074A" }, - { 391, "IPQ8076A" }, - { 392, "IPQ8078A" }, { 394, "SM6125" }, - { 395, "IPQ8070A" }, - { 396, "IPQ8071A" }, { 402, "IPQ6018" }, { 403, "IPQ6028" }, { 421, "IPQ6000" }, { 422, "IPQ6010" }, { 425, "SC7180" }, - { 434, "SM6350" }, { 453, "IPQ6005" }, { 455, "QRB5165" }, - { 457, "SM8450" }, - { 459, "SM7225" }, + { 457, "WAIPIO" }, + { 482, "WAIPIOP" }, + { 518, "KHAJE" }, + { 519, "KALAMA" }, + { 536, "KALAMAP" }, + { 539, "CINDERRU"}, + { 545, "CINDERDU"}, }; +struct soc_sku { + u32 id; + u32 feature_id; + const char *sku_name; +}; + +static const struct soc_sku soc_sku[] = { + { 415, 0, "AB" }, + { 415, 8, "AC" }, +}; + +static ssize_t msm_get_soc_sku(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const char *soc_sku_name = NULL; + int feature_id, idx; + u32 id; + + id = socinfo_get_id(); + feature_id = qcom_smem_get_feature_id(); + + if (feature_id < 0) { + dev_err(dev, "Cannot get feature_id\n"); + return 0; + } + + for (idx = 0; idx < ARRAY_SIZE(soc_sku); idx++) { + if (soc_sku[idx].id == id && + soc_sku[idx].feature_id == feature_id) { + soc_sku_name = soc_sku[idx].sku_name; + break; + } + } + + if (IS_ERR_OR_NULL(soc_sku_name)) { + dev_err(dev, "soc_sku_name not found\n"); + return 0; + } + + return scnprintf(buf, PAGE_SIZE, "%s\n", soc_sku_name); +} +ATTR_DEFINE(soc_sku); + +static struct qcom_socinfo *qsocinfo; +static struct attribute *msm_custom_socinfo_attrs[35]; + +static char *socinfo_get_image_version_base_address(void) +{ + size_t size; + + return qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMAGE_VERSION_TABLE, + &size); +} + +static ssize_t +msm_get_image_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + char *string_address; + + string_address = socinfo_get_image_version_base_address(); + if (IS_ERR_OR_NULL(string_address)) { + pr_err("Failed to get image version base address\n"); + return scnprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "Unknown"); + } + + down_read(&qsocinfo->current_image_rwsem); + string_address += + qsocinfo->current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(&qsocinfo->current_image_rwsem); + return scnprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s\n", + string_address); +} + +static ssize_t +msm_set_image_version(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + char *store_address; + + down_read(&qsocinfo->current_image_rwsem); + if (qsocinfo->current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { + up_read(&qsocinfo->current_image_rwsem); + return count; + } + store_address = socinfo_get_image_version_base_address(); + if (IS_ERR_OR_NULL(store_address)) { + pr_err("Failed to get image version base address\n"); + up_read(&qsocinfo->current_image_rwsem); + return count; + } + store_address += + qsocinfo->current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(&qsocinfo->current_image_rwsem); + scnprintf(store_address, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s", buf); + return count; +} + +static ssize_t +msm_get_image_variant(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + char *string_address; + + string_address = socinfo_get_image_version_base_address(); + if (IS_ERR_OR_NULL(string_address)) { + pr_err("Failed to get image version base address\n"); + return scnprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, + "Unknown"); + } + + down_read(&qsocinfo->current_image_rwsem); + string_address += + qsocinfo->current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(&qsocinfo->current_image_rwsem); + string_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET; + return scnprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s\n", + string_address); +} + +static ssize_t +msm_set_image_variant(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + char *store_address; + + down_read(&qsocinfo->current_image_rwsem); + if (qsocinfo->current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { + up_read(&qsocinfo->current_image_rwsem); + return count; + } + store_address = socinfo_get_image_version_base_address(); + if (IS_ERR_OR_NULL(store_address)) { + pr_err("Failed to get image version base address\n"); + up_read(&qsocinfo->current_image_rwsem); + return count; + } + store_address += + qsocinfo->current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(&qsocinfo->current_image_rwsem); + store_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET; + scnprintf(store_address, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s", buf); + return count; +} + +static ssize_t +msm_get_image_crm_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + char *string_address; + + string_address = socinfo_get_image_version_base_address(); + if (IS_ERR_OR_NULL(string_address)) { + pr_err("Failed to get image version base address\n"); + return scnprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "Unknown"); + } + down_read(&qsocinfo->current_image_rwsem); + string_address += + qsocinfo->current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(&qsocinfo->current_image_rwsem); + string_address += SMEM_IMAGE_VERSION_OEM_OFFSET; + return scnprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.33s\n", + string_address); +} + +static ssize_t +msm_set_image_crm_version(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + char *store_address; + + down_read(&qsocinfo->current_image_rwsem); + if (qsocinfo->current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { + up_read(&qsocinfo->current_image_rwsem); + return count; + } + store_address = socinfo_get_image_version_base_address(); + if (IS_ERR_OR_NULL(store_address)) { + pr_err("Failed to get image version base address\n"); + up_read(&qsocinfo->current_image_rwsem); + return count; + } + store_address += + qsocinfo->current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + up_read(&qsocinfo->current_image_rwsem); + store_address += SMEM_IMAGE_VERSION_OEM_OFFSET; + scnprintf(store_address, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.33s", buf); + return count; +} + +static ssize_t +msm_get_image_number(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + + down_read(&qsocinfo->current_image_rwsem); + ret = scnprintf(buf, PAGE_SIZE, "%d\n", + qsocinfo->current_image); + up_read(&qsocinfo->current_image_rwsem); + return ret; + +} + +static ssize_t +msm_select_image(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret, digit; + + ret = kstrtoint(buf, 10, &digit); + if (ret) + return ret; + down_write(&qsocinfo->current_image_rwsem); + if (digit >= 0 && digit < SMEM_IMAGE_VERSION_BLOCKS_COUNT) + qsocinfo->current_image = digit; + else + qsocinfo->current_image = 0; + up_write(&qsocinfo->current_image_rwsem); + return count; +} + +static ssize_t +msm_get_images(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + int image; + char *image_address; + + image_address = socinfo_get_image_version_base_address(); + if (IS_ERR_OR_NULL(image_address)) + return scnprintf(buf, PAGE_SIZE, "Unavailable\n"); + + *buf = '\0'; + for (image = 0; image < SMEM_IMAGE_VERSION_BLOCKS_COUNT; image++) { + if (*image_address == '\0') { + image_address += SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + continue; + } + + pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d:\n", + image); + pos += scnprintf(buf + pos, PAGE_SIZE - pos, + "\tCRM:\t\t%-.75s\n", image_address); + pos += scnprintf(buf + pos, PAGE_SIZE - pos, + "\tVariant:\t%-.20s\n", + image_address + SMEM_IMAGE_VERSION_VARIANT_OFFSET); + pos += scnprintf(buf + pos, PAGE_SIZE - pos, + "\tVersion:\t%-.33s\n", + image_address + SMEM_IMAGE_VERSION_OEM_OFFSET); + + image_address += SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + } + + return pos; +} + +static struct device_attribute image_version = +__ATTR(image_version, 0644, + msm_get_image_version, msm_set_image_version); + +static struct device_attribute image_variant = +__ATTR(image_variant, 0644, + msm_get_image_variant, msm_set_image_variant); + +static struct device_attribute image_crm_version = +__ATTR(image_crm_version, 0644, + msm_get_image_crm_version, msm_set_image_crm_version); + +static struct device_attribute select_image = +__ATTR(select_image, 0644, + msm_get_image_number, msm_select_image); + +static struct device_attribute images = +__ATTR(images, 0444, msm_get_images, NULL); + + +static umode_t soc_info_attribute(struct kobject *kobj, + struct attribute *attr, + int index) +{ + return attr->mode; +} + +static const struct attribute_group custom_soc_attr_group = { + .attrs = msm_custom_socinfo_attrs, + .is_visible = soc_info_attribute, +}; + +static void socinfo_populate_sysfs(struct qcom_socinfo *qcom_socinfo) +{ + int i = 0; + + switch (socinfo_format) { + case SOCINFO_VERSION(0, 15): + msm_custom_socinfo_attrs[i++] = &dev_attr_soc_sku.attr; + msm_custom_socinfo_attrs[i++] = &dev_attr_nmodem_supported.attr; + case SOCINFO_VERSION(0, 14): + msm_custom_socinfo_attrs[i++] = &dev_attr_num_clusters.attr; + msm_custom_socinfo_attrs[i++] = + &dev_attr_ncluster_array_offset.attr; + msm_custom_socinfo_attrs[i++] = + &dev_attr_num_defective_parts.attr; + msm_custom_socinfo_attrs[i++] = + &dev_attr_ndefective_parts_array_offset.attr; + case SOCINFO_VERSION(0, 13): + msm_custom_socinfo_attrs[i++] = &dev_attr_nproduct_id.attr; + msm_custom_socinfo_attrs[i++] = &dev_attr_chip_id.attr; + case SOCINFO_VERSION(0, 12): + msm_custom_socinfo_attrs[i++] = &dev_attr_chip_family.attr; + msm_custom_socinfo_attrs[i++] = + &dev_attr_raw_device_family.attr; + msm_custom_socinfo_attrs[i++] = + &dev_attr_raw_device_number.attr; + case SOCINFO_VERSION(0, 11): + case SOCINFO_VERSION(0, 10): + case SOCINFO_VERSION(0, 9): + msm_custom_socinfo_attrs[i++] = &dev_attr_foundry_id.attr; + case SOCINFO_VERSION(0, 8): + case SOCINFO_VERSION(0, 7): + msm_custom_socinfo_attrs[i++] = &dev_attr_pmic_model.attr; + msm_custom_socinfo_attrs[i++] = + &dev_attr_pmic_die_revision.attr; + case SOCINFO_VERSION(0, 6): + msm_custom_socinfo_attrs[i++] = + &dev_attr_platform_subtype_id.attr; + msm_custom_socinfo_attrs[i++] = &dev_attr_platform_subtype.attr; + case SOCINFO_VERSION(0, 5): + msm_custom_socinfo_attrs[i++] = &dev_attr_accessory_chip.attr; + case SOCINFO_VERSION(0, 4): + msm_custom_socinfo_attrs[i++] = &dev_attr_platform_version.attr; + case SOCINFO_VERSION(0, 3): + msm_custom_socinfo_attrs[i++] = &dev_attr_hw_platform.attr; + case SOCINFO_VERSION(0, 2): + msm_custom_socinfo_attrs[i++] = &dev_attr_raw_id.attr; + msm_custom_socinfo_attrs[i++] = &dev_attr_raw_version.attr; + case SOCINFO_VERSION(0, 1): + break; + default: + pr_err("Unknown socinfo format: v%u.%u\n", + SOCINFO_MAJOR(socinfo_format), + SOCINFO_MINOR(socinfo_format)); + break; + } + + msm_custom_socinfo_attrs[i++] = &image_version.attr; + msm_custom_socinfo_attrs[i++] = &image_variant.attr; + msm_custom_socinfo_attrs[i++] = &image_crm_version.attr; + msm_custom_socinfo_attrs[i++] = &select_image.attr; + msm_custom_socinfo_attrs[i++] = &images.attr; + msm_custom_socinfo_attrs[i++] = NULL; + qcom_socinfo->attr.custom_attr_group = &custom_soc_attr_group; +} + +static void socinfo_print(void) +{ + uint32_t f_maj = SOCINFO_MAJOR(socinfo_format); + uint32_t f_min = SOCINFO_MINOR(socinfo_format); + uint32_t v_maj = SOCINFO_MAJOR(le32_to_cpu(socinfo->ver)); + uint32_t v_min = SOCINFO_MINOR(le32_to_cpu(socinfo->ver)); + + switch (socinfo_format) { + case SOCINFO_VERSION(0, 1): + pr_info("v%u.%u, id=%u, ver=%u.%u\n", + f_maj, f_min, socinfo->id, v_maj, v_min); + break; + case SOCINFO_VERSION(0, 2): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver); + break; + case SOCINFO_VERSION(0, 3): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat); + break; + case SOCINFO_VERSION(0, 4): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver); + break; + case SOCINFO_VERSION(0, 5): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip); + break; + case SOCINFO_VERSION(0, 6): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u hw_plat_subtype=%u\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip, + socinfo->hw_plat_subtype); + break; + case SOCINFO_VERSION(0, 7): + case SOCINFO_VERSION(0, 8): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, " \ + "hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, " \ + "hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip, + socinfo->hw_plat_subtype, + socinfo->pmic_model, + socinfo->pmic_die_rev); + break; + case SOCINFO_VERSION(0, 9): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, " \ + "hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, " \ + "hw_plat_subtype=%u, pmic_model=%u, " \ + "pmic_die_revision=%u foundry_id=%u\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip, + socinfo->hw_plat_subtype, + socinfo->pmic_model, + socinfo->pmic_die_rev, + socinfo->foundry_id); + break; + case SOCINFO_VERSION(0, 10): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u," \ + "hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, " \ + "hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u " \ + "foundry_id=%u > serial_number=%u\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip, + socinfo->hw_plat_subtype, + socinfo->pmic_model, + socinfo->pmic_die_rev, + socinfo->foundry_id, + socinfo->serial_num); + break; + case SOCINFO_VERSION(0, 11): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u," \ + "hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, " \ + "hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u " \ + "foundry_id=%u serial_number=%u > num_pmics=%u\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip, + socinfo->hw_plat_subtype, + socinfo->pmic_model, + socinfo->pmic_die_rev, + socinfo->foundry_id, + socinfo->serial_num, + socinfo->num_pmics); + break; + case SOCINFO_VERSION(0, 12): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, " \ + "hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, " \ + "hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u " \ + "foundry_id=%u serial_number=%u > num_pmics=%u " \ + "chip_family=0x%x raw_device_family=0x%x raw_device_number=0x%x\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip, + socinfo->hw_plat_subtype, + socinfo->pmic_model, + socinfo->pmic_die_rev, + socinfo->foundry_id, + socinfo->serial_num, + socinfo->num_pmics, + socinfo->chip_family, + socinfo->raw_device_family, + socinfo->raw_device_num); + break; + case SOCINFO_VERSION(0, 13): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u," \ + "hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, " \ + "hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u " \ + "foundry_id=%u serial_number=%u > num_pmics=%u chip_family=0x%x " \ + "raw_device_family=0x%x raw_device_number=0x%x nproduct_id=0x%x\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip, + socinfo->hw_plat_subtype, + socinfo->pmic_model, + socinfo->pmic_die_rev, + socinfo->foundry_id, + socinfo->serial_num, + socinfo->num_pmics, + socinfo->chip_family, + socinfo->raw_device_family, + socinfo->raw_device_num, + socinfo->nproduct_id); + break; + case SOCINFO_VERSION(0, 14): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u," \ + "hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, " \ + "hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u " \ + "foundry_id=%u serial_number=%u > num_pmics=%u chip_family=0x%x " \ + "raw_device_family=0x%x raw_device_number=0x%x nproduct_id=0x%x " \ + "num_clusters=0x%x ncluster_array_offset=0x%x " \ + "num_defective_parts=0x%x ndefective_parts_array_offset=0x%x\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip, + socinfo->hw_plat_subtype, + socinfo->pmic_model, + socinfo->pmic_die_rev, + socinfo->foundry_id, + socinfo->serial_num, + socinfo->num_pmics, + socinfo->chip_family, + socinfo->raw_device_family, + socinfo->raw_device_num, + socinfo->nproduct_id, + socinfo->num_clusters, + socinfo->ncluster_array_offset, + socinfo->num_defective_parts, + socinfo->ndefective_parts_array_offset); + break; + case SOCINFO_VERSION(0, 15): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u," \ + "hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, " \ + "hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u " \ + "foundry_id=%u serial_number=%u > num_pmics=%u chip_family=0x%x " \ + "raw_device_family=0x%x raw_device_number=0x%x nproduct_id=0x%x " \ + "num_clusters=0x%x ncluster_array_offset=0x%x " \ + "num_defective_parts=0x%x ndefective_parts_array_offset=0x%x " \ + "> \nmodem_supported=0x%x\n", + f_maj, f_min, socinfo->id, v_maj, v_min, + socinfo->raw_id, socinfo->raw_ver, + socinfo->hw_plat, + socinfo->plat_ver, + socinfo->accessory_chip, + socinfo->hw_plat_subtype, + socinfo->pmic_model, + socinfo->pmic_die_rev, + socinfo->foundry_id, + socinfo->serial_num, + socinfo->num_pmics, + socinfo->chip_family, + socinfo->raw_device_family, + socinfo->raw_device_num, + socinfo->nproduct_id, + socinfo->num_clusters, + socinfo->ncluster_array_offset, + socinfo->num_defective_parts, + socinfo->ndefective_parts_array_offset, + socinfo->nmodem_supported); + break; + default: + pr_err("Unknown format found: v%u.%u\n", f_maj, f_min); + break; + } +} + static const char *socinfo_machine(struct device *dev, unsigned int id) { int idx; @@ -332,6 +1398,26 @@ static const char *socinfo_machine(struct device *dev, unsigned int id) return NULL; } +uint32_t socinfo_get_id(void) +{ + return (socinfo) ? le32_to_cpu(socinfo->id) : 0; +} +EXPORT_SYMBOL(socinfo_get_id); + +const char *socinfo_get_id_string(void) +{ + uint32_t id = socinfo_get_id(); + + return socinfo_machine(NULL, id); +} +EXPORT_SYMBOL(socinfo_get_id_string); + +uint32_t socinfo_get_serial_number(void) +{ + return (socinfo) ? le32_to_cpu(socinfo->serial_num) : 0; +} +EXPORT_SYMBOL(socinfo_get_serial_number); + #ifdef CONFIG_DEBUG_FS #define QCOM_OPEN(name, _func) \ @@ -619,6 +1705,9 @@ static int qcom_socinfo_probe(struct platform_device *pdev) return PTR_ERR(info); } + socinfo_format = le32_to_cpu(info->fmt); + socinfo = info; + qs = devm_kzalloc(&pdev->dev, sizeof(*qs), GFP_KERNEL); if (!qs) return -ENOMEM; @@ -631,10 +1720,14 @@ static int qcom_socinfo_probe(struct platform_device *pdev) qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u", SOCINFO_MAJOR(le32_to_cpu(info->ver)), SOCINFO_MINOR(le32_to_cpu(info->ver))); + qs->attr.soc_id = kasprintf(GFP_KERNEL, "%d", socinfo_get_id()); if (offsetof(struct socinfo, serial_num) <= item_size) - qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL, - "%u", - le32_to_cpu(info->serial_num)); + qs->attr.serial_number = kasprintf(GFP_KERNEL, "%u", socinfo_get_serial_number()); + + qsocinfo = qs; + init_rwsem(&qs->current_image_rwsem); + socinfo_populate_sysfs(qs); + socinfo_print(); qs->soc_dev = soc_device_register(&qs->attr); if (IS_ERR(qs->soc_dev)) diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h new file mode 100644 index 000000000000..3f458a511322 --- /dev/null +++ b/include/soc/qcom/socinfo.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + */ + +#ifndef __SOC_QCOM_SOCINFO_H__ +#define __SOC_QCOM_SOCINFO_H__ + +#include + +#if IS_ENABLED(CONFIG_QCOM_SOCINFO) +uint32_t socinfo_get_id(void); +uint32_t socinfo_get_serial_number(void); +const char *socinfo_get_id_string(void); +#else +static inline uint32_t socinfo_get_id(void) +{ + return 0; +} + +static inline uint32_t socinfo_get_serial_number(void) +{ + return 0; +} + +static inline const char *socinfo_get_id_string(void) +{ + return "N/A"; +} +#endif /* CONFIG_QCOM_SOCINFO */ + +#endif /* __SOC_QCOM_SOCINFO_H__ */