/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ /* * SOC Info Routines * */ #include #include #include #include #include #include #include #include #include #include #include #include "boot_stats.h" #define BUILD_ID_LENGTH 32 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 = 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_INVALID }; const char *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] = "MTP", [HW_PLATFORM_LIQUID] = "Liquid", [HW_PLATFORM_DRAGON] = "Dragon", [HW_PLATFORM_QRD] = "QRD", [HW_PLATFORM_HRD] = "HRD", [HW_PLATFORM_DTV] = "DTV", }; enum { ACCESSORY_CHIP_UNKNOWN = 0, ACCESSORY_CHIP_CHARM = 58, }; enum { PLATFORM_SUBTYPE_UNKNOWN = 0x0, PLATFORM_SUBTYPE_CHARM = 0x1, PLATFORM_SUBTYPE_STRANGE = 0x2, PLATFORM_SUBTYPE_STRANGE_2A = 0x3, PLATFORM_SUBTYPE_INVALID, }; const char *hw_platform_subtype[] = { [PLATFORM_SUBTYPE_UNKNOWN] = "Unknown", [PLATFORM_SUBTYPE_CHARM] = "charm", [PLATFORM_SUBTYPE_STRANGE] = "strange", [PLATFORM_SUBTYPE_STRANGE_2A] = "strange_2a," }; /* Used to parse shared memory. Must match the modem. */ struct socinfo_v1 { uint32_t format; uint32_t id; uint32_t version; char build_id[BUILD_ID_LENGTH]; }; struct socinfo_v2 { struct socinfo_v1 v1; /* only valid when format==2 */ uint32_t raw_id; uint32_t raw_version; }; struct socinfo_v3 { struct socinfo_v2 v2; /* only valid when format==3 */ uint32_t hw_platform; }; struct socinfo_v4 { struct socinfo_v3 v3; /* only valid when format==4 */ uint32_t platform_version; }; struct socinfo_v5 { struct socinfo_v4 v4; /* only valid when format==5 */ uint32_t accessory_chip; }; struct socinfo_v6 { struct socinfo_v5 v5; /* only valid when format==6 */ uint32_t hw_platform_subtype; }; struct socinfo_v7 { struct socinfo_v6 v6; /* only valid when format==7 */ uint32_t pmic_model; uint32_t pmic_die_revision; }; struct socinfo_v8 { struct socinfo_v7 v7; /* only valid when format==8*/ uint32_t pmic_model_1; uint32_t pmic_die_revision_1; uint32_t pmic_model_2; uint32_t pmic_die_revision_2; }; static union { struct socinfo_v1 v1; struct socinfo_v2 v2; struct socinfo_v3 v3; struct socinfo_v4 v4; struct socinfo_v5 v5; struct socinfo_v6 v6; struct socinfo_v7 v7; struct socinfo_v8 v8; } *socinfo; static enum msm_cpu cpu_of_id[] = { /* 7x01 IDs */ [1] = MSM_CPU_7X01, [16] = MSM_CPU_7X01, [17] = MSM_CPU_7X01, [18] = MSM_CPU_7X01, [19] = MSM_CPU_7X01, [23] = MSM_CPU_7X01, [25] = MSM_CPU_7X01, [26] = MSM_CPU_7X01, [32] = MSM_CPU_7X01, [33] = MSM_CPU_7X01, [34] = MSM_CPU_7X01, [35] = MSM_CPU_7X01, /* 7x25 IDs */ [20] = MSM_CPU_7X25, [21] = MSM_CPU_7X25, /* 7225 */ [24] = MSM_CPU_7X25, /* 7525 */ [27] = MSM_CPU_7X25, /* 7625 */ [39] = MSM_CPU_7X25, [40] = MSM_CPU_7X25, [41] = MSM_CPU_7X25, [42] = MSM_CPU_7X25, [62] = MSM_CPU_7X25, /* 7625-1 */ [63] = MSM_CPU_7X25, /* 7225-1 */ [66] = MSM_CPU_7X25, /* 7225-2 */ /* 7x27 IDs */ [43] = MSM_CPU_7X27, [44] = MSM_CPU_7X27, [61] = MSM_CPU_7X27, [67] = MSM_CPU_7X27, /* 7227-1 */ [68] = MSM_CPU_7X27, /* 7627-1 */ [69] = MSM_CPU_7X27, /* 7627-2 */ /* 8x50 IDs */ [30] = MSM_CPU_8X50, [36] = MSM_CPU_8X50, [37] = MSM_CPU_8X50, [38] = MSM_CPU_8X50, /* 7x30 IDs */ [59] = MSM_CPU_7X30, [60] = MSM_CPU_7X30, /* 8x55 IDs */ [74] = MSM_CPU_8X55, [75] = MSM_CPU_8X55, [85] = MSM_CPU_8X55, /* 8x60 IDs */ [70] = MSM_CPU_8X60, [71] = MSM_CPU_8X60, [86] = MSM_CPU_8X60, /* 8960 IDs */ [87] = MSM_CPU_8960, /* 7x25A IDs */ [88] = MSM_CPU_7X25A, [89] = MSM_CPU_7X25A, [96] = MSM_CPU_7X25A, /* 7x27A IDs */ [90] = MSM_CPU_7X27A, [91] = MSM_CPU_7X27A, [92] = MSM_CPU_7X27A, [97] = MSM_CPU_7X27A, /* FSM9xxx ID */ [94] = FSM_CPU_9XXX, [95] = FSM_CPU_9XXX, /* 7x25AA ID */ [98] = MSM_CPU_7X25AA, [99] = MSM_CPU_7X25AA, [100] = MSM_CPU_7X25AA, /* 7x27AA ID */ [101] = MSM_CPU_7X27AA, [102] = MSM_CPU_7X27AA, [103] = MSM_CPU_7X27AA, [136] = MSM_CPU_7X27AA, /* 9x15 ID */ [104] = MSM_CPU_9615, [105] = MSM_CPU_9615, [106] = MSM_CPU_9615, [107] = MSM_CPU_9615, [171] = MSM_CPU_9615, /* 8064 IDs */ [109] = MSM_CPU_8064, /* 8930 IDs */ [116] = MSM_CPU_8930, [117] = MSM_CPU_8930, [118] = MSM_CPU_8930, [119] = MSM_CPU_8930, [179] = MSM_CPU_8930, /* 8627 IDs */ [120] = MSM_CPU_8627, [121] = MSM_CPU_8627, /* 8660A ID */ [122] = MSM_CPU_8960, /* 8260A ID */ [123] = MSM_CPU_8960, /* 8060A ID */ [124] = MSM_CPU_8960, /* 8974 IDs */ [126] = MSM_CPU_8974, [184] = MSM_CPU_8974, [185] = MSM_CPU_8974, [186] = MSM_CPU_8974, /* 8625 IDs */ [127] = MSM_CPU_8625, [128] = MSM_CPU_8625, [129] = MSM_CPU_8625, [137] = MSM_CPU_8625, [167] = MSM_CPU_8625, /* 8064 MPQ ID */ [130] = MSM_CPU_8064, /* 7x25AB IDs */ [131] = MSM_CPU_7X25AB, [132] = MSM_CPU_7X25AB, [133] = MSM_CPU_7X25AB, [135] = MSM_CPU_7X25AB, /* 9625 IDs */ [134] = MSM_CPU_9625, [148] = MSM_CPU_9625, [149] = MSM_CPU_9625, [150] = MSM_CPU_9625, [151] = MSM_CPU_9625, [152] = MSM_CPU_9625, [173] = MSM_CPU_9625, [174] = MSM_CPU_9625, [175] = MSM_CPU_9625, /* 8960AB IDs */ [138] = MSM_CPU_8960AB, [139] = MSM_CPU_8960AB, [140] = MSM_CPU_8960AB, [141] = MSM_CPU_8960AB, /* 8930AA IDs */ [142] = MSM_CPU_8930AA, [143] = MSM_CPU_8930AA, [144] = MSM_CPU_8930AA, [160] = MSM_CPU_8930AA, [180] = MSM_CPU_8930AA, /* 8226 IDs */ [145] = MSM_CPU_8226, [158] = MSM_CPU_8226, [159] = MSM_CPU_8226, [198] = MSM_CPU_8226, [199] = MSM_CPU_8226, [200] = MSM_CPU_8226, [205] = MSM_CPU_8226, /* 8092 IDs */ [146] = MSM_CPU_8092, /* 8610 IDs */ [147] = MSM_CPU_8610, [161] = MSM_CPU_8610, [162] = MSM_CPU_8610, [163] = MSM_CPU_8610, [164] = MSM_CPU_8610, [165] = MSM_CPU_8610, [166] = MSM_CPU_8610, /* 8064AB IDs */ [153] = MSM_CPU_8064AB, /* 8930AB IDs */ [154] = MSM_CPU_8930AB, [155] = MSM_CPU_8930AB, [156] = MSM_CPU_8930AB, [157] = MSM_CPU_8930AB, [181] = MSM_CPU_8930AB, /* 8625Q IDs */ [168] = MSM_CPU_8625Q, [169] = MSM_CPU_8625Q, [170] = MSM_CPU_8625Q, /* 8064AA IDs */ [172] = MSM_CPU_8064AA, /* 8084 IDs */ [178] = MSM_CPU_8084, /* krypton IDs */ [187] = MSM_CPU_KRYPTON, /* FSM9900 ID */ [188] = FSM_CPU_9900, /* Samarium IDs */ [195] = MSM_CPU_SAMARIUM, /* Uninitialized IDs are not known to run Linux. MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are considered as unknown CPU. */ }; static enum msm_cpu cur_cpu; static struct socinfo_v1 dummy_socinfo = { .format = 1, .version = 1, }; uint32_t socinfo_get_id(void) { return (socinfo) ? socinfo->v1.id : 0; } EXPORT_SYMBOL_GPL(socinfo_get_id); uint32_t socinfo_get_version(void) { return (socinfo) ? socinfo->v1.version : 0; } char *socinfo_get_build_id(void) { return (socinfo) ? socinfo->v1.build_id : NULL; } uint32_t socinfo_get_raw_id(void) { return socinfo ? (socinfo->v1.format >= 2 ? socinfo->v2.raw_id : 0) : 0; } uint32_t socinfo_get_raw_version(void) { return socinfo ? (socinfo->v1.format >= 2 ? socinfo->v2.raw_version : 0) : 0; } uint32_t socinfo_get_platform_type(void) { return socinfo ? (socinfo->v1.format >= 3 ? socinfo->v3.hw_platform : 0) : 0; } uint32_t socinfo_get_platform_version(void) { return socinfo ? (socinfo->v1.format >= 4 ? socinfo->v4.platform_version : 0) : 0; } /* This information is directly encoded by the machine id */ /* Thus no external callers rely on this information at the moment */ static uint32_t socinfo_get_accessory_chip(void) { return socinfo ? (socinfo->v1.format >= 5 ? socinfo->v5.accessory_chip : 0) : 0; } uint32_t socinfo_get_platform_subtype(void) { return socinfo ? (socinfo->v1.format >= 6 ? socinfo->v6.hw_platform_subtype : 0) : 0; } enum pmic_model socinfo_get_pmic_model(void) { return socinfo ? (socinfo->v1.format >= 7 ? socinfo->v7.pmic_model : PMIC_MODEL_UNKNOWN) : PMIC_MODEL_UNKNOWN; } uint32_t socinfo_get_pmic_die_revision(void) { return socinfo ? (socinfo->v1.format >= 7 ? socinfo->v7.pmic_die_revision : 0) : 0; } static uint32_t socinfo_get_format(void) { return socinfo ? socinfo->v1.format : 0; } enum msm_cpu socinfo_get_msm_cpu(void) { return cur_cpu; } EXPORT_SYMBOL_GPL(socinfo_get_msm_cpu); static ssize_t socinfo_show_id(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } return snprintf(buf, PAGE_SIZE, "%u\n", socinfo_get_id()); } static ssize_t socinfo_show_version(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { uint32_t version; if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } version = socinfo_get_version(); return snprintf(buf, PAGE_SIZE, "%u.%u\n", SOCINFO_VERSION_MAJOR(version), SOCINFO_VERSION_MINOR(version)); } static ssize_t socinfo_show_build_id(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } return snprintf(buf, PAGE_SIZE, "%-.32s\n", socinfo_get_build_id()); } static ssize_t socinfo_show_raw_id(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } if (socinfo->v1.format < 2) { pr_err("%s: Raw ID not available!\n", __func__); return 0; } return snprintf(buf, PAGE_SIZE, "%u\n", socinfo_get_raw_id()); } static ssize_t socinfo_show_raw_version(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } if (socinfo->v1.format < 2) { pr_err("%s: Raw version not available!\n", __func__); return 0; } return snprintf(buf, PAGE_SIZE, "%u\n", socinfo_get_raw_version()); } static ssize_t socinfo_show_platform_type(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { uint32_t hw_type; if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } if (socinfo->v1.format < 3) { pr_err("%s: platform type not available!\n", __func__); return 0; } hw_type = socinfo_get_platform_type(); if (hw_type >= HW_PLATFORM_INVALID) { pr_err("%s: Invalid hardware platform type found\n", __func__); hw_type = HW_PLATFORM_UNKNOWN; } return snprintf(buf, PAGE_SIZE, "%-.32s\n", hw_platform[hw_type]); } static ssize_t socinfo_show_platform_version(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } if (socinfo->v1.format < 4) { pr_err("%s: platform version not available!\n", __func__); return 0; } return snprintf(buf, PAGE_SIZE, "%u\n", socinfo_get_platform_version()); } static ssize_t socinfo_show_accessory_chip(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } if (socinfo->v1.format < 5) { pr_err("%s: accessory chip not available!\n", __func__); return 0; } return snprintf(buf, PAGE_SIZE, "%u\n", socinfo_get_accessory_chip()); } static ssize_t socinfo_show_platform_subtype(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { uint32_t hw_subtype; if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } if (socinfo->v1.format < 6) { pr_err("%s: platform subtype not available!\n", __func__); return 0; } hw_subtype = socinfo_get_platform_subtype(); if (hw_subtype >= PLATFORM_SUBTYPE_INVALID) { pr_err("%s: Invalid hardware platform sub type found\n", __func__); hw_subtype = PLATFORM_SUBTYPE_UNKNOWN; } return snprintf(buf, PAGE_SIZE, "%-.32s\n", hw_platform_subtype[hw_subtype]); } static ssize_t socinfo_show_pmic_model(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } if (socinfo->v1.format < 7) { pr_err("%s: pmic_model not available!\n", __func__); return 0; } return snprintf(buf, PAGE_SIZE, "%u\n", socinfo_get_pmic_model()); } static ssize_t socinfo_show_pmic_die_revision(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return 0; } if (socinfo->v1.format < 7) { pr_err("%s: pmic_die_revision not available!\n", __func__); return 0; } return snprintf(buf, PAGE_SIZE, "%u\n", socinfo_get_pmic_die_revision()); } static ssize_t msm_get_vendor(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "Qualcomm\n"); } 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()); } 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()); } static ssize_t msm_get_build_id(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%-.32s\n", socinfo_get_build_id()); } 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]); } 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()); } 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()); } 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(); return snprintf(buf, PAGE_SIZE, "%-.32s\n", hw_platform_subtype[hw_subtype]); } 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()); } 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()); } static struct sysdev_attribute socinfo_v1_files[] = { _SYSDEV_ATTR(id, 0444, socinfo_show_id, NULL), _SYSDEV_ATTR(version, 0444, socinfo_show_version, NULL), _SYSDEV_ATTR(build_id, 0444, socinfo_show_build_id, NULL), }; static struct sysdev_attribute socinfo_v2_files[] = { _SYSDEV_ATTR(raw_id, 0444, socinfo_show_raw_id, NULL), _SYSDEV_ATTR(raw_version, 0444, socinfo_show_raw_version, NULL), }; static struct sysdev_attribute socinfo_v3_files[] = { _SYSDEV_ATTR(hw_platform, 0444, socinfo_show_platform_type, NULL), }; static struct sysdev_attribute socinfo_v4_files[] = { _SYSDEV_ATTR(platform_version, 0444, socinfo_show_platform_version, NULL), }; static struct sysdev_attribute socinfo_v5_files[] = { _SYSDEV_ATTR(accessory_chip, 0444, socinfo_show_accessory_chip, NULL), }; static struct sysdev_attribute socinfo_v6_files[] = { _SYSDEV_ATTR(platform_subtype, 0444, socinfo_show_platform_subtype, NULL), }; static struct sysdev_attribute socinfo_v7_files[] = { _SYSDEV_ATTR(pmic_model, 0444, socinfo_show_pmic_model, NULL), _SYSDEV_ATTR(pmic_die_revision, 0444, socinfo_show_pmic_die_revision, NULL), }; static struct device_attribute msm_soc_attr_raw_version = __ATTR(raw_version, S_IRUGO, msm_get_raw_version, NULL); static struct device_attribute msm_soc_attr_raw_id = __ATTR(raw_id, S_IRUGO, msm_get_raw_id, NULL); static struct device_attribute msm_soc_attr_vendor = __ATTR(vendor, S_IRUGO, msm_get_vendor, NULL); static struct device_attribute msm_soc_attr_build_id = __ATTR(build_id, S_IRUGO, msm_get_build_id, NULL); static struct device_attribute msm_soc_attr_hw_platform = __ATTR(hw_platform, S_IRUGO, msm_get_hw_platform, NULL); static struct device_attribute msm_soc_attr_platform_version = __ATTR(platform_version, S_IRUGO, msm_get_platform_version, NULL); static struct device_attribute msm_soc_attr_accessory_chip = __ATTR(accessory_chip, S_IRUGO, msm_get_accessory_chip, NULL); static struct device_attribute msm_soc_attr_platform_subtype = __ATTR(platform_subtype, S_IRUGO, msm_get_platform_subtype, NULL); static struct device_attribute msm_soc_attr_pmic_model = __ATTR(pmic_model, S_IRUGO, msm_get_pmic_model, NULL); static struct device_attribute msm_soc_attr_pmic_die_revision = __ATTR(pmic_die_revision, S_IRUGO, msm_get_pmic_die_revision, NULL); static struct sysdev_class soc_sysdev_class = { .name = "soc", }; static struct sys_device soc_sys_device = { .id = 0, .cls = &soc_sysdev_class, }; static int __init socinfo_create_files(struct sys_device *dev, struct sysdev_attribute files[], int size) { int i; for (i = 0; i < size; i++) { int err = sysdev_create_file(dev, &files[i]); if (err) { pr_err("%s: sysdev_create_file(%s)=%d\n", __func__, files[i].attr.name, err); return err; } } return 0; } static void * __init setup_dummy_socinfo(void) { if (early_machine_is_mpq8092()) { dummy_socinfo.id = 146; strlcpy(dummy_socinfo.build_id, "mpq8092 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_apq8084()) { dummy_socinfo.id = 178; strlcpy(dummy_socinfo.build_id, "apq8084 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msmkrypton()) { dummy_socinfo.id = 187; strlcpy(dummy_socinfo.build_id, "msmkrypton - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msmsamarium()) { dummy_socinfo.id = 195; strlcpy(dummy_socinfo.build_id, "msmsamarium - ", sizeof(dummy_socinfo.build_id)); } strlcat(dummy_socinfo.build_id, "Dummy socinfo", sizeof(dummy_socinfo.build_id)); return (void *) &dummy_socinfo; } static void __init populate_soc_sysfs_files(struct device *msm_soc_device) { uint32_t legacy_format = socinfo_get_format(); device_create_file(msm_soc_device, &msm_soc_attr_vendor); switch (legacy_format) { case 8: case 7: device_create_file(msm_soc_device, &msm_soc_attr_pmic_model); device_create_file(msm_soc_device, &msm_soc_attr_pmic_die_revision); case 6: device_create_file(msm_soc_device, &msm_soc_attr_platform_subtype); case 5: device_create_file(msm_soc_device, &msm_soc_attr_accessory_chip); case 4: device_create_file(msm_soc_device, &msm_soc_attr_platform_version); case 3: device_create_file(msm_soc_device, &msm_soc_attr_hw_platform); case 2: device_create_file(msm_soc_device, &msm_soc_attr_raw_id); device_create_file(msm_soc_device, &msm_soc_attr_raw_version); case 1: device_create_file(msm_soc_device, &msm_soc_attr_build_id); break; default: pr_err("%s:Unknown socinfo format:%u\n", __func__, legacy_format); break; } return; } static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr) { uint32_t soc_version = socinfo_get_version(); soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", socinfo_get_id()); soc_dev_attr->machine = "Snapdragon"; soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u.%u", SOCINFO_VERSION_MAJOR(soc_version), SOCINFO_VERSION_MINOR(soc_version)); return; } static int __init socinfo_init_sysdev(void) { int err; struct device *msm_soc_device; struct soc_device *soc_dev; struct soc_device_attribute *soc_dev_attr; if (!socinfo) { pr_err("%s: No socinfo found!\n", __func__); return -ENODEV; } soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); if (!soc_dev_attr) { pr_err("%s: Soc Device alloc failed!\n", __func__); return -ENOMEM; } soc_info_populate(soc_dev_attr); soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR_OR_NULL(soc_dev)) { kfree(soc_dev_attr); pr_err("%s: Soc device register failed\n", __func__); return -EIO; } msm_soc_device = soc_device_to_device(soc_dev); populate_soc_sysfs_files(msm_soc_device); err = sysdev_class_register(&soc_sysdev_class); if (err) { pr_err("%s: sysdev_class_register fail (%d)\n", __func__, err); return err; } err = sysdev_register(&soc_sys_device); if (err) { pr_err("%s: sysdev_register fail (%d)\n", __func__, err); return err; } socinfo_create_files(&soc_sys_device, socinfo_v1_files, ARRAY_SIZE(socinfo_v1_files)); if (socinfo->v1.format < 2) return err; socinfo_create_files(&soc_sys_device, socinfo_v2_files, ARRAY_SIZE(socinfo_v2_files)); if (socinfo->v1.format < 3) return err; socinfo_create_files(&soc_sys_device, socinfo_v3_files, ARRAY_SIZE(socinfo_v3_files)); if (socinfo->v1.format < 4) return err; socinfo_create_files(&soc_sys_device, socinfo_v4_files, ARRAY_SIZE(socinfo_v4_files)); if (socinfo->v1.format < 5) return err; socinfo_create_files(&soc_sys_device, socinfo_v5_files, ARRAY_SIZE(socinfo_v5_files)); if (socinfo->v1.format < 6) return err; socinfo_create_files(&soc_sys_device, socinfo_v6_files, ARRAY_SIZE(socinfo_v6_files)); if (socinfo->v1.format < 7) return err; socinfo_create_files(&soc_sys_device, socinfo_v7_files, ARRAY_SIZE(socinfo_v7_files)); return 0; } arch_initcall(socinfo_init_sysdev); static void socinfo_print(void) { switch (socinfo->v1.format) { case 1: pr_info("%s: v%u, id=%u, ver=%u.%u\n", __func__, socinfo->v1.format, socinfo->v1.id, SOCINFO_VERSION_MAJOR(socinfo->v1.version), SOCINFO_VERSION_MINOR(socinfo->v1.version)); break; case 2: pr_info("%s: v%u, id=%u, ver=%u.%u, " "raw_id=%u, raw_ver=%u\n", __func__, socinfo->v1.format, socinfo->v1.id, SOCINFO_VERSION_MAJOR(socinfo->v1.version), SOCINFO_VERSION_MINOR(socinfo->v1.version), socinfo->v2.raw_id, socinfo->v2.raw_version); break; case 3: pr_info("%s: v%u, id=%u, ver=%u.%u, " "raw_id=%u, raw_ver=%u, hw_plat=%u\n", __func__, socinfo->v1.format, socinfo->v1.id, SOCINFO_VERSION_MAJOR(socinfo->v1.version), SOCINFO_VERSION_MINOR(socinfo->v1.version), socinfo->v2.raw_id, socinfo->v2.raw_version, socinfo->v3.hw_platform); break; case 4: pr_info("%s: v%u, id=%u, ver=%u.%u, " "raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n", __func__, socinfo->v1.format, socinfo->v1.id, SOCINFO_VERSION_MAJOR(socinfo->v1.version), SOCINFO_VERSION_MINOR(socinfo->v1.version), socinfo->v2.raw_id, socinfo->v2.raw_version, socinfo->v3.hw_platform, socinfo->v4.platform_version); break; case 5: pr_info("%s: v%u, id=%u, ver=%u.%u, " "raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n" " accessory_chip=%u\n", __func__, socinfo->v1.format, socinfo->v1.id, SOCINFO_VERSION_MAJOR(socinfo->v1.version), SOCINFO_VERSION_MINOR(socinfo->v1.version), socinfo->v2.raw_id, socinfo->v2.raw_version, socinfo->v3.hw_platform, socinfo->v4.platform_version, socinfo->v5.accessory_chip); break; case 6: pr_info("%s: v%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", __func__, socinfo->v1.format, socinfo->v1.id, SOCINFO_VERSION_MAJOR(socinfo->v1.version), SOCINFO_VERSION_MINOR(socinfo->v1.version), socinfo->v2.raw_id, socinfo->v2.raw_version, socinfo->v3.hw_platform, socinfo->v4.platform_version, socinfo->v5.accessory_chip, socinfo->v6.hw_platform_subtype); break; case 8: case 7: pr_info("%s: v%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", __func__, socinfo->v1.format, socinfo->v1.id, SOCINFO_VERSION_MAJOR(socinfo->v1.version), SOCINFO_VERSION_MINOR(socinfo->v1.version), socinfo->v2.raw_id, socinfo->v2.raw_version, socinfo->v3.hw_platform, socinfo->v4.platform_version, socinfo->v5.accessory_chip, socinfo->v6.hw_platform_subtype, socinfo->v7.pmic_model, socinfo->v7.pmic_die_revision); break; default: pr_err("%s: Unknown format found\n", __func__); break; } } int __init socinfo_init(void) { socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v8)); if (!socinfo) socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v7)); if (!socinfo) socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v6)); if (!socinfo) socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v5)); if (!socinfo) socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v4)); if (!socinfo) socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v3)); if (!socinfo) socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v2)); if (!socinfo) socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v1)); if (!socinfo) { pr_warn("%s: Can't find SMEM_HW_SW_BUILD_ID; falling back on dummy values.\n", __func__); socinfo = setup_dummy_socinfo(); } WARN(!socinfo_get_id(), "Unknown SOC ID!\n"); WARN(socinfo_get_id() >= ARRAY_SIZE(cpu_of_id), "New IDs added! ID => CPU mapping might need an update.\n"); if (socinfo->v1.id < ARRAY_SIZE(cpu_of_id)) cur_cpu = cpu_of_id[socinfo->v1.id]; boot_stats_init(); socinfo_print(); return 0; } const int get_core_count(void) { if (!(read_cpuid_mpidr() & BIT(31))) return 1; if (read_cpuid_mpidr() & BIT(30)) return 1; /* 1 + the PART[1:0] field of MIDR */ return ((read_cpuid_id() >> 4) & 3) + 1; } const int read_msm_cpu_type(void) { if (socinfo_get_msm_cpu() != MSM_CPU_UNKNOWN) return socinfo_get_msm_cpu(); switch (read_cpuid_id()) { case 0x510F02D0: case 0x510F02D2: case 0x510F02D4: return MSM_CPU_8X60; case 0x510F04D0: case 0x510F04D1: case 0x510F04D2: case 0x511F04D0: case 0x512F04D0: return MSM_CPU_8960; case 0x51404D11: /* We can't get here unless we are in bringup */ return MSM_CPU_8930; case 0x510F06F0: return MSM_CPU_8064; case 0x511F06F1: case 0x511F06F2: case 0x512F06F0: return MSM_CPU_8974; default: return MSM_CPU_UNKNOWN; }; } const int cpu_is_krait(void) { return ((read_cpuid_id() & 0xFF00FC00) == 0x51000400); } const int cpu_is_krait_v1(void) { switch (read_cpuid_id()) { case 0x510F04D0: case 0x510F04D1: case 0x510F04D2: return 1; default: return 0; }; } const int cpu_is_krait_v2(void) { switch (read_cpuid_id()) { case 0x511F04D0: case 0x511F04D1: case 0x511F04D2: case 0x511F04D3: case 0x511F04D4: case 0x510F06F0: case 0x510F06F1: case 0x510F06F2: return 1; default: return 0; }; } const int cpu_is_krait_v3(void) { switch (read_cpuid_id()) { case 0x512F04D0: case 0x511F06F0: case 0x511F06F1: case 0x511F06F2: case 0x510F05D0: return 1; default: return 0; }; }