Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'qcom-drivers-for-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/drivers

Qualcomm driver updates for v5.18

This refactors the Qualcomm mdt file loader, to partially decouple it
from the SCM peripheral-authentication-service. This is needed as newer
platforms, such as the Qualcomm SM8450, require the metadata to remain
accessible to TrustZone during a longer time. This is followed by the
introduction of remoteproc drivers for SM8450 (Snapdragon 8 Gen 1).

It changes the way hardware version differences are handled in the LLCC
driver and introduces support for Qualcomm SM8450. While updating the dt
binding for LLCC it also introduces the missing SM8350 compatible.

The ocmem and aoss drivers gains missing put_device() calls and rpmpd
gains a missing check for kcalloc() failure.

The SPM driver is updated to avoid instantiating the SPM cpuidle devices
if the CPUs aren't controlled by SPM, such as when Snapdragon 8916
operates in 32-bit mode without PSCI.

The RPM power-domain driver gains MSM8226 support.

Lastly the socinfo driver gains knowledge about a few new SoCs and
PMICs.

* tag 'qcom-drivers-for-5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: (37 commits)
soc: qcom: rpmpd: Add MSM8226 support
dt-bindings: power: rpmpd: Add MSM8226 to rpmpd binding
soc: qcom: mdt_loader: Fix split-firmware condition
dt-bindings: arm: msm: Add LLCC compatible for SM8450
dt-bindings: arm: msm: Add LLCC compatible for SM8350
soc: qcom: llcc: Add configuration data for SM8450 SoC
soc: qcom: llcc: Update register offsets for newer LLCC HW
soc: qcom: llcc: Add missing llcc configuration data
soc: qcom: llcc: Add write-cache cacheable support
soc: qcom: llcc: Update the logic for version info extraction
soc: qcom: llcc: Add support for 16 ways of allocation
soc: qcom: socinfo: Add some more PMICs and SoCs
firmware: qcom: scm: Add support for MC boot address API
firmware: qcom: scm: Drop cpumask parameter from set_boot_addr()
firmware: qcom: scm: Simplify set_cold/warm_boot_addr()
cpuidle: qcom-spm: Check if any CPU is managed by SPM
remoteproc: qcom: pas: Add SM8450 remoteproc support
dt-bindings: remoteproc: qcom: pas: Add SM8450 PAS compatibles
remoteproc: qcom: pas: Carry PAS metadata context
soc: qcom: mdt_loader: Extract PAS operations
...

Link: https://lore.kernel.org/r/20220301042055.1804859-1-bjorn.andersson@linaro.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+537 -224
+2
Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml
··· 27 27 - qcom,sm6350-llcc 28 28 - qcom,sm8150-llcc 29 29 - qcom,sm8250-llcc 30 + - qcom,sm8350-llcc 31 + - qcom,sm8450-llcc 30 32 31 33 reg: 32 34 items:
+1
Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
··· 17 17 compatible: 18 18 enum: 19 19 - qcom,mdm9607-rpmpd 20 + - qcom,msm8226-rpmpd 20 21 - qcom,msm8916-rpmpd 21 22 - qcom,msm8939-rpmpd 22 23 - qcom,msm8953-rpmpd
+16
Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml
··· 47 47 - qcom,sm8350-cdsp-pas 48 48 - qcom,sm8350-slpi-pas 49 49 - qcom,sm8350-mpss-pas 50 + - qcom,sm8450-adsp-pas 51 + - qcom,sm8450-cdsp-pas 52 + - qcom,sm8450-mpss-pas 53 + - qcom,sm8450-slpi-pas 50 54 51 55 reg: 52 56 maxItems: 1 ··· 179 175 - qcom,sm8350-cdsp-pas 180 176 - qcom,sm8350-slpi-pas 181 177 - qcom,sm8350-mpss-pas 178 + - qcom,sm8450-adsp-pas 179 + - qcom,sm8450-cdsp-pas 180 + - qcom,sm8450-slpi-pas 181 + - qcom,sm8450-mpss-pas 182 182 then: 183 183 properties: 184 184 clocks: ··· 291 283 - qcom,sm8350-adsp-pas 292 284 - qcom,sm8350-cdsp-pas 293 285 - qcom,sm8350-slpi-pas 286 + - qcom,sm8450-adsp-pas 287 + - qcom,sm8450-cdsp-pas 288 + - qcom,sm8450-slpi-pas 294 289 then: 295 290 properties: 296 291 interrupts: ··· 323 312 - qcom,sm6350-mpss-pas 324 313 - qcom,sm8150-mpss-pas 325 314 - qcom,sm8350-mpss-pas 315 + - qcom,sm8450-mpss-pas 326 316 then: 327 317 properties: 328 318 interrupts: ··· 446 434 - qcom,sm6350-mpss-pas 447 435 - qcom,sm8150-mpss-pas 448 436 - qcom,sm8350-mpss-pas 437 + - qcom,sm8450-mpss-pas 449 438 then: 450 439 properties: 451 440 power-domains: ··· 471 458 - qcom,sm8250-slpi-pas 472 459 - qcom,sm8350-adsp-pas 473 460 - qcom,sm8350-slpi-pas 461 + - qcom,sm8450-adsp-pas 462 + - qcom,sm8450-slpi-pas 474 463 then: 475 464 properties: 476 465 power-domains: ··· 490 475 contains: 491 476 enum: 492 477 - qcom,sm8350-cdsp-pas 478 + - qcom,sm8450-cdsp-pas 493 479 then: 494 480 properties: 495 481 power-domains:
+1 -2
arch/arm/mach-qcom/platsmp.c
··· 357 357 { 358 358 int cpu; 359 359 360 - if (qcom_scm_set_cold_boot_addr(secondary_startup_arm, 361 - cpu_present_mask)) { 360 + if (qcom_scm_set_cold_boot_addr(secondary_startup_arm)) { 362 361 for_each_present_cpu(cpu) { 363 362 if (cpu == smp_processor_id()) 364 363 continue;
+24 -4
drivers/cpuidle/cpuidle-qcom-spm.c
··· 122 122 if (ret <= 0) 123 123 return ret ? : -ENODEV; 124 124 125 - ret = qcom_scm_set_warm_boot_addr(cpu_resume_arm, cpumask_of(cpu)); 126 - if (ret) 127 - return ret; 128 - 129 125 return cpuidle_register(&data->cpuidle_driver, NULL); 130 126 } 131 127 ··· 131 135 132 136 if (!qcom_scm_is_available()) 133 137 return -EPROBE_DEFER; 138 + 139 + ret = qcom_scm_set_warm_boot_addr(cpu_resume_arm); 140 + if (ret) 141 + return dev_err_probe(&pdev->dev, ret, "set warm boot addr failed"); 134 142 135 143 for_each_possible_cpu(cpu) { 136 144 ret = spm_cpuidle_register(&pdev->dev, cpu); ··· 155 155 }, 156 156 }; 157 157 158 + static bool __init qcom_spm_find_any_cpu(void) 159 + { 160 + struct device_node *cpu_node, *saw_node; 161 + 162 + for_each_of_cpu_node(cpu_node) { 163 + saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0); 164 + if (of_device_is_available(saw_node)) { 165 + of_node_put(saw_node); 166 + of_node_put(cpu_node); 167 + return true; 168 + } 169 + of_node_put(saw_node); 170 + } 171 + return false; 172 + } 173 + 158 174 static int __init qcom_spm_cpuidle_init(void) 159 175 { 160 176 struct platform_device *pdev; ··· 179 163 ret = platform_driver_register(&spm_cpuidle_driver); 180 164 if (ret) 181 165 return ret; 166 + 167 + /* Make sure there is actually any CPU managed by the SPM */ 168 + if (!qcom_spm_find_any_cpu()) 169 + return 0; 182 170 183 171 pdev = platform_device_register_simple("qcom-spm-cpuidle", 184 172 -1, NULL, 0);
+128 -105
drivers/firmware/qcom_scm.c
··· 49 49 __le64 mem_size; 50 50 }; 51 51 52 - #define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00 53 - #define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01 54 - #define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 55 - #define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20 56 - 57 - #define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04 58 - #define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02 59 - #define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10 60 - #define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40 61 - 62 - struct qcom_scm_wb_entry { 63 - int flag; 64 - void *entry; 52 + /* Each bit configures cold/warm boot address for one of the 4 CPUs */ 53 + static const u8 qcom_scm_cpu_cold_bits[QCOM_SCM_BOOT_MAX_CPUS] = { 54 + 0, BIT(0), BIT(3), BIT(5) 65 55 }; 66 - 67 - static struct qcom_scm_wb_entry qcom_scm_wb[] = { 68 - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 }, 69 - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 }, 70 - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 }, 71 - { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 }, 56 + static const u8 qcom_scm_cpu_warm_bits[QCOM_SCM_BOOT_MAX_CPUS] = { 57 + BIT(2), BIT(1), BIT(4), BIT(6) 72 58 }; 73 59 74 60 static const char * const qcom_scm_convention_names[] = { ··· 165 179 /** 166 180 * qcom_scm_call() - Invoke a syscall in the secure world 167 181 * @dev: device 168 - * @svc_id: service identifier 169 - * @cmd_id: command identifier 170 182 * @desc: Descriptor structure containing arguments and return values 183 + * @res: Structure containing results from SMC/HVC call 171 184 * 172 185 * Sends a command to the SCM and waits for the command to finish processing. 173 186 * This should *only* be called in pre-emptible context. ··· 190 205 /** 191 206 * qcom_scm_call_atomic() - atomic variation of qcom_scm_call() 192 207 * @dev: device 193 - * @svc_id: service identifier 194 - * @cmd_id: command identifier 195 208 * @desc: Descriptor structure containing arguments and return values 196 209 * @res: Structure containing results from SMC/HVC call 197 210 * ··· 243 260 return ret ? false : !!res.result[0]; 244 261 } 245 262 246 - /** 247 - * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus 248 - * @entry: Entry point function for the cpus 249 - * @cpus: The cpumask of cpus that will use the entry point 250 - * 251 - * Set the Linux entry point for the SCM to transfer control to when coming 252 - * out of a power down. CPU power down may be executed on cpuidle or hotplug. 253 - */ 254 - int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) 263 + static int qcom_scm_set_boot_addr(void *entry, const u8 *cpu_bits) 255 264 { 256 - int ret; 257 - int flags = 0; 258 265 int cpu; 259 - struct qcom_scm_desc desc = { 260 - .svc = QCOM_SCM_SVC_BOOT, 261 - .cmd = QCOM_SCM_BOOT_SET_ADDR, 262 - .arginfo = QCOM_SCM_ARGS(2), 263 - }; 264 - 265 - /* 266 - * Reassign only if we are switching from hotplug entry point 267 - * to cpuidle entry point or vice versa. 268 - */ 269 - for_each_cpu(cpu, cpus) { 270 - if (entry == qcom_scm_wb[cpu].entry) 271 - continue; 272 - flags |= qcom_scm_wb[cpu].flag; 273 - } 274 - 275 - /* No change in entry function */ 276 - if (!flags) 277 - return 0; 278 - 279 - desc.args[0] = flags; 280 - desc.args[1] = virt_to_phys(entry); 281 - 282 - ret = qcom_scm_call(__scm->dev, &desc, NULL); 283 - if (!ret) { 284 - for_each_cpu(cpu, cpus) 285 - qcom_scm_wb[cpu].entry = entry; 286 - } 287 - 288 - return ret; 289 - } 290 - EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); 291 - 292 - /** 293 - * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus 294 - * @entry: Entry point function for the cpus 295 - * @cpus: The cpumask of cpus that will use the entry point 296 - * 297 - * Set the cold boot address of the cpus. Any cpu outside the supported 298 - * range would be removed from the cpu present mask. 299 - */ 300 - int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) 301 - { 302 - int flags = 0; 303 - int cpu; 304 - int scm_cb_flags[] = { 305 - QCOM_SCM_FLAG_COLDBOOT_CPU0, 306 - QCOM_SCM_FLAG_COLDBOOT_CPU1, 307 - QCOM_SCM_FLAG_COLDBOOT_CPU2, 308 - QCOM_SCM_FLAG_COLDBOOT_CPU3, 309 - }; 266 + unsigned int flags = 0; 310 267 struct qcom_scm_desc desc = { 311 268 .svc = QCOM_SCM_SVC_BOOT, 312 269 .cmd = QCOM_SCM_BOOT_SET_ADDR, ··· 254 331 .owner = ARM_SMCCC_OWNER_SIP, 255 332 }; 256 333 257 - if (!cpus || cpumask_empty(cpus)) 258 - return -EINVAL; 259 - 260 - for_each_cpu(cpu, cpus) { 261 - if (cpu < ARRAY_SIZE(scm_cb_flags)) 262 - flags |= scm_cb_flags[cpu]; 263 - else 264 - set_cpu_present(cpu, false); 334 + for_each_present_cpu(cpu) { 335 + if (cpu >= QCOM_SCM_BOOT_MAX_CPUS) 336 + return -EINVAL; 337 + flags |= cpu_bits[cpu]; 265 338 } 266 339 267 340 desc.args[0] = flags; ··· 265 346 266 347 return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL); 267 348 } 349 + 350 + static int qcom_scm_set_boot_addr_mc(void *entry, unsigned int flags) 351 + { 352 + struct qcom_scm_desc desc = { 353 + .svc = QCOM_SCM_SVC_BOOT, 354 + .cmd = QCOM_SCM_BOOT_SET_ADDR_MC, 355 + .owner = ARM_SMCCC_OWNER_SIP, 356 + .arginfo = QCOM_SCM_ARGS(6), 357 + .args = { 358 + virt_to_phys(entry), 359 + /* Apply to all CPUs in all affinity levels */ 360 + ~0ULL, ~0ULL, ~0ULL, ~0ULL, 361 + flags, 362 + }, 363 + }; 364 + 365 + /* Need a device for DMA of the additional arguments */ 366 + if (!__scm || __get_convention() == SMC_CONVENTION_LEGACY) 367 + return -EOPNOTSUPP; 368 + 369 + return qcom_scm_call(__scm->dev, &desc, NULL); 370 + } 371 + 372 + /** 373 + * qcom_scm_set_warm_boot_addr() - Set the warm boot address for all cpus 374 + * @entry: Entry point function for the cpus 375 + * 376 + * Set the Linux entry point for the SCM to transfer control to when coming 377 + * out of a power down. CPU power down may be executed on cpuidle or hotplug. 378 + */ 379 + int qcom_scm_set_warm_boot_addr(void *entry) 380 + { 381 + if (qcom_scm_set_boot_addr_mc(entry, QCOM_SCM_BOOT_MC_FLAG_WARMBOOT)) 382 + /* Fallback to old SCM call */ 383 + return qcom_scm_set_boot_addr(entry, qcom_scm_cpu_warm_bits); 384 + return 0; 385 + } 386 + EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); 387 + 388 + /** 389 + * qcom_scm_set_cold_boot_addr() - Set the cold boot address for all cpus 390 + * @entry: Entry point function for the cpus 391 + */ 392 + int qcom_scm_set_cold_boot_addr(void *entry) 393 + { 394 + if (qcom_scm_set_boot_addr_mc(entry, QCOM_SCM_BOOT_MC_FLAG_COLDBOOT)) 395 + /* Fallback to old SCM call */ 396 + return qcom_scm_set_boot_addr(entry, qcom_scm_cpu_cold_bits); 397 + return 0; 398 + } 268 399 EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); 269 400 270 401 /** 271 402 * qcom_scm_cpu_power_down() - Power down the cpu 272 - * @flags - Flags to flush cache 403 + * @flags: Flags to flush cache 273 404 * 274 405 * This is an end point to power down cpu. If there was a pending interrupt, 275 406 * the control would return from this function, otherwise, the cpu jumps to the ··· 404 435 * and optional blob of data used for authenticating the metadata 405 436 * and the rest of the firmware 406 437 * @size: size of the metadata 438 + * @ctx: optional metadata context 407 439 * 408 - * Returns 0 on success. 440 + * Return: 0 on success. 441 + * 442 + * Upon successful return, the PAS metadata context (@ctx) will be used to 443 + * track the metadata allocation, this needs to be released by invoking 444 + * qcom_scm_pas_metadata_release() by the caller. 409 445 */ 410 - int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) 446 + int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size, 447 + struct qcom_scm_pas_metadata *ctx) 411 448 { 412 449 dma_addr_t mdata_phys; 413 450 void *mdata_buf; ··· 442 467 443 468 ret = qcom_scm_clk_enable(); 444 469 if (ret) 445 - goto free_metadata; 470 + goto out; 446 471 447 472 desc.args[1] = mdata_phys; 448 473 ··· 450 475 451 476 qcom_scm_clk_disable(); 452 477 453 - free_metadata: 454 - dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys); 478 + out: 479 + if (ret < 0 || !ctx) { 480 + dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys); 481 + } else if (ctx) { 482 + ctx->ptr = mdata_buf; 483 + ctx->phys = mdata_phys; 484 + ctx->size = size; 485 + } 455 486 456 487 return ret ? : res.result[0]; 457 488 } 458 489 EXPORT_SYMBOL(qcom_scm_pas_init_image); 490 + 491 + /** 492 + * qcom_scm_pas_metadata_release() - release metadata context 493 + * @ctx: metadata context 494 + */ 495 + void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx) 496 + { 497 + if (!ctx->ptr) 498 + return; 499 + 500 + dma_free_coherent(__scm->dev, ctx->size, ctx->ptr, ctx->phys); 501 + 502 + ctx->ptr = NULL; 503 + ctx->phys = 0; 504 + ctx->size = 0; 505 + } 506 + EXPORT_SYMBOL(qcom_scm_pas_metadata_release); 459 507 460 508 /** 461 509 * qcom_scm_pas_mem_setup() - Prepare the memory related to a given peripheral ··· 747 749 }; 748 750 int ret; 749 751 750 - desc.args[0] = addr; 751 - desc.args[1] = size; 752 - desc.args[2] = spare; 753 - desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL, 754 - QCOM_SCM_VAL); 755 - 756 752 ret = qcom_scm_call(__scm->dev, &desc, NULL); 757 753 758 754 /* the pg table has been initialized already, ignore the error */ ··· 756 764 return ret; 757 765 } 758 766 EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init); 767 + 768 + int qcom_scm_iommu_set_cp_pool_size(u32 spare, u32 size) 769 + { 770 + struct qcom_scm_desc desc = { 771 + .svc = QCOM_SCM_SVC_MP, 772 + .cmd = QCOM_SCM_MP_IOMMU_SET_CP_POOL_SIZE, 773 + .arginfo = QCOM_SCM_ARGS(2), 774 + .args[0] = size, 775 + .args[1] = spare, 776 + .owner = ARM_SMCCC_OWNER_SIP, 777 + }; 778 + 779 + return qcom_scm_call(__scm->dev, &desc, NULL); 780 + } 781 + EXPORT_SYMBOL(qcom_scm_iommu_set_cp_pool_size); 759 782 760 783 int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size, 761 784 u32 cp_nonpixel_start, ··· 1137 1130 return ret; 1138 1131 } 1139 1132 EXPORT_SYMBOL(qcom_scm_hdcp_req); 1133 + 1134 + int qcom_scm_iommu_set_pt_format(u32 sec_id, u32 ctx_num, u32 pt_fmt) 1135 + { 1136 + struct qcom_scm_desc desc = { 1137 + .svc = QCOM_SCM_SVC_SMMU_PROGRAM, 1138 + .cmd = QCOM_SCM_SMMU_PT_FORMAT, 1139 + .arginfo = QCOM_SCM_ARGS(3), 1140 + .args[0] = sec_id, 1141 + .args[1] = ctx_num, 1142 + .args[2] = pt_fmt, /* 0: LPAE AArch32 - 1: AArch64 */ 1143 + .owner = ARM_SMCCC_OWNER_SIP, 1144 + }; 1145 + 1146 + return qcom_scm_call(__scm->dev, &desc, NULL); 1147 + } 1148 + EXPORT_SYMBOL(qcom_scm_iommu_set_pt_format); 1140 1149 1141 1150 int qcom_scm_qsmmu500_wait_safe_toggle(bool en) 1142 1151 {
+7
drivers/firmware/qcom_scm.h
··· 78 78 #define QCOM_SCM_BOOT_SET_ADDR 0x01 79 79 #define QCOM_SCM_BOOT_TERMINATE_PC 0x02 80 80 #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 81 + #define QCOM_SCM_BOOT_SET_ADDR_MC 0x11 81 82 #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a 82 83 #define QCOM_SCM_FLUSH_FLAG_MASK 0x3 84 + #define QCOM_SCM_BOOT_MAX_CPUS 4 85 + #define QCOM_SCM_BOOT_MC_FLAG_AARCH64 BIT(0) 86 + #define QCOM_SCM_BOOT_MC_FLAG_COLDBOOT BIT(1) 87 + #define QCOM_SCM_BOOT_MC_FLAG_WARMBOOT BIT(2) 83 88 84 89 #define QCOM_SCM_SVC_PIL 0x02 85 90 #define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01 ··· 105 100 #define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02 106 101 #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03 107 102 #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04 103 + #define QCOM_SCM_MP_IOMMU_SET_CP_POOL_SIZE 0x05 108 104 #define QCOM_SCM_MP_VIDEO_VAR 0x08 109 105 #define QCOM_SCM_MP_ASSIGN 0x16 110 106 ··· 125 119 #define QCOM_SCM_LMH_LIMIT_DCVSH 0x10 126 120 127 121 #define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 122 + #define QCOM_SCM_SMMU_PT_FORMAT 0x01 128 123 #define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x03 129 124 #define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x02 130 125
+4 -3
drivers/remoteproc/qcom_q6v5_mss.c
··· 928 928 regmap_write(halt_map, offset + AXI_HALTREQ_REG, 0); 929 929 } 930 930 931 - static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) 931 + static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw, 932 + const char *fw_name) 932 933 { 933 934 unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; 934 935 dma_addr_t phys; ··· 940 939 void *ptr; 941 940 int ret; 942 941 943 - metadata = qcom_mdt_read_metadata(fw, &size); 942 + metadata = qcom_mdt_read_metadata(fw, &size, fw_name, qproc->dev); 944 943 if (IS_ERR(metadata)) 945 944 return PTR_ERR(metadata); 946 945 ··· 1290 1289 /* Initialize the RMB validator */ 1291 1290 writel(0, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG); 1292 1291 1293 - ret = q6v5_mpss_init_image(qproc, fw); 1292 + ret = q6v5_mpss_init_image(qproc, fw, qproc->hexagon_mdt_image); 1294 1293 if (ret) 1295 1294 goto release_firmware; 1296 1295
+33 -3
drivers/remoteproc/qcom_q6v5_pas.c
··· 79 79 struct qcom_rproc_subdev smd_subdev; 80 80 struct qcom_rproc_ssr ssr_subdev; 81 81 struct qcom_sysmon *sysmon; 82 + 83 + struct qcom_scm_pas_metadata pas_metadata; 82 84 }; 83 85 84 86 static void adsp_minidump(struct rproc *rproc) ··· 128 126 } 129 127 } 130 128 129 + static int adsp_unprepare(struct rproc *rproc) 130 + { 131 + struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; 132 + 133 + /* 134 + * adsp_load() did pass pas_metadata to the SCM driver for storing 135 + * metadata context. It might have been released already if 136 + * auth_and_reset() was successful, but in other cases clean it up 137 + * here. 138 + */ 139 + qcom_scm_pas_metadata_release(&adsp->pas_metadata); 140 + 141 + return 0; 142 + } 143 + 131 144 static int adsp_load(struct rproc *rproc, const struct firmware *fw) 132 145 { 133 146 struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv; 134 147 int ret; 135 148 136 - ret = qcom_mdt_load(adsp->dev, fw, rproc->firmware, adsp->pas_id, 137 - adsp->mem_region, adsp->mem_phys, adsp->mem_size, 138 - &adsp->mem_reloc); 149 + ret = qcom_mdt_pas_init(adsp->dev, fw, rproc->firmware, adsp->pas_id, 150 + adsp->mem_phys, &adsp->pas_metadata); 151 + if (ret) 152 + return ret; 153 + 154 + ret = qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, adsp->pas_id, 155 + adsp->mem_region, adsp->mem_phys, adsp->mem_size, 156 + &adsp->mem_reloc); 139 157 if (ret) 140 158 return ret; 141 159 ··· 206 184 qcom_scm_pas_shutdown(adsp->pas_id); 207 185 goto disable_px_supply; 208 186 } 187 + 188 + qcom_scm_pas_metadata_release(&adsp->pas_metadata); 209 189 210 190 return 0; 211 191 ··· 279 255 } 280 256 281 257 static const struct rproc_ops adsp_ops = { 258 + .unprepare = adsp_unprepare, 282 259 .start = adsp_start, 283 260 .stop = adsp_stop, 284 261 .da_to_va = adsp_da_to_va, ··· 289 264 }; 290 265 291 266 static const struct rproc_ops adsp_minidump_ops = { 267 + .unprepare = adsp_unprepare, 292 268 .start = adsp_start, 293 269 .stop = adsp_stop, 294 270 .da_to_va = adsp_da_to_va, ··· 879 853 { .compatible = "qcom,sm8350-cdsp-pas", .data = &sm8350_cdsp_resource}, 880 854 { .compatible = "qcom,sm8350-slpi-pas", .data = &sm8350_slpi_resource}, 881 855 { .compatible = "qcom,sm8350-mpss-pas", .data = &mpss_resource_init}, 856 + { .compatible = "qcom,sm8450-adsp-pas", .data = &sm8350_adsp_resource}, 857 + { .compatible = "qcom,sm8450-cdsp-pas", .data = &sm8350_cdsp_resource}, 858 + { .compatible = "qcom,sm8450-slpi-pas", .data = &sm8350_slpi_resource}, 859 + { .compatible = "qcom,sm8450-mpss-pas", .data = &mpss_resource_init}, 882 860 { }, 883 861 }; 884 862 MODULE_DEVICE_TABLE(of, adsp_of_match);
-1
drivers/soc/qcom/apr.c
··· 653 653 654 654 pdr_handle_release(apr->pdr); 655 655 device_for_each_child(&rpdev->dev, NULL, apr_remove_device); 656 - flush_workqueue(apr->rxwq); 657 656 destroy_workqueue(apr->rxwq); 658 657 } 659 658
+91 -16
drivers/soc/qcom/llcc-qcom.c
··· 29 29 #define ATTR1_FIXED_SIZE_SHIFT 0x03 30 30 #define ATTR1_PRIORITY_SHIFT 0x04 31 31 #define ATTR1_MAX_CAP_SHIFT 0x10 32 - #define ATTR0_RES_WAYS_MASK GENMASK(11, 0) 33 - #define ATTR0_BONUS_WAYS_MASK GENMASK(27, 16) 32 + #define ATTR0_RES_WAYS_MASK GENMASK(15, 0) 33 + #define ATTR0_BONUS_WAYS_MASK GENMASK(31, 16) 34 34 #define ATTR0_BONUS_WAYS_SHIFT 0x10 35 35 #define LLCC_STATUS_READ_DELAY 100 36 36 37 37 #define CACHE_LINE_SIZE_SHIFT 6 38 38 39 - #define LLCC_COMMON_HW_INFO 0x00030000 40 - #define LLCC_MAJOR_VERSION_MASK GENMASK(31, 24) 41 - 42 - #define LLCC_COMMON_STATUS0 0x0003000c 43 39 #define LLCC_LB_CNT_MASK GENMASK(31, 28) 44 40 #define LLCC_LB_CNT_SHIFT 28 45 41 ··· 48 52 #define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00 49 53 #define LLCC_TRP_PCB_ACT 0x21f04 50 54 #define LLCC_TRP_WRSC_EN 0x21f20 55 + #define LLCC_TRP_WRSC_CACHEABLE_EN 0x21f2c 51 56 52 57 #define BANK_OFFSET_STRIDE 0x80000 58 + 59 + #define LLCC_VERSION_2_0_0_0 0x02000000 60 + #define LLCC_VERSION_2_1_0_0 0x02010000 53 61 54 62 /** 55 63 * struct llcc_slice_config - Data associated with the llcc slice ··· 79 79 * collapse. 80 80 * @activate_on_init: Activate the slice immediately after it is programmed 81 81 * @write_scid_en: Bit enables write cache support for a given scid. 82 + * @write_scid_cacheable_en: Enables write cache cacheable support for a 83 + * given scid (not supported on v2 or older hardware). 82 84 */ 83 85 struct llcc_slice_config { 84 86 u32 usecase_id; ··· 96 94 bool retain_on_pc; 97 95 bool activate_on_init; 98 96 bool write_scid_en; 97 + bool write_scid_cacheable_en; 99 98 }; 100 99 101 100 struct qcom_llcc_config { 102 101 const struct llcc_slice_config *sct_data; 103 102 int size; 104 103 bool need_llcc_cfg; 104 + const u32 *reg_offset; 105 + }; 106 + 107 + enum llcc_reg_offset { 108 + LLCC_COMMON_HW_INFO, 109 + LLCC_COMMON_STATUS0, 105 110 }; 106 111 107 112 static const struct llcc_slice_config sc7180_data[] = { ··· 226 217 { LLCC_CPUHWT, 5, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 1 }, 227 218 }; 228 219 220 + static const struct llcc_slice_config sm8450_data[] = { 221 + {LLCC_CPUSS, 1, 3072, 1, 0, 0xFFFF, 0x0, 0, 0, 0, 1, 1, 0, 0 }, 222 + {LLCC_VIDSC0, 2, 512, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 223 + {LLCC_AUDIO, 6, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, 224 + {LLCC_MDMHPGRW, 7, 1024, 3, 0, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 225 + {LLCC_MODHW, 9, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 226 + {LLCC_CMPT, 10, 4096, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 227 + {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 228 + {LLCC_GPU, 12, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 1, 0 }, 229 + {LLCC_MMUHWT, 13, 768, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0 }, 230 + {LLCC_DISP, 16, 4096, 2, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 231 + {LLCC_MDMPNG, 21, 1024, 1, 1, 0xF000, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 232 + {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, 233 + {LLCC_CVP, 28, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 234 + {LLCC_MODPE, 29, 64, 1, 1, 0xF000, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 235 + {LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xF0, 1, 0, 0, 1, 0, 0, 0 }, 236 + {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0 }, 237 + {LLCC_CVPFW, 17, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 238 + {LLCC_CPUSS1, 3, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 239 + {LLCC_CAMEXP0, 4, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 240 + {LLCC_CPUMTE, 23, 256, 1, 1, 0x0FFF, 0x0, 0, 0, 0, 0, 1, 0, 0 }, 241 + {LLCC_CPUHWT, 5, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 1, 0, 0 }, 242 + {LLCC_CAMEXP1, 27, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 }, 243 + {LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, 244 + }; 245 + 246 + static const u32 llcc_v1_2_reg_offset[] = { 247 + [LLCC_COMMON_HW_INFO] = 0x00030000, 248 + [LLCC_COMMON_STATUS0] = 0x0003000c, 249 + }; 250 + 251 + static const u32 llcc_v21_reg_offset[] = { 252 + [LLCC_COMMON_HW_INFO] = 0x00034000, 253 + [LLCC_COMMON_STATUS0] = 0x0003400c, 254 + }; 255 + 229 256 static const struct qcom_llcc_config sc7180_cfg = { 230 257 .sct_data = sc7180_data, 231 258 .size = ARRAY_SIZE(sc7180_data), 232 259 .need_llcc_cfg = true, 260 + .reg_offset = llcc_v1_2_reg_offset, 233 261 }; 234 262 235 263 static const struct qcom_llcc_config sc7280_cfg = { 236 264 .sct_data = sc7280_data, 237 265 .size = ARRAY_SIZE(sc7280_data), 238 266 .need_llcc_cfg = true, 267 + .reg_offset = llcc_v1_2_reg_offset, 239 268 }; 240 269 241 270 static const struct qcom_llcc_config sdm845_cfg = { 242 271 .sct_data = sdm845_data, 243 272 .size = ARRAY_SIZE(sdm845_data), 244 273 .need_llcc_cfg = false, 274 + .reg_offset = llcc_v1_2_reg_offset, 245 275 }; 246 276 247 277 static const struct qcom_llcc_config sm6350_cfg = { 248 278 .sct_data = sm6350_data, 249 279 .size = ARRAY_SIZE(sm6350_data), 280 + .need_llcc_cfg = true, 281 + .reg_offset = llcc_v1_2_reg_offset, 250 282 }; 251 283 252 284 static const struct qcom_llcc_config sm8150_cfg = { 253 285 .sct_data = sm8150_data, 254 286 .size = ARRAY_SIZE(sm8150_data), 287 + .need_llcc_cfg = true, 288 + .reg_offset = llcc_v1_2_reg_offset, 255 289 }; 256 290 257 291 static const struct qcom_llcc_config sm8250_cfg = { 258 292 .sct_data = sm8250_data, 259 293 .size = ARRAY_SIZE(sm8250_data), 294 + .need_llcc_cfg = true, 295 + .reg_offset = llcc_v1_2_reg_offset, 260 296 }; 261 297 262 298 static const struct qcom_llcc_config sm8350_cfg = { 263 299 .sct_data = sm8350_data, 264 300 .size = ARRAY_SIZE(sm8350_data), 301 + .need_llcc_cfg = true, 302 + .reg_offset = llcc_v1_2_reg_offset, 303 + }; 304 + 305 + static const struct qcom_llcc_config sm8450_cfg = { 306 + .sct_data = sm8450_data, 307 + .size = ARRAY_SIZE(sm8450_data), 308 + .need_llcc_cfg = true, 309 + .reg_offset = llcc_v21_reg_offset, 265 310 }; 266 311 267 312 static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; ··· 567 504 return ret; 568 505 } 569 506 570 - if (drv_data->major_version == 2) { 507 + if (drv_data->version >= LLCC_VERSION_2_0_0_0) { 571 508 u32 wren; 572 509 573 510 wren = config->write_scid_en << config->slice_id; 574 511 ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_WRSC_EN, 575 512 BIT(config->slice_id), wren); 513 + if (ret) 514 + return ret; 515 + } 516 + 517 + if (drv_data->version >= LLCC_VERSION_2_1_0_0) { 518 + u32 wr_cache_en; 519 + 520 + wr_cache_en = config->write_scid_cacheable_en << config->slice_id; 521 + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_WRSC_CACHEABLE_EN, 522 + BIT(config->slice_id), wr_cache_en); 576 523 if (ret) 577 524 return ret; 578 525 } ··· 671 598 goto err; 672 599 } 673 600 674 - /* Extract major version of the IP */ 675 - ret = regmap_read(drv_data->bcast_regmap, LLCC_COMMON_HW_INFO, &version); 601 + cfg = of_device_get_match_data(&pdev->dev); 602 + 603 + /* Extract version of the IP */ 604 + ret = regmap_read(drv_data->bcast_regmap, cfg->reg_offset[LLCC_COMMON_HW_INFO], 605 + &version); 676 606 if (ret) 677 607 goto err; 678 608 679 - drv_data->major_version = FIELD_GET(LLCC_MAJOR_VERSION_MASK, version); 609 + drv_data->version = version; 680 610 681 - ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, 682 - &num_banks); 611 + ret = regmap_read(drv_data->regmap, cfg->reg_offset[LLCC_COMMON_STATUS0], 612 + &num_banks); 683 613 if (ret) 684 614 goto err; 685 615 ··· 690 614 num_banks >>= LLCC_LB_CNT_SHIFT; 691 615 drv_data->num_banks = num_banks; 692 616 693 - cfg = of_device_get_match_data(&pdev->dev); 694 617 llcc_cfg = cfg->sct_data; 695 618 sz = cfg->size; 696 619 ··· 707 632 for (i = 0; i < num_banks; i++) 708 633 drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; 709 634 710 - drv_data->bitmap = devm_kcalloc(dev, 711 - BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), 712 - GFP_KERNEL); 635 + drv_data->bitmap = devm_bitmap_zalloc(dev, drv_data->max_slices, 636 + GFP_KERNEL); 713 637 if (!drv_data->bitmap) { 714 638 ret = -ENOMEM; 715 639 goto err; ··· 746 672 { .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg }, 747 673 { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg }, 748 674 { .compatible = "qcom,sm8350-llcc", .data = &sm8350_cfg }, 675 + { .compatible = "qcom,sm8450-llcc", .data = &sm8450_cfg }, 749 676 { } 750 677 }; 751 678
+151 -81
drivers/soc/qcom/mdt_loader.c
··· 31 31 return true; 32 32 } 33 33 34 + static ssize_t mdt_load_split_segment(void *ptr, const struct elf32_phdr *phdrs, 35 + unsigned int segment, const char *fw_name, 36 + struct device *dev) 37 + { 38 + const struct elf32_phdr *phdr = &phdrs[segment]; 39 + const struct firmware *seg_fw; 40 + char *seg_name; 41 + ssize_t ret; 42 + 43 + if (strlen(fw_name) < 4) 44 + return -EINVAL; 45 + 46 + seg_name = kstrdup(fw_name, GFP_KERNEL); 47 + if (!seg_name) 48 + return -ENOMEM; 49 + 50 + sprintf(seg_name + strlen(fw_name) - 3, "b%02d", segment); 51 + ret = request_firmware_into_buf(&seg_fw, seg_name, dev, 52 + ptr, phdr->p_filesz); 53 + if (ret) { 54 + dev_err(dev, "error %zd loading %s\n", ret, seg_name); 55 + kfree(seg_name); 56 + return ret; 57 + } 58 + 59 + if (seg_fw->size != phdr->p_filesz) { 60 + dev_err(dev, 61 + "failed to load segment %d from truncated file %s\n", 62 + segment, seg_name); 63 + ret = -EINVAL; 64 + } 65 + 66 + release_firmware(seg_fw); 67 + kfree(seg_name); 68 + 69 + return ret; 70 + } 71 + 34 72 /** 35 73 * qcom_mdt_get_size() - acquire size of the memory region needed to load mdt 36 74 * @fw: firmware object for the mdt file ··· 121 83 * 122 84 * Return: pointer to data, or ERR_PTR() 123 85 */ 124 - void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len) 86 + void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len, 87 + const char *fw_name, struct device *dev) 125 88 { 126 89 const struct elf32_phdr *phdrs; 127 90 const struct elf32_hdr *ehdr; 91 + unsigned int hash_segment = 0; 128 92 size_t hash_offset; 129 93 size_t hash_size; 130 94 size_t ehdr_size; 95 + unsigned int i; 96 + ssize_t ret; 131 97 void *data; 132 98 133 99 ehdr = (struct elf32_hdr *)fw->data; ··· 143 101 if (phdrs[0].p_type == PT_LOAD) 144 102 return ERR_PTR(-EINVAL); 145 103 146 - if ((phdrs[1].p_flags & QCOM_MDT_TYPE_MASK) != QCOM_MDT_TYPE_HASH) 104 + for (i = 1; i < ehdr->e_phnum; i++) { 105 + if ((phdrs[i].p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH) { 106 + hash_segment = i; 107 + break; 108 + } 109 + } 110 + 111 + if (!hash_segment) { 112 + dev_err(dev, "no hash segment found in %s\n", fw_name); 147 113 return ERR_PTR(-EINVAL); 114 + } 148 115 149 116 ehdr_size = phdrs[0].p_filesz; 150 - hash_size = phdrs[1].p_filesz; 117 + hash_size = phdrs[hash_segment].p_filesz; 151 118 152 119 data = kmalloc(ehdr_size + hash_size, GFP_KERNEL); 153 120 if (!data) 154 121 return ERR_PTR(-ENOMEM); 155 122 156 - /* Is the header and hash already packed */ 157 - if (ehdr_size + hash_size == fw->size) 158 - hash_offset = phdrs[0].p_filesz; 159 - else 160 - hash_offset = phdrs[1].p_offset; 161 - 123 + /* Copy ELF header */ 162 124 memcpy(data, fw->data, ehdr_size); 163 - memcpy(data + ehdr_size, fw->data + hash_offset, hash_size); 125 + 126 + if (ehdr_size + hash_size == fw->size) { 127 + /* Firmware is split and hash is packed following the ELF header */ 128 + hash_offset = phdrs[0].p_filesz; 129 + memcpy(data + ehdr_size, fw->data + hash_offset, hash_size); 130 + } else if (phdrs[hash_segment].p_offset + hash_size <= fw->size) { 131 + /* Hash is in its own segment, but within the loaded file */ 132 + hash_offset = phdrs[hash_segment].p_offset; 133 + memcpy(data + ehdr_size, fw->data + hash_offset, hash_size); 134 + } else { 135 + /* Hash is in its own segment, beyond the loaded file */ 136 + ret = mdt_load_split_segment(data + ehdr_size, phdrs, hash_segment, fw_name, dev); 137 + if (ret) { 138 + kfree(data); 139 + return ERR_PTR(ret); 140 + } 141 + } 164 142 165 143 *data_len = ehdr_size + hash_size; 166 144 ··· 188 126 } 189 127 EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata); 190 128 129 + /** 130 + * qcom_mdt_pas_init() - initialize PAS region for firmware loading 131 + * @dev: device handle to associate resources with 132 + * @fw: firmware object for the mdt file 133 + * @firmware: name of the firmware, for construction of segment file names 134 + * @pas_id: PAS identifier 135 + * @mem_phys: physical address of allocated memory region 136 + * @ctx: PAS metadata context, to be released by caller 137 + * 138 + * Returns 0 on success, negative errno otherwise. 139 + */ 140 + int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, 141 + const char *fw_name, int pas_id, phys_addr_t mem_phys, 142 + struct qcom_scm_pas_metadata *ctx) 143 + { 144 + const struct elf32_phdr *phdrs; 145 + const struct elf32_phdr *phdr; 146 + const struct elf32_hdr *ehdr; 147 + phys_addr_t min_addr = PHYS_ADDR_MAX; 148 + phys_addr_t max_addr = 0; 149 + size_t metadata_len; 150 + void *metadata; 151 + int ret; 152 + int i; 153 + 154 + ehdr = (struct elf32_hdr *)fw->data; 155 + phdrs = (struct elf32_phdr *)(ehdr + 1); 156 + 157 + for (i = 0; i < ehdr->e_phnum; i++) { 158 + phdr = &phdrs[i]; 159 + 160 + if (!mdt_phdr_valid(phdr)) 161 + continue; 162 + 163 + if (phdr->p_paddr < min_addr) 164 + min_addr = phdr->p_paddr; 165 + 166 + if (phdr->p_paddr + phdr->p_memsz > max_addr) 167 + max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K); 168 + } 169 + 170 + metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev); 171 + if (IS_ERR(metadata)) { 172 + ret = PTR_ERR(metadata); 173 + dev_err(dev, "error %d reading firmware %s metadata\n", ret, fw_name); 174 + goto out; 175 + } 176 + 177 + ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, ctx); 178 + kfree(metadata); 179 + if (ret) { 180 + /* Invalid firmware metadata */ 181 + dev_err(dev, "error %d initializing firmware %s\n", ret, fw_name); 182 + goto out; 183 + } 184 + 185 + ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); 186 + if (ret) { 187 + /* Unable to set up relocation */ 188 + dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name); 189 + goto out; 190 + } 191 + 192 + out: 193 + return ret; 194 + } 195 + EXPORT_SYMBOL_GPL(qcom_mdt_pas_init); 196 + 191 197 static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, 192 - const char *firmware, int pas_id, void *mem_region, 198 + const char *fw_name, int pas_id, void *mem_region, 193 199 phys_addr_t mem_phys, size_t mem_size, 194 200 phys_addr_t *reloc_base, bool pas_init) 195 201 { 196 202 const struct elf32_phdr *phdrs; 197 203 const struct elf32_phdr *phdr; 198 204 const struct elf32_hdr *ehdr; 199 - const struct firmware *seg_fw; 200 205 phys_addr_t mem_reloc; 201 206 phys_addr_t min_addr = PHYS_ADDR_MAX; 202 - phys_addr_t max_addr = 0; 203 - size_t metadata_len; 204 - size_t fw_name_len; 205 207 ssize_t offset; 206 - void *metadata; 207 - char *fw_name; 208 208 bool relocate = false; 209 209 void *ptr; 210 210 int ret = 0; ··· 277 153 278 154 ehdr = (struct elf32_hdr *)fw->data; 279 155 phdrs = (struct elf32_phdr *)(ehdr + 1); 280 - 281 - fw_name_len = strlen(firmware); 282 - if (fw_name_len <= 4) 283 - return -EINVAL; 284 - 285 - fw_name = kstrdup(firmware, GFP_KERNEL); 286 - if (!fw_name) 287 - return -ENOMEM; 288 - 289 - if (pas_init) { 290 - metadata = qcom_mdt_read_metadata(fw, &metadata_len); 291 - if (IS_ERR(metadata)) { 292 - ret = PTR_ERR(metadata); 293 - dev_err(dev, "error %d reading firmware %s metadata\n", 294 - ret, fw_name); 295 - goto out; 296 - } 297 - 298 - ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len); 299 - 300 - kfree(metadata); 301 - if (ret) { 302 - /* Invalid firmware metadata */ 303 - dev_err(dev, "error %d initializing firmware %s\n", 304 - ret, fw_name); 305 - goto out; 306 - } 307 - } 308 156 309 157 for (i = 0; i < ehdr->e_phnum; i++) { 310 158 phdr = &phdrs[i]; ··· 289 193 290 194 if (phdr->p_paddr < min_addr) 291 195 min_addr = phdr->p_paddr; 292 - 293 - if (phdr->p_paddr + phdr->p_memsz > max_addr) 294 - max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K); 295 196 } 296 197 297 198 if (relocate) { 298 - if (pas_init) { 299 - ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, 300 - max_addr - min_addr); 301 - if (ret) { 302 - /* Unable to set up relocation */ 303 - dev_err(dev, "error %d setting up firmware %s\n", 304 - ret, fw_name); 305 - goto out; 306 - } 307 - } 308 - 309 199 /* 310 200 * The image is relocatable, so offset each segment based on 311 201 * the lowest segment address. ··· 328 246 329 247 ptr = mem_region + offset; 330 248 331 - if (phdr->p_filesz && phdr->p_offset < fw->size) { 249 + if (phdr->p_filesz && phdr->p_offset < fw->size && 250 + phdr->p_offset + phdr->p_filesz <= fw->size) { 332 251 /* Firmware is large enough to be non-split */ 333 252 if (phdr->p_offset + phdr->p_filesz > fw->size) { 334 253 dev_err(dev, "file %s segment %d would be truncated\n", ··· 341 258 memcpy(ptr, fw->data + phdr->p_offset, phdr->p_filesz); 342 259 } else if (phdr->p_filesz) { 343 260 /* Firmware not large enough, load split-out segments */ 344 - sprintf(fw_name + fw_name_len - 3, "b%02d", i); 345 - ret = request_firmware_into_buf(&seg_fw, fw_name, dev, 346 - ptr, phdr->p_filesz); 347 - if (ret) { 348 - dev_err(dev, "error %d loading %s\n", 349 - ret, fw_name); 261 + ret = mdt_load_split_segment(ptr, phdrs, i, fw_name, dev); 262 + if (ret) 350 263 break; 351 - } 352 - 353 - if (seg_fw->size != phdr->p_filesz) { 354 - dev_err(dev, 355 - "failed to load segment %d from truncated file %s\n", 356 - i, fw_name); 357 - release_firmware(seg_fw); 358 - ret = -EINVAL; 359 - break; 360 - } 361 - 362 - release_firmware(seg_fw); 363 264 } 364 265 365 266 if (phdr->p_memsz > phdr->p_filesz) ··· 352 285 353 286 if (reloc_base) 354 287 *reloc_base = mem_reloc; 355 - 356 - out: 357 - kfree(fw_name); 358 288 359 289 return ret; 360 290 } ··· 374 310 phys_addr_t mem_phys, size_t mem_size, 375 311 phys_addr_t *reloc_base) 376 312 { 313 + int ret; 314 + 315 + ret = qcom_mdt_pas_init(dev, fw, firmware, pas_id, mem_phys, NULL); 316 + if (ret) 317 + return ret; 318 + 377 319 return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys, 378 320 mem_size, reloc_base, true); 379 321 }
+1
drivers/soc/qcom/ocmem.c
··· 206 206 ocmem = platform_get_drvdata(pdev); 207 207 if (!ocmem) { 208 208 dev_err(dev, "Cannot get ocmem\n"); 209 + put_device(&pdev->dev); 209 210 return ERR_PTR(-ENODEV); 210 211 } 211 212 return ocmem;
+6 -2
drivers/soc/qcom/qcom_aoss.c
··· 451 451 452 452 qmp = platform_get_drvdata(pdev); 453 453 454 - return qmp ? qmp : ERR_PTR(-EPROBE_DEFER); 454 + if (!qmp) { 455 + put_device(&pdev->dev); 456 + return ERR_PTR(-EPROBE_DEFER); 457 + } 458 + return qmp; 455 459 } 456 460 EXPORT_SYMBOL(qmp_get); 457 461 ··· 501 497 } 502 498 503 499 irq = platform_get_irq(pdev, 0); 504 - ret = devm_request_irq(&pdev->dev, irq, qmp_intr, IRQF_ONESHOT, 500 + ret = devm_request_irq(&pdev->dev, irq, qmp_intr, 0, 505 501 "aoss-qmp", qmp); 506 502 if (ret < 0) { 507 503 dev_err(&pdev->dev, "failed to request interrupt\n");
+20
drivers/soc/qcom/rpmpd.c
··· 138 138 .max_state = RPM_SMD_LEVEL_TURBO, 139 139 }; 140 140 141 + /* msm8226 RPM Power Domains */ 142 + DEFINE_RPMPD_PAIR(msm8226, vddcx, vddcx_ao, SMPA, CORNER, 1); 143 + DEFINE_RPMPD_VFC(msm8226, vddcx_vfc, SMPA, 1); 144 + 145 + static struct rpmpd *msm8226_rpmpds[] = { 146 + [MSM8226_VDDCX] = &msm8226_vddcx, 147 + [MSM8226_VDDCX_AO] = &msm8226_vddcx_ao, 148 + [MSM8226_VDDCX_VFC] = &msm8226_vddcx_vfc, 149 + }; 150 + 151 + static const struct rpmpd_desc msm8226_desc = { 152 + .rpmpds = msm8226_rpmpds, 153 + .num_pds = ARRAY_SIZE(msm8226_rpmpds), 154 + .max_state = MAX_CORNER_RPMPD_STATE, 155 + }; 156 + 141 157 /* msm8939 RPM Power Domains */ 142 158 DEFINE_RPMPD_PAIR(msm8939, vddmd, vddmd_ao, SMPA, CORNER, 1); 143 159 DEFINE_RPMPD_VFC(msm8939, vddmd_vfc, SMPA, 1); ··· 452 436 453 437 static const struct of_device_id rpmpd_match_table[] = { 454 438 { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc }, 439 + { .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc }, 455 440 { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc }, 456 441 { .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc }, 457 442 { .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc }, ··· 627 610 628 611 data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains), 629 612 GFP_KERNEL); 613 + if (!data->domains) 614 + return -ENOMEM; 615 + 630 616 data->num_domains = num; 631 617 632 618 for (i = 0; i < num; i++) {
+12
drivers/soc/qcom/socinfo.c
··· 104 104 [36] = "PM8009", 105 105 [38] = "PM8150C", 106 106 [41] = "SMB2351", 107 + [47] = "PMK8350", 108 + [48] = "PM8350", 109 + [49] = "PM8350C", 110 + [50] = "PM8350B", 111 + [51] = "PMR735A", 112 + [52] = "PMR735B", 113 + [58] = "PM8450", 114 + [65] = "PM8010", 107 115 }; 108 116 #endif /* CONFIG_DEBUG_FS */ 109 117 ··· 322 314 { 422, "IPQ6010" }, 323 315 { 425, "SC7180" }, 324 316 { 434, "SM6350" }, 317 + { 439, "SM8350" }, 318 + { 449, "SC8280XP" }, 325 319 { 453, "IPQ6005" }, 326 320 { 455, "QRB5165" }, 327 321 { 457, "SM8450" }, 328 322 { 459, "SM7225" }, 323 + { 460, "SA8540P" }, 324 + { 480, "SM8450" }, 329 325 }; 330 326 331 327 static const char *socinfo_machine(struct device *dev, unsigned int id)
+5
include/dt-bindings/power/qcom-rpmpd.h
··· 139 139 #define MDM9607_VDDMX_AO 4 140 140 #define MDM9607_VDDMX_VFL 5 141 141 142 + /* MSM8226 Power Domain Indexes */ 143 + #define MSM8226_VDDCX 0 144 + #define MSM8226_VDDCX_AO 1 145 + #define MSM8226_VDDCX_VFC 2 146 + 142 147 /* MSM8939 Power Domains */ 143 148 #define MSM8939_VDDMDCX 0 144 149 #define MSM8939_VDDMDCX_AO 1
+13 -3
include/linux/qcom_scm.h
··· 63 63 64 64 extern bool qcom_scm_is_available(void); 65 65 66 - extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); 67 - extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); 66 + extern int qcom_scm_set_cold_boot_addr(void *entry); 67 + extern int qcom_scm_set_warm_boot_addr(void *entry); 68 68 extern void qcom_scm_cpu_power_down(u32 flags); 69 69 extern int qcom_scm_set_remote_state(u32 state, u32 id); 70 70 71 + struct qcom_scm_pas_metadata { 72 + void *ptr; 73 + dma_addr_t phys; 74 + ssize_t size; 75 + }; 76 + 71 77 extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, 72 - size_t size); 78 + size_t size, 79 + struct qcom_scm_pas_metadata *ctx); 80 + void qcom_scm_pas_metadata_release(struct qcom_scm_pas_metadata *ctx); 73 81 extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, 74 82 phys_addr_t size); 75 83 extern int qcom_scm_pas_auth_and_reset(u32 peripheral); ··· 91 83 extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); 92 84 extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size); 93 85 extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); 86 + extern int qcom_scm_iommu_set_cp_pool_size(u32 spare, u32 size); 94 87 extern int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size, 95 88 u32 cp_nonpixel_start, 96 89 u32 cp_nonpixel_size); ··· 116 107 extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, 117 108 u32 *resp); 118 109 110 + extern int qcom_scm_iommu_set_pt_format(u32 sec_id, u32 ctx_num, u32 pt_fmt); 119 111 extern int qcom_scm_qsmmu500_wait_safe_toggle(bool en); 120 112 121 113 extern int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val,
+7 -2
include/linux/soc/qcom/llcc-qcom.h
··· 35 35 #define LLCC_WRCACHE 31 36 36 #define LLCC_CVPFW 32 37 37 #define LLCC_CPUSS1 33 38 + #define LLCC_CAMEXP0 34 39 + #define LLCC_CPUMTE 35 38 40 #define LLCC_CPUHWT 36 41 + #define LLCC_MDMCLAD2 37 42 + #define LLCC_CAMEXP1 38 43 + #define LLCC_AENPU 45 39 44 40 45 /** 41 46 * struct llcc_slice_desc - Cache slice descriptor ··· 88 83 * @bitmap: Bit map to track the active slice ids 89 84 * @offsets: Pointer to the bank offsets array 90 85 * @ecc_irq: interrupt for llcc cache error detection and reporting 91 - * @major_version: Indicates the LLCC major version 86 + * @version: Indicates the LLCC version 92 87 */ 93 88 struct llcc_drv_data { 94 89 struct regmap *regmap; ··· 101 96 unsigned long *bitmap; 102 97 u32 *offsets; 103 98 int ecc_irq; 104 - u32 major_version; 99 + u32 version; 105 100 }; 106 101 107 102 #if IS_ENABLED(CONFIG_QCOM_LLCC)
+15 -2
include/linux/soc/qcom/mdt_loader.h
··· 10 10 11 11 struct device; 12 12 struct firmware; 13 + struct qcom_scm_pas_metadata; 13 14 14 15 #if IS_ENABLED(CONFIG_QCOM_MDT_LOADER) 15 16 16 17 ssize_t qcom_mdt_get_size(const struct firmware *fw); 18 + int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, 19 + const char *fw_name, int pas_id, phys_addr_t mem_phys, 20 + struct qcom_scm_pas_metadata *pas_metadata_ctx); 17 21 int qcom_mdt_load(struct device *dev, const struct firmware *fw, 18 22 const char *fw_name, int pas_id, void *mem_region, 19 23 phys_addr_t mem_phys, size_t mem_size, ··· 27 23 const char *fw_name, int pas_id, void *mem_region, 28 24 phys_addr_t mem_phys, size_t mem_size, 29 25 phys_addr_t *reloc_base); 30 - void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len); 26 + void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len, 27 + const char *fw_name, struct device *dev); 31 28 32 29 #else /* !IS_ENABLED(CONFIG_QCOM_MDT_LOADER) */ 33 30 34 31 static inline ssize_t qcom_mdt_get_size(const struct firmware *fw) 32 + { 33 + return -ENODEV; 34 + } 35 + 36 + static inline int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, 37 + const char *fw_name, int pas_id, phys_addr_t mem_phys, 38 + struct qcom_scm_pas_metadata *pas_metadata_ctx) 35 39 { 36 40 return -ENODEV; 37 41 } ··· 63 51 } 64 52 65 53 static inline void *qcom_mdt_read_metadata(const struct firmware *fw, 66 - size_t *data_len) 54 + size_t *data_len, const char *fw_name, 55 + struct device *dev) 67 56 { 68 57 return ERR_PTR(-ENODEV); 69 58 }