qcom_scm.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*
  2. * Qualcomm SCM driver
  3. *
  4. * Copyright (c) 2010,2015, The Linux Foundation. All rights reserved.
  5. * Copyright (C) 2015 Linaro Ltd.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 and
  9. * only version 2 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. */
  17. #include <linux/platform_device.h>
  18. #include <linux/init.h>
  19. #include <linux/cpumask.h>
  20. #include <linux/export.h>
  21. #include <linux/dma-mapping.h>
  22. #include <linux/types.h>
  23. #include <linux/qcom_scm.h>
  24. #include <linux/of.h>
  25. #include <linux/of_platform.h>
  26. #include <linux/clk.h>
  27. #include <linux/reset-controller.h>
  28. #include "qcom_scm.h"
  29. struct qcom_scm {
  30. struct device *dev;
  31. struct clk *core_clk;
  32. struct clk *iface_clk;
  33. struct clk *bus_clk;
  34. struct reset_controller_dev reset;
  35. };
  36. static struct qcom_scm *__scm;
  37. static int qcom_scm_clk_enable(void)
  38. {
  39. int ret;
  40. ret = clk_prepare_enable(__scm->core_clk);
  41. if (ret)
  42. goto bail;
  43. ret = clk_prepare_enable(__scm->iface_clk);
  44. if (ret)
  45. goto disable_core;
  46. ret = clk_prepare_enable(__scm->bus_clk);
  47. if (ret)
  48. goto disable_iface;
  49. return 0;
  50. disable_iface:
  51. clk_disable_unprepare(__scm->iface_clk);
  52. disable_core:
  53. clk_disable_unprepare(__scm->core_clk);
  54. bail:
  55. return ret;
  56. }
  57. static void qcom_scm_clk_disable(void)
  58. {
  59. clk_disable_unprepare(__scm->core_clk);
  60. clk_disable_unprepare(__scm->iface_clk);
  61. clk_disable_unprepare(__scm->bus_clk);
  62. }
  63. /**
  64. * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
  65. * @entry: Entry point function for the cpus
  66. * @cpus: The cpumask of cpus that will use the entry point
  67. *
  68. * Set the cold boot address of the cpus. Any cpu outside the supported
  69. * range would be removed from the cpu present mask.
  70. */
  71. int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
  72. {
  73. return __qcom_scm_set_cold_boot_addr(entry, cpus);
  74. }
  75. EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
  76. /**
  77. * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
  78. * @entry: Entry point function for the cpus
  79. * @cpus: The cpumask of cpus that will use the entry point
  80. *
  81. * Set the Linux entry point for the SCM to transfer control to when coming
  82. * out of a power down. CPU power down may be executed on cpuidle or hotplug.
  83. */
  84. int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
  85. {
  86. return __qcom_scm_set_warm_boot_addr(__scm->dev, entry, cpus);
  87. }
  88. EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
  89. /**
  90. * qcom_scm_cpu_power_down() - Power down the cpu
  91. * @flags - Flags to flush cache
  92. *
  93. * This is an end point to power down cpu. If there was a pending interrupt,
  94. * the control would return from this function, otherwise, the cpu jumps to the
  95. * warm boot entry point set for this cpu upon reset.
  96. */
  97. void qcom_scm_cpu_power_down(u32 flags)
  98. {
  99. __qcom_scm_cpu_power_down(flags);
  100. }
  101. EXPORT_SYMBOL(qcom_scm_cpu_power_down);
  102. /**
  103. * qcom_scm_hdcp_available() - Check if secure environment supports HDCP.
  104. *
  105. * Return true if HDCP is supported, false if not.
  106. */
  107. bool qcom_scm_hdcp_available(void)
  108. {
  109. int ret = qcom_scm_clk_enable();
  110. if (ret)
  111. return ret;
  112. ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP,
  113. QCOM_SCM_CMD_HDCP);
  114. qcom_scm_clk_disable();
  115. return ret > 0 ? true : false;
  116. }
  117. EXPORT_SYMBOL(qcom_scm_hdcp_available);
  118. /**
  119. * qcom_scm_hdcp_req() - Send HDCP request.
  120. * @req: HDCP request array
  121. * @req_cnt: HDCP request array count
  122. * @resp: response buffer passed to SCM
  123. *
  124. * Write HDCP register(s) through SCM.
  125. */
  126. int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
  127. {
  128. int ret = qcom_scm_clk_enable();
  129. if (ret)
  130. return ret;
  131. ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp);
  132. qcom_scm_clk_disable();
  133. return ret;
  134. }
  135. EXPORT_SYMBOL(qcom_scm_hdcp_req);
  136. /**
  137. * qcom_scm_pas_supported() - Check if the peripheral authentication service is
  138. * available for the given peripherial
  139. * @peripheral: peripheral id
  140. *
  141. * Returns true if PAS is supported for this peripheral, otherwise false.
  142. */
  143. bool qcom_scm_pas_supported(u32 peripheral)
  144. {
  145. int ret;
  146. ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
  147. QCOM_SCM_PAS_IS_SUPPORTED_CMD);
  148. if (ret <= 0)
  149. return false;
  150. return __qcom_scm_pas_supported(__scm->dev, peripheral);
  151. }
  152. EXPORT_SYMBOL(qcom_scm_pas_supported);
  153. /**
  154. * qcom_scm_pas_init_image() - Initialize peripheral authentication service
  155. * state machine for a given peripheral, using the
  156. * metadata
  157. * @peripheral: peripheral id
  158. * @metadata: pointer to memory containing ELF header, program header table
  159. * and optional blob of data used for authenticating the metadata
  160. * and the rest of the firmware
  161. * @size: size of the metadata
  162. *
  163. * Returns 0 on success.
  164. */
  165. int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
  166. {
  167. dma_addr_t mdata_phys;
  168. void *mdata_buf;
  169. int ret;
  170. /*
  171. * During the scm call memory protection will be enabled for the meta
  172. * data blob, so make sure it's physically contiguous, 4K aligned and
  173. * non-cachable to avoid XPU violations.
  174. */
  175. mdata_buf = dma_alloc_coherent(__scm->dev, size, &mdata_phys,
  176. GFP_KERNEL);
  177. if (!mdata_buf) {
  178. dev_err(__scm->dev, "Allocation of metadata buffer failed.\n");
  179. return -ENOMEM;
  180. }
  181. memcpy(mdata_buf, metadata, size);
  182. ret = qcom_scm_clk_enable();
  183. if (ret)
  184. goto free_metadata;
  185. ret = __qcom_scm_pas_init_image(__scm->dev, peripheral, mdata_phys);
  186. qcom_scm_clk_disable();
  187. free_metadata:
  188. dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
  189. return ret;
  190. }
  191. EXPORT_SYMBOL(qcom_scm_pas_init_image);
  192. /**
  193. * qcom_scm_pas_mem_setup() - Prepare the memory related to a given peripheral
  194. * for firmware loading
  195. * @peripheral: peripheral id
  196. * @addr: start address of memory area to prepare
  197. * @size: size of the memory area to prepare
  198. *
  199. * Returns 0 on success.
  200. */
  201. int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
  202. {
  203. int ret;
  204. ret = qcom_scm_clk_enable();
  205. if (ret)
  206. return ret;
  207. ret = __qcom_scm_pas_mem_setup(__scm->dev, peripheral, addr, size);
  208. qcom_scm_clk_disable();
  209. return ret;
  210. }
  211. EXPORT_SYMBOL(qcom_scm_pas_mem_setup);
  212. /**
  213. * qcom_scm_pas_auth_and_reset() - Authenticate the given peripheral firmware
  214. * and reset the remote processor
  215. * @peripheral: peripheral id
  216. *
  217. * Return 0 on success.
  218. */
  219. int qcom_scm_pas_auth_and_reset(u32 peripheral)
  220. {
  221. int ret;
  222. ret = qcom_scm_clk_enable();
  223. if (ret)
  224. return ret;
  225. ret = __qcom_scm_pas_auth_and_reset(__scm->dev, peripheral);
  226. qcom_scm_clk_disable();
  227. return ret;
  228. }
  229. EXPORT_SYMBOL(qcom_scm_pas_auth_and_reset);
  230. /**
  231. * qcom_scm_pas_shutdown() - Shut down the remote processor
  232. * @peripheral: peripheral id
  233. *
  234. * Returns 0 on success.
  235. */
  236. int qcom_scm_pas_shutdown(u32 peripheral)
  237. {
  238. int ret;
  239. ret = qcom_scm_clk_enable();
  240. if (ret)
  241. return ret;
  242. ret = __qcom_scm_pas_shutdown(__scm->dev, peripheral);
  243. qcom_scm_clk_disable();
  244. return ret;
  245. }
  246. EXPORT_SYMBOL(qcom_scm_pas_shutdown);
  247. static int qcom_scm_pas_reset_assert(struct reset_controller_dev *rcdev,
  248. unsigned long idx)
  249. {
  250. if (idx != 0)
  251. return -EINVAL;
  252. return __qcom_scm_pas_mss_reset(__scm->dev, 1);
  253. }
  254. static int qcom_scm_pas_reset_deassert(struct reset_controller_dev *rcdev,
  255. unsigned long idx)
  256. {
  257. if (idx != 0)
  258. return -EINVAL;
  259. return __qcom_scm_pas_mss_reset(__scm->dev, 0);
  260. }
  261. static const struct reset_control_ops qcom_scm_pas_reset_ops = {
  262. .assert = qcom_scm_pas_reset_assert,
  263. .deassert = qcom_scm_pas_reset_deassert,
  264. };
  265. /**
  266. * qcom_scm_is_available() - Checks if SCM is available
  267. */
  268. bool qcom_scm_is_available(void)
  269. {
  270. return !!__scm;
  271. }
  272. EXPORT_SYMBOL(qcom_scm_is_available);
  273. static int qcom_scm_probe(struct platform_device *pdev)
  274. {
  275. struct qcom_scm *scm;
  276. int ret;
  277. scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL);
  278. if (!scm)
  279. return -ENOMEM;
  280. scm->core_clk = devm_clk_get(&pdev->dev, "core");
  281. if (IS_ERR(scm->core_clk)) {
  282. if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER)
  283. return PTR_ERR(scm->core_clk);
  284. scm->core_clk = NULL;
  285. }
  286. if (of_device_is_compatible(pdev->dev.of_node, "qcom,scm")) {
  287. scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
  288. if (IS_ERR(scm->iface_clk)) {
  289. if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER)
  290. dev_err(&pdev->dev, "failed to acquire iface clk\n");
  291. return PTR_ERR(scm->iface_clk);
  292. }
  293. scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
  294. if (IS_ERR(scm->bus_clk)) {
  295. if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER)
  296. dev_err(&pdev->dev, "failed to acquire bus clk\n");
  297. return PTR_ERR(scm->bus_clk);
  298. }
  299. }
  300. scm->reset.ops = &qcom_scm_pas_reset_ops;
  301. scm->reset.nr_resets = 1;
  302. scm->reset.of_node = pdev->dev.of_node;
  303. reset_controller_register(&scm->reset);
  304. /* vote for max clk rate for highest performance */
  305. ret = clk_set_rate(scm->core_clk, INT_MAX);
  306. if (ret)
  307. return ret;
  308. __scm = scm;
  309. __scm->dev = &pdev->dev;
  310. __qcom_scm_init();
  311. return 0;
  312. }
  313. static const struct of_device_id qcom_scm_dt_match[] = {
  314. { .compatible = "qcom,scm-apq8064",},
  315. { .compatible = "qcom,scm-msm8660",},
  316. { .compatible = "qcom,scm-msm8960",},
  317. { .compatible = "qcom,scm",},
  318. {}
  319. };
  320. static struct platform_driver qcom_scm_driver = {
  321. .driver = {
  322. .name = "qcom_scm",
  323. .of_match_table = qcom_scm_dt_match,
  324. },
  325. .probe = qcom_scm_probe,
  326. };
  327. static int __init qcom_scm_init(void)
  328. {
  329. struct device_node *np, *fw_np;
  330. int ret;
  331. fw_np = of_find_node_by_name(NULL, "firmware");
  332. if (!fw_np)
  333. return -ENODEV;
  334. np = of_find_matching_node(fw_np, qcom_scm_dt_match);
  335. if (!np) {
  336. of_node_put(fw_np);
  337. return -ENODEV;
  338. }
  339. of_node_put(np);
  340. ret = of_platform_populate(fw_np, qcom_scm_dt_match, NULL, NULL);
  341. of_node_put(fw_np);
  342. if (ret)
  343. return ret;
  344. return platform_driver_register(&qcom_scm_driver);
  345. }
  346. subsys_initcall(qcom_scm_init);