| 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 | |
| 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/soc/qcom/socinfo.h> |
| 15 | #include <linux/string.h> |
| 16 | #include <linux/stringify.h> |
| 17 | #include <linux/sys_soc.h> |
| 18 | #include <linux/types.h> |
| 19 | |
| 20 | #include <linux/unaligned.h> |
| 21 | |
| 22 | #include <dt-bindings/arm/qcom,ids.h> |
| 23 | |
| 24 | /* Helper macros to create soc_id table */ |
| 25 | #define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id) |
| 26 | #define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name) |
| 27 | |
| 28 | #ifdef CONFIG_DEBUG_FS |
| 29 | #define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 |
| 30 | #define SMEM_IMAGE_VERSION_SIZE 4096 |
| 31 | #define SMEM_IMAGE_VERSION_NAME_SIZE 75 |
| 32 | #define SMEM_IMAGE_VERSION_VARIANT_SIZE 20 |
| 33 | #define SMEM_IMAGE_VERSION_OEM_SIZE 32 |
| 34 | |
| 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_TZSECAPP_INDEX 2 |
| 41 | #define SMEM_IMAGE_TABLE_RPM_INDEX 3 |
| 42 | #define SMEM_IMAGE_TABLE_SDI_INDEX 4 |
| 43 | #define SMEM_IMAGE_TABLE_HYP_INDEX 5 |
| 44 | #define SMEM_IMAGE_TABLE_ADSP1_INDEX 6 |
| 45 | #define SMEM_IMAGE_TABLE_ADSP2_INDEX 7 |
| 46 | #define SMEM_IMAGE_TABLE_CDSP2_INDEX 8 |
| 47 | #define SMEM_IMAGE_TABLE_APPSBL_INDEX 9 |
| 48 | #define SMEM_IMAGE_TABLE_APPS_INDEX 10 |
| 49 | #define SMEM_IMAGE_TABLE_MPSS_INDEX 11 |
| 50 | #define SMEM_IMAGE_TABLE_ADSP_INDEX 12 |
| 51 | #define SMEM_IMAGE_TABLE_CNSS_INDEX 13 |
| 52 | #define SMEM_IMAGE_TABLE_VIDEO_INDEX 14 |
| 53 | #define SMEM_IMAGE_TABLE_DSPS_INDEX 15 |
| 54 | #define SMEM_IMAGE_TABLE_CDSP_INDEX 16 |
| 55 | #define SMEM_IMAGE_TABLE_NPU_INDEX 17 |
| 56 | #define SMEM_IMAGE_TABLE_WPSS_INDEX 18 |
| 57 | #define SMEM_IMAGE_TABLE_CDSP1_INDEX 19 |
| 58 | #define SMEM_IMAGE_TABLE_GPDSP_INDEX 20 |
| 59 | #define SMEM_IMAGE_TABLE_GPDSP1_INDEX 21 |
| 60 | #define SMEM_IMAGE_TABLE_SENSORPD_INDEX 22 |
| 61 | #define SMEM_IMAGE_TABLE_AUDIOPD_INDEX 23 |
| 62 | #define SMEM_IMAGE_TABLE_OEMPD_INDEX 24 |
| 63 | #define SMEM_IMAGE_TABLE_CHARGERPD_INDEX 25 |
| 64 | #define SMEM_IMAGE_TABLE_OISPD_INDEX 26 |
| 65 | #define SMEM_IMAGE_TABLE_SOCCP_INDEX 27 |
| 66 | #define SMEM_IMAGE_TABLE_TME_INDEX 28 |
| 67 | #define SMEM_IMAGE_TABLE_GEARVM_INDEX 29 |
| 68 | #define SMEM_IMAGE_TABLE_UEFI_INDEX 30 |
| 69 | #define SMEM_IMAGE_TABLE_CDSP3_INDEX 31 |
| 70 | #define SMEM_IMAGE_TABLE_AUDIOPD_ADSP1_INDEX 32 |
| 71 | #define SMEM_IMAGE_TABLE_AUDIOPD_ADSP2_INDEX 33 |
| 72 | #define SMEM_IMAGE_TABLE_DCP_INDEX 34 |
| 73 | #define SMEM_IMAGE_TABLE_OOBS_INDEX 35 |
| 74 | #define SMEM_IMAGE_TABLE_OOBNS_INDEX 36 |
| 75 | #define SMEM_IMAGE_TABLE_DEVCFG_INDEX 37 |
| 76 | #define SMEM_IMAGE_TABLE_BTPD_INDEX 38 |
| 77 | #define SMEM_IMAGE_TABLE_QECP_INDEX 39 |
| 78 | |
| 79 | #define SMEM_IMAGE_VERSION_TABLE 469 |
| 80 | #define SMEM_IMAGE_VERSION_TABLE_2 667 |
| 81 | |
| 82 | /* |
| 83 | * SMEM Image table names |
| 84 | */ |
| 85 | static const char *const socinfo_image_names[] = { |
| 86 | [SMEM_IMAGE_TABLE_ADSP1_INDEX] = "adsp1" , |
| 87 | [SMEM_IMAGE_TABLE_ADSP2_INDEX] = "adsp2" , |
| 88 | [SMEM_IMAGE_TABLE_ADSP_INDEX] = "adsp" , |
| 89 | [SMEM_IMAGE_TABLE_APPSBL_INDEX] = "appsbl" , |
| 90 | [SMEM_IMAGE_TABLE_APPS_INDEX] = "apps" , |
| 91 | [SMEM_IMAGE_TABLE_AUDIOPD_INDEX] = "audiopd" , |
| 92 | [SMEM_IMAGE_TABLE_AUDIOPD_ADSP1_INDEX] = "audiopd_adsp1" , |
| 93 | [SMEM_IMAGE_TABLE_AUDIOPD_ADSP2_INDEX] = "audiopd_adsp2" , |
| 94 | [SMEM_IMAGE_TABLE_BOOT_INDEX] = "boot" , |
| 95 | [SMEM_IMAGE_TABLE_BTPD_INDEX] = "btpd" , |
| 96 | [SMEM_IMAGE_TABLE_CDSP1_INDEX] = "cdsp1" , |
| 97 | [SMEM_IMAGE_TABLE_CDSP2_INDEX] = "cdsp2" , |
| 98 | [SMEM_IMAGE_TABLE_CDSP3_INDEX] = "cdsp3" , |
| 99 | [SMEM_IMAGE_TABLE_CDSP_INDEX] = "cdsp" , |
| 100 | [SMEM_IMAGE_TABLE_CHARGERPD_INDEX] = "chargerpd" , |
| 101 | [SMEM_IMAGE_TABLE_CNSS_INDEX] = "cnss" , |
| 102 | [SMEM_IMAGE_TABLE_DCP_INDEX] = "dcp" , |
| 103 | [SMEM_IMAGE_TABLE_DEVCFG_INDEX] = "devcfg" , |
| 104 | [SMEM_IMAGE_TABLE_DSPS_INDEX] = "dsps" , |
| 105 | [SMEM_IMAGE_TABLE_GEARVM_INDEX] = "gearvm" , |
| 106 | [SMEM_IMAGE_TABLE_GPDSP1_INDEX] = "gpdsp1" , |
| 107 | [SMEM_IMAGE_TABLE_GPDSP_INDEX] = "gpdsp" , |
| 108 | [SMEM_IMAGE_TABLE_HYP_INDEX] = "hyp" , |
| 109 | [SMEM_IMAGE_TABLE_MPSS_INDEX] = "mpss" , |
| 110 | [SMEM_IMAGE_TABLE_NPU_INDEX] = "npu" , |
| 111 | [SMEM_IMAGE_TABLE_OEMPD_INDEX] = "oempd" , |
| 112 | [SMEM_IMAGE_TABLE_OISPD_INDEX] = "oispd" , |
| 113 | [SMEM_IMAGE_TABLE_OOBNS_INDEX] = "oobns" , |
| 114 | [SMEM_IMAGE_TABLE_OOBS_INDEX] = "oobs" , |
| 115 | [SMEM_IMAGE_TABLE_QECP_INDEX] = "qecp" , |
| 116 | [SMEM_IMAGE_TABLE_RPM_INDEX] = "rpm" , |
| 117 | [SMEM_IMAGE_TABLE_SDI_INDEX] = "sdi" , |
| 118 | [SMEM_IMAGE_TABLE_SENSORPD_INDEX] = "sensorpd" , |
| 119 | [SMEM_IMAGE_TABLE_SOCCP_INDEX] = "soccp" , |
| 120 | [SMEM_IMAGE_TABLE_TME_INDEX] = "tme" , |
| 121 | [SMEM_IMAGE_TABLE_TZ_INDEX] = "tz" , |
| 122 | [SMEM_IMAGE_TABLE_TZSECAPP_INDEX] = "tzsecapp" , |
| 123 | [SMEM_IMAGE_TABLE_UEFI_INDEX] = "uefi" , |
| 124 | [SMEM_IMAGE_TABLE_VIDEO_INDEX] = "video" , |
| 125 | [SMEM_IMAGE_TABLE_WPSS_INDEX] = "wpss" , |
| 126 | }; |
| 127 | |
| 128 | static const char *const pmic_models[] = { |
| 129 | [0] = "Unknown PMIC model" , |
| 130 | [1] = "PM8941" , |
| 131 | [2] = "PM8841" , |
| 132 | [3] = "PM8019" , |
| 133 | [4] = "PM8226" , |
| 134 | [5] = "PM8110" , |
| 135 | [6] = "PMA8084" , |
| 136 | [7] = "PMI8962" , |
| 137 | [8] = "PMD9635" , |
| 138 | [9] = "PM8994" , |
| 139 | [10] = "PMI8994" , |
| 140 | [11] = "PM8916" , |
| 141 | [12] = "PM8004" , |
| 142 | [13] = "PM8909/PM8058" , |
| 143 | [14] = "PM8028" , |
| 144 | [15] = "PM8901" , |
| 145 | [16] = "PM8950/PM8027" , |
| 146 | [17] = "PMI8950/ISL9519" , |
| 147 | [18] = "PMK8001/PM8921" , |
| 148 | [19] = "PMI8996/PM8018" , |
| 149 | [20] = "PM8998/PM8015" , |
| 150 | [21] = "PMI8998/PM8014" , |
| 151 | [22] = "PM8821" , |
| 152 | [23] = "PM8038" , |
| 153 | [24] = "PM8005/PM8922" , |
| 154 | [25] = "PM8917/PM8937" , |
| 155 | [26] = "PM660L" , |
| 156 | [27] = "PM660" , |
| 157 | [30] = "PM8150" , |
| 158 | [31] = "PM8150L" , |
| 159 | [32] = "PM8150B" , |
| 160 | [33] = "PMK8002" , |
| 161 | [36] = "PM8009" , |
| 162 | [37] = "PMI632" , |
| 163 | [38] = "PM8150C" , |
| 164 | [40] = "PM6150" , |
| 165 | [41] = "SMB2351" , |
| 166 | [44] = "PM8008" , |
| 167 | [45] = "PM6125" , |
| 168 | [46] = "PM7250B" , |
| 169 | [47] = "PMK8350" , |
| 170 | [48] = "PM8350" , |
| 171 | [49] = "PM8350C" , |
| 172 | [50] = "PM8350B" , |
| 173 | [51] = "PMR735A" , |
| 174 | [52] = "PMR735B" , |
| 175 | [54] = "PM6350" , |
| 176 | [55] = "PM4125" , |
| 177 | [58] = "PM8450" , |
| 178 | [65] = "PM8010" , |
| 179 | [69] = "PM8550VS" , |
| 180 | [70] = "PM8550VE" , |
| 181 | [71] = "PM8550B" , |
| 182 | [72] = "PMR735D" , |
| 183 | [73] = "PM8550" , |
| 184 | [74] = "PMK8550" , |
| 185 | [78] = "PMM8650AU" , |
| 186 | [79] = "PMM8650AU_PSAIL" , |
| 187 | [80] = "PM7550" , |
| 188 | [82] = "PMC8380" , |
| 189 | [83] = "SMB2360" , |
| 190 | [91] = "PMIV0108" , |
| 191 | }; |
| 192 | |
| 193 | struct socinfo_params { |
| 194 | u32 raw_device_family; |
| 195 | u32 hw_plat_subtype; |
| 196 | u32 accessory_chip; |
| 197 | u32 raw_device_num; |
| 198 | u32 chip_family; |
| 199 | u32 foundry_id; |
| 200 | u32 plat_ver; |
| 201 | u32 raw_ver; |
| 202 | u32 hw_plat; |
| 203 | u32 fmt; |
| 204 | u32 nproduct_id; |
| 205 | u32 num_clusters; |
| 206 | u32 ncluster_array_offset; |
| 207 | u32 num_subset_parts; |
| 208 | u32 nsubset_parts_array_offset; |
| 209 | u32 nmodem_supported; |
| 210 | u32 feature_code; |
| 211 | u32 pcode; |
| 212 | u32 oem_variant; |
| 213 | u32 num_func_clusters; |
| 214 | u32 boot_cluster; |
| 215 | u32 boot_core; |
| 216 | u32 raw_package_type; |
| 217 | }; |
| 218 | |
| 219 | struct smem_image_version { |
| 220 | char name[SMEM_IMAGE_VERSION_NAME_SIZE]; |
| 221 | char variant[SMEM_IMAGE_VERSION_VARIANT_SIZE]; |
| 222 | char pad; |
| 223 | char oem[SMEM_IMAGE_VERSION_OEM_SIZE]; |
| 224 | }; |
| 225 | #endif /* CONFIG_DEBUG_FS */ |
| 226 | |
| 227 | struct qcom_socinfo { |
| 228 | struct soc_device *soc_dev; |
| 229 | struct soc_device_attribute attr; |
| 230 | #ifdef CONFIG_DEBUG_FS |
| 231 | struct dentry *dbg_root; |
| 232 | struct socinfo_params info; |
| 233 | #endif /* CONFIG_DEBUG_FS */ |
| 234 | }; |
| 235 | |
| 236 | struct soc_id { |
| 237 | unsigned int id; |
| 238 | const char *name; |
| 239 | }; |
| 240 | |
| 241 | static const struct soc_id soc_id[] = { |
| 242 | { qcom_board_id(MSM8260) }, |
| 243 | { qcom_board_id(MSM8660) }, |
| 244 | { qcom_board_id(APQ8060) }, |
| 245 | { qcom_board_id(MSM8960) }, |
| 246 | { qcom_board_id(APQ8064) }, |
| 247 | { qcom_board_id(MSM8930) }, |
| 248 | { qcom_board_id(MSM8630) }, |
| 249 | { qcom_board_id(MSM8230) }, |
| 250 | { qcom_board_id(APQ8030) }, |
| 251 | { qcom_board_id(MSM8627) }, |
| 252 | { qcom_board_id(MSM8227) }, |
| 253 | { qcom_board_id(MSM8660A) }, |
| 254 | { qcom_board_id(MSM8260A) }, |
| 255 | { qcom_board_id(APQ8060A) }, |
| 256 | { qcom_board_id(MSM8974) }, |
| 257 | { qcom_board_id(MSM8225) }, |
| 258 | { qcom_board_id(MSM8625) }, |
| 259 | { qcom_board_id(MPQ8064) }, |
| 260 | { qcom_board_id(MSM8960AB) }, |
| 261 | { qcom_board_id(APQ8060AB) }, |
| 262 | { qcom_board_id(MSM8260AB) }, |
| 263 | { qcom_board_id(MSM8660AB) }, |
| 264 | { qcom_board_id(MSM8930AA) }, |
| 265 | { qcom_board_id(MSM8630AA) }, |
| 266 | { qcom_board_id(MSM8230AA) }, |
| 267 | { qcom_board_id(MSM8626) }, |
| 268 | { qcom_board_id(MSM8610) }, |
| 269 | { qcom_board_id(APQ8064AB) }, |
| 270 | { qcom_board_id(MSM8930AB) }, |
| 271 | { qcom_board_id(MSM8630AB) }, |
| 272 | { qcom_board_id(MSM8230AB) }, |
| 273 | { qcom_board_id(APQ8030AB) }, |
| 274 | { qcom_board_id(MSM8226) }, |
| 275 | { qcom_board_id(MSM8526) }, |
| 276 | { qcom_board_id(APQ8030AA) }, |
| 277 | { qcom_board_id(MSM8110) }, |
| 278 | { qcom_board_id(MSM8210) }, |
| 279 | { qcom_board_id(MSM8810) }, |
| 280 | { qcom_board_id(MSM8212) }, |
| 281 | { qcom_board_id(MSM8612) }, |
| 282 | { qcom_board_id(MSM8112) }, |
| 283 | { qcom_board_id(MSM8125) }, |
| 284 | { qcom_board_id(MSM8225Q) }, |
| 285 | { qcom_board_id(MSM8625Q) }, |
| 286 | { qcom_board_id(MSM8125Q) }, |
| 287 | { qcom_board_id(APQ8064AA) }, |
| 288 | { qcom_board_id(APQ8084) }, |
| 289 | { qcom_board_id(MSM8130) }, |
| 290 | { qcom_board_id(MSM8130AA) }, |
| 291 | { qcom_board_id(MSM8130AB) }, |
| 292 | { qcom_board_id(MSM8627AA) }, |
| 293 | { qcom_board_id(MSM8227AA) }, |
| 294 | { qcom_board_id(APQ8074) }, |
| 295 | { qcom_board_id(MSM8274) }, |
| 296 | { qcom_board_id(MSM8674) }, |
| 297 | { qcom_board_id(MDM9635) }, |
| 298 | { qcom_board_id_named(MSM8974PRO_AC, "MSM8974PRO-AC" ) }, |
| 299 | { qcom_board_id(MSM8126) }, |
| 300 | { qcom_board_id(APQ8026) }, |
| 301 | { qcom_board_id(MSM8926) }, |
| 302 | { qcom_board_id(IPQ8062) }, |
| 303 | { qcom_board_id(IPQ8064) }, |
| 304 | { qcom_board_id(IPQ8066) }, |
| 305 | { qcom_board_id(IPQ8068) }, |
| 306 | { qcom_board_id(MSM8326) }, |
| 307 | { qcom_board_id(MSM8916) }, |
| 308 | { qcom_board_id(MSM8994) }, |
| 309 | { qcom_board_id_named(APQ8074PRO_AA, "APQ8074PRO-AA" ) }, |
| 310 | { qcom_board_id_named(APQ8074PRO_AB, "APQ8074PRO-AB" ) }, |
| 311 | { qcom_board_id_named(APQ8074PRO_AC, "APQ8074PRO-AC" ) }, |
| 312 | { qcom_board_id_named(MSM8274PRO_AA, "MSM8274PRO-AA" ) }, |
| 313 | { qcom_board_id_named(MSM8274PRO_AB, "MSM8274PRO-AB" ) }, |
| 314 | { qcom_board_id_named(MSM8274PRO_AC, "MSM8274PRO-AC" ) }, |
| 315 | { qcom_board_id_named(MSM8674PRO_AA, "MSM8674PRO-AA" ) }, |
| 316 | { qcom_board_id_named(MSM8674PRO_AB, "MSM8674PRO-AB" ) }, |
| 317 | { qcom_board_id_named(MSM8674PRO_AC, "MSM8674PRO-AC" ) }, |
| 318 | { qcom_board_id_named(MSM8974PRO_AA, "MSM8974PRO-AA" ) }, |
| 319 | { qcom_board_id_named(MSM8974PRO_AB, "MSM8974PRO-AB" ) }, |
| 320 | { qcom_board_id(APQ8028) }, |
| 321 | { qcom_board_id(MSM8128) }, |
| 322 | { qcom_board_id(MSM8228) }, |
| 323 | { qcom_board_id(MSM8528) }, |
| 324 | { qcom_board_id(MSM8628) }, |
| 325 | { qcom_board_id(MSM8928) }, |
| 326 | { qcom_board_id(MSM8510) }, |
| 327 | { qcom_board_id(MSM8512) }, |
| 328 | { qcom_board_id(MSM8936) }, |
| 329 | { qcom_board_id(MDM9640) }, |
| 330 | { qcom_board_id(MSM8939) }, |
| 331 | { qcom_board_id(APQ8036) }, |
| 332 | { qcom_board_id(APQ8039) }, |
| 333 | { qcom_board_id(MSM8236) }, |
| 334 | { qcom_board_id(MSM8636) }, |
| 335 | { qcom_board_id(MSM8909) }, |
| 336 | { qcom_board_id(MSM8996) }, |
| 337 | { qcom_board_id(APQ8016) }, |
| 338 | { qcom_board_id(MSM8216) }, |
| 339 | { qcom_board_id(MSM8116) }, |
| 340 | { qcom_board_id(MSM8616) }, |
| 341 | { qcom_board_id(MSM8992) }, |
| 342 | { qcom_board_id(APQ8092) }, |
| 343 | { qcom_board_id(APQ8094) }, |
| 344 | { qcom_board_id(MSM8209) }, |
| 345 | { qcom_board_id(MSM8208) }, |
| 346 | { qcom_board_id(MDM9209) }, |
| 347 | { qcom_board_id(MDM9309) }, |
| 348 | { qcom_board_id(MDM9609) }, |
| 349 | { qcom_board_id(MSM8239) }, |
| 350 | { qcom_board_id(MSM8952) }, |
| 351 | { qcom_board_id(APQ8009) }, |
| 352 | { qcom_board_id(MSM8956) }, |
| 353 | { qcom_board_id(MSM8929) }, |
| 354 | { qcom_board_id(MSM8629) }, |
| 355 | { qcom_board_id(MSM8229) }, |
| 356 | { qcom_board_id(APQ8029) }, |
| 357 | { qcom_board_id(APQ8056) }, |
| 358 | { qcom_board_id(MSM8609) }, |
| 359 | { qcom_board_id(APQ8076) }, |
| 360 | { qcom_board_id(MSM8976) }, |
| 361 | { qcom_board_id(IPQ8065) }, |
| 362 | { qcom_board_id(IPQ8069) }, |
| 363 | { qcom_board_id(MDM9650) }, |
| 364 | { qcom_board_id(MDM9655) }, |
| 365 | { qcom_board_id(MDM9250) }, |
| 366 | { qcom_board_id(MDM9255) }, |
| 367 | { qcom_board_id(MDM9350) }, |
| 368 | { qcom_board_id(APQ8052) }, |
| 369 | { qcom_board_id(MDM9607) }, |
| 370 | { qcom_board_id(APQ8096) }, |
| 371 | { qcom_board_id(MSM8998) }, |
| 372 | { qcom_board_id(MSM8953) }, |
| 373 | { qcom_board_id(MSM8937) }, |
| 374 | { qcom_board_id(APQ8037) }, |
| 375 | { qcom_board_id(MDM8207) }, |
| 376 | { qcom_board_id(MDM9207) }, |
| 377 | { qcom_board_id(MDM9307) }, |
| 378 | { qcom_board_id(MDM9628) }, |
| 379 | { qcom_board_id(MSM8909W) }, |
| 380 | { qcom_board_id(APQ8009W) }, |
| 381 | { qcom_board_id(MSM8996L) }, |
| 382 | { qcom_board_id(MSM8917) }, |
| 383 | { qcom_board_id(APQ8053) }, |
| 384 | { qcom_board_id(MSM8996SG) }, |
| 385 | { qcom_board_id(APQ8017) }, |
| 386 | { qcom_board_id(MSM8217) }, |
| 387 | { qcom_board_id(MSM8617) }, |
| 388 | { qcom_board_id(MSM8996AU) }, |
| 389 | { qcom_board_id(APQ8096AU) }, |
| 390 | { qcom_board_id(APQ8096SG) }, |
| 391 | { qcom_board_id(MSM8940) }, |
| 392 | { qcom_board_id(SDX201) }, |
| 393 | { qcom_board_id(SDM660) }, |
| 394 | { qcom_board_id(SDM630) }, |
| 395 | { qcom_board_id(APQ8098) }, |
| 396 | { qcom_board_id(MSM8920) }, |
| 397 | { qcom_board_id(SDM845) }, |
| 398 | { qcom_board_id(MDM9206) }, |
| 399 | { qcom_board_id(IPQ8074) }, |
| 400 | { qcom_board_id(SDA660) }, |
| 401 | { qcom_board_id(SDM658) }, |
| 402 | { qcom_board_id(SDA658) }, |
| 403 | { qcom_board_id(SDA630) }, |
| 404 | { qcom_board_id(MSM8905) }, |
| 405 | { qcom_board_id(SDX202) }, |
| 406 | { qcom_board_id(SDM670) }, |
| 407 | { qcom_board_id(SDM450) }, |
| 408 | { qcom_board_id(SM8150) }, |
| 409 | { qcom_board_id(SDA845) }, |
| 410 | { qcom_board_id(IPQ8072) }, |
| 411 | { qcom_board_id(IPQ8076) }, |
| 412 | { qcom_board_id(IPQ8078) }, |
| 413 | { qcom_board_id(SDM636) }, |
| 414 | { qcom_board_id(SDA636) }, |
| 415 | { qcom_board_id(SDM632) }, |
| 416 | { qcom_board_id(SDA632) }, |
| 417 | { qcom_board_id(SDA450) }, |
| 418 | { qcom_board_id(SDM439) }, |
| 419 | { qcom_board_id(SDM429) }, |
| 420 | { qcom_board_id(SM8250) }, |
| 421 | { qcom_board_id(SA8155) }, |
| 422 | { qcom_board_id(SDA439) }, |
| 423 | { qcom_board_id(SDA429) }, |
| 424 | { qcom_board_id(SM7150) }, |
| 425 | { qcom_board_id(SM7150P) }, |
| 426 | { qcom_board_id(IPQ8070) }, |
| 427 | { qcom_board_id(IPQ8071) }, |
| 428 | { qcom_board_id(QM215) }, |
| 429 | { qcom_board_id(IPQ8072A) }, |
| 430 | { qcom_board_id(IPQ8074A) }, |
| 431 | { qcom_board_id(IPQ8076A) }, |
| 432 | { qcom_board_id(IPQ8078A) }, |
| 433 | { qcom_board_id(SM6125) }, |
| 434 | { qcom_board_id(IPQ8070A) }, |
| 435 | { qcom_board_id(IPQ8071A) }, |
| 436 | { qcom_board_id(IPQ8172) }, |
| 437 | { qcom_board_id(IPQ8173) }, |
| 438 | { qcom_board_id(IPQ8174) }, |
| 439 | { qcom_board_id(IPQ6018) }, |
| 440 | { qcom_board_id(IPQ6028) }, |
| 441 | { qcom_board_id(SDM429W) }, |
| 442 | { qcom_board_id(SM4250) }, |
| 443 | { qcom_board_id(IPQ6000) }, |
| 444 | { qcom_board_id(IPQ6010) }, |
| 445 | { qcom_board_id(SC7180) }, |
| 446 | { qcom_board_id(SM6350) }, |
| 447 | { qcom_board_id(QCM2150) }, |
| 448 | { qcom_board_id(SDA429W) }, |
| 449 | { qcom_board_id(SM8350) }, |
| 450 | { qcom_board_id(QCM2290) }, |
| 451 | { qcom_board_id(SM7125) }, |
| 452 | { qcom_board_id(SM6115) }, |
| 453 | { qcom_board_id(IPQ5010) }, |
| 454 | { qcom_board_id(IPQ5018) }, |
| 455 | { qcom_board_id(IPQ5028) }, |
| 456 | { qcom_board_id(SC8280XP) }, |
| 457 | { qcom_board_id(IPQ6005) }, |
| 458 | { qcom_board_id(QRB5165) }, |
| 459 | { qcom_board_id(SM8450) }, |
| 460 | { qcom_board_id(SM7225) }, |
| 461 | { qcom_board_id(SA8295P) }, |
| 462 | { qcom_board_id(SA8540P) }, |
| 463 | { qcom_board_id(QCM4290) }, |
| 464 | { qcom_board_id(QCS4290) }, |
| 465 | { qcom_board_id(SM7325) }, |
| 466 | { qcom_board_id_named(SM8450_2, "SM8450" ) }, |
| 467 | { qcom_board_id_named(SM8450_3, "SM8450" ) }, |
| 468 | { qcom_board_id(SC7280) }, |
| 469 | { qcom_board_id(SC7180P) }, |
| 470 | { qcom_board_id(QCM6490) }, |
| 471 | { qcom_board_id(QCS6490) }, |
| 472 | { qcom_board_id(SM7325P) }, |
| 473 | { qcom_board_id(IPQ5000) }, |
| 474 | { qcom_board_id(IPQ0509) }, |
| 475 | { qcom_board_id(IPQ0518) }, |
| 476 | { qcom_board_id(SM6375) }, |
| 477 | { qcom_board_id(IPQ9514) }, |
| 478 | { qcom_board_id(IPQ9550) }, |
| 479 | { qcom_board_id(IPQ9554) }, |
| 480 | { qcom_board_id(IPQ9570) }, |
| 481 | { qcom_board_id(IPQ9574) }, |
| 482 | { qcom_board_id(SM8550) }, |
| 483 | { qcom_board_id(IPQ5016) }, |
| 484 | { qcom_board_id(IPQ9510) }, |
| 485 | { qcom_board_id(QRB4210) }, |
| 486 | { qcom_board_id(QRB2210) }, |
| 487 | { qcom_board_id(SAR2130P) }, |
| 488 | { qcom_board_id(SM8475) }, |
| 489 | { qcom_board_id(SM8475P) }, |
| 490 | { qcom_board_id(SA8255P) }, |
| 491 | { qcom_board_id(SA8775P) }, |
| 492 | { qcom_board_id(QRU1000) }, |
| 493 | { qcom_board_id(SM8475_2) }, |
| 494 | { qcom_board_id(QDU1000) }, |
| 495 | { qcom_board_id(X1E80100) }, |
| 496 | { qcom_board_id(SM8650) }, |
| 497 | { qcom_board_id(SM4450) }, |
| 498 | { qcom_board_id(SAR1130P) }, |
| 499 | { qcom_board_id(QDU1010) }, |
| 500 | { qcom_board_id(QRU1032) }, |
| 501 | { qcom_board_id(QRU1052) }, |
| 502 | { qcom_board_id(QRU1062) }, |
| 503 | { qcom_board_id(IPQ5332) }, |
| 504 | { qcom_board_id(IPQ5322) }, |
| 505 | { qcom_board_id(IPQ5312) }, |
| 506 | { qcom_board_id(IPQ5302) }, |
| 507 | { qcom_board_id(QCS8550) }, |
| 508 | { qcom_board_id(QCM8550) }, |
| 509 | { qcom_board_id(SM8750) }, |
| 510 | { qcom_board_id(IPQ5300) }, |
| 511 | { qcom_board_id(SM7635) }, |
| 512 | { qcom_board_id(SM6650) }, |
| 513 | { qcom_board_id(SM6650P) }, |
| 514 | { qcom_board_id(IPQ5321) }, |
| 515 | { qcom_board_id(IPQ5424) }, |
| 516 | { qcom_board_id(QCM6690) }, |
| 517 | { qcom_board_id(QCS6690) }, |
| 518 | { qcom_board_id(SM8850) }, |
| 519 | { qcom_board_id(IPQ5404) }, |
| 520 | { qcom_board_id(QCS9100) }, |
| 521 | { qcom_board_id(QCS8300) }, |
| 522 | { qcom_board_id(QCS8275) }, |
| 523 | { qcom_board_id(QCS9075) }, |
| 524 | { qcom_board_id(QCS615) }, |
| 525 | }; |
| 526 | |
| 527 | static const char *socinfo_machine(struct device *dev, unsigned int id) |
| 528 | { |
| 529 | int idx; |
| 530 | |
| 531 | for (idx = 0; idx < ARRAY_SIZE(soc_id); idx++) { |
| 532 | if (soc_id[idx].id == id) |
| 533 | return soc_id[idx].name; |
| 534 | } |
| 535 | |
| 536 | return NULL; |
| 537 | } |
| 538 | |
| 539 | #ifdef CONFIG_DEBUG_FS |
| 540 | |
| 541 | #define QCOM_OPEN(name, _func) \ |
| 542 | static int qcom_open_##name(struct inode *inode, struct file *file) \ |
| 543 | { \ |
| 544 | return single_open(file, _func, inode->i_private); \ |
| 545 | } \ |
| 546 | \ |
| 547 | static const struct file_operations qcom_ ##name## _ops = { \ |
| 548 | .open = qcom_open_##name, \ |
| 549 | .read = seq_read, \ |
| 550 | .llseek = seq_lseek, \ |
| 551 | .release = single_release, \ |
| 552 | } |
| 553 | |
| 554 | #define DEBUGFS_ADD(info, name) \ |
| 555 | debugfs_create_file(__stringify(name), 0444, \ |
| 556 | qcom_socinfo->dbg_root, \ |
| 557 | info, &qcom_ ##name## _ops) |
| 558 | |
| 559 | |
| 560 | static int qcom_show_build_id(struct seq_file *seq, void *p) |
| 561 | { |
| 562 | struct socinfo *socinfo = seq->private; |
| 563 | |
| 564 | seq_printf(m: seq, fmt: "%s\n" , socinfo->build_id); |
| 565 | |
| 566 | return 0; |
| 567 | } |
| 568 | |
| 569 | static int qcom_show_pmic_model(struct seq_file *seq, void *p) |
| 570 | { |
| 571 | struct socinfo *socinfo = seq->private; |
| 572 | int model = SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_model)); |
| 573 | |
| 574 | if (model < 0) |
| 575 | return -EINVAL; |
| 576 | |
| 577 | if (model < ARRAY_SIZE(pmic_models) && pmic_models[model]) |
| 578 | seq_printf(m: seq, fmt: "%s\n" , pmic_models[model]); |
| 579 | else |
| 580 | seq_printf(m: seq, fmt: "unknown (%d)\n" , model); |
| 581 | |
| 582 | return 0; |
| 583 | } |
| 584 | |
| 585 | static int qcom_show_pmic_model_array(struct seq_file *seq, void *p) |
| 586 | { |
| 587 | struct socinfo *socinfo = seq->private; |
| 588 | unsigned int num_pmics = le32_to_cpu(socinfo->num_pmics); |
| 589 | unsigned int pmic_array_offset = le32_to_cpu(socinfo->pmic_array_offset); |
| 590 | int i; |
| 591 | void *ptr = socinfo; |
| 592 | |
| 593 | ptr += pmic_array_offset; |
| 594 | |
| 595 | /* No need for bounds checking, it happened at socinfo_debugfs_init */ |
| 596 | for (i = 0; i < num_pmics; i++) { |
| 597 | unsigned int model = SOCINFO_MINOR(get_unaligned_le32(ptr + 2 * i * sizeof(u32))); |
| 598 | unsigned int die_rev = get_unaligned_le32(p: ptr + (2 * i + 1) * sizeof(u32)); |
| 599 | |
| 600 | if (model < ARRAY_SIZE(pmic_models) && pmic_models[model]) |
| 601 | seq_printf(m: seq, fmt: "%s %u.%u\n" , pmic_models[model], |
| 602 | SOCINFO_MAJOR(die_rev), |
| 603 | SOCINFO_MINOR(die_rev)); |
| 604 | else |
| 605 | seq_printf(m: seq, fmt: "unknown (%d)\n" , model); |
| 606 | } |
| 607 | |
| 608 | return 0; |
| 609 | } |
| 610 | |
| 611 | static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p) |
| 612 | { |
| 613 | struct socinfo *socinfo = seq->private; |
| 614 | |
| 615 | seq_printf(m: seq, fmt: "%u.%u\n" , |
| 616 | SOCINFO_MAJOR(le32_to_cpu(socinfo->pmic_die_rev)), |
| 617 | SOCINFO_MINOR(le32_to_cpu(socinfo->pmic_die_rev))); |
| 618 | |
| 619 | return 0; |
| 620 | } |
| 621 | |
| 622 | static int qcom_show_chip_id(struct seq_file *seq, void *p) |
| 623 | { |
| 624 | struct socinfo *socinfo = seq->private; |
| 625 | |
| 626 | seq_printf(m: seq, fmt: "%s\n" , socinfo->chip_id); |
| 627 | |
| 628 | return 0; |
| 629 | } |
| 630 | |
| 631 | QCOM_OPEN(build_id, qcom_show_build_id); |
| 632 | QCOM_OPEN(pmic_model, qcom_show_pmic_model); |
| 633 | QCOM_OPEN(pmic_model_array, qcom_show_pmic_model_array); |
| 634 | QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision); |
| 635 | QCOM_OPEN(chip_id, qcom_show_chip_id); |
| 636 | |
| 637 | #define DEFINE_IMAGE_OPS(type) \ |
| 638 | static int show_image_##type(struct seq_file *seq, void *p) \ |
| 639 | { \ |
| 640 | struct smem_image_version *image_version = seq->private; \ |
| 641 | if (image_version->type[0] != '\0') \ |
| 642 | seq_printf(seq, "%s\n", image_version->type); \ |
| 643 | return 0; \ |
| 644 | } \ |
| 645 | static int open_image_##type(struct inode *inode, struct file *file) \ |
| 646 | { \ |
| 647 | return single_open(file, show_image_##type, inode->i_private); \ |
| 648 | } \ |
| 649 | \ |
| 650 | static const struct file_operations qcom_image_##type##_ops = { \ |
| 651 | .open = open_image_##type, \ |
| 652 | .read = seq_read, \ |
| 653 | .llseek = seq_lseek, \ |
| 654 | .release = single_release, \ |
| 655 | } |
| 656 | |
| 657 | DEFINE_IMAGE_OPS(name); |
| 658 | DEFINE_IMAGE_OPS(variant); |
| 659 | DEFINE_IMAGE_OPS(oem); |
| 660 | |
| 661 | static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, |
| 662 | struct socinfo *info, size_t info_size) |
| 663 | { |
| 664 | struct smem_image_version *versions; |
| 665 | struct dentry *dentry; |
| 666 | size_t size; |
| 667 | int i, j; |
| 668 | unsigned int num_pmics; |
| 669 | unsigned int pmic_array_offset; |
| 670 | |
| 671 | qcom_socinfo->dbg_root = debugfs_create_dir(name: "qcom_socinfo" , NULL); |
| 672 | |
| 673 | qcom_socinfo->info.fmt = __le32_to_cpu(info->fmt); |
| 674 | |
| 675 | debugfs_create_x32(name: "info_fmt" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 676 | value: &qcom_socinfo->info.fmt); |
| 677 | |
| 678 | switch (qcom_socinfo->info.fmt) { |
| 679 | case SOCINFO_VERSION(0, 23): |
| 680 | case SOCINFO_VERSION(0, 22): |
| 681 | case SOCINFO_VERSION(0, 21): |
| 682 | case SOCINFO_VERSION(0, 20): |
| 683 | qcom_socinfo->info.raw_package_type = __le32_to_cpu(info->raw_package_type); |
| 684 | debugfs_create_u32(name: "raw_package_type" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 685 | value: &qcom_socinfo->info.raw_package_type); |
| 686 | fallthrough; |
| 687 | case SOCINFO_VERSION(0, 19): |
| 688 | qcom_socinfo->info.num_func_clusters = __le32_to_cpu(info->num_func_clusters); |
| 689 | qcom_socinfo->info.boot_cluster = __le32_to_cpu(info->boot_cluster); |
| 690 | qcom_socinfo->info.boot_core = __le32_to_cpu(info->boot_core); |
| 691 | |
| 692 | debugfs_create_u32(name: "num_func_clusters" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 693 | value: &qcom_socinfo->info.num_func_clusters); |
| 694 | debugfs_create_u32(name: "boot_cluster" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 695 | value: &qcom_socinfo->info.boot_cluster); |
| 696 | debugfs_create_u32(name: "boot_core" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 697 | value: &qcom_socinfo->info.boot_core); |
| 698 | fallthrough; |
| 699 | case SOCINFO_VERSION(0, 18): |
| 700 | case SOCINFO_VERSION(0, 17): |
| 701 | qcom_socinfo->info.oem_variant = __le32_to_cpu(info->oem_variant); |
| 702 | debugfs_create_u32(name: "oem_variant" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 703 | value: &qcom_socinfo->info.oem_variant); |
| 704 | fallthrough; |
| 705 | case SOCINFO_VERSION(0, 16): |
| 706 | qcom_socinfo->info.feature_code = __le32_to_cpu(info->feature_code); |
| 707 | qcom_socinfo->info.pcode = __le32_to_cpu(info->pcode); |
| 708 | |
| 709 | debugfs_create_u32(name: "feature_code" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 710 | value: &qcom_socinfo->info.feature_code); |
| 711 | debugfs_create_u32(name: "pcode" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 712 | value: &qcom_socinfo->info.pcode); |
| 713 | fallthrough; |
| 714 | case SOCINFO_VERSION(0, 15): |
| 715 | qcom_socinfo->info.nmodem_supported = __le32_to_cpu(info->nmodem_supported); |
| 716 | |
| 717 | debugfs_create_u32(name: "nmodem_supported" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 718 | value: &qcom_socinfo->info.nmodem_supported); |
| 719 | fallthrough; |
| 720 | case SOCINFO_VERSION(0, 14): |
| 721 | qcom_socinfo->info.num_clusters = __le32_to_cpu(info->num_clusters); |
| 722 | qcom_socinfo->info.ncluster_array_offset = __le32_to_cpu(info->ncluster_array_offset); |
| 723 | qcom_socinfo->info.num_subset_parts = __le32_to_cpu(info->num_subset_parts); |
| 724 | qcom_socinfo->info.nsubset_parts_array_offset = |
| 725 | __le32_to_cpu(info->nsubset_parts_array_offset); |
| 726 | |
| 727 | debugfs_create_u32(name: "num_clusters" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 728 | value: &qcom_socinfo->info.num_clusters); |
| 729 | debugfs_create_u32(name: "ncluster_array_offset" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 730 | value: &qcom_socinfo->info.ncluster_array_offset); |
| 731 | debugfs_create_u32(name: "num_subset_parts" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 732 | value: &qcom_socinfo->info.num_subset_parts); |
| 733 | debugfs_create_u32(name: "nsubset_parts_array_offset" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 734 | value: &qcom_socinfo->info.nsubset_parts_array_offset); |
| 735 | fallthrough; |
| 736 | case SOCINFO_VERSION(0, 13): |
| 737 | qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id); |
| 738 | |
| 739 | debugfs_create_u32(name: "nproduct_id" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 740 | value: &qcom_socinfo->info.nproduct_id); |
| 741 | DEBUGFS_ADD(info, chip_id); |
| 742 | fallthrough; |
| 743 | case SOCINFO_VERSION(0, 12): |
| 744 | qcom_socinfo->info.chip_family = |
| 745 | __le32_to_cpu(info->chip_family); |
| 746 | qcom_socinfo->info.raw_device_family = |
| 747 | __le32_to_cpu(info->raw_device_family); |
| 748 | qcom_socinfo->info.raw_device_num = |
| 749 | __le32_to_cpu(info->raw_device_num); |
| 750 | |
| 751 | debugfs_create_x32(name: "chip_family" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 752 | value: &qcom_socinfo->info.chip_family); |
| 753 | debugfs_create_x32(name: "raw_device_family" , mode: 0444, |
| 754 | parent: qcom_socinfo->dbg_root, |
| 755 | value: &qcom_socinfo->info.raw_device_family); |
| 756 | debugfs_create_x32(name: "raw_device_number" , mode: 0444, |
| 757 | parent: qcom_socinfo->dbg_root, |
| 758 | value: &qcom_socinfo->info.raw_device_num); |
| 759 | fallthrough; |
| 760 | case SOCINFO_VERSION(0, 11): |
| 761 | num_pmics = le32_to_cpu(info->num_pmics); |
| 762 | pmic_array_offset = le32_to_cpu(info->pmic_array_offset); |
| 763 | if (pmic_array_offset + 2 * num_pmics * sizeof(u32) <= info_size) |
| 764 | DEBUGFS_ADD(info, pmic_model_array); |
| 765 | fallthrough; |
| 766 | case SOCINFO_VERSION(0, 10): |
| 767 | case SOCINFO_VERSION(0, 9): |
| 768 | qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id); |
| 769 | |
| 770 | debugfs_create_u32(name: "foundry_id" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 771 | value: &qcom_socinfo->info.foundry_id); |
| 772 | fallthrough; |
| 773 | case SOCINFO_VERSION(0, 8): |
| 774 | case SOCINFO_VERSION(0, 7): |
| 775 | DEBUGFS_ADD(info, pmic_model); |
| 776 | DEBUGFS_ADD(info, pmic_die_rev); |
| 777 | fallthrough; |
| 778 | case SOCINFO_VERSION(0, 6): |
| 779 | qcom_socinfo->info.hw_plat_subtype = |
| 780 | __le32_to_cpu(info->hw_plat_subtype); |
| 781 | |
| 782 | debugfs_create_u32(name: "hardware_platform_subtype" , mode: 0444, |
| 783 | parent: qcom_socinfo->dbg_root, |
| 784 | value: &qcom_socinfo->info.hw_plat_subtype); |
| 785 | fallthrough; |
| 786 | case SOCINFO_VERSION(0, 5): |
| 787 | qcom_socinfo->info.accessory_chip = |
| 788 | __le32_to_cpu(info->accessory_chip); |
| 789 | |
| 790 | debugfs_create_u32(name: "accessory_chip" , mode: 0444, |
| 791 | parent: qcom_socinfo->dbg_root, |
| 792 | value: &qcom_socinfo->info.accessory_chip); |
| 793 | fallthrough; |
| 794 | case SOCINFO_VERSION(0, 4): |
| 795 | qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver); |
| 796 | |
| 797 | debugfs_create_u32(name: "platform_version" , mode: 0444, |
| 798 | parent: qcom_socinfo->dbg_root, |
| 799 | value: &qcom_socinfo->info.plat_ver); |
| 800 | fallthrough; |
| 801 | case SOCINFO_VERSION(0, 3): |
| 802 | qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat); |
| 803 | |
| 804 | debugfs_create_u32(name: "hardware_platform" , mode: 0444, |
| 805 | parent: qcom_socinfo->dbg_root, |
| 806 | value: &qcom_socinfo->info.hw_plat); |
| 807 | fallthrough; |
| 808 | case SOCINFO_VERSION(0, 2): |
| 809 | qcom_socinfo->info.raw_ver = __le32_to_cpu(info->raw_ver); |
| 810 | |
| 811 | debugfs_create_u32(name: "raw_version" , mode: 0444, parent: qcom_socinfo->dbg_root, |
| 812 | value: &qcom_socinfo->info.raw_ver); |
| 813 | fallthrough; |
| 814 | case SOCINFO_VERSION(0, 1): |
| 815 | DEBUGFS_ADD(info, build_id); |
| 816 | break; |
| 817 | } |
| 818 | |
| 819 | for (i = 0, j = 0; i < ARRAY_SIZE(socinfo_image_names); i++, j++) { |
| 820 | if (!socinfo_image_names[i]) |
| 821 | continue; |
| 822 | |
| 823 | if (i == 0) { |
| 824 | versions = qcom_smem_get(QCOM_SMEM_HOST_ANY, |
| 825 | SMEM_IMAGE_VERSION_TABLE, |
| 826 | size: &size); |
| 827 | } else if (i == 32) { |
| 828 | versions = qcom_smem_get(QCOM_SMEM_HOST_ANY, |
| 829 | SMEM_IMAGE_VERSION_TABLE_2, |
| 830 | size: &size); |
| 831 | if (IS_ERR(ptr: versions)) |
| 832 | break; |
| 833 | |
| 834 | j = 0; |
| 835 | } |
| 836 | |
| 837 | dentry = debugfs_create_dir(name: socinfo_image_names[i], |
| 838 | parent: qcom_socinfo->dbg_root); |
| 839 | debugfs_create_file("name" , 0444, dentry, &versions[j], |
| 840 | &qcom_image_name_ops); |
| 841 | debugfs_create_file("variant" , 0444, dentry, &versions[j], |
| 842 | &qcom_image_variant_ops); |
| 843 | debugfs_create_file("oem" , 0444, dentry, &versions[j], |
| 844 | &qcom_image_oem_ops); |
| 845 | } |
| 846 | } |
| 847 | |
| 848 | static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) |
| 849 | { |
| 850 | debugfs_remove_recursive(dentry: qcom_socinfo->dbg_root); |
| 851 | } |
| 852 | #else |
| 853 | static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, |
| 854 | struct socinfo *info, size_t info_size) |
| 855 | { |
| 856 | } |
| 857 | static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) { } |
| 858 | #endif /* CONFIG_DEBUG_FS */ |
| 859 | |
| 860 | static int qcom_socinfo_probe(struct platform_device *pdev) |
| 861 | { |
| 862 | struct qcom_socinfo *qs; |
| 863 | struct socinfo *info; |
| 864 | size_t item_size; |
| 865 | |
| 866 | info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, |
| 867 | size: &item_size); |
| 868 | if (IS_ERR(ptr: info)) { |
| 869 | dev_err(&pdev->dev, "Couldn't find socinfo\n" ); |
| 870 | return PTR_ERR(ptr: info); |
| 871 | } |
| 872 | |
| 873 | qs = devm_kzalloc(dev: &pdev->dev, size: sizeof(*qs), GFP_KERNEL); |
| 874 | if (!qs) |
| 875 | return -ENOMEM; |
| 876 | |
| 877 | qs->attr.family = "Snapdragon" ; |
| 878 | qs->attr.machine = socinfo_machine(dev: &pdev->dev, |
| 879 | le32_to_cpu(info->id)); |
| 880 | qs->attr.soc_id = devm_kasprintf(dev: &pdev->dev, GFP_KERNEL, fmt: "%u" , |
| 881 | le32_to_cpu(info->id)); |
| 882 | qs->attr.revision = devm_kasprintf(dev: &pdev->dev, GFP_KERNEL, fmt: "%u.%u" , |
| 883 | SOCINFO_MAJOR(le32_to_cpu(info->ver)), |
| 884 | SOCINFO_MINOR(le32_to_cpu(info->ver))); |
| 885 | if (!qs->attr.soc_id || !qs->attr.revision) |
| 886 | return -ENOMEM; |
| 887 | |
| 888 | if (offsetofend(struct socinfo, serial_num) <= item_size) { |
| 889 | qs->attr.serial_number = devm_kasprintf(dev: &pdev->dev, GFP_KERNEL, |
| 890 | fmt: "%u" , |
| 891 | le32_to_cpu(info->serial_num)); |
| 892 | if (!qs->attr.serial_number) |
| 893 | return -ENOMEM; |
| 894 | } |
| 895 | |
| 896 | qs->soc_dev = soc_device_register(soc_plat_dev_attr: &qs->attr); |
| 897 | if (IS_ERR(ptr: qs->soc_dev)) |
| 898 | return PTR_ERR(ptr: qs->soc_dev); |
| 899 | |
| 900 | socinfo_debugfs_init(qcom_socinfo: qs, info, info_size: item_size); |
| 901 | |
| 902 | /* Feed the soc specific unique data into entropy pool */ |
| 903 | add_device_randomness(buf: info, len: item_size); |
| 904 | |
| 905 | platform_set_drvdata(pdev, data: qs); |
| 906 | |
| 907 | return 0; |
| 908 | } |
| 909 | |
| 910 | static void qcom_socinfo_remove(struct platform_device *pdev) |
| 911 | { |
| 912 | struct qcom_socinfo *qs = platform_get_drvdata(pdev); |
| 913 | |
| 914 | soc_device_unregister(soc_dev: qs->soc_dev); |
| 915 | |
| 916 | socinfo_debugfs_exit(qcom_socinfo: qs); |
| 917 | } |
| 918 | |
| 919 | static struct platform_driver qcom_socinfo_driver = { |
| 920 | .probe = qcom_socinfo_probe, |
| 921 | .remove = qcom_socinfo_remove, |
| 922 | .driver = { |
| 923 | .name = "qcom-socinfo" , |
| 924 | }, |
| 925 | }; |
| 926 | |
| 927 | module_platform_driver(qcom_socinfo_driver); |
| 928 | |
| 929 | MODULE_DESCRIPTION("Qualcomm SoCinfo driver" ); |
| 930 | MODULE_LICENSE("GPL v2" ); |
| 931 | MODULE_ALIAS("platform:qcom-socinfo" ); |
| 932 | |