112 lines
3 KiB
C
112 lines
3 KiB
C
|
/* Copyright (c) 2010, 2014, The Linux Foundation. All rights reserved.
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License version 2 and
|
||
|
* only version 2 as published by the Free Software Foundation.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*/
|
||
|
|
||
|
#include <linux/module.h>
|
||
|
#include <linux/slab.h>
|
||
|
#include <soc/qcom/scm.h>
|
||
|
#include <soc/qcom/scm-boot.h>
|
||
|
|
||
|
/*
|
||
|
* Set the cold/warm boot address for one of the CPU cores.
|
||
|
*/
|
||
|
int scm_set_boot_addr(phys_addr_t addr, unsigned int flags)
|
||
|
{
|
||
|
struct {
|
||
|
u32 flags;
|
||
|
u32 addr;
|
||
|
} cmd;
|
||
|
|
||
|
cmd.addr = addr;
|
||
|
cmd.flags = flags;
|
||
|
return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
|
||
|
&cmd, sizeof(cmd), NULL, 0);
|
||
|
}
|
||
|
EXPORT_SYMBOL(scm_set_boot_addr);
|
||
|
|
||
|
/**
|
||
|
* scm_set_boot_addr_mc - Set entry physical address for cpus
|
||
|
* @addr: 32bit physical address
|
||
|
* @aff0: Collective bitmask of the affinity-level-0 of the mpidr
|
||
|
* 1<<aff0_CPU0| 1<<aff0_CPU1....... | 1<<aff0_CPU32
|
||
|
* Supports maximum 32 cpus under any affinity level.
|
||
|
* @aff1: Collective bitmask of the affinity-level-1 of the mpidr
|
||
|
* @aff2: Collective bitmask of the affinity-level-2 of the mpidr
|
||
|
* @flags: Flag to differentiate between coldboot vs warmboot
|
||
|
*/
|
||
|
int scm_set_boot_addr_mc(phys_addr_t addr, u32 aff0,
|
||
|
u32 aff1, u32 aff2, u32 flags)
|
||
|
{
|
||
|
struct {
|
||
|
u32 addr;
|
||
|
u32 aff0;
|
||
|
u32 aff1;
|
||
|
u32 aff2;
|
||
|
u32 reserved;
|
||
|
u32 flags;
|
||
|
} cmd;
|
||
|
struct scm_desc desc = {0};
|
||
|
|
||
|
if (!is_scm_armv8()) {
|
||
|
cmd.addr = addr;
|
||
|
cmd.aff0 = aff0;
|
||
|
cmd.aff1 = aff1;
|
||
|
cmd.aff2 = aff2;
|
||
|
/*
|
||
|
* Reserved for future chips with affinity level 3 effectively
|
||
|
* 1 << 0
|
||
|
*/
|
||
|
cmd.reserved = ~0U;
|
||
|
cmd.flags = flags | SCM_FLAG_HLOS;
|
||
|
return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR_MC,
|
||
|
&cmd, sizeof(cmd), NULL, 0);
|
||
|
}
|
||
|
|
||
|
flags = flags | SCM_FLAG_HLOS;
|
||
|
desc.args[0] = addr;
|
||
|
desc.args[1] = aff0;
|
||
|
desc.args[2] = aff1;
|
||
|
desc.args[3] = aff2;
|
||
|
desc.args[4] = ~0ULL;
|
||
|
desc.args[5] = flags;
|
||
|
desc.arginfo = SCM_ARGS(6);
|
||
|
|
||
|
return scm_call2(SCM_SIP_FNID(SCM_SVC_BOOT, SCM_BOOT_ADDR_MC), &desc);
|
||
|
}
|
||
|
EXPORT_SYMBOL(scm_set_boot_addr_mc);
|
||
|
|
||
|
/**
|
||
|
* scm_set_warm_boot_addr_mc_for_all -
|
||
|
* Set entry physical address for __all__ possible cpus
|
||
|
* This API passes all_set mask to secure-os and relies
|
||
|
* on secure-os to appropriately
|
||
|
* set the boot-address on the current system.
|
||
|
* @addr: 32bit physical address
|
||
|
*/
|
||
|
|
||
|
int scm_set_warm_boot_addr_mc_for_all(phys_addr_t addr)
|
||
|
{
|
||
|
return scm_set_boot_addr_mc(addr, ~0U, ~0U, ~0U,
|
||
|
SCM_FLAG_WARMBOOT_MC);
|
||
|
}
|
||
|
EXPORT_SYMBOL(scm_set_warm_boot_addr_mc_for_all);
|
||
|
|
||
|
/**
|
||
|
* scm_is_mc_boot_available -
|
||
|
* Checks if TZ supports the boot API for multi-cluster configuration
|
||
|
* Returns true if available and false otherwise
|
||
|
*/
|
||
|
int scm_is_mc_boot_available(void)
|
||
|
{
|
||
|
return scm_is_call_available(SCM_SVC_BOOT, SCM_BOOT_ADDR_MC);
|
||
|
}
|
||
|
EXPORT_SYMBOL(scm_is_mc_boot_available);
|