socinfo.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2017-2019, Linaro Ltd.
  5. */
  6. #include <linux/debugfs.h>
  7. #include <linux/err.h>
  8. #include <linux/module.h>
  9. #include <linux/platform_device.h>
  10. #include <linux/random.h>
  11. #include <linux/slab.h>
  12. #include <linux/soc/qcom/smem.h>
  13. #include <linux/string.h>
  14. #include <linux/sys_soc.h>
  15. #include <linux/types.h>
  16. /*
  17. * SoC version type with major number in the upper 16 bits and minor
  18. * number in the lower 16 bits.
  19. */
  20. #define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff)
  21. #define SOCINFO_MINOR(ver) ((ver) & 0xffff)
  22. #define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff))
  23. #define SMEM_SOCINFO_BUILD_ID_LENGTH 32
  24. /*
  25. * SMEM item id, used to acquire handles to respective
  26. * SMEM region.
  27. */
  28. #define SMEM_HW_SW_BUILD_ID 137
  29. #ifdef CONFIG_DEBUG_FS
  30. #define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
  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_OEM_SIZE 32
  35. /*
  36. * SMEM Image table indices
  37. */
  38. #define SMEM_IMAGE_TABLE_BOOT_INDEX 0
  39. #define SMEM_IMAGE_TABLE_TZ_INDEX 1
  40. #define SMEM_IMAGE_TABLE_RPM_INDEX 3
  41. #define SMEM_IMAGE_TABLE_APPS_INDEX 10
  42. #define SMEM_IMAGE_TABLE_MPSS_INDEX 11
  43. #define SMEM_IMAGE_TABLE_ADSP_INDEX 12
  44. #define SMEM_IMAGE_TABLE_CNSS_INDEX 13
  45. #define SMEM_IMAGE_TABLE_VIDEO_INDEX 14
  46. #define SMEM_IMAGE_VERSION_TABLE 469
  47. /*
  48. * SMEM Image table names
  49. */
  50. static const char *const socinfo_image_names[] = {
  51. [SMEM_IMAGE_TABLE_ADSP_INDEX] = "adsp",
  52. [SMEM_IMAGE_TABLE_APPS_INDEX] = "apps",
  53. [SMEM_IMAGE_TABLE_BOOT_INDEX] = "boot",
  54. [SMEM_IMAGE_TABLE_CNSS_INDEX] = "cnss",
  55. [SMEM_IMAGE_TABLE_MPSS_INDEX] = "mpss",
  56. [SMEM_IMAGE_TABLE_RPM_INDEX] = "rpm",
  57. [SMEM_IMAGE_TABLE_TZ_INDEX] = "tz",
  58. [SMEM_IMAGE_TABLE_VIDEO_INDEX] = "video",
  59. };
  60. static const char *const pmic_models[] = {
  61. [0] = "Unknown PMIC model",
  62. [9] = "PM8994",
  63. [11] = "PM8916",
  64. [13] = "PM8058",
  65. [14] = "PM8028",
  66. [15] = "PM8901",
  67. [16] = "PM8027",
  68. [17] = "ISL9519",
  69. [18] = "PM8921",
  70. [19] = "PM8018",
  71. [20] = "PM8015",
  72. [21] = "PM8014",
  73. [22] = "PM8821",
  74. [23] = "PM8038",
  75. [24] = "PM8922",
  76. [25] = "PM8917",
  77. };
  78. #endif /* CONFIG_DEBUG_FS */
  79. /* Socinfo SMEM item structure */
  80. struct socinfo {
  81. __le32 fmt;
  82. __le32 id;
  83. __le32 ver;
  84. char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH];
  85. /* Version 2 */
  86. __le32 raw_id;
  87. __le32 raw_ver;
  88. /* Version 3 */
  89. __le32 hw_plat;
  90. /* Version 4 */
  91. __le32 plat_ver;
  92. /* Version 5 */
  93. __le32 accessory_chip;
  94. /* Version 6 */
  95. __le32 hw_plat_subtype;
  96. /* Version 7 */
  97. __le32 pmic_model;
  98. __le32 pmic_die_rev;
  99. /* Version 8 */
  100. __le32 pmic_model_1;
  101. __le32 pmic_die_rev_1;
  102. __le32 pmic_model_2;
  103. __le32 pmic_die_rev_2;
  104. /* Version 9 */
  105. __le32 foundry_id;
  106. /* Version 10 */
  107. __le32 serial_num;
  108. /* Version 11 */
  109. __le32 num_pmics;
  110. __le32 pmic_array_offset;
  111. /* Version 12 */
  112. __le32 chip_family;
  113. __le32 raw_device_family;
  114. __le32 raw_device_num;
  115. };
  116. #ifdef CONFIG_DEBUG_FS
  117. struct socinfo_params {
  118. u32 raw_device_family;
  119. u32 hw_plat_subtype;
  120. u32 accessory_chip;
  121. u32 raw_device_num;
  122. u32 chip_family;
  123. u32 foundry_id;
  124. u32 plat_ver;
  125. u32 raw_ver;
  126. u32 hw_plat;
  127. u32 fmt;
  128. };
  129. struct smem_image_version {
  130. char name[SMEM_IMAGE_VERSION_NAME_SIZE];
  131. char variant[SMEM_IMAGE_VERSION_VARIANT_SIZE];
  132. char pad;
  133. char oem[SMEM_IMAGE_VERSION_OEM_SIZE];
  134. };
  135. #endif /* CONFIG_DEBUG_FS */
  136. struct qcom_socinfo {
  137. struct soc_device *soc_dev;
  138. struct soc_device_attribute attr;
  139. #ifdef CONFIG_DEBUG_FS
  140. struct dentry *dbg_root;
  141. struct socinfo_params info;
  142. #endif /* CONFIG_DEBUG_FS */
  143. };
  144. struct soc_id {
  145. unsigned int id;
  146. const char *name;
  147. };
  148. static const struct soc_id soc_id[] = {
  149. { 87, "MSM8960" },
  150. { 109, "APQ8064" },
  151. { 122, "MSM8660A" },
  152. { 123, "MSM8260A" },
  153. { 124, "APQ8060A" },
  154. { 126, "MSM8974" },
  155. { 130, "MPQ8064" },
  156. { 138, "MSM8960AB" },
  157. { 139, "APQ8060AB" },
  158. { 140, "MSM8260AB" },
  159. { 141, "MSM8660AB" },
  160. { 178, "APQ8084" },
  161. { 184, "APQ8074" },
  162. { 185, "MSM8274" },
  163. { 186, "MSM8674" },
  164. { 194, "MSM8974PRO" },
  165. { 206, "MSM8916" },
  166. { 208, "APQ8074-AA" },
  167. { 209, "APQ8074-AB" },
  168. { 210, "APQ8074PRO" },
  169. { 211, "MSM8274-AA" },
  170. { 212, "MSM8274-AB" },
  171. { 213, "MSM8274PRO" },
  172. { 214, "MSM8674-AA" },
  173. { 215, "MSM8674-AB" },
  174. { 216, "MSM8674PRO" },
  175. { 217, "MSM8974-AA" },
  176. { 218, "MSM8974-AB" },
  177. { 246, "MSM8996" },
  178. { 247, "APQ8016" },
  179. { 248, "MSM8216" },
  180. { 249, "MSM8116" },
  181. { 250, "MSM8616" },
  182. { 291, "APQ8096" },
  183. { 305, "MSM8996SG" },
  184. { 310, "MSM8996AU" },
  185. { 311, "APQ8096AU" },
  186. { 312, "APQ8096SG" },
  187. };
  188. static const char *socinfo_machine(struct device *dev, unsigned int id)
  189. {
  190. int idx;
  191. for (idx = 0; idx < ARRAY_SIZE(soc_id); idx++) {
  192. if (soc_id[idx].id == id)
  193. return soc_id[idx].name;
  194. }
  195. return NULL;
  196. }
  197. #ifdef CONFIG_DEBUG_FS
  198. #define QCOM_OPEN(name, _func) \
  199. static int qcom_open_##name(struct inode *inode, struct file *file) \
  200. { \
  201. return single_open(file, _func, inode->i_private); \
  202. } \
  203. \
  204. static const struct file_operations qcom_ ##name## _ops = { \
  205. .open = qcom_open_##name, \
  206. .read = seq_read, \
  207. .llseek = seq_lseek, \
  208. .release = single_release, \
  209. }
  210. #define DEBUGFS_ADD(info, name) \
  211. debugfs_create_file(__stringify(name), 0400, \
  212. qcom_socinfo->dbg_root, \
  213. info, &qcom_ ##name## _ops)
  214. static int qcom_show_build_id(struct seq_file *seq, void *p)
  215. {
  216. struct socinfo *socinfo = seq->private;
  217. seq_printf(seq, "%s\n", socinfo->build_id);
  218. return 0;
  219. }
  220. static int qcom_show_pmic_model(struct seq_file *seq, void *p)
  221. {
  222. struct socinfo *socinfo = seq->private;
  223. int model = SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_model));
  224. if (model < 0)
  225. return -EINVAL;
  226. seq_printf(seq, "%s\n", pmic_models[model]);
  227. return 0;
  228. }
  229. static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p)
  230. {
  231. struct socinfo *socinfo = seq->private;
  232. seq_printf(seq, "%u.%u\n",
  233. SOCINFO_MAJOR(le32_to_cpu(socinfo->pmic_die_rev)),
  234. SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_die_rev)));
  235. return 0;
  236. }
  237. QCOM_OPEN(build_id, qcom_show_build_id);
  238. QCOM_OPEN(pmic_model, qcom_show_pmic_model);
  239. QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision);
  240. #define DEFINE_IMAGE_OPS(type) \
  241. static int show_image_##type(struct seq_file *seq, void *p) \
  242. { \
  243. struct smem_image_version *image_version = seq->private; \
  244. seq_puts(seq, image_version->type); \
  245. seq_puts(seq, "\n"); \
  246. return 0; \
  247. } \
  248. static int open_image_##type(struct inode *inode, struct file *file) \
  249. { \
  250. return single_open(file, show_image_##type, inode->i_private); \
  251. } \
  252. \
  253. static const struct file_operations qcom_image_##type##_ops = { \
  254. .open = open_image_##type, \
  255. .read = seq_read, \
  256. .llseek = seq_lseek, \
  257. .release = single_release, \
  258. }
  259. DEFINE_IMAGE_OPS(name);
  260. DEFINE_IMAGE_OPS(variant);
  261. DEFINE_IMAGE_OPS(oem);
  262. static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
  263. struct socinfo *info)
  264. {
  265. struct smem_image_version *versions;
  266. struct dentry *dentry;
  267. size_t size;
  268. int i;
  269. qcom_socinfo->dbg_root = debugfs_create_dir("qcom_socinfo", NULL);
  270. qcom_socinfo->info.fmt = __le32_to_cpu(info->fmt);
  271. switch (qcom_socinfo->info.fmt) {
  272. case SOCINFO_VERSION(0, 12):
  273. qcom_socinfo->info.chip_family =
  274. __le32_to_cpu(info->chip_family);
  275. qcom_socinfo->info.raw_device_family =
  276. __le32_to_cpu(info->raw_device_family);
  277. qcom_socinfo->info.raw_device_num =
  278. __le32_to_cpu(info->raw_device_num);
  279. debugfs_create_x32("chip_family", 0400, qcom_socinfo->dbg_root,
  280. &qcom_socinfo->info.chip_family);
  281. debugfs_create_x32("raw_device_family", 0400,
  282. qcom_socinfo->dbg_root,
  283. &qcom_socinfo->info.raw_device_family);
  284. debugfs_create_x32("raw_device_number", 0400,
  285. qcom_socinfo->dbg_root,
  286. &qcom_socinfo->info.raw_device_num);
  287. /* Fall through */
  288. case SOCINFO_VERSION(0, 11):
  289. case SOCINFO_VERSION(0, 10):
  290. case SOCINFO_VERSION(0, 9):
  291. qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id);
  292. debugfs_create_u32("foundry_id", 0400, qcom_socinfo->dbg_root,
  293. &qcom_socinfo->info.foundry_id);
  294. /* Fall through */
  295. case SOCINFO_VERSION(0, 8):
  296. case SOCINFO_VERSION(0, 7):
  297. DEBUGFS_ADD(info, pmic_model);
  298. DEBUGFS_ADD(info, pmic_die_rev);
  299. /* Fall through */
  300. case SOCINFO_VERSION(0, 6):
  301. qcom_socinfo->info.hw_plat_subtype =
  302. __le32_to_cpu(info->hw_plat_subtype);
  303. debugfs_create_u32("hardware_platform_subtype", 0400,
  304. qcom_socinfo->dbg_root,
  305. &qcom_socinfo->info.hw_plat_subtype);
  306. /* Fall through */
  307. case SOCINFO_VERSION(0, 5):
  308. qcom_socinfo->info.accessory_chip =
  309. __le32_to_cpu(info->accessory_chip);
  310. debugfs_create_u32("accessory_chip", 0400,
  311. qcom_socinfo->dbg_root,
  312. &qcom_socinfo->info.accessory_chip);
  313. /* Fall through */
  314. case SOCINFO_VERSION(0, 4):
  315. qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver);
  316. debugfs_create_u32("platform_version", 0400,
  317. qcom_socinfo->dbg_root,
  318. &qcom_socinfo->info.plat_ver);
  319. /* Fall through */
  320. case SOCINFO_VERSION(0, 3):
  321. qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat);
  322. debugfs_create_u32("hardware_platform", 0400,
  323. qcom_socinfo->dbg_root,
  324. &qcom_socinfo->info.hw_plat);
  325. /* Fall through */
  326. case SOCINFO_VERSION(0, 2):
  327. qcom_socinfo->info.raw_ver = __le32_to_cpu(info->raw_ver);
  328. debugfs_create_u32("raw_version", 0400, qcom_socinfo->dbg_root,
  329. &qcom_socinfo->info.raw_ver);
  330. /* Fall through */
  331. case SOCINFO_VERSION(0, 1):
  332. DEBUGFS_ADD(info, build_id);
  333. break;
  334. }
  335. versions = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMAGE_VERSION_TABLE,
  336. &size);
  337. for (i = 0; i < ARRAY_SIZE(socinfo_image_names); i++) {
  338. if (!socinfo_image_names[i])
  339. continue;
  340. dentry = debugfs_create_dir(socinfo_image_names[i],
  341. qcom_socinfo->dbg_root);
  342. debugfs_create_file("name", 0400, dentry, &versions[i],
  343. &qcom_image_name_ops);
  344. debugfs_create_file("variant", 0400, dentry, &versions[i],
  345. &qcom_image_variant_ops);
  346. debugfs_create_file("oem", 0400, dentry, &versions[i],
  347. &qcom_image_oem_ops);
  348. }
  349. }
  350. static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo)
  351. {
  352. debugfs_remove_recursive(qcom_socinfo->dbg_root);
  353. }
  354. #else
  355. static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
  356. struct socinfo *info)
  357. {
  358. }
  359. static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) { }
  360. #endif /* CONFIG_DEBUG_FS */
  361. static int qcom_socinfo_probe(struct platform_device *pdev)
  362. {
  363. struct qcom_socinfo *qs;
  364. struct socinfo *info;
  365. size_t item_size;
  366. info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID,
  367. &item_size);
  368. if (IS_ERR(info)) {
  369. dev_err(&pdev->dev, "Couldn't find socinfo\n");
  370. return PTR_ERR(info);
  371. }
  372. qs = devm_kzalloc(&pdev->dev, sizeof(*qs), GFP_KERNEL);
  373. if (!qs)
  374. return -ENOMEM;
  375. qs->attr.family = "Snapdragon";
  376. qs->attr.machine = socinfo_machine(&pdev->dev,
  377. le32_to_cpu(info->id));
  378. qs->attr.soc_id = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u",
  379. le32_to_cpu(info->id));
  380. qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u",
  381. SOCINFO_MAJOR(le32_to_cpu(info->ver)),
  382. SOCINFO_MINOR(le32_to_cpu(info->ver)));
  383. if (offsetof(struct socinfo, serial_num) <= item_size)
  384. qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL,
  385. "%u",
  386. le32_to_cpu(info->serial_num));
  387. qs->soc_dev = soc_device_register(&qs->attr);
  388. if (IS_ERR(qs->soc_dev))
  389. return PTR_ERR(qs->soc_dev);
  390. socinfo_debugfs_init(qs, info);
  391. /* Feed the soc specific unique data into entropy pool */
  392. add_device_randomness(info, item_size);
  393. platform_set_drvdata(pdev, qs->soc_dev);
  394. return 0;
  395. }
  396. static int qcom_socinfo_remove(struct platform_device *pdev)
  397. {
  398. struct qcom_socinfo *qs = platform_get_drvdata(pdev);
  399. soc_device_unregister(qs->soc_dev);
  400. socinfo_debugfs_exit(qs);
  401. return 0;
  402. }
  403. static struct platform_driver qcom_socinfo_driver = {
  404. .probe = qcom_socinfo_probe,
  405. .remove = qcom_socinfo_remove,
  406. .driver = {
  407. .name = "qcom-socinfo",
  408. },
  409. };
  410. module_platform_driver(qcom_socinfo_driver);
  411. MODULE_DESCRIPTION("Qualcomm SoCinfo driver");
  412. MODULE_LICENSE("GPL v2");
  413. MODULE_ALIAS("platform:qcom-socinfo");