mss_bl2_setup.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * Copyright (C) 2018 Marvell International Ltd.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. * https://spdx.org/licenses
  6. */
  7. #include <platform_def.h>
  8. #include <common/bl_common.h>
  9. #include <common/debug.h>
  10. #include <drivers/marvell/ccu.h>
  11. #include <drivers/marvell/mochi/ap_setup.h>
  12. #include <drivers/marvell/mochi/cp110_setup.h>
  13. #include <lib/mmio.h>
  14. #include <armada_common.h>
  15. #include <marvell_plat_priv.h> /* timer functionality */
  16. #include "mss_defs.h"
  17. #include "mss_scp_bootloader.h"
  18. /* MSS windows configuration */
  19. #define MSS_AEBR(base) (base + 0x160)
  20. #define MSS_AIBR(base) (base + 0x164)
  21. #define MSS_AEBR_MASK 0xFFF
  22. #define MSS_AIBR_MASK 0xFFF
  23. #define MSS_EXTERNAL_SPACE 0x50000000
  24. #define MSS_EXTERNAL_ACCESS_BIT 28
  25. #define MSS_EXTERNAL_ADDR_MASK 0xfffffff
  26. #define MSS_INTERNAL_ACCESS_BIT 28
  27. struct addr_map_win ccu_mem_map[] = {
  28. {MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID}
  29. };
  30. /* Since the scp_bl2 image can contain firmware for cp1 and cp0 coprocessors,
  31. * the access to cp0 and cp1 need to be provided. More precisely it is
  32. * required to:
  33. * - get the information about device id which is stored in CP0 registers
  34. * (to distinguish between cases where we have cp0 and cp1 or standalone cp0)
  35. * - get the access to cp which is needed for loading fw for cp0/cp1
  36. * coprocessors
  37. * This function configures ccu windows accordingly.
  38. *
  39. * Note: there is no need to restore previous ccu configuration, since in next
  40. * phase (BL31) the init_ccu will be called (via apn806_init/
  41. * bl31_plat_arch_setu) and therefore the ccu configuration will be overwritten.
  42. */
  43. static int bl2_plat_mmap_init(void)
  44. {
  45. int cfg_num, win_id, cfg_idx, cp;
  46. cfg_num = ARRAY_SIZE(ccu_mem_map);
  47. /* CCU window-0 should not be counted - it's already used */
  48. if (cfg_num > (MVEBU_CCU_MAX_WINS - 1)) {
  49. ERROR("BL2: %s: trying to open too many windows\n", __func__);
  50. return -1;
  51. }
  52. /* Enable required CCU windows
  53. * Do not touch CCU window 0,
  54. * it's used for the internal registers access
  55. */
  56. for (cfg_idx = 0, win_id = 1;
  57. (win_id < MVEBU_CCU_MAX_WINS) && (cfg_idx < cfg_num); win_id++) {
  58. /* Skip already enabled CCU windows */
  59. if (ccu_is_win_enabled(MVEBU_AP0, win_id))
  60. continue;
  61. /* Enable required CCU windows */
  62. ccu_win_check(&ccu_mem_map[cfg_idx]);
  63. ccu_enable_win(MVEBU_AP0, &ccu_mem_map[cfg_idx], win_id);
  64. cfg_idx++;
  65. }
  66. /* Config address for each cp other than cp0 */
  67. for (cp = 1; cp < CP_COUNT; cp++)
  68. update_cp110_default_win(cp);
  69. /* There is need to configure IO_WIN windows again to overwrite
  70. * temporary configuration done during update_cp110_default_win
  71. */
  72. init_io_win(MVEBU_AP0);
  73. /* Open AMB bridge required for MG access */
  74. for (cp = 0; cp < CP_COUNT; cp++)
  75. cp110_amb_init(MVEBU_CP_REGS_BASE(cp));
  76. return 0;
  77. }
  78. /*****************************************************************************
  79. * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
  80. * Return 0 on success, -1 otherwise.
  81. *****************************************************************************
  82. */
  83. int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
  84. {
  85. int ret;
  86. INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
  87. /* initialize time (for delay functionality) */
  88. plat_delay_timer_init();
  89. ret = bl2_plat_mmap_init();
  90. if (ret != 0)
  91. return ret;
  92. ret = scp_bootloader_transfer((void *)scp_bl2_image_info->image_base,
  93. scp_bl2_image_info->image_size);
  94. if (ret == 0)
  95. INFO("BL2: SCP_BL2 transferred to SCP\n");
  96. else
  97. ERROR("BL2: SCP_BL2 transfer failure\n");
  98. return ret;
  99. }
  100. uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx)
  101. {
  102. return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_REGS_OFFSET;
  103. }
  104. uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx)
  105. {
  106. return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_SRAM_OFFSET;
  107. }
  108. uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
  109. {
  110. return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET;
  111. }
  112. uint32_t bl2_plat_get_cp_count(int ap_idx)
  113. {
  114. uint32_t revision = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
  115. /* A8040: two CPs.
  116. * A7040: one CP.
  117. */
  118. if (revision == MVEBU_80X0_DEV_ID ||
  119. revision == MVEBU_80X0_CP115_DEV_ID)
  120. return 2;
  121. else if (revision == MVEBU_CN9130_DEV_ID)
  122. return CP_COUNT;
  123. else
  124. return 1;
  125. }
  126. uint32_t bl2_plat_get_ap_count(void)
  127. {
  128. /* A8040 and A7040 have only one AP */
  129. return 1;
  130. }
  131. void bl2_plat_configure_mss_windows(uintptr_t mss_regs)
  132. {
  133. /* set AXI External and Internal Address Bus extension */
  134. mmio_write_32(MSS_AEBR(mss_regs),
  135. ((0x0 >> MSS_EXTERNAL_ACCESS_BIT) & MSS_AEBR_MASK));
  136. mmio_write_32(MSS_AIBR(mss_regs),
  137. ((mss_regs >> MSS_INTERNAL_ACCESS_BIT) & MSS_AIBR_MASK));
  138. }