blob: 447476d6cecdaec3aa4fbb202feb13953b0c6a8b [file] [log] [blame]
/*
* Copyright (C) 2018 Synaptics Incorporated. All rights reserved.
* Copyright (c) 2013-2014 Marvell International Ltd. and its affiliates.
* 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 as
* published by the Free Software Foundation.
*
* INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND
* SYNAPTICS EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE, AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY
* INTELLECTUAL PROPERTY RIGHTS. IN NO EVENT SHALL SYNAPTICS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, OR
* CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION WITH THE USE
* OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED AND
* BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF
* COMPETENT JURISDICTION DOES NOT PERMIT THE DISCLAIMER OF DIRECT
* DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' TOTAL CUMULATIVE LIABILITY
* TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. DOLLARS.
*/
.text
/** SMC Calling Conversion - Argument passing
* Document number: ARM DEN 0028A
*
* http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
*
* [SMC32 Argument passing]
*
* When the SMC32 convention is used, the SMC intructions take up to seven
* 32-bit arguments in register and can return up to four 32-bit values in
* registers.
*
* When an SMC32 call is made from AArch32:
* o Arguments are passed in register R0-R6
* o Results are returned in R0-R3
* o Registers R4-R14 are callee-saved and must be preserved over the SMC call
*
* When an SMC32 call is made from AArch64:
* o Arguments are passed in register X0-X6
* o Results are returned in X0-X3
* o Registers X18-X30 and stack pointers SP_EL0 and SP_ELx are callee-saved and
* must be preserved over the SMC call
*
* [SMC64 Argument passing]
*
* When the SMC64 convention is used, the SMC instructions take up to seven 64-bit
* arguments in registers and can return up to four 64-bit values in register
*
* When an SMC64 call is made from AArch64:
* o Arguments are passed in register X0-X6
* o Results are returned in X0-X3
* o Registers X18-X30 and stack pointers SP_EL0 and SP_ELx are callee-saved and
* must ber preserved over the SMC call
*
* Then calling convention cannot be used by code executing AArch32 state
*/
/** SMC call command with 2 parameters
*
* unsigned long __smc_cmd2(unsigned long func_id,
* unsigned long param0,
* unsigned long param1,
* unsigned long result[2])
*
* @param func_id function ID in x0
* @param param0 parameters 0 in x1
* @param param1 parameters 1 in x2
* @param result pointer to returned results (x1-x2) in x3 if not NULL
*
* @retval 0xffffffff invalidate function ID
* @retval others status
*
*/
.globl __smc_cmd2
__smc_cmd2:
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* Save in the stack, stack pointer MUST be quadword aligned
* that is it must be aligned to 16 bytes. Misalignment
* generates a Stack Alighment fault
* ----------------------------------------------------------
*/
stp x29, x30, [sp, #-32]!
mov x29, sp
/* ----------------------------------------------------------
* x0 = function ID, x1 = param0, x2 = param1
*
* preserve x3 and x19 on the stack
* x3 contains the pointer to returned value
* x19 as a temporary register
* ----------------------------------------------------------
*/
stp x3, x19, [sp, #16]
/* ----------------------------------------------------------
* make smc call now
* ----------------------------------------------------------
*/
smc #0
/* ---------------------------------------------------------
* retrieve the pointer of returned value previously saved
* on the stack
* ---------------------------------------------------------
*/
ldr x19, [sp, #16]
/* ---------------------------------------------------------
* x0-x3 contains the returned value
*
* If the pointer is not NULL saved x1-x2 to result[2]
* ---------------------------------------------------------
*/
cmp x19, #0
b.eq 1f
stp x1, x2, [x19]
1:
/* ----------------------------------------------------------
* restore x19 from stack
* ----------------------------------------------------------
*/
ldr x19, [sp, #24]
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* restore link address register & frame pointer register
* ----------------------------------------------------------
*/
ldp x29, x30, [sp], #32
/* ---------------------------------------------------------
* back to caller
* ---------------------------------------------------------
*/
ret
/** SMC call command with 3 parameters.
*
* unsigned long __smc_cmd3(unsigned long func_id,
* unsigned long param0,
* unsigned long param1,
* unsigned long param2,
* unsigned long result[3]);
*
* unsigned long __smc3(unsigned long func_id,
* unsigned long param0,
* unsigned long param1,
* unsigned long param2,
* unsigned long result[3]);
*
* @param func_id function ID in x0
* @param param0 parameter 0 in x1
* @param param1 parameter 1 in x2
* @param param2 parameter 2 in x3
* @param result pointer to return results (x1-x3) in x4 if not NULL
*
* @retval 0xffffffff invalidate Function ID.
* @retval others status
*/
.globl __smc_cmd3
__smc_cmd3:
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* Save in the stack, stack pointer MUST be quadword aligned
* that is it must be aligned to 16 bytes. Misalignment
* generates a Stack Alighment fault
* ----------------------------------------------------------
*/
stp x29, x30, [sp, #-32]!
mov x29, sp
/* ----------------------------------------------------------
* x0 = function ID, x1 = param0, x2 = param1, x3 = param2
*
* preserve x4 and x19 on the stack
* x4 contains the pointer to returned value
* x19 as a temporary register
* ----------------------------------------------------------
*/
stp x4, x19, [sp, #16]
/* ----------------------------------------------------------
* make smc call now
* ----------------------------------------------------------
*/
smc #0
/* ---------------------------------------------------------
* retrieve the pointer of returned value previously saved
* on the stack
* ---------------------------------------------------------
*/
ldr x19, [sp, #16]
/* ---------------------------------------------------------
* x0-x3 contains the returned value
*
* If the pointer is not NULL saved x1-x3 to result[3]
* ---------------------------------------------------------
*/
cmp x19, #0
b.eq 1f
stp x1, x2, [x19]
str x3, [x19, #16]
1:
/* ----------------------------------------------------------
* restore x19 from stack
* ----------------------------------------------------------
*/
ldr x19, [sp, #24]
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* restore link address register & frame pointer register
* ----------------------------------------------------------
*/
ldp x29, x30, [sp], #32
/* ---------------------------------------------------------
* back to caller
* ---------------------------------------------------------
*/
ret
/** SMC call without results.
*
* unsigned long __smc(unsigned long func_id, ...);
*
* @note it can be used as bellow:
* status = smc_nores(func_id);
* status = smc_nores(func_id, param0);
* status = smc_nores(func_id, param0, param1);
* status = smc_nores(func_id, param0, param1, param2);
*
* @param func_id function ID in x0
* @param param0 parameter 0 in x1
* @param param1 parameter 1 in x2
* @param param2 parameter 2 in x3
*
* @retval 0xffffffff invalidate Function ID.
* @retval others status
*/
.globl __smc
__smc:
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* Save in the stack, stack pointer MUST be quadword aligned
* that is it must be aligned to 16 bytes. Misalignment
* generates a Stack Alighment fault
* ----------------------------------------------------------
*/
stp x29, x30, [sp, #-16]!
mov x29, sp
/* ----------------------------------------------------------
* make smc call now
* ----------------------------------------------------------
*/
smc #0
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* restore link address register & frame pointer register
* ----------------------------------------------------------
*/
ldp x29, x30, [sp], #16
/* ---------------------------------------------------------
* back to caller
* ---------------------------------------------------------
*/
ret
/** SMC call command with 3 parameters.
*
* unsigned long __smc3(unsigned long func_id,
* unsigned long param0,
* unsigned long param1,
* unsigned long param2,
* unsigned long result[4]);
*
* @param func_id function ID in x0
* @param param0 parameter 0 in x1
* @param param1 parameter 1 in x2
* @param param2 parameter 2 in x3
* @param result pointer to return results (x0-x3) in x4 if not NULL
*
* @retval 0xffffffff invalidate Function ID.
* @retval others status
*/
.globl __smc3
__smc3:
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* Save in the stack, stack pointer MUST be quadword aligned
* that is it must be aligned to 16 bytes. Misalignment
* generates a Stack Alighment fault
* ----------------------------------------------------------
*/
stp x29, x30, [sp, #-32]!
mov x29, sp
/* ----------------------------------------------------------
* x0 = function ID, x1 = param0, x2 = param1, x3 = param2
*
* preserve x4 and x19 on the stack
* x4 contains the pointer to returned value
* x19 as a temporary register
* ----------------------------------------------------------
*/
stp x4, x19, [sp, #16]
/* ----------------------------------------------------------
* make smc call now
* ----------------------------------------------------------
*/
smc #0
/* ---------------------------------------------------------
* retrieve the pointer of returned value previously saved
* on the stack
* ---------------------------------------------------------
*/
ldr x19, [sp, #16]
/* ---------------------------------------------------------
* x0-x3 contains the returned value
*
* If the pointer is not NULL saved x0-x3 to result[4]
* ---------------------------------------------------------
*/
cmp x19, #0
b.eq 1f
stp x0, x1, [x19]
stp x2, x3, [x19, #16]
1:
/* ----------------------------------------------------------
* restore x19 from stack
* ----------------------------------------------------------
*/
ldr x19, [sp, #24]
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* restore link address register & frame pointer register
* ----------------------------------------------------------
*/
ldp x29, x30, [sp], #32
/* ---------------------------------------------------------
* back to caller
* ---------------------------------------------------------
*/
ret
/** SMC call with 6 parameters.
*
* unsigned long __smc6(unsigned long func_id,
* const unsigned long param[6],
* unsigned long result[4]);
*
* @param func_id function ID in x0
* @param param buffer to store 6 parmeters in r1
* @param result buffer to return results (x0-x3) in r2 if not NULL
* result[0] is returned by function too
*
* @retval 0xffffffff invalidate Function ID.
* @retval others status
*/
.globl __smc6
__smc6:
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* Save in the stack, stack pointer MUST be quadword aligned
* that is it must be aligned to 16 bytes. Misalignment
* generates a Stack Alighment fault
* ----------------------------------------------------------
*/
stp x29, x30, [sp, #-32]!
mov x29, sp
/* ----------------------------------------------------------
* x0 = function ID
* x1 = pointer to 6 parameters (x1-x6)
* x2 = pointer to return results (x0-x3)
*
* preserve x2 and x19 on the stack
* x2 contains the pointer to the returned value
* x19 as a temporary register
* ----------------------------------------------------------
*/
stp x2, x19, [sp, #16]
/* ----------------------------------------------------------
* Load 6 parameters into r1-r6, will panic if r1=NULL
*
* x19 = ip0, first intra-procedure-call scratch register
* ----------------------------------------------------------
*/
mov x19, x1
ldp x1, x2, [x19]
ldp x3, x4, [x19, #16]
ldp x5, x6, [x19, #32]
/* ----------------------------------------------------------
* make smc call now
* ----------------------------------------------------------
*/
smc #0
/* ---------------------------------------------------------
* retrieve the pointer of returned value previously saved
* on the stack
* ---------------------------------------------------------
*/
ldr x19, [sp, #16]
/* ---------------------------------------------------------
* x0-x3 contains the returned value
*
* If the pointer is not NULL saved x1-x3 to result[4]
* ---------------------------------------------------------
*/
cmp x19, #0
b.eq 1f
stp x0, x1, [x19]
stp x2, x3, [x19, #16]
1:
/* ----------------------------------------------------------
* restore x19 from stack
* ----------------------------------------------------------
*/
ldr x19, [sp, #24]
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* restore link address register & frame pointer register
* ----------------------------------------------------------
*/
ldp x29, x30, [sp], #32
/* ---------------------------------------------------------
* back to caller
* ---------------------------------------------------------
*/
ret