tegra_sip_calls.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  3. * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: BSD-3-Clause
  6. */
  7. #include <assert.h>
  8. #include <errno.h>
  9. #include <arch.h>
  10. #include <arch_helpers.h>
  11. #include <common/bl_common.h>
  12. #include <common/debug.h>
  13. #include <common/runtime_svc.h>
  14. #include <lib/mmio.h>
  15. #include <memctrl.h>
  16. #include <tegra_platform.h>
  17. #include <tegra_private.h>
  18. /*******************************************************************************
  19. * Common Tegra SiP SMCs
  20. ******************************************************************************/
  21. #define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003
  22. #define TEGRA_SIP_FIQ_NS_ENTRYPOINT 0x82000005
  23. #define TEGRA_SIP_FIQ_NS_GET_CONTEXT 0x82000006
  24. /*******************************************************************************
  25. * This function is responsible for handling all SiP calls
  26. ******************************************************************************/
  27. uintptr_t tegra_sip_handler(uint32_t smc_fid,
  28. u_register_t x1,
  29. u_register_t x2,
  30. u_register_t x3,
  31. u_register_t x4,
  32. void *cookie,
  33. void *handle,
  34. u_register_t flags)
  35. {
  36. uint32_t regval, local_x2_32 = (uint32_t)x2;
  37. int32_t err;
  38. /* Check if this is a SoC specific SiP */
  39. err = plat_sip_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
  40. if (err == 0) {
  41. SMC_RET1(handle, (uint64_t)err);
  42. } else {
  43. switch (smc_fid) {
  44. case TEGRA_SIP_NEW_VIDEOMEM_REGION:
  45. /* Check whether Video memory resize is enabled */
  46. if (mmio_read_32(TEGRA_MC_BASE + MC_VIDEO_PROTECT_REG_CTRL)
  47. != MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED) {
  48. ERROR("Video Memory Resize isn't enabled! \n");
  49. SMC_RET1(handle, (uint64_t)-ENOTSUP);
  50. }
  51. /*
  52. * Check if Video Memory overlaps TZDRAM (contains bl31/bl32)
  53. * or falls outside of the valid DRAM range
  54. */
  55. err = bl31_check_ns_address(x1, local_x2_32);
  56. if (err != 0) {
  57. SMC_RET1(handle, (uint64_t)err);
  58. }
  59. /*
  60. * Check if Video Memory is aligned to 1MB.
  61. */
  62. if (((x1 & 0xFFFFFU) != 0U) || ((local_x2_32 & 0xFFFFFU) != 0U)) {
  63. ERROR("Unaligned Video Memory base address!\n");
  64. SMC_RET1(handle, (uint64_t)-ENOTSUP);
  65. }
  66. /*
  67. * The GPU is the user of the Video Memory region. In order to
  68. * transition to the new memory region smoothly, we program the
  69. * new base/size ONLY if the GPU is in reset mode.
  70. */
  71. regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
  72. TEGRA_GPU_RESET_REG_OFFSET);
  73. if ((regval & GPU_RESET_BIT) == 0U) {
  74. ERROR("GPU not in reset! Video Memory setup failed\n");
  75. SMC_RET1(handle, (uint64_t)-ENOTSUP);
  76. }
  77. /* new video memory carveout settings */
  78. tegra_memctrl_videomem_setup(x1, local_x2_32);
  79. /*
  80. * Ensure again that GPU is still in reset after VPR resize
  81. */
  82. regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
  83. TEGRA_GPU_RESET_REG_OFFSET);
  84. if ((regval & GPU_RESET_BIT) == 0U) {
  85. mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_GPU_SET_OFFSET,
  86. GPU_SET_BIT);
  87. }
  88. SMC_RET1(handle, 0);
  89. /*
  90. * The NS world registers the address of its handler to be
  91. * used for processing the FIQ. This is normally used by the
  92. * NS FIQ debugger driver to detect system hangs by programming
  93. * a watchdog timer to fire a FIQ interrupt.
  94. */
  95. case TEGRA_SIP_FIQ_NS_ENTRYPOINT:
  96. if (x1 == 0U) {
  97. SMC_RET1(handle, SMC_UNK);
  98. }
  99. /*
  100. * TODO: Check if x1 contains a valid DRAM address
  101. */
  102. /* store the NS world's entrypoint */
  103. tegra_fiq_set_ns_entrypoint(x1);
  104. SMC_RET1(handle, 0);
  105. /*
  106. * The NS world's FIQ handler issues this SMC to get the NS EL1/EL0
  107. * CPU context when the FIQ interrupt was triggered. This allows the
  108. * NS world to understand the CPU state when the watchdog interrupt
  109. * triggered.
  110. */
  111. case TEGRA_SIP_FIQ_NS_GET_CONTEXT:
  112. /* retrieve context registers when FIQ triggered */
  113. (void)tegra_fiq_get_intr_context();
  114. SMC_RET0(handle);
  115. default:
  116. ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
  117. break;
  118. }
  119. }
  120. SMC_RET1(handle, SMC_UNK);
  121. }
  122. /* Define a runtime service descriptor for fast SMC calls */
  123. DECLARE_RT_SVC(
  124. tegra_sip_fast,
  125. (OEN_SIP_START),
  126. (OEN_SIP_END),
  127. (SMC_TYPE_FAST),
  128. (NULL),
  129. (tegra_sip_handler)
  130. );