android_kernel_xiaomi_sm8350/drivers/soc/qcom/socinfo.c
Saranya R c7fecf0481 soc: qcom: Add BLAIR-LITE SoC information to socinfo
Add BLAIR-LITE SoC information to socinfo.

Change-Id: I334a80508434ea3aaa972ecb0e2b72586e81dfca
Signed-off-by: Saranya R <quic_sarar@quicinc.com>
2024-01-10 17:38:02 +05:30

1443 lines
38 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2009-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, Linaro Ltd.
*/
#include <linux/err.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>
#include <linux/string.h>
#include <linux/sys_soc.h>
#include <linux/types.h>
#include <soc/qcom/socinfo.h>
/*
* SoC version type with major number in the upper 16 bits and minor
* number in the lower 16 bits.
*/
#define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff)
#define SOCINFO_MINOR(ver) ((ver) & 0xffff)
#define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff))
#define SMEM_SOCINFO_BUILD_ID_LENGTH 32
#define SMEM_SOCINFO_CHIP_ID_LENGTH 32
/*
* SMEM item id, used to acquire handles to respective
* SMEM region.
*/
#define SMEM_HW_SW_BUILD_ID 137
#define SMEM_IMAGE_VERSION_TABLE 469
static uint32_t socinfo_format;
static const char *sku;
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_ADP = 25,
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_ADP] = "ADP",
[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",
};
static const char * const adp_hw_platform_subtype[] = {
[0] = "ADP",
};
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",
};
enum {
/* External SKU */
SKU_UNKNOWN = 0x0,
SKU_AA = 0x1,
SKU_AB = 0x2,
SKU_AC = 0x3,
SKU_AD = 0x4,
SKU_AE = 0x5,
SKU_AF = 0x6,
SKU_EXT_RESERVE,
/* Internal SKU */
SKU_Y0 = 0xf1,
SKU_Y1 = 0xf2,
SKU_Y2 = 0xf3,
SKU_Y3 = 0xf4,
SKU_Y4 = 0xf5,
SKU_Y5 = 0xf6,
SKU_Y6 = 0xf7,
SKU_Y7 = 0xf8,
SKU_INT_RESERVE,
};
static const char * const hw_platform_esku[] = {
[SKU_UNKNOWN] = "Unknown",
[SKU_AA] = "AA",
[SKU_AB] = "AB",
[SKU_AC] = "AC",
[SKU_AD] = "AD",
[SKU_AE] = "AE",
[SKU_AF] = "AF",
};
#define SKU_INT_MASK 0x0f
static const char * const hw_platform_isku[] = {
[SKU_Y0 & SKU_INT_MASK] = "Y0",
[SKU_Y1 & SKU_INT_MASK] = "Y1",
[SKU_Y2 & SKU_INT_MASK] = "Y2",
[SKU_Y3 & SKU_INT_MASK] = "Y3",
[SKU_Y4 & SKU_INT_MASK] = "Y4",
[SKU_Y5 & SKU_INT_MASK] = "Y5",
[SKU_Y6 & SKU_INT_MASK] = "Y6",
[SKU_Y7 & SKU_INT_MASK] = "Y7",
};
/* Socinfo SMEM item structure */
static struct socinfo {
__le32 fmt;
__le32 id;
__le32 ver;
char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH];
/* Version 2 */
__le32 raw_id;
__le32 raw_ver;
/* Version 3 */
__le32 hw_plat;
/* Version 4 */
__le32 plat_ver;
/* Version 5 */
__le32 accessory_chip;
/* Version 6 */
__le32 hw_plat_subtype;
/* Version 7 */
__le32 pmic_model;
__le32 pmic_die_rev;
/* Version 8 */
__le32 pmic_model_1;
__le32 pmic_die_rev_1;
__le32 pmic_model_2;
__le32 pmic_die_rev_2;
/* Version 9 */
__le32 foundry_id;
/* Version 10 */
__le32 serial_num;
/* Version 11 */
__le32 num_pmics;
__le32 pmic_array_offset;
/* Version 12 */
__le32 chip_family;
__le32 raw_device_family;
__le32 raw_device_num;
/* Version 13 */
__le32 nproduct_id;
char chip_name[SMEM_SOCINFO_CHIP_ID_LENGTH];
/* Version 14 */
__le32 num_clusters;
__le32 ncluster_array_offset;
__le32 num_defective_parts;
__le32 ndefective_parts_array_offset;
/* Version 15 */
__le32 nmodem_supported;
/* Version 16 */
__le32 esku;
__le32 nproduct_code;
__le32 npartnamemap_offset;
__le32 nnum_partname_mapping;
} *socinfo;
/* sysfs attributes */
#define ATTR_DEFINE(param) \
static DEVICE_ATTR(param, 0644, \
msm_get_##param, \
NULL)
#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
int softsku_idx;
module_param_named(softsku_idx, softsku_idx, int, 0644);
/* 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 10 */
uint32_t socinfo_get_serial_number(void)
{
return socinfo ?
(socinfo_format >= SOCINFO_VERSION(0, 10) ?
le32_to_cpu(socinfo->serial_num) : 0)
: 0;
}
EXPORT_SYMBOL(socinfo_get_serial_number);
/* 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_name : "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 16 */
static uint32_t socinfo_get_eskuid(void)
{
return socinfo ?
(socinfo_format >= SOCINFO_VERSION(0, 16) ?
le32_to_cpu(socinfo->esku) : 0)
: 0;
}
static const char *socinfo_get_esku_mapping(void)
{
uint32_t id = socinfo_get_eskuid();
if (id > SKU_UNKNOWN && id < SKU_EXT_RESERVE)
return hw_platform_esku[id];
else if (id >= SKU_Y0 && id < SKU_INT_RESERVE)
return hw_platform_isku[id & SKU_INT_MASK];
return NULL;
}
static uint32_t socinfo_get_nproduct_code(void)
{
return socinfo ?
(socinfo_format >= SOCINFO_VERSION(0, 16) ?
le32_to_cpu(socinfo->nproduct_code) : 0)
: 0;
}
/* Version 2 */
static ssize_t
msm_get_raw_id(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return snprintf(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 snprintf(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 snprintf(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 snprintf(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 snprintf(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 snprintf(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 snprintf(buf, PAGE_SIZE, "%-.32s\n",
qrd_hw_platform_subtype[hw_subtype]);
} else if (socinfo_get_platform_type() == HW_PLATFORM_ADP) {
return scnprintf(buf, PAGE_SIZE, "%-.32s\n",
adp_hw_platform_subtype[0]);
} else {
if (hw_subtype >= PLATFORM_SUBTYPE_INVALID) {
pr_err("Invalid hardware platform subtype\n");
hw_subtype = PLATFORM_SUBTYPE_INVALID;
}
return snprintf(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 snprintf(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 snprintf(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 snprintf(buf, PAGE_SIZE, "%u\n",
socinfo_get_foundry_id());
}
ATTR_DEFINE(foundry_id);
/* Version 10 */
static ssize_t
msm_get_serial_number(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%u\n",
socinfo_get_serial_number());
}
ATTR_DEFINE(serial_number);
/* Version 11 (skip) */
/* Version 12 */
static ssize_t
msm_get_chip_family(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return snprintf(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 snprintf(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 snprintf(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 snprintf(buf, PAGE_SIZE, "0x%x\n",
socinfo_get_nproduct_id());
}
ATTR_DEFINE(nproduct_id);
static ssize_t
msm_get_chip_name(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%-.32s\n",
socinfo_get_chip_name());
}
ATTR_DEFINE(chip_name);
/* Version 14 */
static ssize_t
msm_get_num_clusters(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return snprintf(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 snprintf(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 snprintf(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 snprintf(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 snprintf(buf, PAGE_SIZE, "0x%x\n",
socinfo_get_nmodem_supported());
}
ATTR_DEFINE(nmodem_supported);
/* Version 16 */
static ssize_t
msm_get_sku(struct device *dev,
struct device_attribute *attr,
char *buf)
{
return sysfs_emit(buf, "%s\n", sku ? sku : "Unknown");
}
ATTR_DEFINE(sku);
static ssize_t
msm_get_esku(struct device *dev,
struct device_attribute *attr,
char *buf)
{
const char *esku = socinfo_get_esku_mapping();
return sysfs_emit(buf, "%s\n", esku ? esku : "Unknown");
}
ATTR_DEFINE(esku);
struct qcom_socinfo {
struct soc_device *soc_dev;
struct soc_device_attribute attr;
uint32_t current_image;
struct rw_semaphore current_image_rwsem;
};
struct soc_id {
unsigned int id;
const char *name;
};
static const struct soc_id soc_id[] = {
{ 87, "MSM8960" },
{ 109, "APQ8064" },
{ 122, "MSM8660A" },
{ 123, "MSM8260A" },
{ 124, "APQ8060A" },
{ 126, "MSM8974" },
{ 130, "MPQ8064" },
{ 138, "MSM8960AB" },
{ 139, "APQ8060AB" },
{ 140, "MSM8260AB" },
{ 141, "MSM8660AB" },
{ 178, "APQ8084" },
{ 184, "APQ8074" },
{ 185, "MSM8274" },
{ 186, "MSM8674" },
{ 194, "MSM8974PRO" },
{ 206, "MSM8916" },
{ 208, "APQ8074-AA" },
{ 209, "APQ8074-AB" },
{ 210, "APQ8074PRO" },
{ 211, "MSM8274-AA" },
{ 212, "MSM8274-AB" },
{ 213, "MSM8274PRO" },
{ 214, "MSM8674-AA" },
{ 215, "MSM8674-AB" },
{ 216, "MSM8674PRO" },
{ 217, "MSM8974-AA" },
{ 218, "MSM8974-AB" },
{ 246, "MSM8996" },
{ 247, "APQ8016" },
{ 248, "MSM8216" },
{ 249, "MSM8116" },
{ 250, "MSM8616" },
{ 291, "APQ8096" },
{ 305, "MSM8996SG" },
{ 310, "MSM8996AU" },
{ 311, "APQ8096AU" },
{ 312, "APQ8096SG" },
{ 356, "KONA" },
{ 362, "SA8155" },
{ 367, "SA8155P" },
{ 377, "SA6155P" },
{ 384, "SA6155"},
{ 405, "SA8195P" },
{ 415, "LAHAINA" },
{ 439, "LAHAINAP" },
{ 449, "SC_DIREWOLF"},
{ 456, "LAHAINA-ATP" },
{ 460, "SA_DIREWOLF_IVI"},
{ 461, "SA_DIREWOLF_ADAS"},
{ 501, "SM8325" },
{ 502, "SM8325P" },
{ 450, "SHIMA" },
{ 454, "HOLI" },
{ 507, "BLAIR" },
{ 578, "BLAIR-LITE" },
{ 565, "BLAIRP" },
{ 628, "BLAIRP-XR" },
{ 647, "BLAIRP-LTE" },
{ 486, "MONACO" },
{ 458, "SDXLEMUR" },
{ 483, "SDXLEMUR-SD"},
{ 509, "SDXLEMUR-LITE"},
{ 475, "YUPIK" },
{ 484, "SDXNIGHTJAR" },
{ 441, "SCUBA" },
{ 497, "YUPIK-IOT" },
{ 498, "YUPIKP-IOT" },
{ 499, "YUPIKP" },
{ 515, "YUPIK-LTE" },
{ 575, "KATMAI" },
{ 576, "KATMAIP" },
};
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 snprintf(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 snprintf(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);
snprintf(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 snprintf(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 snprintf(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;
snprintf(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 snprintf(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 snprintf(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;
snprintf(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 = snprintf(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 snprintf(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 += snprintf(buf + pos, PAGE_SIZE - pos, "%d:\n",
image);
pos += snprintf(buf + pos, PAGE_SIZE - pos,
"\tCRM:\t\t%-.75s\n", image_address);
pos += snprintf(buf + pos, PAGE_SIZE - pos,
"\tVariant:\t%-.20s\n",
image_address + SMEM_IMAGE_VERSION_VARIANT_OFFSET);
pos += snprintf(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, 16):
msm_custom_socinfo_attrs[i++] = &dev_attr_sku.attr;
msm_custom_socinfo_attrs[i++] = &dev_attr_esku.attr;
case SOCINFO_VERSION(0, 15):
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_name.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):
msm_custom_socinfo_attrs[i++] = &dev_attr_serial_number.attr;
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;
case SOCINFO_VERSION(0, 16):
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 sku=%s\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,
sku ? sku : "Unknown");
break;
default:
pr_err("Unknown format found: v%u.%u\n", f_maj, f_min);
break;
}
}
static const char *socinfo_machine(unsigned int id)
{
int idx;
for (idx = 0; idx < ARRAY_SIZE(soc_id); idx++) {
if (soc_id[idx].id == id)
return soc_id[idx].name;
}
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(id);
}
EXPORT_SYMBOL(socinfo_get_id_string);
static int qcom_socinfo_probe(struct platform_device *pdev)
{
struct qcom_socinfo *qs;
struct socinfo *info;
size_t item_size;
const char *machine, *esku;
info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID,
&item_size);
if (IS_ERR(info)) {
dev_err(&pdev->dev, "Couldn't find socinfo\n");
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;
qs->attr.machine = socinfo_machine(le32_to_cpu(info->id));
qs->attr.family = "Snapdragon";
qs->attr.soc_id = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u",
le32_to_cpu(info->id));
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 (socinfo_format >= SOCINFO_VERSION(0, 16)) {
machine = socinfo_machine(le32_to_cpu(info->id));
esku = socinfo_get_esku_mapping();
if (machine && esku)
sku = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s-%u-%s",
machine, socinfo_get_nproduct_code(), esku);
}
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))
return PTR_ERR(qs->soc_dev);
/* Feed the soc specific unique data into entropy pool */
add_device_randomness(info, item_size);
platform_set_drvdata(pdev, qs);
return 0;
}
static int qcom_socinfo_remove(struct platform_device *pdev)
{
struct qcom_socinfo *qs = platform_get_drvdata(pdev);
soc_device_unregister(qs->soc_dev);
return 0;
}
static struct platform_driver qcom_socinfo_driver = {
.probe = qcom_socinfo_probe,
.remove = qcom_socinfo_remove,
.driver = {
.name = "qcom-socinfo",
},
};
module_platform_driver(qcom_socinfo_driver);
MODULE_DESCRIPTION("Qualcomm SoCinfo driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:qcom-socinfo");