bootrom.c 2.6 KB

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