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