android_kernel_samsung_hero.../drivers/soc/qcom/scm-boot.c
2016-08-17 16:41:52 +08:00

111 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);