boot-device.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2015-2017 Socionext Inc.
  4. * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  5. */
  6. #include <common.h>
  7. #include <spl.h>
  8. #include <stdio.h>
  9. #include <linux/log2.h>
  10. #include "../init.h"
  11. #include "../sbc/sbc-regs.h"
  12. #include "../sg-regs.h"
  13. #include "../soc-info.h"
  14. #include "boot-device.h"
  15. struct uniphier_boot_device_info {
  16. unsigned int soc_id;
  17. unsigned int boot_device_sel_shift;
  18. const struct uniphier_boot_device *boot_device_table;
  19. const unsigned int *boot_device_count;
  20. int (*boot_device_is_usb)(u32 pinmon);
  21. unsigned int (*boot_device_fixup)(unsigned int mode);
  22. int have_internal_stm;
  23. };
  24. static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
  25. #if defined(CONFIG_ARCH_UNIPHIER_LD4)
  26. {
  27. .soc_id = UNIPHIER_LD4_ID,
  28. .boot_device_sel_shift = 1,
  29. .boot_device_table = uniphier_ld4_boot_device_table,
  30. .boot_device_count = &uniphier_ld4_boot_device_count,
  31. .have_internal_stm = 1,
  32. },
  33. #endif
  34. #if defined(CONFIG_ARCH_UNIPHIER_PRO4)
  35. {
  36. .soc_id = UNIPHIER_PRO4_ID,
  37. .boot_device_sel_shift = 1,
  38. .boot_device_table = uniphier_ld4_boot_device_table,
  39. .boot_device_count = &uniphier_ld4_boot_device_count,
  40. .have_internal_stm = 0,
  41. },
  42. #endif
  43. #if defined(CONFIG_ARCH_UNIPHIER_SLD8)
  44. {
  45. .soc_id = UNIPHIER_SLD8_ID,
  46. .boot_device_sel_shift = 1,
  47. .boot_device_table = uniphier_ld4_boot_device_table,
  48. .boot_device_count = &uniphier_ld4_boot_device_count,
  49. .have_internal_stm = 1,
  50. },
  51. #endif
  52. #if defined(CONFIG_ARCH_UNIPHIER_PRO5)
  53. {
  54. .soc_id = UNIPHIER_PRO5_ID,
  55. .boot_device_sel_shift = 1,
  56. .boot_device_table = uniphier_pro5_boot_device_table,
  57. .boot_device_count = &uniphier_pro5_boot_device_count,
  58. .have_internal_stm = 0,
  59. },
  60. #endif
  61. #if defined(CONFIG_ARCH_UNIPHIER_PXS2)
  62. {
  63. .soc_id = UNIPHIER_PXS2_ID,
  64. .boot_device_sel_shift = 1,
  65. .boot_device_table = uniphier_pxs2_boot_device_table,
  66. .boot_device_count = &uniphier_pxs2_boot_device_count,
  67. .boot_device_is_usb = uniphier_pxs2_boot_device_is_usb,
  68. .boot_device_fixup = uniphier_pxs2_boot_device_fixup,
  69. .have_internal_stm = 0,
  70. },
  71. #endif
  72. #if defined(CONFIG_ARCH_UNIPHIER_LD6B)
  73. {
  74. .soc_id = UNIPHIER_LD6B_ID,
  75. .boot_device_sel_shift = 1,
  76. .boot_device_table = uniphier_pxs2_boot_device_table,
  77. .boot_device_count = &uniphier_pxs2_boot_device_count,
  78. .boot_device_is_usb = uniphier_pxs2_boot_device_is_usb,
  79. .boot_device_fixup = uniphier_pxs2_boot_device_fixup,
  80. .have_internal_stm = 1, /* STM on A-chip */
  81. },
  82. #endif
  83. #if defined(CONFIG_ARCH_UNIPHIER_LD11)
  84. {
  85. .soc_id = UNIPHIER_LD11_ID,
  86. .boot_device_sel_shift = 1,
  87. .boot_device_table = uniphier_ld11_boot_device_table,
  88. .boot_device_count = &uniphier_ld11_boot_device_count,
  89. .boot_device_is_usb = uniphier_ld11_boot_device_is_usb,
  90. .boot_device_fixup = uniphier_ld11_boot_device_fixup,
  91. .have_internal_stm = 1,
  92. },
  93. #endif
  94. #if defined(CONFIG_ARCH_UNIPHIER_LD20)
  95. {
  96. .soc_id = UNIPHIER_LD20_ID,
  97. .boot_device_sel_shift = 1,
  98. .boot_device_table = uniphier_ld11_boot_device_table,
  99. .boot_device_count = &uniphier_ld11_boot_device_count,
  100. .boot_device_is_usb = uniphier_ld20_boot_device_is_usb,
  101. .boot_device_fixup = uniphier_ld11_boot_device_fixup,
  102. .have_internal_stm = 1,
  103. },
  104. #endif
  105. #if defined(CONFIG_ARCH_UNIPHIER_PXS3)
  106. {
  107. .soc_id = UNIPHIER_PXS3_ID,
  108. .boot_device_sel_shift = 1,
  109. .boot_device_table = uniphier_pxs3_boot_device_table,
  110. .boot_device_count = &uniphier_pxs3_boot_device_count,
  111. .boot_device_is_usb = uniphier_pxs3_boot_device_is_usb,
  112. .have_internal_stm = 0,
  113. },
  114. #endif
  115. };
  116. UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info,
  117. uniphier_boot_device_info)
  118. static unsigned int __uniphier_boot_device_raw(
  119. const struct uniphier_boot_device_info *info)
  120. {
  121. u32 pinmon;
  122. unsigned int boot_sel;
  123. if (boot_is_swapped())
  124. return BOOT_DEVICE_NOR;
  125. pinmon = readl(SG_PINMON0);
  126. if (info->boot_device_is_usb && info->boot_device_is_usb(pinmon))
  127. return BOOT_DEVICE_USB;
  128. boot_sel = pinmon >> info->boot_device_sel_shift;
  129. BUG_ON(!is_power_of_2(*info->boot_device_count));
  130. boot_sel &= *info->boot_device_count - 1;
  131. return info->boot_device_table[boot_sel].boot_device;
  132. }
  133. unsigned int uniphier_boot_device_raw(void)
  134. {
  135. const struct uniphier_boot_device_info *info;
  136. info = uniphier_get_boot_device_info();
  137. if (!info) {
  138. pr_err("unsupported SoC\n");
  139. return BOOT_DEVICE_NONE;
  140. }
  141. return __uniphier_boot_device_raw(info);
  142. }
  143. u32 spl_boot_device(void)
  144. {
  145. const struct uniphier_boot_device_info *info;
  146. u32 raw_mode;
  147. info = uniphier_get_boot_device_info();
  148. if (!info) {
  149. pr_err("unsupported SoC\n");
  150. return BOOT_DEVICE_NONE;
  151. }
  152. raw_mode = __uniphier_boot_device_raw(info);
  153. return info->boot_device_fixup ?
  154. info->boot_device_fixup(raw_mode) : raw_mode;
  155. }
  156. int uniphier_have_internal_stm(void)
  157. {
  158. const struct uniphier_boot_device_info *info;
  159. info = uniphier_get_boot_device_info();
  160. if (!info) {
  161. pr_err("unsupported SoC\n");
  162. return -ENOTSUPP;
  163. }
  164. return info->have_internal_stm;
  165. }
  166. int uniphier_boot_from_backend(void)
  167. {
  168. return !!(readl(SG_PINMON0) & BIT(27));
  169. }
  170. #ifndef CONFIG_SPL_BUILD
  171. static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  172. {
  173. const struct uniphier_boot_device_info *info;
  174. u32 pinmon;
  175. unsigned int boot_device_count, boot_sel;
  176. int i;
  177. info = uniphier_get_boot_device_info();
  178. if (!info) {
  179. pr_err("unsupported SoC\n");
  180. return CMD_RET_FAILURE;
  181. }
  182. if (uniphier_have_internal_stm())
  183. printf("STB Micon: %s\n",
  184. uniphier_boot_from_backend() ? "OFF" : "ON");
  185. printf("Boot Swap: %s\n", boot_is_swapped() ? "ON" : "OFF");
  186. pinmon = readl(SG_PINMON0);
  187. if (info->boot_device_is_usb)
  188. printf("USB Boot: %s\n",
  189. info->boot_device_is_usb(pinmon) ? "ON" : "OFF");
  190. boot_device_count = *info->boot_device_count;
  191. boot_sel = pinmon >> info->boot_device_sel_shift;
  192. boot_sel &= boot_device_count - 1;
  193. printf("\nBoot Mode Sel:\n");
  194. for (i = 0; i < boot_device_count; i++)
  195. printf(" %c %02x %s\n", i == boot_sel ? '*' : ' ', i,
  196. info->boot_device_table[i].desc);
  197. return CMD_RET_SUCCESS;
  198. }
  199. U_BOOT_CMD(
  200. pinmon, 1, 1, do_pinmon,
  201. "pin monitor",
  202. ""
  203. );
  204. #endif /* !CONFIG_SPL_BUILD */