qcom_scm.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  2. * Copyright (C) 2015 Linaro Ltd.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. * 02110-1301, USA.
  17. */
  18. #include <linux/slab.h>
  19. #include <linux/io.h>
  20. #include <linux/module.h>
  21. #include <linux/mutex.h>
  22. #include <linux/errno.h>
  23. #include <linux/err.h>
  24. #include <linux/qcom_scm.h>
  25. #include <asm/outercache.h>
  26. #include <asm/cacheflush.h>
  27. #define QCOM_SCM_ENOMEM -5
  28. #define QCOM_SCM_EOPNOTSUPP -4
  29. #define QCOM_SCM_EINVAL_ADDR -3
  30. #define QCOM_SCM_EINVAL_ARG -2
  31. #define QCOM_SCM_ERROR -1
  32. #define QCOM_SCM_INTERRUPTED 1
  33. #define QCOM_SCM_FLAG_COLDBOOT_CPU0 0x00
  34. #define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01
  35. #define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08
  36. #define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20
  37. #define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04
  38. #define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02
  39. #define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10
  40. #define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40
  41. struct qcom_scm_entry {
  42. int flag;
  43. void *entry;
  44. };
  45. static struct qcom_scm_entry qcom_scm_wb[] = {
  46. { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 },
  47. { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 },
  48. { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 },
  49. { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
  50. };
  51. static DEFINE_MUTEX(qcom_scm_lock);
  52. /**
  53. * struct qcom_scm_command - one SCM command buffer
  54. * @len: total available memory for command and response
  55. * @buf_offset: start of command buffer
  56. * @resp_hdr_offset: start of response buffer
  57. * @id: command to be executed
  58. * @buf: buffer returned from qcom_scm_get_command_buffer()
  59. *
  60. * An SCM command is laid out in memory as follows:
  61. *
  62. * ------------------- <--- struct qcom_scm_command
  63. * | command header |
  64. * ------------------- <--- qcom_scm_get_command_buffer()
  65. * | command buffer |
  66. * ------------------- <--- struct qcom_scm_response and
  67. * | response header | qcom_scm_command_to_response()
  68. * ------------------- <--- qcom_scm_get_response_buffer()
  69. * | response buffer |
  70. * -------------------
  71. *
  72. * There can be arbitrary padding between the headers and buffers so
  73. * you should always use the appropriate qcom_scm_get_*_buffer() routines
  74. * to access the buffers in a safe manner.
  75. */
  76. struct qcom_scm_command {
  77. __le32 len;
  78. __le32 buf_offset;
  79. __le32 resp_hdr_offset;
  80. __le32 id;
  81. __le32 buf[0];
  82. };
  83. /**
  84. * struct qcom_scm_response - one SCM response buffer
  85. * @len: total available memory for response
  86. * @buf_offset: start of response data relative to start of qcom_scm_response
  87. * @is_complete: indicates if the command has finished processing
  88. */
  89. struct qcom_scm_response {
  90. __le32 len;
  91. __le32 buf_offset;
  92. __le32 is_complete;
  93. };
  94. /**
  95. * alloc_qcom_scm_command() - Allocate an SCM command
  96. * @cmd_size: size of the command buffer
  97. * @resp_size: size of the response buffer
  98. *
  99. * Allocate an SCM command, including enough room for the command
  100. * and response headers as well as the command and response buffers.
  101. *
  102. * Returns a valid &qcom_scm_command on success or %NULL if the allocation fails.
  103. */
  104. static struct qcom_scm_command *alloc_qcom_scm_command(size_t cmd_size, size_t resp_size)
  105. {
  106. struct qcom_scm_command *cmd;
  107. size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) + cmd_size +
  108. resp_size;
  109. u32 offset;
  110. cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
  111. if (cmd) {
  112. cmd->len = cpu_to_le32(len);
  113. offset = offsetof(struct qcom_scm_command, buf);
  114. cmd->buf_offset = cpu_to_le32(offset);
  115. cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
  116. }
  117. return cmd;
  118. }
  119. /**
  120. * free_qcom_scm_command() - Free an SCM command
  121. * @cmd: command to free
  122. *
  123. * Free an SCM command.
  124. */
  125. static inline void free_qcom_scm_command(struct qcom_scm_command *cmd)
  126. {
  127. kfree(cmd);
  128. }
  129. /**
  130. * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response
  131. * @cmd: command
  132. *
  133. * Returns a pointer to a response for a command.
  134. */
  135. static inline struct qcom_scm_response *qcom_scm_command_to_response(
  136. const struct qcom_scm_command *cmd)
  137. {
  138. return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
  139. }
  140. /**
  141. * qcom_scm_get_command_buffer() - Get a pointer to a command buffer
  142. * @cmd: command
  143. *
  144. * Returns a pointer to the command buffer of a command.
  145. */
  146. static inline void *qcom_scm_get_command_buffer(const struct qcom_scm_command *cmd)
  147. {
  148. return (void *)cmd->buf;
  149. }
  150. /**
  151. * qcom_scm_get_response_buffer() - Get a pointer to a response buffer
  152. * @rsp: response
  153. *
  154. * Returns a pointer to a response buffer of a response.
  155. */
  156. static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response *rsp)
  157. {
  158. return (void *)rsp + le32_to_cpu(rsp->buf_offset);
  159. }
  160. static int qcom_scm_remap_error(int err)
  161. {
  162. pr_err("qcom_scm_call failed with error code %d\n", err);
  163. switch (err) {
  164. case QCOM_SCM_ERROR:
  165. return -EIO;
  166. case QCOM_SCM_EINVAL_ADDR:
  167. case QCOM_SCM_EINVAL_ARG:
  168. return -EINVAL;
  169. case QCOM_SCM_EOPNOTSUPP:
  170. return -EOPNOTSUPP;
  171. case QCOM_SCM_ENOMEM:
  172. return -ENOMEM;
  173. }
  174. return -EINVAL;
  175. }
  176. static u32 smc(u32 cmd_addr)
  177. {
  178. int context_id;
  179. register u32 r0 asm("r0") = 1;
  180. register u32 r1 asm("r1") = (u32)&context_id;
  181. register u32 r2 asm("r2") = cmd_addr;
  182. do {
  183. asm volatile(
  184. __asmeq("%0", "r0")
  185. __asmeq("%1", "r0")
  186. __asmeq("%2", "r1")
  187. __asmeq("%3", "r2")
  188. #ifdef REQUIRES_SEC
  189. ".arch_extension sec\n"
  190. #endif
  191. "smc #0 @ switch to secure world\n"
  192. : "=r" (r0)
  193. : "r" (r0), "r" (r1), "r" (r2)
  194. : "r3");
  195. } while (r0 == QCOM_SCM_INTERRUPTED);
  196. return r0;
  197. }
  198. static int __qcom_scm_call(const struct qcom_scm_command *cmd)
  199. {
  200. int ret;
  201. u32 cmd_addr = virt_to_phys(cmd);
  202. /*
  203. * Flush the command buffer so that the secure world sees
  204. * the correct data.
  205. */
  206. __cpuc_flush_dcache_area((void *)cmd, cmd->len);
  207. outer_flush_range(cmd_addr, cmd_addr + cmd->len);
  208. ret = smc(cmd_addr);
  209. if (ret < 0)
  210. ret = qcom_scm_remap_error(ret);
  211. return ret;
  212. }
  213. static void qcom_scm_inv_range(unsigned long start, unsigned long end)
  214. {
  215. u32 cacheline_size, ctr;
  216. asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
  217. cacheline_size = 4 << ((ctr >> 16) & 0xf);
  218. start = round_down(start, cacheline_size);
  219. end = round_up(end, cacheline_size);
  220. outer_inv_range(start, end);
  221. while (start < end) {
  222. asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
  223. : "memory");
  224. start += cacheline_size;
  225. }
  226. dsb();
  227. isb();
  228. }
  229. /**
  230. * qcom_scm_call() - Send an SCM command
  231. * @svc_id: service identifier
  232. * @cmd_id: command identifier
  233. * @cmd_buf: command buffer
  234. * @cmd_len: length of the command buffer
  235. * @resp_buf: response buffer
  236. * @resp_len: length of the response buffer
  237. *
  238. * Sends a command to the SCM and waits for the command to finish processing.
  239. *
  240. * A note on cache maintenance:
  241. * Note that any buffers that are expected to be accessed by the secure world
  242. * must be flushed before invoking qcom_scm_call and invalidated in the cache
  243. * immediately after qcom_scm_call returns. Cache maintenance on the command
  244. * and response buffers is taken care of by qcom_scm_call; however, callers are
  245. * responsible for any other cached buffers passed over to the secure world.
  246. */
  247. static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf,
  248. size_t cmd_len, void *resp_buf, size_t resp_len)
  249. {
  250. int ret;
  251. struct qcom_scm_command *cmd;
  252. struct qcom_scm_response *rsp;
  253. unsigned long start, end;
  254. cmd = alloc_qcom_scm_command(cmd_len, resp_len);
  255. if (!cmd)
  256. return -ENOMEM;
  257. cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
  258. if (cmd_buf)
  259. memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
  260. mutex_lock(&qcom_scm_lock);
  261. ret = __qcom_scm_call(cmd);
  262. mutex_unlock(&qcom_scm_lock);
  263. if (ret)
  264. goto out;
  265. rsp = qcom_scm_command_to_response(cmd);
  266. start = (unsigned long)rsp;
  267. do {
  268. qcom_scm_inv_range(start, start + sizeof(*rsp));
  269. } while (!rsp->is_complete);
  270. end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len;
  271. qcom_scm_inv_range(start, end);
  272. if (resp_buf)
  273. memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len);
  274. out:
  275. free_qcom_scm_command(cmd);
  276. return ret;
  277. }
  278. #define SCM_CLASS_REGISTER (0x2 << 8)
  279. #define SCM_MASK_IRQS BIT(5)
  280. #define SCM_ATOMIC(svc, cmd, n) (((((svc) << 10)|((cmd) & 0x3ff)) << 12) | \
  281. SCM_CLASS_REGISTER | \
  282. SCM_MASK_IRQS | \
  283. (n & 0xf))
  284. /**
  285. * qcom_scm_call_atomic1() - Send an atomic SCM command with one argument
  286. * @svc_id: service identifier
  287. * @cmd_id: command identifier
  288. * @arg1: first argument
  289. *
  290. * This shall only be used with commands that are guaranteed to be
  291. * uninterruptable, atomic and SMP safe.
  292. */
  293. static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
  294. {
  295. int context_id;
  296. register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 1);
  297. register u32 r1 asm("r1") = (u32)&context_id;
  298. register u32 r2 asm("r2") = arg1;
  299. asm volatile(
  300. __asmeq("%0", "r0")
  301. __asmeq("%1", "r0")
  302. __asmeq("%2", "r1")
  303. __asmeq("%3", "r2")
  304. #ifdef REQUIRES_SEC
  305. ".arch_extension sec\n"
  306. #endif
  307. "smc #0 @ switch to secure world\n"
  308. : "=r" (r0)
  309. : "r" (r0), "r" (r1), "r" (r2)
  310. : "r3");
  311. return r0;
  312. }
  313. u32 qcom_scm_get_version(void)
  314. {
  315. int context_id;
  316. static u32 version = -1;
  317. register u32 r0 asm("r0");
  318. register u32 r1 asm("r1");
  319. if (version != -1)
  320. return version;
  321. mutex_lock(&qcom_scm_lock);
  322. r0 = 0x1 << 8;
  323. r1 = (u32)&context_id;
  324. do {
  325. asm volatile(
  326. __asmeq("%0", "r0")
  327. __asmeq("%1", "r1")
  328. __asmeq("%2", "r0")
  329. __asmeq("%3", "r1")
  330. #ifdef REQUIRES_SEC
  331. ".arch_extension sec\n"
  332. #endif
  333. "smc #0 @ switch to secure world\n"
  334. : "=r" (r0), "=r" (r1)
  335. : "r" (r0), "r" (r1)
  336. : "r2", "r3");
  337. } while (r0 == QCOM_SCM_INTERRUPTED);
  338. version = r1;
  339. mutex_unlock(&qcom_scm_lock);
  340. return version;
  341. }
  342. EXPORT_SYMBOL(qcom_scm_get_version);
  343. #define QCOM_SCM_SVC_BOOT 0x1
  344. #define QCOM_SCM_BOOT_ADDR 0x1
  345. /*
  346. * Set the cold/warm boot address for one of the CPU cores.
  347. */
  348. static int qcom_scm_set_boot_addr(u32 addr, int flags)
  349. {
  350. struct {
  351. __le32 flags;
  352. __le32 addr;
  353. } cmd;
  354. cmd.addr = cpu_to_le32(addr);
  355. cmd.flags = cpu_to_le32(flags);
  356. return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
  357. &cmd, sizeof(cmd), NULL, 0);
  358. }
  359. /**
  360. * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
  361. * @entry: Entry point function for the cpus
  362. * @cpus: The cpumask of cpus that will use the entry point
  363. *
  364. * Set the cold boot address of the cpus. Any cpu outside the supported
  365. * range would be removed from the cpu present mask.
  366. */
  367. int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
  368. {
  369. int flags = 0;
  370. int cpu;
  371. int scm_cb_flags[] = {
  372. QCOM_SCM_FLAG_COLDBOOT_CPU0,
  373. QCOM_SCM_FLAG_COLDBOOT_CPU1,
  374. QCOM_SCM_FLAG_COLDBOOT_CPU2,
  375. QCOM_SCM_FLAG_COLDBOOT_CPU3,
  376. };
  377. if (!cpus || (cpus && cpumask_empty(cpus)))
  378. return -EINVAL;
  379. for_each_cpu(cpu, cpus) {
  380. if (cpu < ARRAY_SIZE(scm_cb_flags))
  381. flags |= scm_cb_flags[cpu];
  382. else
  383. set_cpu_present(cpu, false);
  384. }
  385. return qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
  386. }
  387. EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
  388. /**
  389. * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
  390. * @entry: Entry point function for the cpus
  391. * @cpus: The cpumask of cpus that will use the entry point
  392. *
  393. * Set the Linux entry point for the SCM to transfer control to when coming
  394. * out of a power down. CPU power down may be executed on cpuidle or hotplug.
  395. */
  396. int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
  397. {
  398. int ret;
  399. int flags = 0;
  400. int cpu;
  401. /*
  402. * Reassign only if we are switching from hotplug entry point
  403. * to cpuidle entry point or vice versa.
  404. */
  405. for_each_cpu(cpu, cpus) {
  406. if (entry == qcom_scm_wb[cpu].entry)
  407. continue;
  408. flags |= qcom_scm_wb[cpu].flag;
  409. }
  410. /* No change in entry function */
  411. if (!flags)
  412. return 0;
  413. ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
  414. if (!ret) {
  415. for_each_cpu(cpu, cpus)
  416. qcom_scm_wb[cpu].entry = entry;
  417. }
  418. return ret;
  419. }
  420. EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
  421. #define QCOM_SCM_CMD_TERMINATE_PC 0x2
  422. #define QCOM_SCM_FLUSH_FLAG_MASK 0x3
  423. /**
  424. * qcom_scm_cpu_power_down() - Power down the cpu
  425. * @flags - Flags to flush cache
  426. *
  427. * This is an end point to power down cpu. If there was a pending interrupt,
  428. * the control would return from this function, otherwise, the cpu jumps to the
  429. * warm boot entry point set for this cpu upon reset.
  430. */
  431. void qcom_scm_cpu_power_down(u32 flags)
  432. {
  433. qcom_scm_call_atomic1(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC,
  434. flags & QCOM_SCM_FLUSH_FLAG_MASK);
  435. }
  436. EXPORT_SYMBOL(qcom_scm_cpu_power_down);