socinfo.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2009-2017, 2021 The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2017-2019, Linaro Ltd.
  5. * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  6. */
  7. #include <linux/debugfs.h>
  8. #include <linux/err.h>
  9. #include <linux/module.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/random.h>
  12. #include <linux/slab.h>
  13. #include <linux/soc/qcom/smem.h>
  14. #include <linux/string.h>
  15. #include <linux/sys_soc.h>
  16. #include <linux/types.h>
  17. #include <soc/qcom/socinfo.h>
  18. #include <asm/unaligned.h>
  19. #include <linux/samsung/debug/sec_debug.h>
  20. /*
  21. * SoC version type with major number in the upper 16 bits and minor
  22. * number in the lower 16 bits.
  23. */
  24. #define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff)
  25. #define SOCINFO_MINOR(ver) ((ver) & 0xffff)
  26. #define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff))
  27. #define SMEM_SOCINFO_BUILD_ID_LENGTH 32
  28. #define SMEM_SOCINFO_CHIP_ID_LENGTH 32
  29. #define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
  30. #define SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE 128
  31. #define SMEM_IMAGE_VERSION_SIZE 4096
  32. #define SMEM_IMAGE_VERSION_NAME_SIZE 75
  33. #define SMEM_IMAGE_VERSION_VARIANT_SIZE 20
  34. #define SMEM_IMAGE_VERSION_VARIANT_OFFSET SMEM_IMAGE_VERSION_NAME_SIZE
  35. #define SMEM_IMAGE_VERSION_OEM_SIZE 32
  36. #define SMEM_IMAGE_VERSION_OEM_OFFSET (SMEM_IMAGE_VERSION_VARIANT_OFFSET+SMEM_IMAGE_VERSION_VARIANT_SIZE)
  37. static uint32_t socinfo_format;
  38. static const char *sku;
  39. enum {
  40. HW_PLATFORM_UNKNOWN = 0,
  41. HW_PLATFORM_SURF = 1,
  42. HW_PLATFORM_FFA = 2,
  43. HW_PLATFORM_FLUID = 3,
  44. HW_PLATFORM_SVLTE_FFA = 4,
  45. HW_PLATFORM_SVLTE_SURF = 5,
  46. HW_PLATFORM_MTP_MDM = 7,
  47. HW_PLATFORM_MTP = 8,
  48. HW_PLATFORM_LIQUID = 9,
  49. /* Dragonboard platform id is assigned as 10 in CDT */
  50. HW_PLATFORM_DRAGON = 10,
  51. HW_PLATFORM_QRD = 11,
  52. HW_PLATFORM_HRD = 13,
  53. HW_PLATFORM_DTV = 14,
  54. HW_PLATFORM_RCM = 21,
  55. HW_PLATFORM_STP = 23,
  56. HW_PLATFORM_SBC = 24,
  57. HW_PLATFORM_ADP = 25,
  58. HW_PLATFORM_HDK = 31,
  59. HW_PLATFORM_ATP = 33,
  60. HW_PLATFORM_IDP = 34,
  61. HW_PLATFORM_QXR = 38,
  62. HW_PLATFORM_INVALID
  63. };
  64. static const char * const hw_platform[] = {
  65. [HW_PLATFORM_UNKNOWN] = "Unknown",
  66. [HW_PLATFORM_SURF] = "Surf",
  67. [HW_PLATFORM_FFA] = "FFA",
  68. [HW_PLATFORM_FLUID] = "Fluid",
  69. [HW_PLATFORM_SVLTE_FFA] = "SVLTE_FFA",
  70. [HW_PLATFORM_SVLTE_SURF] = "SLVTE_SURF",
  71. [HW_PLATFORM_MTP_MDM] = "MDM_MTP_NO_DISPLAY",
  72. [HW_PLATFORM_MTP] = "MTP",
  73. [HW_PLATFORM_RCM] = "RCM",
  74. [HW_PLATFORM_LIQUID] = "Liquid",
  75. [HW_PLATFORM_DRAGON] = "Dragon",
  76. [HW_PLATFORM_QRD] = "QRD",
  77. [HW_PLATFORM_HRD] = "HRD",
  78. [HW_PLATFORM_DTV] = "DTV",
  79. [HW_PLATFORM_STP] = "STP",
  80. [HW_PLATFORM_SBC] = "SBC",
  81. [HW_PLATFORM_ADP] = "ADP",
  82. [HW_PLATFORM_HDK] = "HDK",
  83. [HW_PLATFORM_ATP] = "ATP",
  84. [HW_PLATFORM_IDP] = "IDP",
  85. [HW_PLATFORM_QXR] = "QXR",
  86. };
  87. enum {
  88. PLATFORM_SUBTYPE_QRD = 0x0,
  89. PLATFORM_SUBTYPE_SKUAA = 0x1,
  90. PLATFORM_SUBTYPE_SKUF = 0x2,
  91. PLATFORM_SUBTYPE_SKUAB = 0x3,
  92. PLATFORM_SUBTYPE_SKUG = 0x5,
  93. PLATFORM_SUBTYPE_QRD_INVALID,
  94. };
  95. static const char * const qrd_hw_platform_subtype[] = {
  96. [PLATFORM_SUBTYPE_QRD] = "QRD",
  97. [PLATFORM_SUBTYPE_SKUAA] = "SKUAA",
  98. [PLATFORM_SUBTYPE_SKUF] = "SKUF",
  99. [PLATFORM_SUBTYPE_SKUAB] = "SKUAB",
  100. [PLATFORM_SUBTYPE_SKUG] = "SKUG",
  101. [PLATFORM_SUBTYPE_QRD_INVALID] = "INVALID",
  102. };
  103. enum {
  104. PLATFORM_SUBTYPE_UNKNOWN = 0x0,
  105. PLATFORM_SUBTYPE_CHARM = 0x1,
  106. PLATFORM_SUBTYPE_STRANGE = 0x2,
  107. PLATFORM_SUBTYPE_STRANGE_2A = 0x3,
  108. PLATFORM_SUBTYPE_INVALID,
  109. };
  110. static const char * const hw_platform_subtype[] = {
  111. [PLATFORM_SUBTYPE_UNKNOWN] = "Unknown",
  112. [PLATFORM_SUBTYPE_CHARM] = "charm",
  113. [PLATFORM_SUBTYPE_STRANGE] = "strange",
  114. [PLATFORM_SUBTYPE_STRANGE_2A] = "strange_2a",
  115. [PLATFORM_SUBTYPE_INVALID] = "Invalid",
  116. };
  117. static const char * const hw_platform_feature_code[] = {
  118. [SOCINFO_FC_UNKNOWN] = "Unknown",
  119. [SOCINFO_FC_AA] = "AA",
  120. [SOCINFO_FC_AB] = "AB",
  121. [SOCINFO_FC_AC] = "AC",
  122. [SOCINFO_FC_AD] = "AD",
  123. [SOCINFO_FC_AE] = "AE",
  124. [SOCINFO_FC_AF] = "AF",
  125. [SOCINFO_FC_AG] = "AG",
  126. [SOCINFO_FC_AH] = "AH",
  127. };
  128. static const char * const hw_platform_wfeature_code[] = {
  129. [SOCINFO_FC_W0 - SOCINFO_FC_W0] = "W0",
  130. [SOCINFO_FC_W1 - SOCINFO_FC_W0] = "W1",
  131. [SOCINFO_FC_W2 - SOCINFO_FC_W0] = "W2",
  132. [SOCINFO_FC_W3 - SOCINFO_FC_W0] = "W3",
  133. [SOCINFO_FC_W4 - SOCINFO_FC_W0] = "W4",
  134. [SOCINFO_FC_W5 - SOCINFO_FC_W0] = "W5",
  135. [SOCINFO_FC_W6 - SOCINFO_FC_W0] = "W6",
  136. [SOCINFO_FC_W7 - SOCINFO_FC_W0] = "W7",
  137. [SOCINFO_FC_W8 - SOCINFO_FC_W0] = "W8",
  138. [SOCINFO_FC_W9 - SOCINFO_FC_W0] = "W9",
  139. [SOCINFO_FC_WA - SOCINFO_FC_W0] = "WA",
  140. [SOCINFO_FC_WB - SOCINFO_FC_W0] = "WB",
  141. [SOCINFO_FC_WC - SOCINFO_FC_W0] = "WC",
  142. [SOCINFO_FC_WD - SOCINFO_FC_W0] = "WD",
  143. [SOCINFO_FC_WE - SOCINFO_FC_W0] = "WE",
  144. [SOCINFO_FC_WF - SOCINFO_FC_W0] = "WF",
  145. };
  146. static const char * const hw_platform_ifeature_code[] = {
  147. [SOCINFO_FC_Y0 - SOCINFO_FC_Y0] = "Y0",
  148. [SOCINFO_FC_Y1 - SOCINFO_FC_Y0] = "Y1",
  149. [SOCINFO_FC_Y2 - SOCINFO_FC_Y0] = "Y2",
  150. [SOCINFO_FC_Y3 - SOCINFO_FC_Y0] = "Y3",
  151. [SOCINFO_FC_Y4 - SOCINFO_FC_Y0] = "Y4",
  152. [SOCINFO_FC_Y5 - SOCINFO_FC_Y0] = "Y5",
  153. [SOCINFO_FC_Y6 - SOCINFO_FC_Y0] = "Y6",
  154. [SOCINFO_FC_Y7 - SOCINFO_FC_Y0] = "Y7",
  155. [SOCINFO_FC_Y8 - SOCINFO_FC_Y0] = "Y8",
  156. [SOCINFO_FC_Y9 - SOCINFO_FC_Y0] = "Y9",
  157. [SOCINFO_FC_YA - SOCINFO_FC_Y0] = "YA",
  158. [SOCINFO_FC_YB - SOCINFO_FC_Y0] = "YB",
  159. [SOCINFO_FC_YC - SOCINFO_FC_Y0] = "YC",
  160. [SOCINFO_FC_YD - SOCINFO_FC_Y0] = "YD",
  161. [SOCINFO_FC_YE - SOCINFO_FC_Y0] = "YE",
  162. [SOCINFO_FC_YF - SOCINFO_FC_Y0] = "YF",
  163. };
  164. /*
  165. * SMEM item id, used to acquire handles to respective
  166. * SMEM region.
  167. */
  168. #define SMEM_HW_SW_BUILD_ID 137
  169. #ifdef CONFIG_DEBUG_FS
  170. /*
  171. * SMEM Image table indices
  172. */
  173. #define SMEM_IMAGE_TABLE_BOOT_INDEX 0
  174. #define SMEM_IMAGE_TABLE_TZ_INDEX 1
  175. #define SMEM_IMAGE_TABLE_RPM_INDEX 3
  176. #define SMEM_IMAGE_TABLE_APPS_INDEX 10
  177. #define SMEM_IMAGE_TABLE_MPSS_INDEX 11
  178. #define SMEM_IMAGE_TABLE_ADSP_INDEX 12
  179. #define SMEM_IMAGE_TABLE_CNSS_INDEX 13
  180. #define SMEM_IMAGE_TABLE_VIDEO_INDEX 14
  181. #define SMEM_IMAGE_TABLE_DSPS_INDEX 15
  182. #define SMEM_IMAGE_TABLE_CDSP_INDEX 16
  183. #define SMEM_IMAGE_TABLE_CDSP1_INDEX 19
  184. #define SMEM_IMAGE_TABLE_GPDSP_INDEX 20
  185. #define SMEM_IMAGE_TABLE_GPDSP1_INDEX 21
  186. #define SMEM_IMAGE_VERSION_TABLE 469
  187. /*
  188. * SMEM Image table names
  189. */
  190. static const char *const socinfo_image_names[] = {
  191. [SMEM_IMAGE_TABLE_ADSP_INDEX] = "adsp",
  192. [SMEM_IMAGE_TABLE_APPS_INDEX] = "apps",
  193. [SMEM_IMAGE_TABLE_BOOT_INDEX] = "boot",
  194. [SMEM_IMAGE_TABLE_CNSS_INDEX] = "cnss",
  195. [SMEM_IMAGE_TABLE_MPSS_INDEX] = "mpss",
  196. [SMEM_IMAGE_TABLE_RPM_INDEX] = "rpm",
  197. [SMEM_IMAGE_TABLE_TZ_INDEX] = "tz",
  198. [SMEM_IMAGE_TABLE_VIDEO_INDEX] = "video",
  199. [SMEM_IMAGE_TABLE_DSPS_INDEX] = "dsps",
  200. [SMEM_IMAGE_TABLE_CDSP_INDEX] = "cdsp",
  201. [SMEM_IMAGE_TABLE_CDSP1_INDEX] = "cdsp1",
  202. [SMEM_IMAGE_TABLE_GPDSP_INDEX] = "gpdsp",
  203. [SMEM_IMAGE_TABLE_GPDSP1_INDEX] = "gpdsp1",
  204. };
  205. static const char *const pmic_models[] = {
  206. [0] = "Unknown PMIC model",
  207. [1] = "PM8941",
  208. [2] = "PM8841",
  209. [3] = "PM8019",
  210. [4] = "PM8226",
  211. [5] = "PM8110",
  212. [6] = "PMA8084",
  213. [7] = "PMI8962",
  214. [8] = "PMD9635",
  215. [9] = "PM8994",
  216. [10] = "PMI8994",
  217. [11] = "PM8916",
  218. [12] = "PM8004",
  219. [13] = "PM8909/PM8058",
  220. [14] = "PM8028",
  221. [15] = "PM8901",
  222. [16] = "PM8950/PM8027",
  223. [17] = "PMI8950/ISL9519",
  224. [18] = "PMK8001/PM8921",
  225. [19] = "PMI8996/PM8018",
  226. [20] = "PM8998/PM8015",
  227. [21] = "PMI8998/PM8014",
  228. [22] = "PM8821",
  229. [23] = "PM8038",
  230. [24] = "PM8005/PM8922",
  231. [25] = "PM8917",
  232. [26] = "PM660L",
  233. [27] = "PM660",
  234. [30] = "PM8150",
  235. [31] = "PM8150L",
  236. [32] = "PM8150B",
  237. [33] = "PMK8002",
  238. [36] = "PM8009",
  239. [38] = "PM8150C",
  240. [41] = "SMB2351",
  241. [45] = "PM6125",
  242. [47] = "PMK8350",
  243. [48] = "PM8350",
  244. [49] = "PM8350C",
  245. [50] = "PM8350B",
  246. [51] = "PMR735A",
  247. [52] = "PMR735B",
  248. [58] = "PM8450",
  249. [65] = "PM8010",
  250. };
  251. #endif /* CONFIG_DEBUG_FS */
  252. /* Socinfo SMEM item structure */
  253. struct socinfo {
  254. __le32 fmt;
  255. __le32 id;
  256. __le32 ver;
  257. char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH];
  258. /* Version 2 */
  259. __le32 raw_id;
  260. __le32 raw_ver;
  261. /* Version 3 */
  262. __le32 hw_plat;
  263. /* Version 4 */
  264. __le32 plat_ver;
  265. /* Version 5 */
  266. __le32 accessory_chip;
  267. /* Version 6 */
  268. __le32 hw_plat_subtype;
  269. /* Version 7 */
  270. __le32 pmic_model;
  271. __le32 pmic_die_rev;
  272. /* Version 8 */
  273. __le32 pmic_model_1;
  274. __le32 pmic_die_rev_1;
  275. __le32 pmic_model_2;
  276. __le32 pmic_die_rev_2;
  277. /* Version 9 */
  278. __le32 foundry_id;
  279. /* Version 10 */
  280. __le32 serial_num;
  281. /* Version 11 */
  282. __le32 num_pmics;
  283. __le32 pmic_array_offset;
  284. /* Version 12 */
  285. __le32 chip_family;
  286. __le32 raw_device_family;
  287. __le32 raw_device_num;
  288. /* Version 13 */
  289. __le32 nproduct_id;
  290. char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH];
  291. /* Version 14 */
  292. __le32 num_clusters;
  293. __le32 ncluster_array_offset;
  294. __le32 num_subset_parts;
  295. __le32 nsubset_parts_array_offset;
  296. /* Version 15 */
  297. __le32 nmodem_supported;
  298. /* Version 16 */
  299. __le32 feature_code;
  300. __le32 pcode;
  301. __le32 npartnamemap_offset;
  302. __le32 nnum_partname_mapping;
  303. /* Version 17 */
  304. __le32 oem_variant;
  305. /* Version 18 */
  306. __le32 num_kvps;
  307. __le32 kvps_offset;
  308. /* Version 19 */
  309. __le32 num_func_clusters;
  310. __le32 boot_cluster;
  311. __le32 boot_core;
  312. /* Version 20 */
  313. __le32 raw_package_type;
  314. } *socinfo;
  315. #ifdef CONFIG_DEBUG_FS
  316. struct socinfo_params {
  317. u32 raw_device_family;
  318. u32 hw_plat_subtype;
  319. u32 accessory_chip;
  320. u32 raw_device_num;
  321. u32 chip_family;
  322. u32 foundry_id;
  323. u32 plat_ver;
  324. u32 raw_ver;
  325. u32 hw_plat;
  326. u32 fmt;
  327. u32 nproduct_id;
  328. u32 num_clusters;
  329. u32 ncluster_array_offset;
  330. u32 num_subset_parts;
  331. u32 nsubset_parts_array_offset;
  332. u32 nmodem_supported;
  333. u32 feature_code;
  334. u32 pcode;
  335. u32 oem_variant;
  336. u32 num_func_clusters;
  337. u32 boot_cluster;
  338. u32 boot_core;
  339. u32 raw_package_type;
  340. };
  341. struct smem_image_version {
  342. char name[SMEM_IMAGE_VERSION_NAME_SIZE];
  343. char variant[SMEM_IMAGE_VERSION_VARIANT_SIZE];
  344. char pad;
  345. char oem[SMEM_IMAGE_VERSION_OEM_SIZE];
  346. };
  347. #endif /* CONFIG_DEBUG_FS */
  348. #define MAX_SOCINFO_ATTRS 50
  349. /* sysfs attributes */
  350. #define ATTR_DEFINE(param) \
  351. static DEVICE_ATTR(param, 0444, msm_get_##param, NULL)
  352. /* sysfs attributes for subpart information */
  353. #define CREATE_PART_FUNCTION(part, part_enum) \
  354. static ssize_t \
  355. msm_get_##part(struct device *dev, \
  356. struct device_attribute *attr, \
  357. char *buf) \
  358. { \
  359. u32 *part_info; \
  360. int num_parts = 0; \
  361. int str_pos = 0, i = 0, ret = 0; \
  362. num_parts = socinfo_get_part_count(part_enum); \
  363. if (num_parts <= 0) \
  364. return -EINVAL; \
  365. part_info = kmalloc_array(num_parts, sizeof(*part_info), GFP_KERNEL); \
  366. ret = socinfo_get_subpart_info(part_enum, part_info, num_parts); \
  367. if (ret < 0) { \
  368. kfree(part_info); \
  369. return -EINVAL; \
  370. } \
  371. for (i = 0; i < num_parts; i++) { \
  372. str_pos += scnprintf(buf+str_pos, PAGE_SIZE-str_pos, "0x%x", \
  373. part_info[i]); \
  374. if (i != num_parts-1) \
  375. str_pos += scnprintf(buf+str_pos, PAGE_SIZE-str_pos, ","); \
  376. } \
  377. str_pos += scnprintf(buf+str_pos, PAGE_SIZE-str_pos, "\n"); \
  378. kfree(part_info); \
  379. return str_pos; \
  380. } \
  381. ATTR_DEFINE(part) \
  382. struct qcom_socinfo {
  383. struct soc_device *soc_dev;
  384. struct soc_device_attribute attr;
  385. #ifdef CONFIG_DEBUG_FS
  386. struct dentry *dbg_root;
  387. struct socinfo_params info;
  388. #endif /* CONFIG_DEBUG_FS */
  389. };
  390. struct soc_id {
  391. unsigned int id;
  392. const char *name;
  393. };
  394. #define PART_NAME_MAX 32
  395. struct gpu_info {
  396. __le32 gpu_chip_id;
  397. __le32 vulkan_id;
  398. char part_name[PART_NAME_MAX];
  399. };
  400. struct socinfo_partinfo {
  401. __le32 part_type;
  402. union {
  403. struct gpu_info gpu_info;
  404. };
  405. };
  406. struct socinfo_partinfo partinfo[SOCINFO_PART_MAX_PARTTYPE];
  407. static const struct soc_id soc_id[] = {
  408. { 87, "MSM8960" },
  409. { 109, "APQ8064" },
  410. { 122, "MSM8660A" },
  411. { 123, "MSM8260A" },
  412. { 124, "APQ8060A" },
  413. { 126, "MSM8974" },
  414. { 130, "MPQ8064" },
  415. { 138, "MSM8960AB" },
  416. { 139, "APQ8060AB" },
  417. { 140, "MSM8260AB" },
  418. { 141, "MSM8660AB" },
  419. { 145, "MSM8626" },
  420. { 147, "MSM8610" },
  421. { 153, "APQ8064AB" },
  422. { 158, "MSM8226" },
  423. { 159, "MSM8526" },
  424. { 161, "MSM8110" },
  425. { 162, "MSM8210" },
  426. { 163, "MSM8810" },
  427. { 164, "MSM8212" },
  428. { 165, "MSM8612" },
  429. { 166, "MSM8112" },
  430. { 168, "MSM8225Q" },
  431. { 169, "MSM8625Q" },
  432. { 170, "MSM8125Q" },
  433. { 172, "APQ8064AA" },
  434. { 178, "APQ8084" },
  435. { 184, "APQ8074" },
  436. { 185, "MSM8274" },
  437. { 186, "MSM8674" },
  438. { 194, "MSM8974PRO-AC" },
  439. { 198, "MSM8126" },
  440. { 199, "APQ8026" },
  441. { 200, "MSM8926" },
  442. { 205, "MSM8326" },
  443. { 206, "MSM8916" },
  444. { 207, "MSM8994" },
  445. { 208, "APQ8074PRO-AA" },
  446. { 209, "APQ8074PRO-AB" },
  447. { 210, "APQ8074PRO-AC" },
  448. { 211, "MSM8274PRO-AA" },
  449. { 212, "MSM8274PRO-AB" },
  450. { 213, "MSM8274PRO-AC" },
  451. { 214, "MSM8674PRO-AA" },
  452. { 215, "MSM8674PRO-AB" },
  453. { 216, "MSM8674PRO-AC" },
  454. { 217, "MSM8974PRO-AA" },
  455. { 218, "MSM8974PRO-AB" },
  456. { 219, "APQ8028" },
  457. { 220, "MSM8128" },
  458. { 221, "MSM8228" },
  459. { 222, "MSM8528" },
  460. { 223, "MSM8628" },
  461. { 224, "MSM8928" },
  462. { 225, "MSM8510" },
  463. { 226, "MSM8512" },
  464. { 233, "MSM8936" },
  465. { 239, "MSM8939" },
  466. { 240, "APQ8036" },
  467. { 241, "APQ8039" },
  468. { 246, "MSM8996" },
  469. { 247, "APQ8016" },
  470. { 248, "MSM8216" },
  471. { 249, "MSM8116" },
  472. { 250, "MSM8616" },
  473. { 251, "MSM8992" },
  474. { 253, "APQ8094" },
  475. { 290, "MDM9607" },
  476. { 291, "APQ8096" },
  477. { 292, "MSM8998" },
  478. { 293, "MSM8953" },
  479. { 296, "MDM8207" },
  480. { 297, "MDM9207" },
  481. { 298, "MDM9307" },
  482. { 299, "MDM9628" },
  483. { 304, "APQ8053" },
  484. { 305, "MSM8996SG" },
  485. { 310, "MSM8996AU" },
  486. { 311, "APQ8096AU" },
  487. { 312, "APQ8096SG" },
  488. { 317, "SDM660" },
  489. { 318, "SDM630" },
  490. { 319, "APQ8098" },
  491. { 321, "SDM845" },
  492. { 322, "MDM9206" },
  493. { 323, "IPQ8074" },
  494. { 324, "SDA660" },
  495. { 325, "SDM658" },
  496. { 326, "SDA658" },
  497. { 327, "SDA630" },
  498. { 338, "SDM450" },
  499. { 341, "SDA845" },
  500. { 342, "IPQ8072" },
  501. { 343, "IPQ8076" },
  502. { 344, "IPQ8078" },
  503. { 345, "SDM636" },
  504. { 346, "SDA636" },
  505. { 349, "SDM632" },
  506. { 350, "SDA632" },
  507. { 351, "SDA450" },
  508. { 356, "SM8250" },
  509. { 362, "SA8155" },
  510. { 367, "SA8155P" },
  511. { 375, "IPQ8070" },
  512. { 376, "IPQ8071" },
  513. { 377, "SA6155P" },
  514. { 384, "SA6155" },
  515. { 389, "IPQ8072A" },
  516. { 390, "IPQ8074A" },
  517. { 391, "IPQ8076A" },
  518. { 392, "IPQ8078A" },
  519. { 394, "SM6125" },
  520. { 395, "IPQ8070A" },
  521. { 396, "IPQ8071A" },
  522. { 402, "IPQ6018" },
  523. { 403, "IPQ6028" },
  524. { 405, "SA8195P" },
  525. { 421, "IPQ6000" },
  526. { 422, "IPQ6010" },
  527. { 425, "SC7180" },
  528. { 434, "SM6350" },
  529. { 439, "SM8350" },
  530. { 449, "SC8280XP" },
  531. { 453, "IPQ6005" },
  532. { 454, "HOLI" },
  533. { 455, "QRB5165" },
  534. { 457, "SM8450" },
  535. { 459, "SM7225" },
  536. { 460, "SA8295P" },
  537. { 461, "SA8540P" },
  538. { 472, "HOLIPRO" },
  539. { 480, "SM8450" },
  540. { 482, "SM8450" },
  541. { 487, "SC7280" },
  542. { 495, "SC7180P" },
  543. { 507, "BLAIR" },
  544. { 518, "KHAJE" },
  545. { 519, "KALAMA" },
  546. { 536, "KALAMAP" },
  547. { 539, "CINDERRU" },
  548. { 545, "CINDERDU" },
  549. { 557, "PINEAPPLE" },
  550. { 565, "BLAIRP" },
  551. { 629, "NIOBE" },
  552. { 652, "NIOBE" },
  553. { 577, "PINEAPPLEP" },
  554. { 578, "BLAIR-LITE" },
  555. { 605, "SA_MONACOAU_ADAS" },
  556. { 606, "SA_MONACOAU_IVI" },
  557. { 607, "SA_MONACOAU_SRV1L" },
  558. { 614, "CLIFFS" },
  559. { 620, "SA_MONACOAU_SRV1L_FFC" },
  560. { 623, "PITTI" },
  561. { 632, "CLIFFS7" },
  562. { 636, "VOLCANO" },
  563. { 640, "VOLCANO6" },
  564. { 641, "VOLCANO6P" },
  565. { 642, "CLIFFSP" },
  566. { 643, "CLIFFS7P" },
  567. { 549, "ANORAK" },
  568. };
  569. static struct attribute *msm_custom_socinfo_attrs[MAX_SOCINFO_ATTRS];
  570. static const char *socinfo_machine(struct device *dev, unsigned int id)
  571. {
  572. int idx;
  573. for (idx = 0; idx < ARRAY_SIZE(soc_id); idx++) {
  574. if (soc_id[idx].id == id)
  575. return soc_id[idx].name;
  576. }
  577. return NULL;
  578. }
  579. /* Version 3 */
  580. static uint32_t socinfo_get_platform_type(void)
  581. {
  582. return socinfo ?
  583. (socinfo_format >= SOCINFO_VERSION(0, 3) ?
  584. le32_to_cpu(socinfo->hw_plat) : 0)
  585. : 0;
  586. }
  587. /* Version 4 */
  588. static uint32_t socinfo_get_platform_version(void)
  589. {
  590. return socinfo ?
  591. (socinfo_format >= SOCINFO_VERSION(0, 4) ?
  592. le32_to_cpu(socinfo->plat_ver) : 0)
  593. : 0;
  594. }
  595. /* Version 6 */
  596. static uint32_t socinfo_get_platform_subtype(void)
  597. {
  598. return socinfo ?
  599. (socinfo_format >= SOCINFO_VERSION(0, 6) ?
  600. le32_to_cpu(socinfo->hw_plat_subtype) : 0)
  601. : 0;
  602. }
  603. /* Version 12 */
  604. static uint32_t socinfo_get_chip_family(void)
  605. {
  606. return socinfo ?
  607. (socinfo_format >= SOCINFO_VERSION(0, 12) ?
  608. le32_to_cpu(socinfo->chip_family) : 0)
  609. : 0;
  610. }
  611. /* Version 13 */
  612. static char *socinfo_get_chip_name(void)
  613. {
  614. return socinfo ?
  615. (socinfo_format >= SOCINFO_VERSION(0, 13) ?
  616. socinfo->chip_id : "N/A")
  617. : "N/A";
  618. }
  619. /* Version 14 */
  620. static uint32_t socinfo_get_num_clusters(void)
  621. {
  622. return socinfo ?
  623. (socinfo_format >= SOCINFO_VERSION(0, 14) ?
  624. le32_to_cpu(socinfo->num_clusters) : 0)
  625. : 0;
  626. }
  627. static uint32_t socinfo_get_ncluster_array_offset(void)
  628. {
  629. return socinfo ?
  630. (socinfo_format >= SOCINFO_VERSION(0, 14) ?
  631. le32_to_cpu(socinfo->ncluster_array_offset) : 0)
  632. : 0;
  633. }
  634. static uint32_t socinfo_get_num_subset_parts(void)
  635. {
  636. return socinfo ?
  637. (socinfo_format >= SOCINFO_VERSION(0, 14) ?
  638. le32_to_cpu(socinfo->num_subset_parts) : 0)
  639. : 0;
  640. }
  641. static uint32_t socinfo_get_nsubset_parts_array_offset(void)
  642. {
  643. return socinfo ?
  644. (socinfo_format >= SOCINFO_VERSION(0, 14) ?
  645. le32_to_cpu(socinfo->nsubset_parts_array_offset) : 0)
  646. : 0;
  647. }
  648. static uint32_t
  649. socinfo_get_subset_parts(void)
  650. {
  651. uint32_t num_parts = socinfo_get_num_subset_parts();
  652. uint32_t offset = socinfo_get_nsubset_parts_array_offset();
  653. uint32_t sub_parts = 0;
  654. void *info = socinfo;
  655. uint32_t part_entry;
  656. int i;
  657. if (!num_parts || !offset)
  658. return -EINVAL;
  659. info += offset;
  660. for (i = 0; i < num_parts; i++) {
  661. part_entry = get_unaligned_le32(info);
  662. if (part_entry & 1)
  663. sub_parts |= BIT(i);
  664. info += sizeof(uint32_t);
  665. }
  666. return sub_parts;
  667. }
  668. /* Version 16 */
  669. static uint32_t socinfo_get_feature_code_id(void)
  670. {
  671. uint32_t fc_id;
  672. if (!socinfo || socinfo_format < SOCINFO_VERSION(0, 16))
  673. return SOCINFO_FC_UNKNOWN;
  674. fc_id = le32_to_cpu(socinfo->feature_code);
  675. if (fc_id <= SOCINFO_FC_UNKNOWN || fc_id >= SOCINFO_FC_INT_RESERVE)
  676. return SOCINFO_FC_UNKNOWN;
  677. return fc_id;
  678. }
  679. static const char *socinfo_get_feature_code_mapping(void)
  680. {
  681. uint32_t id = socinfo_get_feature_code_id();
  682. if (id > SOCINFO_FC_UNKNOWN && id < SOCINFO_FC_EXT_RESERVE)
  683. return hw_platform_feature_code[id];
  684. else if (id >= SOCINFO_FC_W0 && id < SOCINFO_FC_SUBPART_RESERVE)
  685. return hw_platform_wfeature_code[id - SOCINFO_FC_W0];
  686. else if (id >= SOCINFO_FC_Y0 && id < SOCINFO_FC_INT_RESERVE)
  687. return hw_platform_ifeature_code[id - SOCINFO_FC_Y0];
  688. return NULL;
  689. }
  690. static uint32_t socinfo_get_pcode_id(void)
  691. {
  692. uint32_t pcode;
  693. if (!socinfo || socinfo_format < SOCINFO_VERSION(0, 16))
  694. return SOCINFO_PCODE_RESERVE;
  695. pcode = le32_to_cpu(socinfo->pcode);
  696. if (pcode <= SOCINFO_PCODE_UNKNOWN || pcode >= SOCINFO_PCODE_RESERVE)
  697. return SOCINFO_PCODE_UNKNOWN;
  698. return pcode;
  699. }
  700. /* Exported APIs */
  701. uint32_t socinfo_get_id(void)
  702. {
  703. return (socinfo) ? le32_to_cpu(socinfo->id) : 0;
  704. }
  705. EXPORT_SYMBOL(socinfo_get_id);
  706. const char *socinfo_get_id_string(void)
  707. {
  708. uint32_t id = socinfo_get_id();
  709. return socinfo_machine(NULL, id);
  710. }
  711. EXPORT_SYMBOL(socinfo_get_id_string);
  712. uint32_t socinfo_get_serial_number(void)
  713. {
  714. return (socinfo) ? le32_to_cpu(socinfo->serial_num) : 0;
  715. }
  716. EXPORT_SYMBOL(socinfo_get_serial_number);
  717. int socinfo_get_feature_code(void)
  718. {
  719. if (socinfo_format < SOCINFO_VERSION(0, 16)) {
  720. pr_warn("socinfo: Feature code is not supported by bootloaders\n");
  721. return -EINVAL;
  722. }
  723. return socinfo_get_feature_code_id();
  724. }
  725. EXPORT_SYMBOL(socinfo_get_feature_code);
  726. int socinfo_get_pcode(void)
  727. {
  728. if (socinfo_format < SOCINFO_VERSION(0, 16)) {
  729. pr_warn("socinfo: pcode is not supported by bootloaders\n");
  730. return -EINVAL;
  731. }
  732. return socinfo_get_pcode_id();
  733. }
  734. EXPORT_SYMBOL(socinfo_get_pcode);
  735. char *socinfo_get_partinfo_part_name(unsigned int part_id)
  736. {
  737. if (socinfo_format < SOCINFO_VERSION(0, 16) || part_id >= SOCINFO_PART_MAX_PARTTYPE)
  738. return NULL;
  739. switch (part_id) {
  740. case SOCINFO_PART_GPU:
  741. return partinfo[part_id].gpu_info.part_name;
  742. default:
  743. break;
  744. }
  745. return NULL;
  746. }
  747. EXPORT_SYMBOL(socinfo_get_partinfo_part_name);
  748. uint32_t socinfo_get_partinfo_chip_id(unsigned int part_id)
  749. {
  750. uint32_t chip_id;
  751. if (socinfo_format < SOCINFO_VERSION(0, 16) || part_id >= SOCINFO_PART_MAX_PARTTYPE)
  752. return 0;
  753. switch (part_id) {
  754. case SOCINFO_PART_GPU:
  755. chip_id = partinfo[part_id].gpu_info.gpu_chip_id;
  756. break;
  757. default:
  758. chip_id = 0;
  759. break;
  760. }
  761. return chip_id;
  762. }
  763. EXPORT_SYMBOL(socinfo_get_partinfo_chip_id);
  764. uint32_t socinfo_get_partinfo_vulkan_id(unsigned int part_id)
  765. {
  766. if (socinfo_format < SOCINFO_VERSION(0, 16) || part_id != SOCINFO_PART_GPU)
  767. return 0;
  768. return partinfo[part_id].gpu_info.vulkan_id;
  769. }
  770. EXPORT_SYMBOL(socinfo_get_partinfo_vulkan_id);
  771. uint32_t
  772. socinfo_get_cluster_info(enum subset_cluster_type cluster)
  773. {
  774. uint32_t sub_cluster, num_cluster, offset;
  775. void *cluster_val;
  776. void *info = socinfo;
  777. if (cluster >= NUM_CLUSTERS_MAX) {
  778. pr_err("Bad cluster\n");
  779. return -EINVAL;
  780. }
  781. num_cluster = socinfo_get_num_clusters();
  782. offset = socinfo_get_ncluster_array_offset();
  783. if (!num_cluster || !offset)
  784. return -EINVAL;
  785. info += offset;
  786. cluster_val = info + (sizeof(uint32_t) * cluster);
  787. sub_cluster = get_unaligned_le32(cluster_val);
  788. return sub_cluster;
  789. }
  790. EXPORT_SYMBOL(socinfo_get_cluster_info);
  791. bool
  792. socinfo_get_part_info(enum subset_part_type part)
  793. {
  794. uint32_t partinfo;
  795. uint32_t num_parts = socinfo_get_num_subset_parts();
  796. if ((part <= PART_UNKNOWN) || (part >= NUM_PARTS_MAX) || (part >= num_parts)) {
  797. pr_err("Bad part number\n");
  798. return false;
  799. }
  800. partinfo = socinfo_get_subset_parts();
  801. if (partinfo < 0) {
  802. pr_err("Failed to get part information\n");
  803. return false;
  804. }
  805. return (partinfo & BIT(part));
  806. }
  807. EXPORT_SYMBOL(socinfo_get_part_info);
  808. /**
  809. * socinfo_get_part_count - Get part count
  810. * @part: The subset_part_type to be checked
  811. *
  812. * Return the number of instances supported by the
  813. * firmware for the part on success and a negative
  814. * errno will be returned in error cases.
  815. */
  816. int
  817. socinfo_get_part_count(enum subset_part_type part)
  818. {
  819. int part_count = 1;
  820. uint32_t num_parts = socinfo_get_num_subset_parts();
  821. /* TODO: part_count to be read from SMEM after firmware adds support */
  822. if ((part <= PART_UNKNOWN) || (part >= NUM_PARTS_MAX) || (part >= num_parts)) {
  823. pr_err("Bad part number\n");
  824. return -EINVAL;
  825. }
  826. return part_count;
  827. }
  828. EXPORT_SYMBOL(socinfo_get_part_count);
  829. /**
  830. * socinfo_get_subpart_info - Get subpart information
  831. * @part: The subset_part_type to be checked
  832. * @part_info: Pointer to the subpart information.
  833. * Used to store the subpart information
  834. * for num_parts instances of the part.
  835. * @num_parts: Number of instances of the part for
  836. * which the subpart information is required.
  837. *
  838. * On success subpart information will be stored in the part_info
  839. * array for minimum of the number of instances requested and
  840. * the number of instances supported by the firmware.
  841. *
  842. * A value of zero will be returned on success and a negative
  843. * errno will be returned in error cases.
  844. */
  845. int
  846. socinfo_get_subpart_info(enum subset_part_type part,
  847. u32 *part_info,
  848. u32 num_parts)
  849. {
  850. uint32_t num_subset_parts = 0, offset = 0;
  851. void *info = socinfo;
  852. u32 i = 0, count = 0;
  853. int part_count = 0;
  854. if (!part_info)
  855. return -EINVAL;
  856. part_count = socinfo_get_part_count(part);
  857. if (part_count <= 0)
  858. return -EINVAL;
  859. num_subset_parts = socinfo_get_num_subset_parts();
  860. offset = socinfo_get_nsubset_parts_array_offset();
  861. if (!num_subset_parts || !offset)
  862. return -EINVAL;
  863. info += (offset + (part * sizeof(u32)));
  864. count = min_t(u32, num_parts, part_count);
  865. for (i = 0; i < count; i++) {
  866. part_info[i] = get_unaligned_le32(info);
  867. info += sizeof(u32);
  868. }
  869. return 0;
  870. }
  871. EXPORT_SYMBOL(socinfo_get_subpart_info);
  872. /* End Exported APIs */
  873. /* Sysfs interface */
  874. /* Version 3 */
  875. static ssize_t
  876. msm_get_hw_platform(struct device *dev,
  877. struct device_attribute *attr,
  878. char *buf)
  879. {
  880. uint32_t hw_type;
  881. hw_type = socinfo_get_platform_type();
  882. return scnprintf(buf, PAGE_SIZE, "%-.32s\n",
  883. hw_platform[hw_type]);
  884. }
  885. ATTR_DEFINE(hw_platform);
  886. /* Version 4 */
  887. static ssize_t
  888. msm_get_platform_version(struct device *dev,
  889. struct device_attribute *attr,
  890. char *buf)
  891. {
  892. return scnprintf(buf, PAGE_SIZE, "%u\n",
  893. socinfo_get_platform_version());
  894. }
  895. ATTR_DEFINE(platform_version);
  896. /* Version 6 */
  897. static ssize_t
  898. msm_get_platform_subtype_id(struct device *dev,
  899. struct device_attribute *attr,
  900. char *buf)
  901. {
  902. uint32_t hw_subtype;
  903. hw_subtype = socinfo_get_platform_subtype();
  904. return scnprintf(buf, PAGE_SIZE, "%u\n",
  905. hw_subtype);
  906. }
  907. ATTR_DEFINE(platform_subtype_id);
  908. static ssize_t
  909. msm_get_platform_subtype(struct device *dev,
  910. struct device_attribute *attr,
  911. char *buf)
  912. {
  913. uint32_t hw_subtype;
  914. hw_subtype = socinfo_get_platform_subtype();
  915. if (socinfo_get_platform_type() == HW_PLATFORM_QRD) {
  916. if (hw_subtype >= PLATFORM_SUBTYPE_QRD_INVALID) {
  917. pr_err("Invalid hardware platform sub type for qrd found\n");
  918. hw_subtype = PLATFORM_SUBTYPE_QRD_INVALID;
  919. }
  920. return scnprintf(buf, PAGE_SIZE, "%-.32s\n",
  921. qrd_hw_platform_subtype[hw_subtype]);
  922. } else {
  923. if (hw_subtype >= PLATFORM_SUBTYPE_INVALID) {
  924. pr_err("Invalid hardware platform subtype\n");
  925. hw_subtype = PLATFORM_SUBTYPE_INVALID;
  926. }
  927. return scnprintf(buf, PAGE_SIZE, "%-.32s\n",
  928. hw_platform_subtype[hw_subtype]);
  929. }
  930. }
  931. ATTR_DEFINE(platform_subtype);
  932. /* Version 12 */
  933. static ssize_t
  934. msm_get_chip_family(struct device *dev,
  935. struct device_attribute *attr,
  936. char *buf)
  937. {
  938. return scnprintf(buf, PAGE_SIZE, "0x%x\n",
  939. socinfo_get_chip_family());
  940. }
  941. ATTR_DEFINE(chip_family);
  942. /* Version 13 */
  943. static ssize_t
  944. msm_get_chip_id(struct device *dev,
  945. struct device_attribute *attr,
  946. char *buf)
  947. {
  948. return scnprintf(buf, PAGE_SIZE, "%-.32s\n",
  949. socinfo_get_chip_name());
  950. }
  951. ATTR_DEFINE(chip_id);
  952. /* Version 14 */
  953. static ssize_t
  954. msm_get_num_clusters(struct device *dev,
  955. struct device_attribute *attr,
  956. char *buf)
  957. {
  958. return scnprintf(buf, PAGE_SIZE, "0x%x\n",
  959. socinfo_get_num_clusters());
  960. }
  961. ATTR_DEFINE(num_clusters);
  962. static ssize_t
  963. msm_get_ncluster_array_offset(struct device *dev,
  964. struct device_attribute *attr,
  965. char *buf)
  966. {
  967. return scnprintf(buf, PAGE_SIZE, "0x%x\n",
  968. socinfo_get_ncluster_array_offset());
  969. }
  970. ATTR_DEFINE(ncluster_array_offset);
  971. static ssize_t
  972. msm_get_subset_cores(struct device *dev,
  973. struct device_attribute *attr,
  974. char *buf)
  975. {
  976. uint32_t sub_cluster = socinfo_get_cluster_info(CLUSTER_CPUSS);
  977. return scnprintf(buf, PAGE_SIZE, "%x\n", sub_cluster);
  978. }
  979. ATTR_DEFINE(subset_cores);
  980. static ssize_t
  981. msm_get_num_subset_parts(struct device *dev,
  982. struct device_attribute *attr,
  983. char *buf)
  984. {
  985. return scnprintf(buf, PAGE_SIZE, "0x%x\n",
  986. socinfo_get_num_subset_parts());
  987. }
  988. ATTR_DEFINE(num_subset_parts);
  989. static ssize_t
  990. msm_get_nsubset_parts_array_offset(struct device *dev,
  991. struct device_attribute *attr,
  992. char *buf)
  993. {
  994. return scnprintf(buf, PAGE_SIZE, "0x%x\n",
  995. socinfo_get_nsubset_parts_array_offset());
  996. }
  997. ATTR_DEFINE(nsubset_parts_array_offset);
  998. static ssize_t
  999. msm_get_subset_parts(struct device *dev,
  1000. struct device_attribute *attr,
  1001. char *buf)
  1002. {
  1003. uint32_t sub_parts = socinfo_get_subset_parts();
  1004. return scnprintf(buf, PAGE_SIZE, "%x\n", sub_parts);
  1005. }
  1006. ATTR_DEFINE(subset_parts);
  1007. CREATE_PART_FUNCTION(gpu, PART_GPU);
  1008. CREATE_PART_FUNCTION(video, PART_VIDEO);
  1009. CREATE_PART_FUNCTION(camera, PART_CAMERA);
  1010. CREATE_PART_FUNCTION(display, PART_DISPLAY);
  1011. CREATE_PART_FUNCTION(audio, PART_AUDIO);
  1012. CREATE_PART_FUNCTION(modem, PART_MODEM);
  1013. CREATE_PART_FUNCTION(wlan, PART_WLAN);
  1014. CREATE_PART_FUNCTION(comp, PART_COMP);
  1015. CREATE_PART_FUNCTION(sensors, PART_SENSORS);
  1016. CREATE_PART_FUNCTION(npu, PART_NPU);
  1017. CREATE_PART_FUNCTION(spss, PART_SPSS);
  1018. CREATE_PART_FUNCTION(nav, PART_NAV);
  1019. CREATE_PART_FUNCTION(comp1, PART_COMP1);
  1020. CREATE_PART_FUNCTION(display1, PART_DISPLAY1);
  1021. CREATE_PART_FUNCTION(nsp, PART_NSP);
  1022. CREATE_PART_FUNCTION(eva, PART_EVA);
  1023. /* Version 16 */
  1024. static ssize_t
  1025. msm_get_sku(struct device *dev,
  1026. struct device_attribute *attr,
  1027. char *buf)
  1028. {
  1029. return sysfs_emit(buf, "%s\n", sku ? sku : "Unknown");
  1030. }
  1031. ATTR_DEFINE(sku);
  1032. static ssize_t
  1033. msm_get_pcode(struct device *dev,
  1034. struct device_attribute *attr,
  1035. char *buf)
  1036. {
  1037. return scnprintf(buf, PAGE_SIZE, "0x%x\n", socinfo_get_pcode_id());
  1038. }
  1039. ATTR_DEFINE(pcode);
  1040. static ssize_t
  1041. msm_get_feature_code(struct device *dev,
  1042. struct device_attribute *attr,
  1043. char *buf)
  1044. {
  1045. const char *feature_code = socinfo_get_feature_code_mapping();
  1046. return sysfs_emit(buf, "%s\n", feature_code ? feature_code : "Unknown");
  1047. }
  1048. ATTR_DEFINE(feature_code);
  1049. static ssize_t
  1050. msm_get_crash(struct device *dev,
  1051. struct device_attribute *attr,
  1052. char *buf)
  1053. {
  1054. int ret = 0;
  1055. int is_debug_low = 0;
  1056. unsigned int debug_level = sec_debug_level();
  1057. switch (debug_level) {
  1058. case SEC_DEBUG_LEVEL_LOW:
  1059. is_debug_low = 1;
  1060. break;
  1061. case SEC_DEBUG_LEVEL_MID:
  1062. is_debug_low = 0;
  1063. break;
  1064. }
  1065. if (!is_debug_low) {
  1066. #ifndef CONFIG_SEC_CDSP_NO_CRASH_FOR_ENG
  1067. BUG_ON(1);
  1068. #endif
  1069. }
  1070. return ret;
  1071. }
  1072. ATTR_DEFINE(crash);
  1073. /* End Sysfs Interfaces */
  1074. static char *socinfo_get_image_version_base_address(void)
  1075. {
  1076. size_t size;
  1077. return qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMAGE_VERSION_TABLE,
  1078. &size);
  1079. }
  1080. static ssize_t msm_get_images(struct device *dev,
  1081. struct device_attribute *attr, char *buf)
  1082. {
  1083. int pos = 0;
  1084. int image;
  1085. char *image_address;
  1086. image_address = socinfo_get_image_version_base_address();
  1087. if (IS_ERR_OR_NULL(image_address))
  1088. return scnprintf(buf, PAGE_SIZE, "Unavailable");
  1089. *buf = '\0';
  1090. for (image = 0; image < SMEM_IMAGE_VERSION_BLOCKS_COUNT; image++) {
  1091. if (*image_address == '\0') {
  1092. image_address += SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
  1093. continue;
  1094. }
  1095. pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d:\n",
  1096. image);
  1097. pos += scnprintf(buf + pos, PAGE_SIZE - pos,
  1098. "\tCRM:\t\t%-.75s\n", image_address);
  1099. pos += scnprintf(buf + pos, PAGE_SIZE - pos,
  1100. "\tVariant:\t%-.20s\n",
  1101. image_address + SMEM_IMAGE_VERSION_VARIANT_OFFSET);
  1102. pos += scnprintf(buf + pos, PAGE_SIZE - pos,
  1103. "\tVersion:\t%-.33s\n",
  1104. image_address + SMEM_IMAGE_VERSION_OEM_OFFSET);
  1105. image_address += SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
  1106. }
  1107. return pos;
  1108. }
  1109. ATTR_DEFINE(images);
  1110. static umode_t soc_info_attribute(struct kobject *kobj,
  1111. struct attribute *attr,
  1112. int index)
  1113. {
  1114. return attr->mode;
  1115. }
  1116. static const struct attribute_group custom_soc_attr_group = {
  1117. .attrs = msm_custom_socinfo_attrs,
  1118. .is_visible = soc_info_attribute,
  1119. };
  1120. static void socinfo_populate_sysfs(struct qcom_socinfo *qcom_socinfo)
  1121. {
  1122. int i = 0;
  1123. switch (socinfo_format) {
  1124. case SOCINFO_VERSION(0, 20):
  1125. case SOCINFO_VERSION(0, 19):
  1126. case SOCINFO_VERSION(0, 18):
  1127. case SOCINFO_VERSION(0, 17):
  1128. case SOCINFO_VERSION(0, 16):
  1129. msm_custom_socinfo_attrs[i++] = &dev_attr_sku.attr;
  1130. msm_custom_socinfo_attrs[i++] = &dev_attr_feature_code.attr;
  1131. msm_custom_socinfo_attrs[i++] = &dev_attr_pcode.attr;
  1132. fallthrough;
  1133. case SOCINFO_VERSION(0, 15):
  1134. case SOCINFO_VERSION(0, 14):
  1135. msm_custom_socinfo_attrs[i++] = &dev_attr_num_clusters.attr;
  1136. msm_custom_socinfo_attrs[i++] =
  1137. &dev_attr_ncluster_array_offset.attr;
  1138. msm_custom_socinfo_attrs[i++] =
  1139. &dev_attr_num_subset_parts.attr;
  1140. msm_custom_socinfo_attrs[i++] =
  1141. &dev_attr_nsubset_parts_array_offset.attr;
  1142. msm_custom_socinfo_attrs[i++] = &dev_attr_subset_cores.attr;
  1143. msm_custom_socinfo_attrs[i++] = &dev_attr_subset_parts.attr;
  1144. msm_custom_socinfo_attrs[i++] = &dev_attr_gpu.attr;
  1145. msm_custom_socinfo_attrs[i++] = &dev_attr_video.attr;
  1146. msm_custom_socinfo_attrs[i++] = &dev_attr_camera.attr;
  1147. msm_custom_socinfo_attrs[i++] = &dev_attr_display.attr;
  1148. msm_custom_socinfo_attrs[i++] = &dev_attr_audio.attr;
  1149. msm_custom_socinfo_attrs[i++] = &dev_attr_modem.attr;
  1150. msm_custom_socinfo_attrs[i++] = &dev_attr_wlan.attr;
  1151. msm_custom_socinfo_attrs[i++] = &dev_attr_comp.attr;
  1152. msm_custom_socinfo_attrs[i++] = &dev_attr_sensors.attr;
  1153. msm_custom_socinfo_attrs[i++] = &dev_attr_npu.attr;
  1154. msm_custom_socinfo_attrs[i++] = &dev_attr_spss.attr;
  1155. msm_custom_socinfo_attrs[i++] = &dev_attr_nav.attr;
  1156. msm_custom_socinfo_attrs[i++] = &dev_attr_comp1.attr;
  1157. msm_custom_socinfo_attrs[i++] = &dev_attr_display1.attr;
  1158. msm_custom_socinfo_attrs[i++] = &dev_attr_nsp.attr;
  1159. msm_custom_socinfo_attrs[i++] = &dev_attr_eva.attr;
  1160. fallthrough;
  1161. case SOCINFO_VERSION(0, 13):
  1162. msm_custom_socinfo_attrs[i++] = &dev_attr_chip_id.attr;
  1163. fallthrough;
  1164. case SOCINFO_VERSION(0, 12):
  1165. msm_custom_socinfo_attrs[i++] = &dev_attr_chip_family.attr;
  1166. msm_custom_socinfo_attrs[i++] = &dev_attr_crash.attr;
  1167. msm_custom_socinfo_attrs[i++] = &dev_attr_images.attr;
  1168. fallthrough;
  1169. case SOCINFO_VERSION(0, 11):
  1170. case SOCINFO_VERSION(0, 10):
  1171. case SOCINFO_VERSION(0, 9):
  1172. case SOCINFO_VERSION(0, 8):
  1173. case SOCINFO_VERSION(0, 7):
  1174. case SOCINFO_VERSION(0, 6):
  1175. msm_custom_socinfo_attrs[i++] =
  1176. &dev_attr_platform_subtype_id.attr;
  1177. msm_custom_socinfo_attrs[i++] = &dev_attr_platform_subtype.attr;
  1178. fallthrough;
  1179. case SOCINFO_VERSION(0, 5):
  1180. case SOCINFO_VERSION(0, 4):
  1181. msm_custom_socinfo_attrs[i++] = &dev_attr_platform_version.attr;
  1182. fallthrough;
  1183. case SOCINFO_VERSION(0, 3):
  1184. msm_custom_socinfo_attrs[i++] = &dev_attr_hw_platform.attr;
  1185. fallthrough;
  1186. case SOCINFO_VERSION(0, 2):
  1187. case SOCINFO_VERSION(0, 1):
  1188. break;
  1189. default:
  1190. pr_err("Unknown socinfo format: v%u.%u\n",
  1191. SOCINFO_MAJOR(socinfo_format),
  1192. SOCINFO_MINOR(socinfo_format));
  1193. break;
  1194. }
  1195. msm_custom_socinfo_attrs[i++] = NULL;
  1196. qcom_socinfo->attr.custom_attr_group = &custom_soc_attr_group;
  1197. }
  1198. void socinfo_enumerate_partinfo_details(void)
  1199. {
  1200. unsigned int partinfo_array_offset;
  1201. unsigned int nnum_partname_mapping;
  1202. void *ptr = socinfo;
  1203. int i, part_type;
  1204. if (socinfo_format < SOCINFO_VERSION(0, 16))
  1205. return;
  1206. partinfo_array_offset = le32_to_cpu(socinfo->npartnamemap_offset);
  1207. nnum_partname_mapping = le32_to_cpu(socinfo->nnum_partname_mapping);
  1208. if (nnum_partname_mapping > SOCINFO_PART_MAX_PARTTYPE) {
  1209. pr_warn("socinfo: Mismatch between bootloaders and hlos\n");
  1210. return;
  1211. }
  1212. ptr += partinfo_array_offset;
  1213. for (i = 0; i < nnum_partname_mapping; i++) {
  1214. part_type = get_unaligned_le32(ptr);
  1215. if (part_type > SOCINFO_PART_MAX_PARTTYPE)
  1216. pr_warn("socinfo: part type mismatch\n");
  1217. partinfo[part_type].part_type = part_type;
  1218. ptr += sizeof(u32);
  1219. partinfo[part_type].gpu_info.gpu_chip_id = get_unaligned_le32(ptr);
  1220. ptr += sizeof(u32);
  1221. partinfo[part_type].gpu_info.vulkan_id = get_unaligned_le32(ptr);
  1222. ptr += sizeof(u32);
  1223. strscpy(partinfo[part_type].gpu_info.part_name, ptr, PART_NAME_MAX);
  1224. ptr += PART_NAME_MAX;
  1225. }
  1226. }
  1227. #ifdef CONFIG_DEBUG_FS
  1228. #define QCOM_OPEN(name, _func) \
  1229. static int qcom_open_##name(struct inode *inode, struct file *file) \
  1230. { \
  1231. return single_open(file, _func, inode->i_private); \
  1232. } \
  1233. \
  1234. static const struct file_operations qcom_ ##name## _ops = { \
  1235. .open = qcom_open_##name, \
  1236. .read = seq_read, \
  1237. .llseek = seq_lseek, \
  1238. .release = single_release, \
  1239. }
  1240. #define DEBUGFS_ADD(info, name) \
  1241. debugfs_create_file(__stringify(name), 0444, \
  1242. qcom_socinfo->dbg_root, \
  1243. info, &qcom_ ##name## _ops)
  1244. static int qcom_show_build_id(struct seq_file *seq, void *p)
  1245. {
  1246. struct socinfo *socinfo = seq->private;
  1247. seq_printf(seq, "%s\n", socinfo->build_id);
  1248. return 0;
  1249. }
  1250. static int qcom_show_pmic_model(struct seq_file *seq, void *p)
  1251. {
  1252. struct socinfo *socinfo = seq->private;
  1253. int model = SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_model));
  1254. if (model < 0)
  1255. return -EINVAL;
  1256. if (model < ARRAY_SIZE(pmic_models) && pmic_models[model])
  1257. seq_printf(seq, "%s\n", pmic_models[model]);
  1258. else
  1259. seq_printf(seq, "unknown (%d)\n", model);
  1260. return 0;
  1261. }
  1262. static int qcom_show_pmic_model_array(struct seq_file *seq, void *p)
  1263. {
  1264. struct socinfo *socinfo = seq->private;
  1265. unsigned int num_pmics = le32_to_cpu(socinfo->num_pmics);
  1266. unsigned int pmic_array_offset = le32_to_cpu(socinfo->pmic_array_offset);
  1267. int i;
  1268. void *ptr = socinfo;
  1269. ptr += pmic_array_offset;
  1270. /* No need for bounds checking, it happened at socinfo_debugfs_init */
  1271. for (i = 0; i < num_pmics; i++) {
  1272. unsigned int model = SOCINFO_MINOR(get_unaligned_le32(ptr + 2 * i * sizeof(u32)));
  1273. unsigned int die_rev = get_unaligned_le32(ptr + (2 * i + 1) * sizeof(u32));
  1274. if (model < ARRAY_SIZE(pmic_models) && pmic_models[model])
  1275. seq_printf(seq, "%s %u.%u\n", pmic_models[model],
  1276. SOCINFO_MAJOR(die_rev),
  1277. SOCINFO_MINOR(die_rev));
  1278. else
  1279. seq_printf(seq, "unknown (%d)\n", model);
  1280. }
  1281. return 0;
  1282. }
  1283. static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p)
  1284. {
  1285. struct socinfo *socinfo = seq->private;
  1286. seq_printf(seq, "%u.%u\n",
  1287. SOCINFO_MAJOR(le32_to_cpu(socinfo->pmic_die_rev)),
  1288. SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_die_rev)));
  1289. return 0;
  1290. }
  1291. static int qcom_show_chip_id(struct seq_file *seq, void *p)
  1292. {
  1293. struct socinfo *socinfo = seq->private;
  1294. seq_printf(seq, "%s\n", socinfo->chip_id);
  1295. return 0;
  1296. }
  1297. QCOM_OPEN(build_id, qcom_show_build_id);
  1298. QCOM_OPEN(pmic_model, qcom_show_pmic_model);
  1299. QCOM_OPEN(pmic_model_array, qcom_show_pmic_model_array);
  1300. QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision);
  1301. QCOM_OPEN(chip_id, qcom_show_chip_id);
  1302. #define DEFINE_IMAGE_OPS(type) \
  1303. static int show_image_##type(struct seq_file *seq, void *p) \
  1304. { \
  1305. struct smem_image_version *image_version = seq->private; \
  1306. if (image_version->type[0] != '\0') \
  1307. seq_printf(seq, "%s\n", image_version->type); \
  1308. return 0; \
  1309. } \
  1310. static int open_image_##type(struct inode *inode, struct file *file) \
  1311. { \
  1312. return single_open(file, show_image_##type, inode->i_private); \
  1313. } \
  1314. \
  1315. static const struct file_operations qcom_image_##type##_ops = { \
  1316. .open = open_image_##type, \
  1317. .read = seq_read, \
  1318. .llseek = seq_lseek, \
  1319. .release = single_release, \
  1320. }
  1321. DEFINE_IMAGE_OPS(name);
  1322. DEFINE_IMAGE_OPS(variant);
  1323. DEFINE_IMAGE_OPS(oem);
  1324. static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
  1325. struct socinfo *info, size_t info_size)
  1326. {
  1327. struct smem_image_version *versions;
  1328. struct dentry *dentry;
  1329. size_t size;
  1330. int i;
  1331. unsigned int num_pmics;
  1332. unsigned int pmic_array_offset;
  1333. qcom_socinfo->dbg_root = debugfs_create_dir("qcom_socinfo", NULL);
  1334. qcom_socinfo->info.fmt = __le32_to_cpu(info->fmt);
  1335. debugfs_create_x32("info_fmt", 0444, qcom_socinfo->dbg_root,
  1336. &qcom_socinfo->info.fmt);
  1337. switch (qcom_socinfo->info.fmt) {
  1338. case SOCINFO_VERSION(0, 20):
  1339. qcom_socinfo->info.raw_package_type = __le32_to_cpu(info->raw_package_type);
  1340. debugfs_create_u32("raw_package_type", 0444, qcom_socinfo->dbg_root,
  1341. &qcom_socinfo->info.raw_package_type);
  1342. fallthrough;
  1343. case SOCINFO_VERSION(0, 19):
  1344. qcom_socinfo->info.num_func_clusters = __le32_to_cpu(info->num_func_clusters);
  1345. qcom_socinfo->info.boot_cluster = __le32_to_cpu(info->boot_cluster);
  1346. qcom_socinfo->info.boot_core = __le32_to_cpu(info->boot_core);
  1347. debugfs_create_u32("num_func_clusters", 0444, qcom_socinfo->dbg_root,
  1348. &qcom_socinfo->info.num_func_clusters);
  1349. debugfs_create_u32("boot_cluster", 0444, qcom_socinfo->dbg_root,
  1350. &qcom_socinfo->info.boot_cluster);
  1351. debugfs_create_u32("boot_core", 0444, qcom_socinfo->dbg_root,
  1352. &qcom_socinfo->info.boot_core);
  1353. fallthrough;
  1354. case SOCINFO_VERSION(0, 18):
  1355. case SOCINFO_VERSION(0, 17):
  1356. qcom_socinfo->info.oem_variant = __le32_to_cpu(info->oem_variant);
  1357. debugfs_create_u32("oem_variant", 0444, qcom_socinfo->dbg_root,
  1358. &qcom_socinfo->info.oem_variant);
  1359. fallthrough;
  1360. case SOCINFO_VERSION(0, 16):
  1361. qcom_socinfo->info.feature_code = __le32_to_cpu(info->feature_code);
  1362. qcom_socinfo->info.pcode = __le32_to_cpu(info->pcode);
  1363. debugfs_create_u32("feature_code", 0444, qcom_socinfo->dbg_root,
  1364. &qcom_socinfo->info.feature_code);
  1365. debugfs_create_u32("pcode", 0444, qcom_socinfo->dbg_root,
  1366. &qcom_socinfo->info.pcode);
  1367. fallthrough;
  1368. case SOCINFO_VERSION(0, 15):
  1369. qcom_socinfo->info.nmodem_supported = __le32_to_cpu(info->nmodem_supported);
  1370. debugfs_create_u32("nmodem_supported", 0444, qcom_socinfo->dbg_root,
  1371. &qcom_socinfo->info.nmodem_supported);
  1372. fallthrough;
  1373. case SOCINFO_VERSION(0, 14):
  1374. qcom_socinfo->info.num_clusters = __le32_to_cpu(info->num_clusters);
  1375. qcom_socinfo->info.ncluster_array_offset = __le32_to_cpu(info->ncluster_array_offset);
  1376. qcom_socinfo->info.num_subset_parts = __le32_to_cpu(info->num_subset_parts);
  1377. qcom_socinfo->info.nsubset_parts_array_offset =
  1378. __le32_to_cpu(info->nsubset_parts_array_offset);
  1379. debugfs_create_u32("num_clusters", 0444, qcom_socinfo->dbg_root,
  1380. &qcom_socinfo->info.num_clusters);
  1381. debugfs_create_u32("ncluster_array_offset", 0444, qcom_socinfo->dbg_root,
  1382. &qcom_socinfo->info.ncluster_array_offset);
  1383. debugfs_create_u32("num_subset_parts", 0444, qcom_socinfo->dbg_root,
  1384. &qcom_socinfo->info.num_subset_parts);
  1385. debugfs_create_u32("nsubset_parts_array_offset", 0444, qcom_socinfo->dbg_root,
  1386. &qcom_socinfo->info.nsubset_parts_array_offset);
  1387. fallthrough;
  1388. case SOCINFO_VERSION(0, 13):
  1389. qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id);
  1390. debugfs_create_u32("nproduct_id", 0444, qcom_socinfo->dbg_root,
  1391. &qcom_socinfo->info.nproduct_id);
  1392. DEBUGFS_ADD(info, chip_id);
  1393. fallthrough;
  1394. case SOCINFO_VERSION(0, 12):
  1395. qcom_socinfo->info.chip_family =
  1396. __le32_to_cpu(info->chip_family);
  1397. qcom_socinfo->info.raw_device_family =
  1398. __le32_to_cpu(info->raw_device_family);
  1399. qcom_socinfo->info.raw_device_num =
  1400. __le32_to_cpu(info->raw_device_num);
  1401. debugfs_create_x32("chip_family", 0444, qcom_socinfo->dbg_root,
  1402. &qcom_socinfo->info.chip_family);
  1403. debugfs_create_x32("raw_device_family", 0444,
  1404. qcom_socinfo->dbg_root,
  1405. &qcom_socinfo->info.raw_device_family);
  1406. debugfs_create_x32("raw_device_number", 0444,
  1407. qcom_socinfo->dbg_root,
  1408. &qcom_socinfo->info.raw_device_num);
  1409. fallthrough;
  1410. case SOCINFO_VERSION(0, 11):
  1411. num_pmics = le32_to_cpu(info->num_pmics);
  1412. pmic_array_offset = le32_to_cpu(info->pmic_array_offset);
  1413. if (pmic_array_offset + 2 * num_pmics * sizeof(u32) <= info_size)
  1414. DEBUGFS_ADD(info, pmic_model_array);
  1415. fallthrough;
  1416. case SOCINFO_VERSION(0, 10):
  1417. case SOCINFO_VERSION(0, 9):
  1418. qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id);
  1419. debugfs_create_u32("foundry_id", 0444, qcom_socinfo->dbg_root,
  1420. &qcom_socinfo->info.foundry_id);
  1421. fallthrough;
  1422. case SOCINFO_VERSION(0, 8):
  1423. case SOCINFO_VERSION(0, 7):
  1424. DEBUGFS_ADD(info, pmic_model);
  1425. DEBUGFS_ADD(info, pmic_die_rev);
  1426. fallthrough;
  1427. case SOCINFO_VERSION(0, 6):
  1428. qcom_socinfo->info.hw_plat_subtype =
  1429. __le32_to_cpu(info->hw_plat_subtype);
  1430. debugfs_create_u32("hardware_platform_subtype", 0444,
  1431. qcom_socinfo->dbg_root,
  1432. &qcom_socinfo->info.hw_plat_subtype);
  1433. fallthrough;
  1434. case SOCINFO_VERSION(0, 5):
  1435. qcom_socinfo->info.accessory_chip =
  1436. __le32_to_cpu(info->accessory_chip);
  1437. debugfs_create_u32("accessory_chip", 0444,
  1438. qcom_socinfo->dbg_root,
  1439. &qcom_socinfo->info.accessory_chip);
  1440. fallthrough;
  1441. case SOCINFO_VERSION(0, 4):
  1442. qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver);
  1443. debugfs_create_u32("platform_version", 0444,
  1444. qcom_socinfo->dbg_root,
  1445. &qcom_socinfo->info.plat_ver);
  1446. fallthrough;
  1447. case SOCINFO_VERSION(0, 3):
  1448. qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat);
  1449. debugfs_create_u32("hardware_platform", 0444,
  1450. qcom_socinfo->dbg_root,
  1451. &qcom_socinfo->info.hw_plat);
  1452. fallthrough;
  1453. case SOCINFO_VERSION(0, 2):
  1454. qcom_socinfo->info.raw_ver = __le32_to_cpu(info->raw_ver);
  1455. debugfs_create_u32("raw_version", 0444, qcom_socinfo->dbg_root,
  1456. &qcom_socinfo->info.raw_ver);
  1457. fallthrough;
  1458. case SOCINFO_VERSION(0, 1):
  1459. DEBUGFS_ADD(info, build_id);
  1460. break;
  1461. }
  1462. versions = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMAGE_VERSION_TABLE,
  1463. &size);
  1464. for (i = 0; i < ARRAY_SIZE(socinfo_image_names); i++) {
  1465. if (!socinfo_image_names[i])
  1466. continue;
  1467. dentry = debugfs_create_dir(socinfo_image_names[i],
  1468. qcom_socinfo->dbg_root);
  1469. debugfs_create_file("name", 0444, dentry, &versions[i],
  1470. &qcom_image_name_ops);
  1471. debugfs_create_file("variant", 0444, dentry, &versions[i],
  1472. &qcom_image_variant_ops);
  1473. debugfs_create_file("oem", 0444, dentry, &versions[i],
  1474. &qcom_image_oem_ops);
  1475. }
  1476. }
  1477. static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo)
  1478. {
  1479. debugfs_remove_recursive(qcom_socinfo->dbg_root);
  1480. }
  1481. #else
  1482. static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
  1483. struct socinfo *info, size_t info_size)
  1484. {
  1485. }
  1486. static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) { }
  1487. #endif /* CONFIG_DEBUG_FS */
  1488. static int qcom_socinfo_probe(struct platform_device *pdev)
  1489. {
  1490. struct qcom_socinfo *qs;
  1491. struct socinfo *info;
  1492. size_t item_size;
  1493. const char *machine, *fc;
  1494. info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID,
  1495. &item_size);
  1496. if (IS_ERR(info)) {
  1497. dev_err(&pdev->dev, "Couldn't find socinfo\n");
  1498. return PTR_ERR(info);
  1499. }
  1500. socinfo_format = le32_to_cpu(info->fmt);
  1501. socinfo = info;
  1502. qs = devm_kzalloc(&pdev->dev, sizeof(*qs), GFP_KERNEL);
  1503. if (!qs)
  1504. return -ENOMEM;
  1505. qs->attr.family = "Snapdragon";
  1506. qs->attr.machine = socinfo_machine(&pdev->dev,
  1507. le32_to_cpu(info->id));
  1508. qs->attr.soc_id = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u",
  1509. le32_to_cpu(info->id));
  1510. qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u",
  1511. SOCINFO_MAJOR(le32_to_cpu(info->ver)),
  1512. SOCINFO_MINOR(le32_to_cpu(info->ver)));
  1513. if (offsetof(struct socinfo, serial_num) <= item_size)
  1514. qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL,
  1515. "%u",
  1516. le32_to_cpu(info->serial_num));
  1517. if (socinfo_format >= SOCINFO_VERSION(0, 16)) {
  1518. socinfo_enumerate_partinfo_details();
  1519. machine = socinfo_machine(&pdev->dev, le32_to_cpu(info->id));
  1520. fc = socinfo_get_feature_code_mapping();
  1521. sku = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s-%u-%s",
  1522. machine, socinfo_get_pcode_id(), fc);
  1523. }
  1524. socinfo_populate_sysfs(qs);
  1525. qs->soc_dev = soc_device_register(&qs->attr);
  1526. if (IS_ERR(qs->soc_dev))
  1527. return PTR_ERR(qs->soc_dev);
  1528. socinfo_debugfs_init(qs, info, item_size);
  1529. /* Feed the soc specific unique data into entropy pool */
  1530. add_device_randomness(info, item_size);
  1531. platform_set_drvdata(pdev, qs);
  1532. return 0;
  1533. }
  1534. static int qcom_socinfo_remove(struct platform_device *pdev)
  1535. {
  1536. struct qcom_socinfo *qs = platform_get_drvdata(pdev);
  1537. soc_device_unregister(qs->soc_dev);
  1538. socinfo_debugfs_exit(qs);
  1539. return 0;
  1540. }
  1541. static struct platform_driver qcom_socinfo_driver = {
  1542. .probe = qcom_socinfo_probe,
  1543. .remove = qcom_socinfo_remove,
  1544. .driver = {
  1545. .name = "qcom-socinfo",
  1546. },
  1547. };
  1548. module_platform_driver(qcom_socinfo_driver);
  1549. MODULE_DESCRIPTION("Qualcomm SoCinfo driver");
  1550. MODULE_LICENSE("GPL v2");
  1551. MODULE_ALIAS("platform:qcom-socinfo");