2019-05-29 17:12:41 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2020-01-08 00:04:10 +03:00
/* Copyright (c) 2010,2015,2019 The Linux Foundation. All rights reserved.
2015-03-12 00:28:10 +03:00
* Copyright ( C ) 2015 Linaro Ltd .
*/
# include <linux/slab.h>
# include <linux/io.h>
# include <linux/module.h>
# include <linux/mutex.h>
# include <linux/errno.h>
# include <linux/err.h>
# include <linux/qcom_scm.h>
2020-01-08 00:04:18 +03:00
# include <linux/arm-smccc.h>
2016-06-04 02:25:25 +03:00
# include <linux/dma-mapping.h>
2015-03-12 00:28:10 +03:00
# include "qcom_scm.h"
# define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00
# define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01
# define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08
# define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20
# define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04
# define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02
# define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10
# define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40
struct qcom_scm_entry {
int flag ;
void * entry ;
} ;
static struct qcom_scm_entry qcom_scm_wb [ ] = {
{ . flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 } ,
{ . flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 } ,
{ . flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 } ,
{ . flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 } ,
} ;
static DEFINE_MUTEX ( qcom_scm_lock ) ;
2020-01-08 00:04:20 +03:00
# define MAX_QCOM_SCM_ARGS 10
# define MAX_QCOM_SCM_RETS 3
enum qcom_scm_arg_types {
QCOM_SCM_VAL ,
QCOM_SCM_RO ,
QCOM_SCM_RW ,
QCOM_SCM_BUFVAL ,
} ;
# define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
( ( ( a ) & 0x3 ) < < 4 ) | \
( ( ( b ) & 0x3 ) < < 6 ) | \
( ( ( c ) & 0x3 ) < < 8 ) | \
( ( ( d ) & 0x3 ) < < 10 ) | \
( ( ( e ) & 0x3 ) < < 12 ) | \
( ( ( f ) & 0x3 ) < < 14 ) | \
( ( ( g ) & 0x3 ) < < 16 ) | \
( ( ( h ) & 0x3 ) < < 18 ) | \
( ( ( i ) & 0x3 ) < < 20 ) | \
( ( ( j ) & 0x3 ) < < 22 ) | \
( ( num ) & 0xf ) )
# define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
/**
* struct qcom_scm_desc
* @ arginfo : Metadata describing the arguments in args [ ]
* @ args : The array of arguments for the secure syscall
*/
struct qcom_scm_desc {
u32 svc ;
u32 cmd ;
u32 arginfo ;
u64 args [ MAX_QCOM_SCM_ARGS ] ;
u32 owner ;
} ;
/**
* struct qcom_scm_res
* @ result : The values returned by the secure syscall
*/
struct qcom_scm_res {
u64 result [ MAX_QCOM_SCM_RETS ] ;
} ;
2020-01-08 00:04:19 +03:00
# define SCM_LEGACY_FNID(s, c) (((s) << 10) | ((c) & 0x3ff))
2015-03-12 00:28:10 +03:00
/**
2020-01-08 00:04:10 +03:00
* struct scm_legacy_command - one SCM command buffer
2015-03-12 00:28:10 +03:00
* @ len : total available memory for command and response
* @ buf_offset : start of command buffer
* @ resp_hdr_offset : start of response buffer
* @ id : command to be executed
2020-01-08 00:04:10 +03:00
* @ buf : buffer returned from scm_legacy_get_command_buffer ( )
2015-03-12 00:28:10 +03:00
*
* An SCM command is laid out in memory as follows :
*
2020-01-08 00:04:10 +03:00
* - - - - - - - - - - - - - - - - - - - < - - - struct scm_legacy_command
2015-03-12 00:28:10 +03:00
* | command header |
2020-01-08 00:04:10 +03:00
* - - - - - - - - - - - - - - - - - - - < - - - scm_legacy_get_command_buffer ( )
2015-03-12 00:28:10 +03:00
* | command buffer |
2020-01-08 00:04:10 +03:00
* - - - - - - - - - - - - - - - - - - - < - - - struct scm_legacy_response and
* | response header | scm_legacy_command_to_response ( )
* - - - - - - - - - - - - - - - - - - - < - - - scm_legacy_get_response_buffer ( )
2015-03-12 00:28:10 +03:00
* | response buffer |
* - - - - - - - - - - - - - - - - - - -
*
* There can be arbitrary padding between the headers and buffers so
2020-01-08 00:04:10 +03:00
* you should always use the appropriate scm_legacy_get_ * _buffer ( ) routines
2015-03-12 00:28:10 +03:00
* to access the buffers in a safe manner .
*/
2020-01-08 00:04:10 +03:00
struct scm_legacy_command {
2015-03-12 00:28:10 +03:00
__le32 len ;
__le32 buf_offset ;
__le32 resp_hdr_offset ;
__le32 id ;
__le32 buf [ 0 ] ;
} ;
/**
2020-01-08 00:04:10 +03:00
* struct scm_legacy_response - one SCM response buffer
2015-03-12 00:28:10 +03:00
* @ len : total available memory for response
2020-01-08 00:04:10 +03:00
* @ buf_offset : start of response data relative to start of scm_legacy_response
2015-03-12 00:28:10 +03:00
* @ is_complete : indicates if the command has finished processing
*/
2020-01-08 00:04:10 +03:00
struct scm_legacy_response {
2015-03-12 00:28:10 +03:00
__le32 len ;
__le32 buf_offset ;
__le32 is_complete ;
} ;
/**
2020-01-08 00:04:10 +03:00
* scm_legacy_command_to_response ( ) - Get a pointer to a scm_legacy_response
2015-03-12 00:28:10 +03:00
* @ cmd : command
*
* Returns a pointer to a response for a command .
*/
2020-01-08 00:04:10 +03:00
static inline struct scm_legacy_response * scm_legacy_command_to_response (
const struct scm_legacy_command * cmd )
2015-03-12 00:28:10 +03:00
{
return ( void * ) cmd + le32_to_cpu ( cmd - > resp_hdr_offset ) ;
}
/**
2020-01-08 00:04:10 +03:00
* scm_legacy_get_command_buffer ( ) - Get a pointer to a command buffer
2015-03-12 00:28:10 +03:00
* @ cmd : command
*
* Returns a pointer to the command buffer of a command .
*/
2020-01-08 00:04:10 +03:00
static inline void * scm_legacy_get_command_buffer (
const struct scm_legacy_command * cmd )
2015-03-12 00:28:10 +03:00
{
return ( void * ) cmd - > buf ;
}
/**
2020-01-08 00:04:10 +03:00
* scm_legacy_get_response_buffer ( ) - Get a pointer to a response buffer
2015-03-12 00:28:10 +03:00
* @ rsp : response
*
* Returns a pointer to a response buffer of a response .
*/
2020-01-08 00:04:10 +03:00
static inline void * scm_legacy_get_response_buffer (
const struct scm_legacy_response * rsp )
2015-03-12 00:28:10 +03:00
{
return ( void * ) rsp + le32_to_cpu ( rsp - > buf_offset ) ;
}
2020-01-08 00:04:10 +03:00
static u32 __scm_legacy_do ( u32 cmd_addr )
2015-03-12 00:28:10 +03:00
{
int context_id ;
2020-01-08 00:04:18 +03:00
struct arm_smccc_res res ;
2015-03-12 00:28:10 +03:00
do {
2020-01-08 00:04:18 +03:00
arm_smccc_smc ( 1 , ( unsigned long ) & context_id , cmd_addr ,
0 , 0 , 0 , 0 , 0 , & res ) ;
} while ( res . a0 = = QCOM_SCM_INTERRUPTED ) ;
return res . a0 ;
2015-03-12 00:28:10 +03:00
}
/**
2020-01-08 00:04:20 +03:00
* qcom_scm_call ( ) - Sends a command to the SCM and waits for the command to
* finish processing .
2015-03-12 00:28:10 +03:00
*
* A note on cache maintenance :
* Note that any buffers that are expected to be accessed by the secure world
* must be flushed before invoking qcom_scm_call and invalidated in the cache
* immediately after qcom_scm_call returns . Cache maintenance on the command
* and response buffers is taken care of by qcom_scm_call ; however , callers are
* responsible for any other cached buffers passed over to the secure world .
*/
2020-01-08 00:04:20 +03:00
static int qcom_scm_call ( struct device * dev , const struct qcom_scm_desc * desc ,
struct qcom_scm_res * res )
2015-03-12 00:28:10 +03:00
{
2020-01-08 00:04:20 +03:00
u8 arglen = desc - > arginfo & 0xf ;
2015-03-12 00:28:10 +03:00
int ret ;
2020-01-08 00:04:20 +03:00
unsigned int i ;
2020-01-08 00:04:10 +03:00
struct scm_legacy_command * cmd ;
struct scm_legacy_response * rsp ;
2020-01-08 00:04:20 +03:00
const size_t cmd_len = arglen * sizeof ( __le32 ) ;
const size_t resp_len = MAX_QCOM_SCM_RETS * sizeof ( __le32 ) ;
2016-06-04 02:25:25 +03:00
size_t alloc_len = sizeof ( * cmd ) + cmd_len + sizeof ( * rsp ) + resp_len ;
dma_addr_t cmd_phys ;
2020-01-08 00:04:20 +03:00
__le32 * arg_buf ;
const __le32 * res_buf ;
2015-03-12 00:28:10 +03:00
2016-06-04 02:25:25 +03:00
cmd = kzalloc ( PAGE_ALIGN ( alloc_len ) , GFP_KERNEL ) ;
2015-03-12 00:28:10 +03:00
if ( ! cmd )
return - ENOMEM ;
2016-06-04 02:25:25 +03:00
cmd - > len = cpu_to_le32 ( alloc_len ) ;
cmd - > buf_offset = cpu_to_le32 ( sizeof ( * cmd ) ) ;
cmd - > resp_hdr_offset = cpu_to_le32 ( sizeof ( * cmd ) + cmd_len ) ;
2020-01-08 00:04:20 +03:00
cmd - > id = cpu_to_le32 ( SCM_LEGACY_FNID ( desc - > svc , desc - > cmd ) ) ;
2016-06-04 02:25:25 +03:00
2020-01-08 00:04:20 +03:00
arg_buf = scm_legacy_get_command_buffer ( cmd ) ;
for ( i = 0 ; i < arglen ; i + + )
arg_buf [ i ] = cpu_to_le32 ( desc - > args [ i ] ) ;
2015-03-12 00:28:10 +03:00
2020-01-08 00:04:10 +03:00
rsp = scm_legacy_command_to_response ( cmd ) ;
2016-06-04 02:25:25 +03:00
cmd_phys = dma_map_single ( dev , cmd , alloc_len , DMA_TO_DEVICE ) ;
if ( dma_mapping_error ( dev , cmd_phys ) ) {
kfree ( cmd ) ;
return - ENOMEM ;
}
2015-03-12 00:28:10 +03:00
mutex_lock ( & qcom_scm_lock ) ;
2020-01-08 00:04:10 +03:00
ret = __scm_legacy_do ( cmd_phys ) ;
2016-06-04 02:25:25 +03:00
if ( ret < 0 )
ret = qcom_scm_remap_error ( ret ) ;
2015-03-12 00:28:10 +03:00
mutex_unlock ( & qcom_scm_lock ) ;
if ( ret )
goto out ;
do {
2016-06-04 02:25:25 +03:00
dma_sync_single_for_cpu ( dev , cmd_phys + sizeof ( * cmd ) + cmd_len ,
sizeof ( * rsp ) , DMA_FROM_DEVICE ) ;
2015-03-12 00:28:10 +03:00
} while ( ! rsp - > is_complete ) ;
2020-01-08 00:04:20 +03:00
dma_sync_single_for_cpu ( dev , cmd_phys + sizeof ( * cmd ) + cmd_len +
le32_to_cpu ( rsp - > buf_offset ) ,
resp_len , DMA_FROM_DEVICE ) ;
if ( res ) {
res_buf = scm_legacy_get_response_buffer ( rsp ) ;
for ( i = 0 ; i < MAX_QCOM_SCM_RETS ; i + + )
res - > result [ i ] = le32_to_cpu ( res_buf [ i ] ) ;
2016-06-04 02:25:25 +03:00
}
2015-03-12 00:28:10 +03:00
out :
2016-06-04 02:25:25 +03:00
dma_unmap_single ( dev , cmd_phys , alloc_len , DMA_TO_DEVICE ) ;
kfree ( cmd ) ;
2015-03-12 00:28:10 +03:00
return ret ;
}
2020-01-08 00:04:10 +03:00
# define SCM_LEGACY_CLASS_REGISTER (0x2 << 8)
# define SCM_LEGACY_MASK_IRQS BIT(5)
# define SCM_LEGACY_ATOMIC_ID(svc, cmd, n) \
2020-01-08 00:04:19 +03:00
( ( SCM_LEGACY_FNID ( svc , cmd ) < < 12 ) | \
2020-01-08 00:04:10 +03:00
SCM_LEGACY_CLASS_REGISTER | \
SCM_LEGACY_MASK_IRQS | \
2015-03-12 00:28:10 +03:00
( n & 0xf ) )
/**
* qcom_scm_call_atomic1 ( ) - Send an atomic SCM command with one argument
* @ svc_id : service identifier
* @ cmd_id : command identifier
* @ arg1 : first argument
*
* This shall only be used with commands that are guaranteed to be
* uninterruptable , atomic and SMP safe .
*/
static s32 qcom_scm_call_atomic1 ( u32 svc , u32 cmd , u32 arg1 )
{
int context_id ;
2020-01-08 00:04:18 +03:00
struct arm_smccc_res res ;
arm_smccc_smc ( SCM_LEGACY_ATOMIC_ID ( svc , cmd , 1 ) ,
( unsigned long ) & context_id , arg1 , 0 , 0 , 0 , 0 , 0 , & res ) ;
2015-03-12 00:28:10 +03:00
2020-01-08 00:04:18 +03:00
return res . a0 ;
2015-03-12 00:28:10 +03:00
}
2016-06-04 02:25:23 +03:00
/**
* qcom_scm_call_atomic2 ( ) - Send an atomic SCM command with two arguments
* @ svc_id : service identifier
* @ cmd_id : command identifier
* @ arg1 : first argument
* @ arg2 : second argument
*
* This shall only be used with commands that are guaranteed to be
* uninterruptable , atomic and SMP safe .
*/
static s32 qcom_scm_call_atomic2 ( u32 svc , u32 cmd , u32 arg1 , u32 arg2 )
{
int context_id ;
2020-01-08 00:04:18 +03:00
struct arm_smccc_res res ;
arm_smccc_smc ( SCM_LEGACY_ATOMIC_ID ( svc , cmd , 2 ) ,
( unsigned long ) & context_id , arg1 , 0 , 0 , 0 , 0 , 0 , & res ) ;
2016-06-04 02:25:23 +03:00
2020-01-08 00:04:18 +03:00
return res . a0 ;
2016-06-04 02:25:23 +03:00
}
2015-03-12 00:28:10 +03:00
/**
* qcom_scm_set_cold_boot_addr ( ) - Set the cold boot address for cpus
* @ entry : Entry point function for the cpus
* @ cpus : The cpumask of cpus that will use the entry point
*
* Set the cold boot address of the cpus . Any cpu outside the supported
* range would be removed from the cpu present mask .
*/
int __qcom_scm_set_cold_boot_addr ( void * entry , const cpumask_t * cpus )
{
int flags = 0 ;
int cpu ;
int scm_cb_flags [ ] = {
QCOM_SCM_FLAG_COLDBOOT_CPU0 ,
QCOM_SCM_FLAG_COLDBOOT_CPU1 ,
QCOM_SCM_FLAG_COLDBOOT_CPU2 ,
QCOM_SCM_FLAG_COLDBOOT_CPU3 ,
} ;
if ( ! cpus | | ( cpus & & cpumask_empty ( cpus ) ) )
return - EINVAL ;
for_each_cpu ( cpu , cpus ) {
if ( cpu < ARRAY_SIZE ( scm_cb_flags ) )
flags | = scm_cb_flags [ cpu ] ;
else
set_cpu_present ( cpu , false ) ;
}
2020-01-08 00:04:11 +03:00
return qcom_scm_call_atomic2 ( QCOM_SCM_SVC_BOOT , QCOM_SCM_BOOT_SET_ADDR ,
2016-06-04 02:25:23 +03:00
flags , virt_to_phys ( entry ) ) ;
2015-03-12 00:28:10 +03:00
}
/**
* qcom_scm_set_warm_boot_addr ( ) - Set the warm boot address for cpus
* @ entry : Entry point function for the cpus
* @ cpus : The cpumask of cpus that will use the entry point
*
* Set the Linux entry point for the SCM to transfer control to when coming
* out of a power down . CPU power down may be executed on cpuidle or hotplug .
*/
2016-06-04 02:25:25 +03:00
int __qcom_scm_set_warm_boot_addr ( struct device * dev , void * entry ,
const cpumask_t * cpus )
2015-03-12 00:28:10 +03:00
{
int ret ;
int flags = 0 ;
int cpu ;
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_BOOT ,
. cmd = QCOM_SCM_BOOT_SET_ADDR ,
} ;
2015-03-12 00:28:10 +03:00
/*
* Reassign only if we are switching from hotplug entry point
* to cpuidle entry point or vice versa .
*/
for_each_cpu ( cpu , cpus ) {
if ( entry = = qcom_scm_wb [ cpu ] . entry )
continue ;
flags | = qcom_scm_wb [ cpu ] . flag ;
}
/* No change in entry function */
if ( ! flags )
return 0 ;
2020-01-08 00:04:20 +03:00
desc . args [ 0 ] = flags ;
desc . args [ 1 ] = virt_to_phys ( entry ) ;
desc . arginfo = QCOM_SCM_ARGS ( 2 ) ;
ret = qcom_scm_call ( dev , & desc , NULL ) ;
2015-03-12 00:28:10 +03:00
if ( ! ret ) {
for_each_cpu ( cpu , cpus )
qcom_scm_wb [ cpu ] . entry = entry ;
}
return ret ;
}
/**
* qcom_scm_cpu_power_down ( ) - Power down the cpu
* @ flags - Flags to flush cache
*
* This is an end point to power down cpu . If there was a pending interrupt ,
* the control would return from this function , otherwise , the cpu jumps to the
* warm boot entry point set for this cpu upon reset .
*/
void __qcom_scm_cpu_power_down ( u32 flags )
{
2020-01-08 00:04:11 +03:00
qcom_scm_call_atomic1 ( QCOM_SCM_SVC_BOOT , QCOM_SCM_BOOT_TERMINATE_PC ,
2015-03-12 00:28:10 +03:00
flags & QCOM_SCM_FLUSH_FLAG_MASK ) ;
}
2015-04-10 23:15:59 +03:00
2016-06-04 02:25:25 +03:00
int __qcom_scm_is_call_available ( struct device * dev , u32 svc_id , u32 cmd_id )
2015-04-10 23:15:59 +03:00
{
int ret ;
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_INFO ,
. cmd = QCOM_SCM_INFO_IS_CALL_AVAIL ,
. args [ 0 ] = SCM_LEGACY_FNID ( svc_id , cmd_id ) ,
. arginfo = QCOM_SCM_ARGS ( 1 ) ,
} ;
struct qcom_scm_res res ;
2015-04-10 23:15:59 +03:00
2020-01-08 00:04:20 +03:00
ret = qcom_scm_call ( dev , & desc , & res ) ;
2015-04-10 23:15:59 +03:00
2020-01-08 00:04:20 +03:00
return ret ? : res . result [ 0 ] ;
2015-04-10 23:15:59 +03:00
}
2016-06-04 02:25:25 +03:00
int __qcom_scm_hdcp_req ( struct device * dev , struct qcom_scm_hdcp_req * req ,
u32 req_cnt , u32 * resp )
2015-04-10 23:15:59 +03:00
{
2020-01-08 00:04:20 +03:00
int ret ;
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_HDCP ,
. cmd = QCOM_SCM_HDCP_INVOKE ,
} ;
struct qcom_scm_res res ;
2015-04-10 23:15:59 +03:00
if ( req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT )
return - ERANGE ;
2020-01-08 00:04:20 +03:00
desc . args [ 0 ] = req [ 0 ] . addr ;
desc . args [ 1 ] = req [ 0 ] . val ;
desc . args [ 2 ] = req [ 1 ] . addr ;
desc . args [ 3 ] = req [ 1 ] . val ;
desc . args [ 4 ] = req [ 2 ] . addr ;
desc . args [ 5 ] = req [ 2 ] . val ;
desc . args [ 6 ] = req [ 3 ] . addr ;
desc . args [ 7 ] = req [ 3 ] . val ;
desc . args [ 8 ] = req [ 4 ] . addr ;
desc . args [ 9 ] = req [ 4 ] . val ;
desc . arginfo = QCOM_SCM_ARGS ( 10 ) ;
ret = qcom_scm_call ( dev , & desc , & res ) ;
* resp = res . result [ 0 ] ;
return ret ;
2015-04-10 23:15:59 +03:00
}
2016-06-04 02:25:26 +03:00
2019-08-23 15:16:33 +03:00
int __qcom_scm_ocmem_lock ( struct device * dev , u32 id , u32 offset , u32 size ,
u32 mode )
{
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_OCMEM ,
. cmd = QCOM_SCM_OCMEM_LOCK_CMD ,
} ;
desc . args [ 0 ] = id ;
desc . args [ 1 ] = offset ;
desc . args [ 2 ] = size ;
desc . args [ 3 ] = mode ;
desc . arginfo = QCOM_SCM_ARGS ( 4 ) ;
return qcom_scm_call ( dev , & desc , NULL ) ;
2019-08-23 15:16:33 +03:00
}
int __qcom_scm_ocmem_unlock ( struct device * dev , u32 id , u32 offset , u32 size )
{
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_OCMEM ,
. cmd = QCOM_SCM_OCMEM_UNLOCK_CMD ,
} ;
desc . args [ 0 ] = id ;
desc . args [ 1 ] = offset ;
desc . args [ 2 ] = size ;
desc . arginfo = QCOM_SCM_ARGS ( 3 ) ;
return qcom_scm_call ( dev , & desc , NULL ) ;
2019-08-23 15:16:33 +03:00
}
2016-06-04 02:25:26 +03:00
void __qcom_scm_init ( void )
{
}
2015-09-23 22:56:12 +03:00
bool __qcom_scm_pas_supported ( struct device * dev , u32 peripheral )
{
int ret ;
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_PIL ,
. cmd = QCOM_SCM_PIL_PAS_IS_SUPPORTED ,
} ;
struct qcom_scm_res res ;
desc . args [ 0 ] = peripheral ;
desc . arginfo = QCOM_SCM_ARGS ( 1 ) ;
2015-09-23 22:56:12 +03:00
2020-01-08 00:04:20 +03:00
ret = qcom_scm_call ( dev , & desc , & res ) ;
2015-09-23 22:56:12 +03:00
2020-01-08 00:04:20 +03:00
return ret ? false : ! ! res . result [ 0 ] ;
2015-09-23 22:56:12 +03:00
}
int __qcom_scm_pas_init_image ( struct device * dev , u32 peripheral ,
dma_addr_t metadata_phys )
{
int ret ;
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_PIL ,
. cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE ,
} ;
struct qcom_scm_res res ;
2015-09-23 22:56:12 +03:00
2020-01-08 00:04:20 +03:00
desc . args [ 0 ] = peripheral ;
desc . args [ 1 ] = metadata_phys ;
desc . arginfo = QCOM_SCM_ARGS ( 2 , QCOM_SCM_VAL , QCOM_SCM_RW ) ;
2015-09-23 22:56:12 +03:00
2020-01-08 00:04:20 +03:00
ret = qcom_scm_call ( dev , & desc , & res ) ;
2015-09-23 22:56:12 +03:00
2020-01-08 00:04:20 +03:00
return ret ? : res . result [ 0 ] ;
2015-09-23 22:56:12 +03:00
}
int __qcom_scm_pas_mem_setup ( struct device * dev , u32 peripheral ,
2020-01-08 00:04:20 +03:00
phys_addr_t addr , phys_addr_t size )
2015-09-23 22:56:12 +03:00
{
int ret ;
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_PIL ,
. cmd = QCOM_SCM_PIL_PAS_MEM_SETUP ,
} ;
struct qcom_scm_res res ;
desc . args [ 0 ] = peripheral ;
desc . args [ 1 ] = addr ;
desc . args [ 2 ] = size ;
desc . arginfo = QCOM_SCM_ARGS ( 3 ) ;
ret = qcom_scm_call ( dev , & desc , & res ) ;
return ret ? : res . result [ 0 ] ;
2015-09-23 22:56:12 +03:00
}
int __qcom_scm_pas_auth_and_reset ( struct device * dev , u32 peripheral )
{
int ret ;
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_PIL ,
. cmd = QCOM_SCM_PIL_PAS_AUTH_AND_RESET ,
} ;
struct qcom_scm_res res ;
desc . args [ 0 ] = peripheral ;
desc . arginfo = QCOM_SCM_ARGS ( 1 ) ;
2015-09-23 22:56:12 +03:00
2020-01-08 00:04:20 +03:00
ret = qcom_scm_call ( dev , & desc , & res ) ;
2015-09-23 22:56:12 +03:00
2020-01-08 00:04:20 +03:00
return ret ? : res . result [ 0 ] ;
2015-09-23 22:56:12 +03:00
}
int __qcom_scm_pas_shutdown ( struct device * dev , u32 peripheral )
{
int ret ;
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_PIL ,
. cmd = QCOM_SCM_PIL_PAS_SHUTDOWN ,
} ;
struct qcom_scm_res res ;
desc . args [ 0 ] = peripheral ;
desc . arginfo = QCOM_SCM_ARGS ( 1 ) ;
2015-09-23 22:56:12 +03:00
2020-01-08 00:04:20 +03:00
ret = qcom_scm_call ( dev , & desc , & res ) ;
2015-09-23 22:56:12 +03:00
2020-01-08 00:04:20 +03:00
return ret ? : res . result [ 0 ] ;
2015-09-23 22:56:12 +03:00
}
2016-06-17 20:40:43 +03:00
int __qcom_scm_pas_mss_reset ( struct device * dev , bool reset )
{
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_PIL ,
. cmd = QCOM_SCM_PIL_PAS_MSS_RESET ,
} ;
struct qcom_scm_res res ;
2016-06-17 20:40:43 +03:00
int ret ;
2020-01-08 00:04:20 +03:00
desc . args [ 0 ] = reset ;
desc . args [ 1 ] = 0 ;
desc . arginfo = QCOM_SCM_ARGS ( 2 ) ;
2016-06-17 20:40:43 +03:00
2020-01-08 00:04:20 +03:00
ret = qcom_scm_call ( dev , & desc , & res ) ;
return ret ? : res . result [ 0 ] ;
2016-06-17 20:40:43 +03:00
}
2017-01-17 08:24:15 +03:00
2017-08-15 01:46:18 +03:00
int __qcom_scm_set_dload_mode ( struct device * dev , bool enable )
{
2020-01-08 00:04:11 +03:00
return qcom_scm_call_atomic2 ( QCOM_SCM_SVC_BOOT , QCOM_SCM_BOOT_SET_DLOAD_MODE ,
enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0 , 0 ) ;
2017-08-15 01:46:18 +03:00
}
2017-01-17 08:24:15 +03:00
int __qcom_scm_set_remote_state ( struct device * dev , u32 state , u32 id )
{
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_BOOT ,
. cmd = QCOM_SCM_BOOT_SET_REMOTE_STATE ,
} ;
struct qcom_scm_res res ;
2017-01-17 08:24:15 +03:00
int ret ;
2020-01-08 00:04:20 +03:00
desc . args [ 0 ] = state ;
desc . args [ 1 ] = id ;
2017-01-17 08:24:15 +03:00
2020-01-08 00:04:20 +03:00
ret = qcom_scm_call ( dev , & desc , & res ) ;
2017-01-17 08:24:15 +03:00
2020-01-08 00:04:20 +03:00
return ret ? : res . result [ 0 ] ;
2017-01-17 08:24:15 +03:00
}
2017-03-14 18:18:03 +03:00
2017-10-24 18:52:24 +03:00
int __qcom_scm_assign_mem ( struct device * dev , phys_addr_t mem_region ,
size_t mem_sz , phys_addr_t src , size_t src_sz ,
phys_addr_t dest , size_t dest_sz )
{
return - ENODEV ;
}
2017-03-14 18:18:03 +03:00
int __qcom_scm_restore_sec_cfg ( struct device * dev , u32 device_id ,
u32 spare )
{
2020-01-08 00:04:20 +03:00
struct qcom_scm_desc desc = {
. svc = QCOM_SCM_SVC_MP ,
. cmd = QCOM_SCM_MP_RESTORE_SEC_CFG ,
} ;
struct qcom_scm_res res ;
int ret ;
2019-08-23 15:16:34 +03:00
2020-01-08 00:04:20 +03:00
desc . args [ 0 ] = device_id ;
desc . args [ 1 ] = spare ;
desc . arginfo = QCOM_SCM_ARGS ( 2 ) ;
2019-08-23 15:16:34 +03:00
2020-01-08 00:04:20 +03:00
ret = qcom_scm_call ( dev , & desc , & res ) ;
2019-08-23 15:16:34 +03:00
2020-01-08 00:04:20 +03:00
return ret ? : res . result [ 0 ] ;
2017-03-14 18:18:03 +03:00
}
2017-03-14 18:18:04 +03:00
int __qcom_scm_iommu_secure_ptbl_size ( struct device * dev , u32 spare ,
size_t * size )
{
return - ENODEV ;
}
int __qcom_scm_iommu_secure_ptbl_init ( struct device * dev , u64 addr , u32 size ,
u32 spare )
{
return - ENODEV ;
}
2017-08-15 01:46:17 +03:00
int __qcom_scm_io_readl ( struct device * dev , phys_addr_t addr ,
unsigned int * val )
{
int ret ;
ret = qcom_scm_call_atomic1 ( QCOM_SCM_SVC_IO , QCOM_SCM_IO_READ , addr ) ;
if ( ret > = 0 )
* val = ret ;
return ret < 0 ? ret : 0 ;
}
int __qcom_scm_io_writel ( struct device * dev , phys_addr_t addr , unsigned int val )
{
return qcom_scm_call_atomic2 ( QCOM_SCM_SVC_IO , QCOM_SCM_IO_WRITE ,
addr , val ) ;
}
2019-09-20 11:04:28 +03:00
int __qcom_scm_qsmmu500_wait_safe_toggle ( struct device * dev , bool enable )
{
return - ENODEV ;
}