tzc_dmc620.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <common/debug.h>
  8. #include <drivers/arm/tzc_dmc620.h>
  9. #include <lib/mmio.h>
  10. /* Mask to extract bit 31 to 16 */
  11. #define MASK_31_16 UINT64_C(0x0000ffff0000)
  12. /* Mask to extract bit 47 to 32 */
  13. #define MASK_47_32 UINT64_C(0xffff00000000)
  14. /* Helper macro for getting dmc_base addr of a dmc_inst */
  15. #define DMC_BASE(plat_data, dmc_inst) \
  16. ((uintptr_t)((plat_data)->dmc_base[(dmc_inst)]))
  17. /* Pointer to the tzc_dmc620_config_data structure populated by the platform */
  18. static const tzc_dmc620_config_data_t *g_plat_config_data;
  19. #if ENABLE_ASSERTIONS
  20. /*
  21. * Helper function to check if the DMC-620 instance is present at the
  22. * base address provided by the platform and also check if at least
  23. * one dmc instance is present.
  24. */
  25. static void tzc_dmc620_validate_plat_driver_data(
  26. const tzc_dmc620_driver_data_t *plat_driver_data)
  27. {
  28. unsigned int dmc_inst, dmc_count, dmc_id;
  29. uintptr_t base;
  30. assert(plat_driver_data != NULL);
  31. dmc_count = plat_driver_data->dmc_count;
  32. assert(dmc_count > 0U);
  33. for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
  34. base = DMC_BASE(plat_driver_data, dmc_inst);
  35. dmc_id = mmio_read_32(base + DMC620_PERIPHERAL_ID_0);
  36. assert(dmc_id == DMC620_PERIPHERAL_ID_0_VALUE);
  37. }
  38. }
  39. #endif
  40. /*
  41. * Program a region with region base and region top addresses of all
  42. * DMC-620 instances.
  43. */
  44. static void tzc_dmc620_configure_region(int region_no,
  45. unsigned long long region_base,
  46. unsigned long long region_top,
  47. unsigned int sec_attr)
  48. {
  49. uint32_t min_31_00, min_47_32;
  50. uint32_t max_31_00, max_47_32;
  51. unsigned int dmc_inst, dmc_count;
  52. uintptr_t base;
  53. const tzc_dmc620_driver_data_t *plat_driver_data;
  54. plat_driver_data = g_plat_config_data->plat_drv_data;
  55. assert(plat_driver_data != NULL);
  56. /* Do range checks on regions. */
  57. assert((region_no >= 0) && (region_no <= DMC620_ACC_ADDR_COUNT));
  58. /* region_base and (region_top + 1) must be 4KB aligned */
  59. assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U);
  60. dmc_count = plat_driver_data->dmc_count;
  61. for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
  62. min_31_00 = (uint32_t)((region_base & MASK_31_16) | sec_attr);
  63. min_47_32 = (uint32_t)((region_base & MASK_47_32)
  64. >> DMC620_ACC_ADDR_WIDTH);
  65. max_31_00 = (uint32_t)(region_top & MASK_31_16);
  66. max_47_32 = (uint32_t)((region_top & MASK_47_32)
  67. >> DMC620_ACC_ADDR_WIDTH);
  68. /* Extract the base address of the DMC-620 instance */
  69. base = DMC_BASE(plat_driver_data, dmc_inst);
  70. /* Configure access address region registers */
  71. mmio_write_32(base + DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no),
  72. min_31_00);
  73. mmio_write_32(base + DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no),
  74. min_47_32);
  75. mmio_write_32(base + DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no),
  76. max_31_00);
  77. mmio_write_32(base + DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no),
  78. max_47_32);
  79. }
  80. }
  81. /*
  82. * Set the action value for all the DMC-620 instances.
  83. */
  84. static void tzc_dmc620_set_action(void)
  85. {
  86. unsigned int dmc_inst, dmc_count;
  87. uintptr_t base;
  88. const tzc_dmc620_driver_data_t *plat_driver_data;
  89. plat_driver_data = g_plat_config_data->plat_drv_data;
  90. dmc_count = plat_driver_data->dmc_count;
  91. for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
  92. /* Extract the base address of the DMC-620 instance */
  93. base = DMC_BASE(plat_driver_data, dmc_inst);
  94. /* Switch to READY */
  95. mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_GO);
  96. mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_EXECUTE);
  97. }
  98. }
  99. /*
  100. * Verify whether the DMC-620 configuration is complete by reading back
  101. * configuration registers and comparing it with the configured value. If
  102. * configuration is incomplete, loop till the configured value is reflected in
  103. * the register.
  104. */
  105. static void tzc_dmc620_verify_complete(void)
  106. {
  107. unsigned int dmc_inst, dmc_count;
  108. uintptr_t base;
  109. const tzc_dmc620_driver_data_t *plat_driver_data;
  110. plat_driver_data = g_plat_config_data->plat_drv_data;
  111. dmc_count = plat_driver_data->dmc_count;
  112. for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
  113. /* Extract the base address of the DMC-620 instance */
  114. base = DMC_BASE(plat_driver_data, dmc_inst);
  115. while ((mmio_read_32(base + DMC620_MEMC_STATUS) &
  116. DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO) {
  117. continue;
  118. }
  119. }
  120. }
  121. /*
  122. * Initialize the DMC-620 TrustZone Controller using the region configuration
  123. * supplied by the platform. The DMC620 controller should be enabled elsewhere
  124. * before invoking this function.
  125. */
  126. void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data)
  127. {
  128. uint8_t i;
  129. /* Check if valid pointer is passed */
  130. assert(plat_config_data != NULL);
  131. /*
  132. * Check if access address count passed by the platform is less than or
  133. * equal to DMC620's access address count
  134. */
  135. assert(plat_config_data->acc_addr_count <= DMC620_ACC_ADDR_COUNT);
  136. #if ENABLE_ASSERTIONS
  137. /* Validates the information passed by platform */
  138. tzc_dmc620_validate_plat_driver_data(plat_config_data->plat_drv_data);
  139. #endif
  140. g_plat_config_data = plat_config_data;
  141. INFO("Configuring DMC-620 TZC settings\n");
  142. for (i = 0U; i < g_plat_config_data->acc_addr_count; i++) {
  143. tzc_dmc620_configure_region(i,
  144. g_plat_config_data->plat_acc_addr_data[i].region_base,
  145. g_plat_config_data->plat_acc_addr_data[i].region_top,
  146. g_plat_config_data->plat_acc_addr_data[i].sec_attr);
  147. }
  148. tzc_dmc620_set_action();
  149. tzc_dmc620_verify_complete();
  150. INFO("DMC-620 TZC setup completed\n");
  151. }