bootrom.c 2.6 KB

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