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 29 #include "qcom_scm.h" 30 31 struct qcom_scm { 32 struct device *dev; 33 struct clk *core_clk; 34 struct clk *iface_clk; 35 struct clk *bus_clk; 36 struct reset_controller_dev reset; 37 }; 38 39 static struct qcom_scm *__scm; 40 41 static int qcom_scm_clk_enable(void) 42 { 43 int ret; 44 45 ret = clk_prepare_enable(__scm->core_clk); 46 if (ret) 47 goto bail; 48 49 ret = clk_prepare_enable(__scm->iface_clk); 50 if (ret) 51 goto disable_core; 52 53 ret = clk_prepare_enable(__scm->bus_clk); 54 if (ret) 55 goto disable_iface; 56 57 return 0; 58 59 disable_iface: 60 clk_disable_unprepare(__scm->iface_clk); 61 disable_core: 62 clk_disable_unprepare(__scm->core_clk); 63 bail: 64 return ret; 65 } 66 67 static void qcom_scm_clk_disable(void) 68 { 69 clk_disable_unprepare(__scm->core_clk); 70 clk_disable_unprepare(__scm->iface_clk); 71 clk_disable_unprepare(__scm->bus_clk); 72 } 73 74 /** 75 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus 76 * @entry: Entry point function for the cpus 77 * @cpus: The cpumask of cpus that will use the entry point 78 * 79 * Set the cold boot address of the cpus. Any cpu outside the supported 80 * range would be removed from the cpu present mask. 81 */ 82 int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus) 83 { 84 return __qcom_scm_set_cold_boot_addr(entry, cpus); 85 } 86 EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr); 87 88 /** 89 * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus 90 * @entry: Entry point function for the cpus 91 * @cpus: The cpumask of cpus that will use the entry point 92 * 93 * Set the Linux entry point for the SCM to transfer control to when coming 94 * out of a power down. CPU power down may be executed on cpuidle or hotplug. 95 */ 96 int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) 97 { 98 return __qcom_scm_set_warm_boot_addr(__scm->dev, entry, cpus); 99 } 100 EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); 101 102 /** 103 * qcom_scm_cpu_power_down() - Power down the cpu 104 * @flags - Flags to flush cache 105 * 106 * This is an end point to power down cpu. If there was a pending interrupt, 107 * the control would return from this function, otherwise, the cpu jumps to the 108 * warm boot entry point set for this cpu upon reset. 109 */ 110 void qcom_scm_cpu_power_down(u32 flags) 111 { 112 __qcom_scm_cpu_power_down(flags); 113 } 114 EXPORT_SYMBOL(qcom_scm_cpu_power_down); 115 116 /** 117 * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. 118 * 119 * Return true if HDCP is supported, false if not. 120 */ 121 bool qcom_scm_hdcp_available(void) 122 { 123 int ret = qcom_scm_clk_enable(); 124 125 if (ret) 126 return ret; 127 128 ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP, 129 QCOM_SCM_CMD_HDCP); 130 131 qcom_scm_clk_disable(); 132 133 return ret > 0 ? true : false; 134 } 135 EXPORT_SYMBOL(qcom_scm_hdcp_available); 136 137 /** 138 * qcom_scm_hdcp_req() - Send HDCP request. 139 * @req: HDCP request array 140 * @req_cnt: HDCP request array count 141 * @resp: response buffer passed to SCM 142 * 143 * Write HDCP register(s) through SCM. 144 */ 145 int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) 146 { 147 int ret = qcom_scm_clk_enable(); 148 149 if (ret) 150 return ret; 151 152 ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp); 153 qcom_scm_clk_disable(); 154 return ret; 155 } 156 EXPORT_SYMBOL(qcom_scm_hdcp_req); 157 158 /** 159 * qcom_scm_pas_supported() - Check if the peripheral authentication service is 160 * available for the given peripherial 161 * @peripheral: peripheral id 162 * 163 * Returns true if PAS is supported for this peripheral, otherwise false. 164 */ 165 bool qcom_scm_pas_supported(u32 peripheral) 166 { 167 int ret; 168 169 ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL, 170 QCOM_SCM_PAS_IS_SUPPORTED_CMD); 171 if (ret <= 0) 172 return false; 173 174 return __qcom_scm_pas_supported(__scm->dev, peripheral); 175 } 176 EXPORT_SYMBOL(qcom_scm_pas_supported); 177 178 /** 179 * qcom_scm_pas_init_image() - Initialize peripheral authentication service 180 * state machine for a given peripheral, using the 181 * metadata 182 * @peripheral: peripheral id 183 * @metadata: pointer to memory containing ELF header, program header table 184 * and optional blob of data used for authenticating the metadata 185 * and the rest of the firmware 186 * @size: size of the metadata 187 * 188 * Returns 0 on success. 189 */ 190 int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) 191 { 192 dma_addr_t mdata_phys; 193 void *mdata_buf; 194 int ret; 195 196 /* 197 * During the scm call memory protection will be enabled for the meta 198 * data blob, so make sure it's physically contiguous, 4K aligned and 199 * non-cachable to avoid XPU violations. 200 */ 201 mdata_buf = dma_alloc_coherent(__scm->dev, size, &mdata_phys, 202 GFP_KERNEL); 203 if (!mdata_buf) { 204 dev_err(__scm->dev, "Allocation of metadata buffer failed.\n"); 205 return -ENOMEM; 206 } 207 memcpy(mdata_buf, metadata, size); 208 209 ret = qcom_scm_clk_enable(); 210 if (ret) 211 goto free_metadata; 212 213 ret = __qcom_scm_pas_init_image(__scm->dev, peripheral, mdata_phys); 214 215 qcom_scm_clk_disable(); 216 217 free_metadata: 218 dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys); 219 220 return ret; 221 } 222 EXPORT_SYMBOL(qcom_scm_pas_init_image); 223 224 /** 225 * qcom_scm_pas_mem_setup() - Prepare the memory related to a given peripheral 226 * for firmware loading 227 * @peripheral: peripheral id 228 * @addr: start address of memory area to prepare 229 * @size: size of the memory area to prepare 230 * 231 * Returns 0 on success. 232 */ 233 int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size) 234 { 235 int ret; 236 237 ret = qcom_scm_clk_enable(); 238 if (ret) 239 return ret; 240 241 ret = __qcom_scm_pas_mem_setup(__scm->dev, peripheral, addr, size); 242 qcom_scm_clk_disable(); 243 244 return ret; 245 } 246 EXPORT_SYMBOL(qcom_scm_pas_mem_setup); 247 248 /** 249 * qcom_scm_pas_auth_and_reset() - Authenticate the given peripheral firmware 250 * and reset the remote processor 251 * @peripheral: peripheral id 252 * 253 * Return 0 on success. 254 */ 255 int qcom_scm_pas_auth_and_reset(u32 peripheral) 256 { 257 int ret; 258 259 ret = qcom_scm_clk_enable(); 260 if (ret) 261 return ret; 262 263 ret = __qcom_scm_pas_auth_and_reset(__scm->dev, peripheral); 264 qcom_scm_clk_disable(); 265 266 return ret; 267 } 268 EXPORT_SYMBOL(qcom_scm_pas_auth_and_reset); 269 270 /** 271 * qcom_scm_pas_shutdown() - Shut down the remote processor 272 * @peripheral: peripheral id 273 * 274 * Returns 0 on success. 275 */ 276 int qcom_scm_pas_shutdown(u32 peripheral) 277 { 278 int ret; 279 280 ret = qcom_scm_clk_enable(); 281 if (ret) 282 return ret; 283 284 ret = __qcom_scm_pas_shutdown(__scm->dev, peripheral); 285 qcom_scm_clk_disable(); 286 287 return ret; 288 } 289 EXPORT_SYMBOL(qcom_scm_pas_shutdown); 290 291 static int qcom_scm_pas_reset_assert(struct reset_controller_dev *rcdev, 292 unsigned long idx) 293 { 294 if (idx != 0) 295 return -EINVAL; 296 297 return __qcom_scm_pas_mss_reset(__scm->dev, 1); 298 } 299 300 static int qcom_scm_pas_reset_deassert(struct reset_controller_dev *rcdev, 301 unsigned long idx) 302 { 303 if (idx != 0) 304 return -EINVAL; 305 306 return __qcom_scm_pas_mss_reset(__scm->dev, 0); 307 } 308 309 static const struct reset_control_ops qcom_scm_pas_reset_ops = { 310 .assert = qcom_scm_pas_reset_assert, 311 .deassert = qcom_scm_pas_reset_deassert, 312 }; 313 314 /** 315 * qcom_scm_is_available() - Checks if SCM is available 316 */ 317 bool qcom_scm_is_available(void) 318 { 319 return !!__scm; 320 } 321 EXPORT_SYMBOL(qcom_scm_is_available); 322 323 static int qcom_scm_probe(struct platform_device *pdev) 324 { 325 struct qcom_scm *scm; 326 int ret; 327 328 scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL); 329 if (!scm) 330 return -ENOMEM; 331 332 scm->core_clk = devm_clk_get(&pdev->dev, "core"); 333 if (IS_ERR(scm->core_clk)) { 334 if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER) 335 return PTR_ERR(scm->core_clk); 336 337 scm->core_clk = NULL; 338 } 339 340 if (of_device_is_compatible(pdev->dev.of_node, "qcom,scm")) { 341 scm->iface_clk = devm_clk_get(&pdev->dev, "iface"); 342 if (IS_ERR(scm->iface_clk)) { 343 if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER) 344 dev_err(&pdev->dev, "failed to acquire iface clk\n"); 345 return PTR_ERR(scm->iface_clk); 346 } 347 348 scm->bus_clk = devm_clk_get(&pdev->dev, "bus"); 349 if (IS_ERR(scm->bus_clk)) { 350 if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER) 351 dev_err(&pdev->dev, "failed to acquire bus clk\n"); 352 return PTR_ERR(scm->bus_clk); 353 } 354 } 355 356 scm->reset.ops = &qcom_scm_pas_reset_ops; 357 scm->reset.nr_resets = 1; 358 scm->reset.of_node = pdev->dev.of_node; 359 reset_controller_register(&scm->reset); 360 361 /* vote for max clk rate for highest performance */ 362 ret = clk_set_rate(scm->core_clk, INT_MAX); 363 if (ret) 364 return ret; 365 366 __scm = scm; 367 __scm->dev = &pdev->dev; 368 369 __qcom_scm_init(); 370 371 return 0; 372 } 373 374 static const struct of_device_id qcom_scm_dt_match[] = { 375 { .compatible = "qcom,scm-apq8064",}, 376 { .compatible = "qcom,scm-msm8660",}, 377 { .compatible = "qcom,scm-msm8960",}, 378 { .compatible = "qcom,scm",}, 379 {} 380 }; 381 382 static struct platform_driver qcom_scm_driver = { 383 .driver = { 384 .name = "qcom_scm", 385 .of_match_table = qcom_scm_dt_match, 386 }, 387 .probe = qcom_scm_probe, 388 }; 389 390 static int __init qcom_scm_init(void) 391 { 392 struct device_node *np, *fw_np; 393 int ret; 394 395 fw_np = of_find_node_by_name(NULL, "firmware"); 396 397 if (!fw_np) 398 return -ENODEV; 399 400 np = of_find_matching_node(fw_np, qcom_scm_dt_match); 401 402 if (!np) { 403 of_node_put(fw_np); 404 return -ENODEV; 405 } 406 407 of_node_put(np); 408 409 ret = of_platform_populate(fw_np, qcom_scm_dt_match, NULL, NULL); 410 411 of_node_put(fw_np); 412 413 if (ret) 414 return ret; 415 416 return platform_driver_register(&qcom_scm_driver); 417 } 418 subsys_initcall(qcom_scm_init); 419