/* * Copyright (c) 2009-2018, 2019 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 * */ #define pr_fmt(fmt) "%s: " fmt, __func__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define BUILD_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 static DECLARE_RWSEM(current_image_rwsem); 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_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_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", }; enum { ACCESSORY_CHIP_UNKNOWN = 0, ACCESSORY_CHIP_CHARM = 58, }; 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, }; const char *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_MOJAVE_V1 = 0x0, PLATFORM_SUBTYPE_MMX = 0x1, PLATFORM_SUBTYPE_MOJAVE_FULL_V2 = 0x2, PLATFORM_SUBTYPE_MOJAVE_BARE_V2 = 0x3, PLATFORM_SUBTYPE_ADP_INVALID, }; const char *adp_hw_platform_subtype[] = { [PLATFORM_SUBTYPE_MOJAVE_V1] = "MOJAVE_V1", [PLATFORM_SUBTYPE_MMX] = "MMX", [PLATFORM_SUBTYPE_MOJAVE_FULL_V2] = "_MOJAVE_V2_FULL", [PLATFORM_SUBTYPE_MOJAVE_BARE_V2] = "_MOJAVE_V2_BARE", [PLATFORM_SUBTYPE_ADP_INVALID] = "INVALID", }; 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", [PLATFORM_SUBTYPE_INVALID] = "Invalid", }; /* Used to parse shared memory. Must match the modem. */ struct socinfo_v0_1 { uint32_t format; uint32_t id; uint32_t version; char build_id[BUILD_ID_LENGTH]; }; struct socinfo_v0_2 { struct socinfo_v0_1 v0_1; uint32_t raw_id; uint32_t raw_version; }; struct socinfo_v0_3 { struct socinfo_v0_2 v0_2; uint32_t hw_platform; }; struct socinfo_v0_4 { struct socinfo_v0_3 v0_3; uint32_t platform_version; }; struct socinfo_v0_5 { struct socinfo_v0_4 v0_4; uint32_t accessory_chip; }; struct socinfo_v0_6 { struct socinfo_v0_5 v0_5; uint32_t hw_platform_subtype; }; struct socinfo_v0_7 { struct socinfo_v0_6 v0_6; uint32_t pmic_model; uint32_t pmic_die_revision; }; struct socinfo_v0_8 { struct socinfo_v0_7 v0_7; uint32_t pmic_model_1; uint32_t pmic_die_revision_1; uint32_t pmic_model_2; uint32_t pmic_die_revision_2; }; struct socinfo_v0_9 { struct socinfo_v0_8 v0_8; uint32_t foundry_id; }; struct socinfo_v0_10 { struct socinfo_v0_9 v0_9; uint32_t serial_number; }; struct socinfo_v0_11 { struct socinfo_v0_10 v0_10; uint32_t num_pmics; uint32_t pmic_array_offset; }; struct socinfo_v0_12 { struct socinfo_v0_11 v0_11; uint32_t chip_family; uint32_t raw_device_family; uint32_t raw_device_number; }; static union { struct socinfo_v0_1 v0_1; struct socinfo_v0_2 v0_2; struct socinfo_v0_3 v0_3; struct socinfo_v0_4 v0_4; struct socinfo_v0_5 v0_5; struct socinfo_v0_6 v0_6; struct socinfo_v0_7 v0_7; struct socinfo_v0_8 v0_8; struct socinfo_v0_9 v0_9; struct socinfo_v0_10 v0_10; struct socinfo_v0_11 v0_11; struct socinfo_v0_12 v0_12; } *socinfo; /* max socinfo format version supported */ #define MAX_SOCINFO_FORMAT SOCINFO_VERSION(0, 12) static struct msm_soc_info cpu_of_id[] = { /* 7x01 IDs */ [0] = {MSM_CPU_UNKNOWN, "Unknown CPU"}, [1] = {MSM_CPU_7X01, "MSM7X01"}, [16] = {MSM_CPU_7X01, "MSM7X01"}, [17] = {MSM_CPU_7X01, "MSM7X01"}, [18] = {MSM_CPU_7X01, "MSM7X01"}, [19] = {MSM_CPU_7X01, "MSM7X01"}, [23] = {MSM_CPU_7X01, "MSM7X01"}, [25] = {MSM_CPU_7X01, "MSM7X01"}, [26] = {MSM_CPU_7X01, "MSM7X01"}, [32] = {MSM_CPU_7X01, "MSM7X01"}, [33] = {MSM_CPU_7X01, "MSM7X01"}, [34] = {MSM_CPU_7X01, "MSM7X01"}, [35] = {MSM_CPU_7X01, "MSM7X01"}, /* 7x25 IDs */ [20] = {MSM_CPU_7X25, "MSM7X25"}, [21] = {MSM_CPU_7X25, "MSM7X25"}, [24] = {MSM_CPU_7X25, "MSM7X25"}, [27] = {MSM_CPU_7X25, "MSM7X25"}, [39] = {MSM_CPU_7X25, "MSM7X25"}, [40] = {MSM_CPU_7X25, "MSM7X25"}, [41] = {MSM_CPU_7X25, "MSM7X25"}, [42] = {MSM_CPU_7X25, "MSM7X25"}, [62] = {MSM_CPU_7X25, "MSM7X25"}, [63] = {MSM_CPU_7X25, "MSM7X25"}, [66] = {MSM_CPU_7X25, "MSM7X25"}, /* 7x27 IDs */ [43] = {MSM_CPU_7X27, "MSM7X27"}, [44] = {MSM_CPU_7X27, "MSM7X27"}, [61] = {MSM_CPU_7X27, "MSM7X27"}, [67] = {MSM_CPU_7X27, "MSM7X27"}, [68] = {MSM_CPU_7X27, "MSM7X27"}, [69] = {MSM_CPU_7X27, "MSM7X27"}, /* 8x50 IDs */ [30] = {MSM_CPU_8X50, "MSM8X50"}, [36] = {MSM_CPU_8X50, "MSM8X50"}, [37] = {MSM_CPU_8X50, "MSM8X50"}, [38] = {MSM_CPU_8X50, "MSM8X50"}, /* 7x30 IDs */ [59] = {MSM_CPU_7X30, "MSM7X30"}, [60] = {MSM_CPU_7X30, "MSM7X30"}, /* 8x55 IDs */ [74] = {MSM_CPU_8X55, "MSM8X55"}, [75] = {MSM_CPU_8X55, "MSM8X55"}, [85] = {MSM_CPU_8X55, "MSM8X55"}, /* 8x60 IDs */ [70] = {MSM_CPU_8X60, "MSM8X60"}, [71] = {MSM_CPU_8X60, "MSM8X60"}, [86] = {MSM_CPU_8X60, "MSM8X60"}, /* 8960 IDs */ [87] = {MSM_CPU_8960, "MSM8960"}, /* 7x25A IDs */ [88] = {MSM_CPU_7X25A, "MSM7X25A"}, [89] = {MSM_CPU_7X25A, "MSM7X25A"}, [96] = {MSM_CPU_7X25A, "MSM7X25A"}, /* 7x27A IDs */ [90] = {MSM_CPU_7X27A, "MSM7X27A"}, [91] = {MSM_CPU_7X27A, "MSM7X27A"}, [92] = {MSM_CPU_7X27A, "MSM7X27A"}, [97] = {MSM_CPU_7X27A, "MSM7X27A"}, /* FSM9xxx ID */ [94] = {FSM_CPU_9XXX, "FSM9XXX"}, [95] = {FSM_CPU_9XXX, "FSM9XXX"}, /* 7x25AA ID */ [98] = {MSM_CPU_7X25AA, "MSM7X25AA"}, [99] = {MSM_CPU_7X25AA, "MSM7X25AA"}, [100] = {MSM_CPU_7X25AA, "MSM7X25AA"}, /* 7x27AA ID */ [101] = {MSM_CPU_7X27AA, "MSM7X27AA"}, [102] = {MSM_CPU_7X27AA, "MSM7X27AA"}, [103] = {MSM_CPU_7X27AA, "MSM7X27AA"}, [136] = {MSM_CPU_7X27AA, "MSM7X27AA"}, /* 9x15 ID */ [104] = {MSM_CPU_9615, "MSM9615"}, [105] = {MSM_CPU_9615, "MSM9615"}, [106] = {MSM_CPU_9615, "MSM9615"}, [107] = {MSM_CPU_9615, "MSM9615"}, [171] = {MSM_CPU_9615, "MSM9615"}, /* 8064 IDs */ [109] = {MSM_CPU_8064, "APQ8064"}, /* 8930 IDs */ [116] = {MSM_CPU_8930, "MSM8930"}, [117] = {MSM_CPU_8930, "MSM8930"}, [118] = {MSM_CPU_8930, "MSM8930"}, [119] = {MSM_CPU_8930, "MSM8930"}, [179] = {MSM_CPU_8930, "MSM8930"}, /* 8627 IDs */ [120] = {MSM_CPU_8627, "MSM8627"}, [121] = {MSM_CPU_8627, "MSM8627"}, /* 8660A ID */ [122] = {MSM_CPU_8960, "MSM8960"}, /* 8260A ID */ [123] = {MSM_CPU_8960, "MSM8960"}, /* 8060A ID */ [124] = {MSM_CPU_8960, "MSM8960"}, /* 8974 IDs */ [126] = {MSM_CPU_8974, "MSM8974"}, [184] = {MSM_CPU_8974, "MSM8974"}, [185] = {MSM_CPU_8974, "MSM8974"}, [186] = {MSM_CPU_8974, "MSM8974"}, /* 8974AA IDs */ [208] = {MSM_CPU_8974PRO_AA, "MSM8974PRO-AA"}, [211] = {MSM_CPU_8974PRO_AA, "MSM8974PRO-AA"}, [214] = {MSM_CPU_8974PRO_AA, "MSM8974PRO-AA"}, [217] = {MSM_CPU_8974PRO_AA, "MSM8974PRO-AA"}, /* 8974AB IDs */ [209] = {MSM_CPU_8974PRO_AB, "MSM8974PRO-AB"}, [212] = {MSM_CPU_8974PRO_AB, "MSM8974PRO-AB"}, [215] = {MSM_CPU_8974PRO_AB, "MSM8974PRO-AB"}, [218] = {MSM_CPU_8974PRO_AB, "MSM8974PRO-AB"}, /* 8974AC IDs */ [194] = {MSM_CPU_8974PRO_AC, "MSM8974PRO-AC"}, [210] = {MSM_CPU_8974PRO_AC, "MSM8974PRO-AC"}, [213] = {MSM_CPU_8974PRO_AC, "MSM8974PRO-AC"}, [216] = {MSM_CPU_8974PRO_AC, "MSM8974PRO-AC"}, /* 8625 IDs */ [127] = {MSM_CPU_8625, "MSM8625"}, [128] = {MSM_CPU_8625, "MSM8625"}, [129] = {MSM_CPU_8625, "MSM8625"}, [137] = {MSM_CPU_8625, "MSM8625"}, [167] = {MSM_CPU_8625, "MSM8625"}, /* 8064 MPQ ID */ [130] = {MSM_CPU_8064, "APQ8064"}, /* 7x25AB IDs */ [131] = {MSM_CPU_7X25AB, "MSM7X25AB"}, [132] = {MSM_CPU_7X25AB, "MSM7X25AB"}, [133] = {MSM_CPU_7X25AB, "MSM7X25AB"}, [135] = {MSM_CPU_7X25AB, "MSM7X25AB"}, /* 9625 IDs */ [134] = {MSM_CPU_9625, "MSM9625"}, [148] = {MSM_CPU_9625, "MSM9625"}, [149] = {MSM_CPU_9625, "MSM9625"}, [150] = {MSM_CPU_9625, "MSM9625"}, [151] = {MSM_CPU_9625, "MSM9625"}, [152] = {MSM_CPU_9625, "MSM9625"}, [173] = {MSM_CPU_9625, "MSM9625"}, [174] = {MSM_CPU_9625, "MSM9625"}, [175] = {MSM_CPU_9625, "MSM9625"}, /* 8960AB IDs */ [138] = {MSM_CPU_8960AB, "MSM8960AB"}, [139] = {MSM_CPU_8960AB, "MSM8960AB"}, [140] = {MSM_CPU_8960AB, "MSM8960AB"}, [141] = {MSM_CPU_8960AB, "MSM8960AB"}, /* 8930AA IDs */ [142] = {MSM_CPU_8930AA, "MSM8930AA"}, [143] = {MSM_CPU_8930AA, "MSM8930AA"}, [144] = {MSM_CPU_8930AA, "MSM8930AA"}, [160] = {MSM_CPU_8930AA, "MSM8930AA"}, [180] = {MSM_CPU_8930AA, "MSM8930AA"}, /* 8226 IDs */ [145] = {MSM_CPU_8226, "MSM8626"}, [158] = {MSM_CPU_8226, "MSM8226"}, [159] = {MSM_CPU_8226, "MSM8526"}, [198] = {MSM_CPU_8226, "MSM8126"}, [199] = {MSM_CPU_8226, "APQ8026"}, [200] = {MSM_CPU_8226, "MSM8926"}, [205] = {MSM_CPU_8226, "MSM8326"}, [219] = {MSM_CPU_8226, "APQ8028"}, [220] = {MSM_CPU_8226, "MSM8128"}, [221] = {MSM_CPU_8226, "MSM8228"}, [222] = {MSM_CPU_8226, "MSM8528"}, [223] = {MSM_CPU_8226, "MSM8628"}, [224] = {MSM_CPU_8226, "MSM8928"}, /* 8610 IDs */ [147] = {MSM_CPU_8610, "MSM8610"}, [161] = {MSM_CPU_8610, "MSM8110"}, [162] = {MSM_CPU_8610, "MSM8210"}, [163] = {MSM_CPU_8610, "MSM8810"}, [164] = {MSM_CPU_8610, "MSM8212"}, [165] = {MSM_CPU_8610, "MSM8612"}, [166] = {MSM_CPU_8610, "MSM8112"}, [225] = {MSM_CPU_8610, "MSM8510"}, [226] = {MSM_CPU_8610, "MSM8512"}, /* 8064AB IDs */ [153] = {MSM_CPU_8064AB, "APQ8064AB"}, /* 8930AB IDs */ [154] = {MSM_CPU_8930AB, "MSM8930AB"}, [155] = {MSM_CPU_8930AB, "MSM8930AB"}, [156] = {MSM_CPU_8930AB, "MSM8930AB"}, [157] = {MSM_CPU_8930AB, "MSM8930AB"}, [181] = {MSM_CPU_8930AB, "MSM8930AB"}, /* 8625Q IDs */ [168] = {MSM_CPU_8625Q, "MSM8225Q"}, [169] = {MSM_CPU_8625Q, "MSM8625Q"}, [170] = {MSM_CPU_8625Q, "MSM8125Q"}, /* 8064AA IDs */ [172] = {MSM_CPU_8064AA, "APQ8064AA"}, /* 8084 IDs */ [178] = {MSM_CPU_8084, "APQ8084"}, /* 9630 IDs */ [187] = {MSM_CPU_9630, "MDM9630"}, [227] = {MSM_CPU_9630, "MDM9630"}, [228] = {MSM_CPU_9630, "MDM9630"}, [229] = {MSM_CPU_9630, "MDM9630"}, [230] = {MSM_CPU_9630, "MDM9630"}, [231] = {MSM_CPU_9630, "MDM9630"}, /* FSM9900 ID */ [188] = {FSM_CPU_9900, "FSM9900"}, [189] = {FSM_CPU_9900, "FSM9900"}, [190] = {FSM_CPU_9900, "FSM9900"}, [191] = {FSM_CPU_9900, "FSM9900"}, [192] = {FSM_CPU_9900, "FSM9900"}, [193] = {FSM_CPU_9900, "FSM9900"}, /* 8916 IDs */ [206] = {MSM_CPU_8916, "MSM8916"}, [247] = {MSM_CPU_8916, "APQ8016"}, [248] = {MSM_CPU_8916, "MSM8216"}, [249] = {MSM_CPU_8916, "MSM8116"}, [250] = {MSM_CPU_8916, "MSM8616"}, /* 8936 IDs */ [233] = {MSM_CPU_8936, "MSM8936"}, [240] = {MSM_CPU_8936, "APQ8036"}, [242] = {MSM_CPU_8936, "MSM8236"}, /* 8939 IDs */ [239] = {MSM_CPU_8939, "MSM8939"}, [241] = {MSM_CPU_8939, "APQ8039"}, [263] = {MSM_CPU_8939, "MSM8239"}, /* 8909 IDs */ [245] = {MSM_CPU_8909, "MSM8909"}, [258] = {MSM_CPU_8909, "MSM8209"}, [259] = {MSM_CPU_8909, "MSM8208"}, [265] = {MSM_CPU_8909, "APQ8009"}, [260] = {MSM_CPU_8909, "MDMFERRUM"}, [261] = {MSM_CPU_8909, "MDMFERRUM"}, [262] = {MSM_CPU_8909, "MDMFERRUM"}, [300] = {MSM_CPU_8909, "MSM8909W"}, [301] = {MSM_CPU_8909, "APQ8009W"}, /* ZIRC IDs */ [234] = {MSM_CPU_ZIRC, "MSMZIRC"}, [235] = {MSM_CPU_ZIRC, "MSMZIRC"}, [236] = {MSM_CPU_ZIRC, "MSMZIRC"}, [237] = {MSM_CPU_ZIRC, "MSMZIRC"}, [238] = {MSM_CPU_ZIRC, "MSMZIRC"}, /* 8994 ID */ [207] = {MSM_CPU_8994, "MSM8994"}, [253] = {MSM_CPU_8994, "APQ8094"}, /* 8992 ID */ [251] = {MSM_CPU_8992, "MSM8992"}, /* FSM9010 ID */ [254] = {FSM_CPU_9010, "FSM9010"}, [255] = {FSM_CPU_9010, "FSM9010"}, [256] = {FSM_CPU_9010, "FSM9010"}, [257] = {FSM_CPU_9010, "FSM9010"}, /* Tellurium ID */ [264] = {MSM_CPU_TELLURIUM, "MSMTELLURIUM"}, /* 8996 IDs */ [246] = {MSM_CPU_8996, "MSM8996"}, [291] = {MSM_CPU_8996, "APQ8096"}, [305] = {MSM_CPU_8996, "MSM8996pro"}, [310] = {MSM_CPU_8996, "MSM8996"}, [311] = {MSM_CPU_8996, "APQ8096"}, [312] = {MSM_CPU_8996, "APQ8096pro"}, [315] = {MSM_CPU_8996, "MSM8996pro"}, [316] = {MSM_CPU_8996, "APQ8096pro"}, [387] = {MSM_CPU_8996, "APQ8096A"}, /* 8976 ID */ [266] = {MSM_CPU_8976, "MSM8976"}, /* 8929 IDs */ [268] = {MSM_CPU_8929, "MSM8929"}, [269] = {MSM_CPU_8929, "MSM8629"}, [270] = {MSM_CPU_8929, "MSM8229"}, [271] = {MSM_CPU_8929, "APQ8029"}, /* Cobalt IDs */ [292] = {MSM_CPU_8998, "MSM8998"}, [319] = {MSM_CPU_8998, "APQ8098"}, /* Hamster ID */ [306] = {MSM_CPU_HAMSTER, "MSMHAMSTER"}, /* 660 ID */ [317] = {MSM_CPU_660, "SDM660"}, [324] = {MSM_CPU_660, "SDA660"}, [325] = {MSM_CPU_660, "SDM658"}, [326] = {MSM_CPU_660, "SDA658"}, /* 630 ID */ [318] = {MSM_CPU_630, "SDM630"}, [327] = {MSM_CPU_630, "SDA630"}, /* 636 ID */ [345] = {MSM_CPU_636, "SDM636"}, [346] = {MSM_CPU_636, "SDA636"}, /* 455 ID */ [385] = {MSM_CPU_455, "SDM455"}, /* IPQ ID */ [402] = {IPQ_CPU_6018, "IPQ6018"}, [403] = {IPQ_CPU_6028, "IPQ6028"}, [421] = {IPQ_CPU_6000, "IPQ6000"}, [422] = {IPQ_CPU_6010, "IPQ6010"}, [453] = {IPQ_CPU_6005, "IPQ6005"}, /* 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 int current_image; static uint32_t socinfo_format; static struct socinfo_v0_1 dummy_socinfo = { .format = SOCINFO_VERSION(0, 1), .version = 1, }; uint32_t socinfo_get_id(void) { return (socinfo) ? socinfo->v0_1.id : 0; } EXPORT_SYMBOL(socinfo_get_id); static char *socinfo_get_id_string(void) { return (socinfo) ? cpu_of_id[socinfo->v0_1.id].soc_id_string : NULL; } uint32_t socinfo_get_version(void) { return (socinfo) ? socinfo->v0_1.version : 0; } char *socinfo_get_build_id(void) { return (socinfo) ? socinfo->v0_1.build_id : NULL; } static char *msm_read_hardware_id(void) { static char msm_soc_str[256] = "Qualcomm Technologies, Inc "; static bool string_generated; int ret = 0; if (string_generated) return msm_soc_str; if (!socinfo) goto err_path; if (!cpu_of_id[socinfo->v0_1.id].soc_id_string) goto err_path; ret = strlcat(msm_soc_str, cpu_of_id[socinfo->v0_1.id].soc_id_string, sizeof(msm_soc_str)); if (ret > sizeof(msm_soc_str)) goto err_path; string_generated = true; return msm_soc_str; err_path: return "UNKNOWN SOC TYPE"; } uint32_t socinfo_get_raw_id(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 2) ? socinfo->v0_2.raw_id : 0) : 0; } uint32_t socinfo_get_raw_version(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 2) ? socinfo->v0_2.raw_version : 0) : 0; } uint32_t socinfo_get_platform_type(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 3) ? socinfo->v0_3.hw_platform : 0) : 0; } uint32_t socinfo_get_platform_version(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 4) ? socinfo->v0_4.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_format >= SOCINFO_VERSION(0, 5) ? socinfo->v0_5.accessory_chip : 0) : 0; } uint32_t socinfo_get_platform_subtype(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 6) ? socinfo->v0_6.hw_platform_subtype : 0) : 0; } static uint32_t socinfo_get_foundry_id(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 9) ? socinfo->v0_9.foundry_id : 0) : 0; } uint32_t socinfo_get_serial_number(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 10) ? socinfo->v0_10.serial_number : 0) : 0; } EXPORT_SYMBOL(socinfo_get_serial_number); static uint32_t socinfo_get_chip_family(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 12) ? socinfo->v0_12.chip_family : 0) : 0; } static uint32_t socinfo_get_raw_device_family(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 12) ? socinfo->v0_12.raw_device_family : 0) : 0; } static uint32_t socinfo_get_raw_device_number(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 12) ? socinfo->v0_12.raw_device_number : 0) : 0; } enum pmic_model socinfo_get_pmic_model(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 7) ? socinfo->v0_7.pmic_model : PMIC_MODEL_UNKNOWN) : PMIC_MODEL_UNKNOWN; } uint32_t socinfo_get_pmic_die_revision(void) { return socinfo ? (socinfo_format >= SOCINFO_VERSION(0, 7) ? socinfo->v0_7.pmic_die_revision : 0) : 0; } static char *socinfo_get_image_version_base_address(void) { return smem_find(SMEM_IMAGE_VERSION_TABLE, SMEM_IMAGE_VERSION_SIZE, 0, SMEM_ANY_HOST_FLAG); } enum msm_cpu socinfo_get_msm_cpu(void) { return cur_cpu; } EXPORT_SYMBOL(socinfo_get_msm_cpu); static ssize_t msm_get_vendor(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "QTI\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(); if (HW_PLATFORM_QRD == socinfo_get_platform_type()) { 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]); } if (socinfo_get_platform_type() == HW_PLATFORM_ADP) { if (hw_subtype >= PLATFORM_SUBTYPE_ADP_INVALID) { pr_err("Invalid hardware platform sub type for adp found\n"); hw_subtype = PLATFORM_SUBTYPE_ADP_INVALID; } return snprintf(buf, PAGE_SIZE, "%-.32s\n", adp_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 snprintf(buf, PAGE_SIZE, "%-.32s\n", hw_platform_subtype[hw_subtype]); } } 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); } 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()); } 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()); } 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()); } 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()); } 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()); } 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 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"); return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "Unknown"); } down_read(¤t_image_rwsem); string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; up_read(¤t_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(¤t_image_rwsem); if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { up_read(¤t_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"); up_read(¤t_image_rwsem); return count; } store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; up_read(¤t_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"); return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "Unknown"); } down_read(¤t_image_rwsem); string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; up_read(¤t_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(¤t_image_rwsem); if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { up_read(¤t_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"); up_read(¤t_image_rwsem); return count; } store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; up_read(¤t_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"); return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "Unknown"); } down_read(¤t_image_rwsem); string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; up_read(¤t_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(¤t_image_rwsem); if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) { up_read(¤t_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"); up_read(¤t_image_rwsem); return count; } store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; up_read(¤t_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(¤t_image_rwsem); ret = snprintf(buf, PAGE_SIZE, "%d\n", current_image); up_read(¤t_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(¤t_image_rwsem); if (0 <= digit && digit < SMEM_IMAGE_VERSION_BLOCKS_COUNT) current_image = digit; else current_image = 0; up_write(¤t_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 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); /* Platform Subtype String is being deprecated. Use Platform * Subtype ID instead. */ static struct device_attribute msm_soc_attr_platform_subtype_id = __ATTR(platform_subtype_id, S_IRUGO, msm_get_platform_subtype_id, NULL); static struct device_attribute msm_soc_attr_foundry_id = __ATTR(foundry_id, S_IRUGO, msm_get_foundry_id, NULL); static struct device_attribute msm_soc_attr_serial_number = __ATTR(serial_number, S_IRUGO, msm_get_serial_number, NULL); static struct device_attribute msm_soc_attr_chip_family = __ATTR(chip_family, S_IRUGO, msm_get_chip_family, NULL); static struct device_attribute msm_soc_attr_raw_device_family = __ATTR(raw_device_family, S_IRUGO, msm_get_raw_device_family, NULL); static struct device_attribute msm_soc_attr_raw_device_number = __ATTR(raw_device_number, S_IRUGO, msm_get_raw_device_number, 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 device_attribute image_version = __ATTR(image_version, S_IRUGO | S_IWUSR, msm_get_image_version, msm_set_image_version); static struct device_attribute image_variant = __ATTR(image_variant, S_IRUGO | S_IWUSR, msm_get_image_variant, msm_set_image_variant); static struct device_attribute image_crm_version = __ATTR(image_crm_version, S_IRUGO | S_IWUSR, msm_get_image_crm_version, msm_set_image_crm_version); static struct device_attribute select_image = __ATTR(select_image, S_IRUGO | S_IWUSR, msm_get_image_number, msm_select_image); static struct device_attribute images = __ATTR(images, S_IRUGO, msm_get_images, NULL); static void * __init setup_dummy_socinfo(void) { 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_mdm9630()) { dummy_socinfo.id = 187; strlcpy(dummy_socinfo.build_id, "mdm9630 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msm8909()) { dummy_socinfo.id = 245; strlcpy(dummy_socinfo.build_id, "msm8909 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msm8916()) { dummy_socinfo.id = 206; strlcpy(dummy_socinfo.build_id, "msm8916 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msm8939()) { dummy_socinfo.id = 239; strlcpy(dummy_socinfo.build_id, "msm8939 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msm8936()) { dummy_socinfo.id = 233; strlcpy(dummy_socinfo.build_id, "msm8936 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msmzirc()) { dummy_socinfo.id = 238; strlcpy(dummy_socinfo.build_id, "msmzirc - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msm8994()) { dummy_socinfo.id = 207; strlcpy(dummy_socinfo.build_id, "msm8994 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msm8992()) { dummy_socinfo.id = 251; strlcpy(dummy_socinfo.build_id, "msm8992 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msm8976()) { dummy_socinfo.id = 266; strlcpy(dummy_socinfo.build_id, "msm8976 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msmtellurium()) { dummy_socinfo.id = 264; strlcpy(dummy_socinfo.build_id, "msmtellurium - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msm8996()) { dummy_socinfo.id = 246; strlcpy(dummy_socinfo.build_id, "msm8996 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msm8929()) { dummy_socinfo.id = 268; strlcpy(dummy_socinfo.build_id, "msm8929 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msm8998()) { dummy_socinfo.id = 292; strlcpy(dummy_socinfo.build_id, "msm8998 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_msmhamster()) { dummy_socinfo.id = 306; strlcpy(dummy_socinfo.build_id, "msmhamster - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sdm660()) { dummy_socinfo.id = 317; strlcpy(dummy_socinfo.build_id, "sdm660 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sda660()) { dummy_socinfo.id = 324; strlcpy(dummy_socinfo.build_id, "sda660 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sdm455()) { dummy_socinfo.id = 385; strlcpy(dummy_socinfo.build_id, "sdm455 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sdm658()) { dummy_socinfo.id = 325; strlcpy(dummy_socinfo.build_id, "sdm658 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sda658()) { dummy_socinfo.id = 326; strlcpy(dummy_socinfo.build_id, "sda658 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sdm630()) { dummy_socinfo.id = 318; strlcpy(dummy_socinfo.build_id, "sdm630 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sda630()) { dummy_socinfo.id = 327; strlcpy(dummy_socinfo.build_id, "sda630 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sdm636()) { dummy_socinfo.id = 345; strlcpy(dummy_socinfo.build_id, "sdm636 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_sda636()) { dummy_socinfo.id = 346; strlcpy(dummy_socinfo.build_id, "sda636 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_apq8098()) { dummy_socinfo.id = 319; strlcpy(dummy_socinfo.build_id, "apq8098 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_ipq6018()) { dummy_socinfo.id = 402; strlcpy(dummy_socinfo.build_id, "ipq6018 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_ipq6028()) { dummy_socinfo.id = 403; strlcpy(dummy_socinfo.build_id, "ipq6028 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_ipq6000()) { dummy_socinfo.id = 421; strlcpy(dummy_socinfo.build_id, "ipq6000 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_ipq6010()) { dummy_socinfo.id = 422; strlcpy(dummy_socinfo.build_id, "ipq6010 - ", sizeof(dummy_socinfo.build_id)); } else if (early_machine_is_ipq6005()) { dummy_socinfo.id = 453; strlcpy(dummy_socinfo.build_id, "ipq6005 - ", 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) { device_create_file(msm_soc_device, &msm_soc_attr_vendor); device_create_file(msm_soc_device, &image_version); device_create_file(msm_soc_device, &image_variant); device_create_file(msm_soc_device, &image_crm_version); device_create_file(msm_soc_device, &select_image); device_create_file(msm_soc_device, &images); switch (socinfo_format) { case SOCINFO_VERSION(0, 12): device_create_file(msm_soc_device, &msm_soc_attr_chip_family); device_create_file(msm_soc_device, &msm_soc_attr_raw_device_family); device_create_file(msm_soc_device, &msm_soc_attr_raw_device_number); case SOCINFO_VERSION(0, 11): case SOCINFO_VERSION(0, 10): device_create_file(msm_soc_device, &msm_soc_attr_serial_number); case SOCINFO_VERSION(0, 9): device_create_file(msm_soc_device, &msm_soc_attr_foundry_id); case SOCINFO_VERSION(0, 8): case SOCINFO_VERSION(0, 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 SOCINFO_VERSION(0, 6): device_create_file(msm_soc_device, &msm_soc_attr_platform_subtype); device_create_file(msm_soc_device, &msm_soc_attr_platform_subtype_id); case SOCINFO_VERSION(0, 5): device_create_file(msm_soc_device, &msm_soc_attr_accessory_chip); case SOCINFO_VERSION(0, 4): device_create_file(msm_soc_device, &msm_soc_attr_platform_version); case SOCINFO_VERSION(0, 3): device_create_file(msm_soc_device, &msm_soc_attr_hw_platform); case SOCINFO_VERSION(0, 2): device_create_file(msm_soc_device, &msm_soc_attr_raw_id); device_create_file(msm_soc_device, &msm_soc_attr_raw_version); case SOCINFO_VERSION(0, 1): device_create_file(msm_soc_device, &msm_soc_attr_build_id); break; default: pr_err("Unknown socinfo format: v%u.%u\n", SOCINFO_VERSION_MAJOR(socinfo_format), SOCINFO_VERSION_MINOR(socinfo_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->family = "Snapdragon"; soc_dev_attr->machine = socinfo_get_id_string(); 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_sysfs(void) { struct device *msm_soc_device; struct soc_device *soc_dev; struct soc_device_attribute *soc_dev_attr; if (!socinfo) { pr_err("No socinfo found!\n"); return -ENODEV; } soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); if (!soc_dev_attr) { pr_err("Soc Device alloc failed!\n"); 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("Soc device register failed\n"); return -EIO; } msm_soc_device = soc_device_to_device(soc_dev); populate_soc_sysfs_files(msm_soc_device); return 0; } late_initcall(socinfo_init_sysfs); static void socinfo_print(void) { uint32_t f_maj = SOCINFO_VERSION_MAJOR(socinfo_format); uint32_t f_min = SOCINFO_VERSION_MINOR(socinfo_format); uint32_t v_maj = SOCINFO_VERSION_MAJOR(socinfo->v0_1.version); uint32_t v_min = SOCINFO_VERSION_MINOR(socinfo->v0_1.version); switch (socinfo_format) { case SOCINFO_VERSION(0, 1): pr_info("v%u.%u, id=%u, ver=%u.%u\n", f_maj, f_min, socinfo->v0_1.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->v0_1.id, v_maj, v_min, socinfo->v0_2.raw_id, socinfo->v0_2.raw_version); 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->v0_1.id, v_maj, v_min, socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, socinfo->v0_3.hw_platform); 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->v0_1.id, v_maj, v_min, socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, socinfo->v0_3.hw_platform, socinfo->v0_4.platform_version); 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->v0_1.id, v_maj, v_min, socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, socinfo->v0_3.hw_platform, socinfo->v0_4.platform_version, socinfo->v0_5.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->v0_1.id, v_maj, v_min, socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, socinfo->v0_3.hw_platform, socinfo->v0_4.platform_version, socinfo->v0_5.accessory_chip, socinfo->v0_6.hw_platform_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->v0_1.id, v_maj, v_min, socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, socinfo->v0_3.hw_platform, socinfo->v0_4.platform_version, socinfo->v0_5.accessory_chip, socinfo->v0_6.hw_platform_subtype, socinfo->v0_7.pmic_model, socinfo->v0_7.pmic_die_revision); 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->v0_1.id, v_maj, v_min, socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, socinfo->v0_3.hw_platform, socinfo->v0_4.platform_version, socinfo->v0_5.accessory_chip, socinfo->v0_6.hw_platform_subtype, socinfo->v0_7.pmic_model, socinfo->v0_7.pmic_die_revision, socinfo->v0_9.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->v0_1.id, v_maj, v_min, socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, socinfo->v0_3.hw_platform, socinfo->v0_4.platform_version, socinfo->v0_5.accessory_chip, socinfo->v0_6.hw_platform_subtype, socinfo->v0_7.pmic_model, socinfo->v0_7.pmic_die_revision, socinfo->v0_9.foundry_id, socinfo->v0_10.serial_number); 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->v0_1.id, v_maj, v_min, socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, socinfo->v0_3.hw_platform, socinfo->v0_4.platform_version, socinfo->v0_5.accessory_chip, socinfo->v0_6.hw_platform_subtype, socinfo->v0_7.pmic_model, socinfo->v0_7.pmic_die_revision, socinfo->v0_9.foundry_id, socinfo->v0_10.serial_number, socinfo->v0_11.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->v0_1.id, v_maj, v_min, socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, socinfo->v0_3.hw_platform, socinfo->v0_4.platform_version, socinfo->v0_5.accessory_chip, socinfo->v0_6.hw_platform_subtype, socinfo->v0_7.pmic_model, socinfo->v0_7.pmic_die_revision, socinfo->v0_9.foundry_id, socinfo->v0_10.serial_number, socinfo->v0_11.num_pmics, socinfo->v0_12.chip_family, socinfo->v0_12.raw_device_family, socinfo->v0_12.raw_device_number); break; default: pr_err("Unknown format found: v%u.%u\n", f_maj, f_min); break; } } static void socinfo_select_format(void) { uint32_t f_maj = SOCINFO_VERSION_MAJOR(socinfo->v0_1.format); uint32_t f_min = SOCINFO_VERSION_MINOR(socinfo->v0_1.format); if (f_maj != 0) { pr_err("Unsupported format v%u.%u. Falling back to dummy values.\n", f_maj, f_min); socinfo = setup_dummy_socinfo(); } if (socinfo->v0_1.format > MAX_SOCINFO_FORMAT) { pr_warn("Unsupported format v%u.%u. Falling back to v%u.%u.\n", f_maj, f_min, SOCINFO_VERSION_MAJOR(MAX_SOCINFO_FORMAT), SOCINFO_VERSION_MINOR(MAX_SOCINFO_FORMAT)); socinfo_format = MAX_SOCINFO_FORMAT; } else { socinfo_format = socinfo->v0_1.format; } } int __init socinfo_init(void) { static bool socinfo_init_done; size_t size; if (socinfo_init_done) return 0; socinfo = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, &size); if (IS_ERR_OR_NULL(socinfo)) { pr_warn("Can't find SMEM_HW_SW_BUILD_ID; falling back on dummy values.\n"); socinfo = setup_dummy_socinfo(); } socinfo_select_format(); WARN(!socinfo_get_id(), "Unknown SOC ID!\n"); if (socinfo_get_id() >= ARRAY_SIZE(cpu_of_id)) BUG_ON("New IDs added! ID => CPU mapping needs an update.\n"); else cur_cpu = cpu_of_id[socinfo->v0_1.id].generic_soc_type; boot_stats_init(); socinfo_print(); arch_read_hardware_id = msm_read_hardware_id; socinfo_init_done = true; return 0; } subsys_initcall(socinfo_init);