boot-device.c 6.8 KB

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