bootrom.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /**
  3. * Copyright (c) 2017 Google, Inc
  4. */
  5. #include <common.h>
  6. #include <asm/arch/bootrom.h>
  7. #include <asm/arch/boot_mode.h>
  8. #include <asm/io.h>
  9. #include <asm/setjmp.h>
  10. #include <asm/system.h>
  11. /*
  12. * Force the jmp_buf to the data-section, as .bss will not be valid
  13. * when save_boot_params is invoked.
  14. */
  15. static jmp_buf brom_ctx __section(".data");
  16. static void _back_to_bootrom(enum rockchip_bootrom_cmd brom_cmd)
  17. {
  18. longjmp(brom_ctx, brom_cmd);
  19. }
  20. void back_to_bootrom(enum rockchip_bootrom_cmd brom_cmd)
  21. {
  22. #if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT)
  23. puts("Returning to boot ROM...\n");
  24. #endif
  25. _back_to_bootrom(brom_cmd);
  26. }
  27. /*
  28. * we back to bootrom download mode if get a
  29. * BOOT_BROM_DOWNLOAD flag in boot mode register
  30. *
  31. * note: the boot mode register is configured by
  32. * application(next stage bootloader, kernel, etc),
  33. * and the bootrom never check this register, so we need
  34. * to check it and back to bootrom at very early bootstage(before
  35. * some basic configurations(such as interrupts) been
  36. * changed by TPL/SPL, as the bootrom download operation
  37. * relys on many default settings(such as interrupts) by
  38. * it's self.
  39. */
  40. static bool check_back_to_brom_dnl_flag(void)
  41. {
  42. u32 boot_mode;
  43. if (CONFIG_ROCKCHIP_BOOT_MODE_REG) {
  44. boot_mode = readl(CONFIG_ROCKCHIP_BOOT_MODE_REG);
  45. if (boot_mode == BOOT_BROM_DOWNLOAD) {
  46. writel(0, CONFIG_ROCKCHIP_BOOT_MODE_REG);
  47. return true;
  48. }
  49. }
  50. return false;
  51. }
  52. /*
  53. * All Rockchip BROM implementations enter with a valid stack-pointer,
  54. * so this can safely be implemented in C (providing a single
  55. * implementation both for ARMv7 and AArch64).
  56. */
  57. int save_boot_params(void)
  58. {
  59. int ret = setjmp(brom_ctx);
  60. switch (ret) {
  61. case 0:
  62. if (check_back_to_brom_dnl_flag())
  63. _back_to_bootrom(BROM_BOOT_ENTER_DNL);
  64. /*
  65. * This is the initial pass through this function
  66. * (i.e. saving the context), setjmp just setup up the
  67. * brom_ctx: transfer back into the startup-code at
  68. * 'save_boot_params_ret' and let the compiler know
  69. * that this will not return.
  70. */
  71. save_boot_params_ret();
  72. while (true)
  73. /* does not return */;
  74. break;
  75. case BROM_BOOT_NEXTSTAGE:
  76. /*
  77. * To instruct the BROM to boot the next stage, we
  78. * need to return 0 to it: i.e. we need to rewrite
  79. * the return code once more.
  80. */
  81. ret = 0;
  82. break;
  83. case BROM_BOOT_ENTER_DNL:
  84. /*
  85. * A non-zero return value will instruct the BROM enter
  86. * download mode.
  87. */
  88. ret = 1;
  89. break;
  90. default:
  91. #if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT)
  92. puts("FATAL: unexpected command to back_to_bootrom()\n");
  93. #endif
  94. hang();
  95. };
  96. return ret;
  97. }