1 /* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 #include <linux/slab.h>
20 #include <linux/module.h>
21 #include <linux/mutex.h>
22 #include <linux/errno.h>
23 #include <linux/err.h>
25 #include <asm/cacheflush.h>
29 /* Cache line size for msm8x60 */
30 #define CACHELINESIZE 32
33 #define SCM_EOPNOTSUPP -4
34 #define SCM_EINVAL_ADDR -3
35 #define SCM_EINVAL_ARG -2
37 #define SCM_INTERRUPTED 1
39 static DEFINE_MUTEX(scm_lock
);
42 * struct scm_command - one SCM command buffer
43 * @len: total available memory for command and response
44 * @buf_offset: start of command buffer
45 * @resp_hdr_offset: start of response buffer
46 * @id: command to be executed
47 * @buf: buffer returned from scm_get_command_buffer()
49 * An SCM command is laid out in memory as follows:
51 * ------------------- <--- struct scm_command
53 * ------------------- <--- scm_get_command_buffer()
55 * ------------------- <--- struct scm_response and
56 * | response header | scm_command_to_response()
57 * ------------------- <--- scm_get_response_buffer()
61 * There can be arbitrary padding between the headers and buffers so
62 * you should always use the appropriate scm_get_*_buffer() routines
63 * to access the buffers in a safe manner.
74 * struct scm_response - one SCM response buffer
75 * @len: total available memory for response
76 * @buf_offset: start of response data relative to start of scm_response
77 * @is_complete: indicates if the command has finished processing
86 * alloc_scm_command() - Allocate an SCM command
87 * @cmd_size: size of the command buffer
88 * @resp_size: size of the response buffer
90 * Allocate an SCM command, including enough room for the command
91 * and response headers as well as the command and response buffers.
93 * Returns a valid &scm_command on success or %NULL if the allocation fails.
95 static struct scm_command
*alloc_scm_command(size_t cmd_size
, size_t resp_size
)
97 struct scm_command
*cmd
;
98 size_t len
= sizeof(*cmd
) + sizeof(struct scm_response
) + cmd_size
+
101 cmd
= kzalloc(PAGE_ALIGN(len
), GFP_KERNEL
);
104 cmd
->buf_offset
= offsetof(struct scm_command
, buf
);
105 cmd
->resp_hdr_offset
= cmd
->buf_offset
+ cmd_size
;
111 * free_scm_command() - Free an SCM command
112 * @cmd: command to free
114 * Free an SCM command.
116 static inline void free_scm_command(struct scm_command
*cmd
)
122 * scm_command_to_response() - Get a pointer to a scm_response
125 * Returns a pointer to a response for a command.
127 static inline struct scm_response
*scm_command_to_response(
128 const struct scm_command
*cmd
)
130 return (void *)cmd
+ cmd
->resp_hdr_offset
;
134 * scm_get_command_buffer() - Get a pointer to a command buffer
137 * Returns a pointer to the command buffer of a command.
139 static inline void *scm_get_command_buffer(const struct scm_command
*cmd
)
141 return (void *)cmd
->buf
;
145 * scm_get_response_buffer() - Get a pointer to a response buffer
148 * Returns a pointer to a response buffer of a response.
150 static inline void *scm_get_response_buffer(const struct scm_response
*rsp
)
152 return (void *)rsp
+ rsp
->buf_offset
;
155 static int scm_remap_error(int err
)
160 case SCM_EINVAL_ADDR
:
171 static u32
smc(u32 cmd_addr
)
174 register u32 r0
asm("r0") = 1;
175 register u32 r1
asm("r1") = (u32
)&context_id
;
176 register u32 r2
asm("r2") = cmd_addr
;
184 ".arch_extension sec\n"
186 "smc #0 @ switch to secure world\n"
188 : "r" (r0
), "r" (r1
), "r" (r2
)
190 } while (r0
== SCM_INTERRUPTED
);
195 static int __scm_call(const struct scm_command
*cmd
)
198 u32 cmd_addr
= virt_to_phys(cmd
);
201 * Flush the entire cache here so callers don't have to remember
202 * to flush the cache when passing physical addresses to the secure
203 * side in the buffer.
208 ret
= scm_remap_error(ret
);
214 * scm_call() - Send an SCM command
215 * @svc_id: service identifier
216 * @cmd_id: command identifier
217 * @cmd_buf: command buffer
218 * @cmd_len: length of the command buffer
219 * @resp_buf: response buffer
220 * @resp_len: length of the response buffer
222 * Sends a command to the SCM and waits for the command to finish processing.
224 int scm_call(u32 svc_id
, u32 cmd_id
, const void *cmd_buf
, size_t cmd_len
,
225 void *resp_buf
, size_t resp_len
)
228 struct scm_command
*cmd
;
229 struct scm_response
*rsp
;
231 cmd
= alloc_scm_command(cmd_len
, resp_len
);
235 cmd
->id
= (svc_id
<< 10) | cmd_id
;
237 memcpy(scm_get_command_buffer(cmd
), cmd_buf
, cmd_len
);
239 mutex_lock(&scm_lock
);
240 ret
= __scm_call(cmd
);
241 mutex_unlock(&scm_lock
);
245 rsp
= scm_command_to_response(cmd
);
247 u32 start
= (u32
)rsp
;
248 u32 end
= (u32
)scm_get_response_buffer(rsp
) + resp_len
;
249 start
&= ~(CACHELINESIZE
- 1);
250 while (start
< end
) {
251 asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start
)
253 start
+= CACHELINESIZE
;
255 } while (!rsp
->is_complete
);
258 memcpy(resp_buf
, scm_get_response_buffer(rsp
), resp_len
);
260 free_scm_command(cmd
);
263 EXPORT_SYMBOL(scm_call
);
265 u32
scm_get_version(void)
268 static u32 version
= -1;
269 register u32 r0
asm("r0");
270 register u32 r1
asm("r1");
275 mutex_lock(&scm_lock
);
278 r1
= (u32
)&context_id
;
285 "smc #0 @ switch to secure world\n"
286 : "=r" (r0
), "=r" (r1
)
289 } while (r0
== SCM_INTERRUPTED
);
292 mutex_unlock(&scm_lock
);
296 EXPORT_SYMBOL(scm_get_version
);