root/drivers/firmware/qcom_scm-64.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. qcom_scm_call
  2. __qcom_scm_set_cold_boot_addr
  3. __qcom_scm_set_warm_boot_addr
  4. __qcom_scm_cpu_power_down
  5. __qcom_scm_is_call_available
  6. __qcom_scm_hdcp_req
  7. __qcom_scm_init
  8. __qcom_scm_pas_supported
  9. __qcom_scm_pas_init_image
  10. __qcom_scm_pas_mem_setup
  11. __qcom_scm_pas_auth_and_reset
  12. __qcom_scm_pas_shutdown
  13. __qcom_scm_pas_mss_reset
  14. __qcom_scm_set_remote_state
  15. __qcom_scm_assign_mem
  16. __qcom_scm_restore_sec_cfg
  17. __qcom_scm_iommu_secure_ptbl_size
  18. __qcom_scm_iommu_secure_ptbl_init
  19. __qcom_scm_set_dload_mode
  20. __qcom_scm_io_readl
  21. __qcom_scm_io_writel

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
   3  */
   4 
   5 #include <linux/io.h>
   6 #include <linux/errno.h>
   7 #include <linux/delay.h>
   8 #include <linux/mutex.h>
   9 #include <linux/slab.h>
  10 #include <linux/types.h>
  11 #include <linux/qcom_scm.h>
  12 #include <linux/arm-smccc.h>
  13 #include <linux/dma-mapping.h>
  14 
  15 #include "qcom_scm.h"
  16 
  17 #define QCOM_SCM_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF))
  18 
  19 #define MAX_QCOM_SCM_ARGS 10
  20 #define MAX_QCOM_SCM_RETS 3
  21 
  22 enum qcom_scm_arg_types {
  23         QCOM_SCM_VAL,
  24         QCOM_SCM_RO,
  25         QCOM_SCM_RW,
  26         QCOM_SCM_BUFVAL,
  27 };
  28 
  29 #define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
  30                            (((a) & 0x3) << 4) | \
  31                            (((b) & 0x3) << 6) | \
  32                            (((c) & 0x3) << 8) | \
  33                            (((d) & 0x3) << 10) | \
  34                            (((e) & 0x3) << 12) | \
  35                            (((f) & 0x3) << 14) | \
  36                            (((g) & 0x3) << 16) | \
  37                            (((h) & 0x3) << 18) | \
  38                            (((i) & 0x3) << 20) | \
  39                            (((j) & 0x3) << 22) | \
  40                            ((num) & 0xf))
  41 
  42 #define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
  43 
  44 /**
  45  * struct qcom_scm_desc
  46  * @arginfo:    Metadata describing the arguments in args[]
  47  * @args:       The array of arguments for the secure syscall
  48  * @res:        The values returned by the secure syscall
  49  */
  50 struct qcom_scm_desc {
  51         u32 arginfo;
  52         u64 args[MAX_QCOM_SCM_ARGS];
  53 };
  54 
  55 static u64 qcom_smccc_convention = -1;
  56 static DEFINE_MUTEX(qcom_scm_lock);
  57 
  58 #define QCOM_SCM_EBUSY_WAIT_MS 30
  59 #define QCOM_SCM_EBUSY_MAX_RETRY 20
  60 
  61 #define N_EXT_QCOM_SCM_ARGS 7
  62 #define FIRST_EXT_ARG_IDX 3
  63 #define N_REGISTER_ARGS (MAX_QCOM_SCM_ARGS - N_EXT_QCOM_SCM_ARGS + 1)
  64 
  65 /**
  66  * qcom_scm_call() - Invoke a syscall in the secure world
  67  * @dev:        device
  68  * @svc_id:     service identifier
  69  * @cmd_id:     command identifier
  70  * @desc:       Descriptor structure containing arguments and return values
  71  *
  72  * Sends a command to the SCM and waits for the command to finish processing.
  73  * This should *only* be called in pre-emptible context.
  74 */
  75 static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
  76                          const struct qcom_scm_desc *desc,
  77                          struct arm_smccc_res *res)
  78 {
  79         int arglen = desc->arginfo & 0xf;
  80         int retry_count = 0, i;
  81         u32 fn_id = QCOM_SCM_FNID(svc_id, cmd_id);
  82         u64 cmd, x5 = desc->args[FIRST_EXT_ARG_IDX];
  83         dma_addr_t args_phys = 0;
  84         void *args_virt = NULL;
  85         size_t alloc_len;
  86         struct arm_smccc_quirk quirk = {.id = ARM_SMCCC_QUIRK_QCOM_A6};
  87 
  88         if (unlikely(arglen > N_REGISTER_ARGS)) {
  89                 alloc_len = N_EXT_QCOM_SCM_ARGS * sizeof(u64);
  90                 args_virt = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
  91 
  92                 if (!args_virt)
  93                         return -ENOMEM;
  94 
  95                 if (qcom_smccc_convention == ARM_SMCCC_SMC_32) {
  96                         __le32 *args = args_virt;
  97 
  98                         for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
  99                                 args[i] = cpu_to_le32(desc->args[i +
 100                                                       FIRST_EXT_ARG_IDX]);
 101                 } else {
 102                         __le64 *args = args_virt;
 103 
 104                         for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
 105                                 args[i] = cpu_to_le64(desc->args[i +
 106                                                       FIRST_EXT_ARG_IDX]);
 107                 }
 108 
 109                 args_phys = dma_map_single(dev, args_virt, alloc_len,
 110                                            DMA_TO_DEVICE);
 111 
 112                 if (dma_mapping_error(dev, args_phys)) {
 113                         kfree(args_virt);
 114                         return -ENOMEM;
 115                 }
 116 
 117                 x5 = args_phys;
 118         }
 119 
 120         do {
 121                 mutex_lock(&qcom_scm_lock);
 122 
 123                 cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL,
 124                                          qcom_smccc_convention,
 125                                          ARM_SMCCC_OWNER_SIP, fn_id);
 126 
 127                 quirk.state.a6 = 0;
 128 
 129                 do {
 130                         arm_smccc_smc_quirk(cmd, desc->arginfo, desc->args[0],
 131                                       desc->args[1], desc->args[2], x5,
 132                                       quirk.state.a6, 0, res, &quirk);
 133 
 134                         if (res->a0 == QCOM_SCM_INTERRUPTED)
 135                                 cmd = res->a0;
 136 
 137                 } while (res->a0 == QCOM_SCM_INTERRUPTED);
 138 
 139                 mutex_unlock(&qcom_scm_lock);
 140 
 141                 if (res->a0 == QCOM_SCM_V2_EBUSY) {
 142                         if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
 143                                 break;
 144                         msleep(QCOM_SCM_EBUSY_WAIT_MS);
 145                 }
 146         }  while (res->a0 == QCOM_SCM_V2_EBUSY);
 147 
 148         if (args_virt) {
 149                 dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
 150                 kfree(args_virt);
 151         }
 152 
 153         if ((long)res->a0 < 0)
 154                 return qcom_scm_remap_error(res->a0);
 155 
 156         return 0;
 157 }
 158 
 159 /**
 160  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
 161  * @entry: Entry point function for the cpus
 162  * @cpus: The cpumask of cpus that will use the entry point
 163  *
 164  * Set the cold boot address of the cpus. Any cpu outside the supported
 165  * range would be removed from the cpu present mask.
 166  */
 167 int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
 168 {
 169         return -ENOTSUPP;
 170 }
 171 
 172 /**
 173  * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
 174  * @dev: Device pointer
 175  * @entry: Entry point function for the cpus
 176  * @cpus: The cpumask of cpus that will use the entry point
 177  *
 178  * Set the Linux entry point for the SCM to transfer control to when coming
 179  * out of a power down. CPU power down may be executed on cpuidle or hotplug.
 180  */
 181 int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
 182                                   const cpumask_t *cpus)
 183 {
 184         return -ENOTSUPP;
 185 }
 186 
 187 /**
 188  * qcom_scm_cpu_power_down() - Power down the cpu
 189  * @flags - Flags to flush cache
 190  *
 191  * This is an end point to power down cpu. If there was a pending interrupt,
 192  * the control would return from this function, otherwise, the cpu jumps to the
 193  * warm boot entry point set for this cpu upon reset.
 194  */
 195 void __qcom_scm_cpu_power_down(u32 flags)
 196 {
 197 }
 198 
 199 int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
 200 {
 201         int ret;
 202         struct qcom_scm_desc desc = {0};
 203         struct arm_smccc_res res;
 204 
 205         desc.arginfo = QCOM_SCM_ARGS(1);
 206         desc.args[0] = QCOM_SCM_FNID(svc_id, cmd_id) |
 207                         (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT);
 208 
 209         ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
 210                             &desc, &res);
 211 
 212         return ret ? : res.a1;
 213 }
 214 
 215 int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
 216                         u32 req_cnt, u32 *resp)
 217 {
 218         int ret;
 219         struct qcom_scm_desc desc = {0};
 220         struct arm_smccc_res res;
 221 
 222         if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
 223                 return -ERANGE;
 224 
 225         desc.args[0] = req[0].addr;
 226         desc.args[1] = req[0].val;
 227         desc.args[2] = req[1].addr;
 228         desc.args[3] = req[1].val;
 229         desc.args[4] = req[2].addr;
 230         desc.args[5] = req[2].val;
 231         desc.args[6] = req[3].addr;
 232         desc.args[7] = req[3].val;
 233         desc.args[8] = req[4].addr;
 234         desc.args[9] = req[4].val;
 235         desc.arginfo = QCOM_SCM_ARGS(10);
 236 
 237         ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, &desc,
 238                             &res);
 239         *resp = res.a1;
 240 
 241         return ret;
 242 }
 243 
 244 void __qcom_scm_init(void)
 245 {
 246         u64 cmd;
 247         struct arm_smccc_res res;
 248         u32 function = QCOM_SCM_FNID(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD);
 249 
 250         /* First try a SMC64 call */
 251         cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64,
 252                                  ARM_SMCCC_OWNER_SIP, function);
 253 
 254         arm_smccc_smc(cmd, QCOM_SCM_ARGS(1), cmd & (~BIT(ARM_SMCCC_TYPE_SHIFT)),
 255                       0, 0, 0, 0, 0, &res);
 256 
 257         if (!res.a0 && res.a1)
 258                 qcom_smccc_convention = ARM_SMCCC_SMC_64;
 259         else
 260                 qcom_smccc_convention = ARM_SMCCC_SMC_32;
 261 }
 262 
 263 bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral)
 264 {
 265         int ret;
 266         struct qcom_scm_desc desc = {0};
 267         struct arm_smccc_res res;
 268 
 269         desc.args[0] = peripheral;
 270         desc.arginfo = QCOM_SCM_ARGS(1);
 271 
 272         ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
 273                                 QCOM_SCM_PAS_IS_SUPPORTED_CMD,
 274                                 &desc, &res);
 275 
 276         return ret ? false : !!res.a1;
 277 }
 278 
 279 int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
 280                               dma_addr_t metadata_phys)
 281 {
 282         int ret;
 283         struct qcom_scm_desc desc = {0};
 284         struct arm_smccc_res res;
 285 
 286         desc.args[0] = peripheral;
 287         desc.args[1] = metadata_phys;
 288         desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW);
 289 
 290         ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD,
 291                                 &desc, &res);
 292 
 293         return ret ? : res.a1;
 294 }
 295 
 296 int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
 297                               phys_addr_t addr, phys_addr_t size)
 298 {
 299         int ret;
 300         struct qcom_scm_desc desc = {0};
 301         struct arm_smccc_res res;
 302 
 303         desc.args[0] = peripheral;
 304         desc.args[1] = addr;
 305         desc.args[2] = size;
 306         desc.arginfo = QCOM_SCM_ARGS(3);
 307 
 308         ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MEM_SETUP_CMD,
 309                                 &desc, &res);
 310 
 311         return ret ? : res.a1;
 312 }
 313 
 314 int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral)
 315 {
 316         int ret;
 317         struct qcom_scm_desc desc = {0};
 318         struct arm_smccc_res res;
 319 
 320         desc.args[0] = peripheral;
 321         desc.arginfo = QCOM_SCM_ARGS(1);
 322 
 323         ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
 324                                 QCOM_SCM_PAS_AUTH_AND_RESET_CMD,
 325                                 &desc, &res);
 326 
 327         return ret ? : res.a1;
 328 }
 329 
 330 int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral)
 331 {
 332         int ret;
 333         struct qcom_scm_desc desc = {0};
 334         struct arm_smccc_res res;
 335 
 336         desc.args[0] = peripheral;
 337         desc.arginfo = QCOM_SCM_ARGS(1);
 338 
 339         ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_SHUTDOWN_CMD,
 340                         &desc, &res);
 341 
 342         return ret ? : res.a1;
 343 }
 344 
 345 int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
 346 {
 347         struct qcom_scm_desc desc = {0};
 348         struct arm_smccc_res res;
 349         int ret;
 350 
 351         desc.args[0] = reset;
 352         desc.args[1] = 0;
 353         desc.arginfo = QCOM_SCM_ARGS(2);
 354 
 355         ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MSS_RESET, &desc,
 356                             &res);
 357 
 358         return ret ? : res.a1;
 359 }
 360 
 361 int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
 362 {
 363         struct qcom_scm_desc desc = {0};
 364         struct arm_smccc_res res;
 365         int ret;
 366 
 367         desc.args[0] = state;
 368         desc.args[1] = id;
 369         desc.arginfo = QCOM_SCM_ARGS(2);
 370 
 371         ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_REMOTE_STATE,
 372                             &desc, &res);
 373 
 374         return ret ? : res.a1;
 375 }
 376 
 377 int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region,
 378                           size_t mem_sz, phys_addr_t src, size_t src_sz,
 379                           phys_addr_t dest, size_t dest_sz)
 380 {
 381         int ret;
 382         struct qcom_scm_desc desc = {0};
 383         struct arm_smccc_res res;
 384 
 385         desc.args[0] = mem_region;
 386         desc.args[1] = mem_sz;
 387         desc.args[2] = src;
 388         desc.args[3] = src_sz;
 389         desc.args[4] = dest;
 390         desc.args[5] = dest_sz;
 391         desc.args[6] = 0;
 392 
 393         desc.arginfo = QCOM_SCM_ARGS(7, QCOM_SCM_RO, QCOM_SCM_VAL,
 394                                      QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_RO,
 395                                      QCOM_SCM_VAL, QCOM_SCM_VAL);
 396 
 397         ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
 398                             QCOM_MEM_PROT_ASSIGN_ID,
 399                             &desc, &res);
 400 
 401         return ret ? : res.a1;
 402 }
 403 
 404 int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare)
 405 {
 406         struct qcom_scm_desc desc = {0};
 407         struct arm_smccc_res res;
 408         int ret;
 409 
 410         desc.args[0] = device_id;
 411         desc.args[1] = spare;
 412         desc.arginfo = QCOM_SCM_ARGS(2);
 413 
 414         ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, QCOM_SCM_RESTORE_SEC_CFG,
 415                             &desc, &res);
 416 
 417         return ret ? : res.a1;
 418 }
 419 
 420 int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
 421                                       size_t *size)
 422 {
 423         struct qcom_scm_desc desc = {0};
 424         struct arm_smccc_res res;
 425         int ret;
 426 
 427         desc.args[0] = spare;
 428         desc.arginfo = QCOM_SCM_ARGS(1);
 429 
 430         ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
 431                             QCOM_SCM_IOMMU_SECURE_PTBL_SIZE, &desc, &res);
 432 
 433         if (size)
 434                 *size = res.a1;
 435 
 436         return ret ? : res.a2;
 437 }
 438 
 439 int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
 440                                       u32 spare)
 441 {
 442         struct qcom_scm_desc desc = {0};
 443         struct arm_smccc_res res;
 444         int ret;
 445 
 446         desc.args[0] = addr;
 447         desc.args[1] = size;
 448         desc.args[2] = spare;
 449         desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
 450                                      QCOM_SCM_VAL);
 451 
 452         ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
 453                             QCOM_SCM_IOMMU_SECURE_PTBL_INIT, &desc, &res);
 454 
 455         /* the pg table has been initialized already, ignore the error */
 456         if (ret == -EPERM)
 457                 ret = 0;
 458 
 459         return ret;
 460 }
 461 
 462 int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
 463 {
 464         struct qcom_scm_desc desc = {0};
 465         struct arm_smccc_res res;
 466 
 467         desc.args[0] = QCOM_SCM_SET_DLOAD_MODE;
 468         desc.args[1] = enable ? QCOM_SCM_SET_DLOAD_MODE : 0;
 469         desc.arginfo = QCOM_SCM_ARGS(2);
 470 
 471         return qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_SET_DLOAD_MODE,
 472                              &desc, &res);
 473 }
 474 
 475 int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr,
 476                         unsigned int *val)
 477 {
 478         struct qcom_scm_desc desc = {0};
 479         struct arm_smccc_res res;
 480         int ret;
 481 
 482         desc.args[0] = addr;
 483         desc.arginfo = QCOM_SCM_ARGS(1);
 484 
 485         ret = qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_READ,
 486                             &desc, &res);
 487         if (ret >= 0)
 488                 *val = res.a1;
 489 
 490         return ret < 0 ? ret : 0;
 491 }
 492 
 493 int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val)
 494 {
 495         struct qcom_scm_desc desc = {0};
 496         struct arm_smccc_res res;
 497 
 498         desc.args[0] = addr;
 499         desc.args[1] = val;
 500         desc.arginfo = QCOM_SCM_ARGS(2);
 501 
 502         return qcom_scm_call(dev, QCOM_SCM_SVC_IO, QCOM_SCM_IO_WRITE,
 503                              &desc, &res);
 504 }

/* [<][>][^][v][top][bottom][index][help] */