17
17
#include <linux/reset-controller.h>
18
18
#include <linux/arm-smccc.h>
19
19
20
+ #include <asm/smp_plat.h>
21
+
20
22
#include "qcom_scm.h"
21
23
22
24
static bool download_mode = IS_ENABLED (CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT );
@@ -260,15 +262,36 @@ static bool __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
260
262
return ret ? false : !!res .result [0 ];
261
263
}
262
264
263
- /**
264
- * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
265
- * @entry: Entry point function for the cpus
266
- * @cpus: The cpumask of cpus that will use the entry point
267
- *
268
- * Set the Linux entry point for the SCM to transfer control to when coming
269
- * out of a power down. CPU power down may be executed on cpuidle or hotplug.
270
- */
271
- int qcom_scm_set_warm_boot_addr (void * entry , const cpumask_t * cpus )
265
+ static int __qcom_scm_set_boot_addr_mc (void * entry , const cpumask_t * cpus ,
266
+ unsigned int flags )
267
+ {
268
+ struct qcom_scm_desc desc = {
269
+ .svc = QCOM_SCM_SVC_BOOT ,
270
+ .cmd = QCOM_SCM_BOOT_SET_ADDR_MC ,
271
+ .owner = ARM_SMCCC_OWNER_SIP ,
272
+ .arginfo = QCOM_SCM_ARGS (6 ),
273
+ };
274
+ unsigned int cpu ;
275
+ u64 map ;
276
+
277
+ /* Need a device for DMA of the additional arguments */
278
+ if (!__scm || __get_convention () == SMC_CONVENTION_LEGACY )
279
+ return - EOPNOTSUPP ;
280
+
281
+ desc .args [0 ] = virt_to_phys (entry );
282
+ for_each_cpu (cpu , cpus ) {
283
+ map = cpu_logical_map (cpu );
284
+ desc .args [1 ] |= BIT (MPIDR_AFFINITY_LEVEL (map , 0 ));
285
+ desc .args [2 ] |= BIT (MPIDR_AFFINITY_LEVEL (map , 1 ));
286
+ desc .args [3 ] |= BIT (MPIDR_AFFINITY_LEVEL (map , 2 ));
287
+ }
288
+ desc .args [4 ] = ~0ULL ; /* Reserved for affinity level 3 */
289
+ desc .args [5 ] = flags ;
290
+
291
+ return qcom_scm_call (__scm -> dev , & desc , NULL );
292
+ }
293
+
294
+ static int __qcom_scm_set_warm_boot_addr (void * entry , const cpumask_t * cpus )
272
295
{
273
296
int ret ;
274
297
int flags = 0 ;
@@ -304,17 +327,28 @@ int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
304
327
305
328
return ret ;
306
329
}
307
- EXPORT_SYMBOL (qcom_scm_set_warm_boot_addr );
308
330
309
331
/**
310
- * qcom_scm_set_cold_boot_addr () - Set the cold boot address for cpus
332
+ * qcom_scm_set_warm_boot_addr () - Set the warm boot address for cpus
311
333
* @entry: Entry point function for the cpus
312
334
* @cpus: The cpumask of cpus that will use the entry point
313
335
*
314
- * Set the cold boot address of the cpus. Any cpu outside the supported
315
- * range would be removed from the cpu present mask .
336
+ * Set the Linux entry point for the SCM to transfer control to when coming
337
+ * out of a power down. CPU power down may be executed on cpuidle or hotplug .
316
338
*/
317
- int qcom_scm_set_cold_boot_addr (void * entry , const cpumask_t * cpus )
339
+ int qcom_scm_set_warm_boot_addr (void * entry , const cpumask_t * cpus )
340
+ {
341
+ if (!cpus || cpumask_empty (cpus ))
342
+ return - EINVAL ;
343
+
344
+ if (__qcom_scm_set_boot_addr_mc (entry , cpus , QCOM_SCM_BOOT_MC_FLAG_WARMBOOT ))
345
+ /* Fallback to old SCM call */
346
+ return __qcom_scm_set_warm_boot_addr (entry , cpus );
347
+ return 0 ;
348
+ }
349
+ EXPORT_SYMBOL (qcom_scm_set_warm_boot_addr );
350
+
351
+ static int __qcom_scm_set_cold_boot_addr (void * entry , const cpumask_t * cpus )
318
352
{
319
353
int flags = 0 ;
320
354
int cpu ;
@@ -331,9 +365,6 @@ int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
331
365
.owner = ARM_SMCCC_OWNER_SIP ,
332
366
};
333
367
334
- if (!cpus || cpumask_empty (cpus ))
335
- return - EINVAL ;
336
-
337
368
for_each_cpu (cpu , cpus ) {
338
369
if (cpu < ARRAY_SIZE (scm_cb_flags ))
339
370
flags |= scm_cb_flags [cpu ];
@@ -346,6 +377,25 @@ int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
346
377
347
378
return qcom_scm_call_atomic (__scm ? __scm -> dev : NULL , & desc , NULL );
348
379
}
380
+
381
+ /**
382
+ * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
383
+ * @entry: Entry point function for the cpus
384
+ * @cpus: The cpumask of cpus that will use the entry point
385
+ *
386
+ * Set the cold boot address of the cpus. Any cpu outside the supported
387
+ * range would be removed from the cpu present mask.
388
+ */
389
+ int qcom_scm_set_cold_boot_addr (void * entry , const cpumask_t * cpus )
390
+ {
391
+ if (!cpus || cpumask_empty (cpus ))
392
+ return - EINVAL ;
393
+
394
+ if (__qcom_scm_set_boot_addr_mc (entry , cpus , QCOM_SCM_BOOT_MC_FLAG_COLDBOOT ))
395
+ /* Fallback to old SCM call */
396
+ return __qcom_scm_set_cold_boot_addr (entry , cpus );
397
+ return 0 ;
398
+ }
349
399
EXPORT_SYMBOL (qcom_scm_set_cold_boot_addr );
350
400
351
401
/**
0 commit comments