• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
7 #include <common.h>
8 #include <spl.h>
9 #include <stdio.h>
10 #include <linux/io.h>
11 #include <linux/log2.h>
12 
13 #include "../init.h"
14 #include "../sbc/sbc-regs.h"
15 #include "../sg-regs.h"
16 #include "../soc-info.h"
17 #include "boot-device.h"
18 
19 struct uniphier_boot_device_info {
20 	unsigned int soc_id;
21 	unsigned int boot_device_sel_shift;
22 	const struct uniphier_boot_device *boot_device_table;
23 	const unsigned int *boot_device_count;
24 	int (*boot_device_is_sd)(u32 pinmon);
25 	int (*boot_device_is_usb)(u32 pinmon);
26 	unsigned int (*boot_device_fixup)(unsigned int mode);
27 	int (*boot_is_swapped)(void);
28 	bool have_internal_stm;
29 };
30 
31 static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
32 #if defined(CONFIG_ARCH_UNIPHIER_LD4)
33 	{
34 		.soc_id = UNIPHIER_LD4_ID,
35 		.boot_device_sel_shift = 1,
36 		.boot_device_table = uniphier_ld4_boot_device_table,
37 		.boot_device_count = &uniphier_ld4_boot_device_count,
38 		.boot_is_swapped = uniphier_sbc_boot_is_swapped,
39 		.have_internal_stm = true,
40 	},
41 #endif
42 #if defined(CONFIG_ARCH_UNIPHIER_PRO4)
43 	{
44 		.soc_id = UNIPHIER_PRO4_ID,
45 		.boot_device_sel_shift = 1,
46 		.boot_device_table = uniphier_ld4_boot_device_table,
47 		.boot_device_count = &uniphier_ld4_boot_device_count,
48 		.boot_is_swapped = uniphier_sbc_boot_is_swapped,
49 		.have_internal_stm = false,
50 	},
51 #endif
52 #if defined(CONFIG_ARCH_UNIPHIER_SLD8)
53 	{
54 		.soc_id = UNIPHIER_SLD8_ID,
55 		.boot_device_sel_shift = 1,
56 		.boot_device_table = uniphier_ld4_boot_device_table,
57 		.boot_device_count = &uniphier_ld4_boot_device_count,
58 		.boot_is_swapped = uniphier_sbc_boot_is_swapped,
59 		.have_internal_stm = true,
60 	},
61 #endif
62 #if defined(CONFIG_ARCH_UNIPHIER_PRO5)
63 	{
64 		.soc_id = UNIPHIER_PRO5_ID,
65 		.boot_device_sel_shift = 1,
66 		.boot_device_table = uniphier_pro5_boot_device_table,
67 		.boot_device_count = &uniphier_pro5_boot_device_count,
68 		.boot_is_swapped = uniphier_sbc_boot_is_swapped,
69 		.have_internal_stm = false,
70 	},
71 #endif
72 #if defined(CONFIG_ARCH_UNIPHIER_PXS2)
73 	{
74 		.soc_id = UNIPHIER_PXS2_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 		.boot_is_swapped = uniphier_sbc_boot_is_swapped,
81 		.have_internal_stm = false,
82 	},
83 #endif
84 #if defined(CONFIG_ARCH_UNIPHIER_LD6B)
85 	{
86 		.soc_id = UNIPHIER_LD6B_ID,
87 		.boot_device_sel_shift = 1,
88 		.boot_device_table = uniphier_pxs2_boot_device_table,
89 		.boot_device_count = &uniphier_pxs2_boot_device_count,
90 		.boot_device_is_usb = uniphier_pxs2_boot_device_is_usb,
91 		.boot_device_fixup = uniphier_pxs2_boot_device_fixup,
92 		.boot_is_swapped = uniphier_sbc_boot_is_swapped,
93 		.have_internal_stm = true,	/* 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_is_swapped = uniphier_sbc_boot_is_swapped,
104 		.have_internal_stm = true,
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_is_swapped = uniphier_sbc_boot_is_swapped,
115 		.have_internal_stm = true,
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 		.boot_is_swapped = uniphier_sbc_boot_is_swapped,
126 		.have_internal_stm = false,
127 	},
128 #endif
129 };
UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info,uniphier_boot_device_info)130 UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info,
131 			     uniphier_boot_device_info)
132 
133 static unsigned int __uniphier_boot_device_raw(
134 				const struct uniphier_boot_device_info *info)
135 {
136 	u32 pinmon;
137 	unsigned int boot_sel;
138 
139 	if (info->boot_is_swapped && info->boot_is_swapped())
140 		return BOOT_DEVICE_NOR;
141 
142 	pinmon = readl(sg_base + SG_PINMON0);
143 
144 	if (info->boot_device_is_sd && info->boot_device_is_sd(pinmon))
145 		return BOOT_DEVICE_MMC2;
146 
147 	if (info->boot_device_is_usb && info->boot_device_is_usb(pinmon))
148 		return BOOT_DEVICE_USB;
149 
150 	boot_sel = pinmon >> info->boot_device_sel_shift;
151 
152 	BUG_ON(!is_power_of_2(*info->boot_device_count));
153 	boot_sel &= *info->boot_device_count - 1;
154 
155 	return info->boot_device_table[boot_sel].boot_device;
156 }
157 
uniphier_boot_device_raw(void)158 unsigned int uniphier_boot_device_raw(void)
159 {
160 	const struct uniphier_boot_device_info *info;
161 
162 	info = uniphier_get_boot_device_info();
163 	if (!info) {
164 		pr_err("unsupported SoC\n");
165 		return BOOT_DEVICE_NONE;
166 	}
167 
168 	return __uniphier_boot_device_raw(info);
169 }
170 
spl_boot_device(void)171 u32 spl_boot_device(void)
172 {
173 	const struct uniphier_boot_device_info *info;
174 	u32 raw_mode;
175 
176 	info = uniphier_get_boot_device_info();
177 	if (!info) {
178 		pr_err("unsupported SoC\n");
179 		return BOOT_DEVICE_NONE;
180 	}
181 
182 	raw_mode = __uniphier_boot_device_raw(info);
183 
184 	return info->boot_device_fixup ?
185 				info->boot_device_fixup(raw_mode) : raw_mode;
186 }
187 
uniphier_have_internal_stm(void)188 int uniphier_have_internal_stm(void)
189 {
190 	const struct uniphier_boot_device_info *info;
191 
192 	info = uniphier_get_boot_device_info();
193 	if (!info) {
194 		pr_err("unsupported SoC\n");
195 		return -ENOTSUPP;
196 	}
197 
198 	return info->have_internal_stm;
199 }
200 
uniphier_boot_from_backend(void)201 int uniphier_boot_from_backend(void)
202 {
203 	return !!(readl(sg_base + SG_PINMON0) & BIT(27));
204 }
205 
206 #ifndef CONFIG_SPL_BUILD
207 
do_pinmon(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])208 static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
209 {
210 	const struct uniphier_boot_device_info *info;
211 	u32 pinmon;
212 	unsigned int boot_device_count, boot_sel;
213 	int i;
214 
215 	info = uniphier_get_boot_device_info();
216 	if (!info) {
217 		pr_err("unsupported SoC\n");
218 		return CMD_RET_FAILURE;
219 	}
220 
221 	if (uniphier_have_internal_stm())
222 		printf("STB Micon: %s\n",
223 		       uniphier_boot_from_backend() ? "OFF" : "ON");
224 
225 	if (info->boot_is_swapped)
226 		printf("Boot Swap: %s\n",
227 		       info->boot_is_swapped() ? "ON" : "OFF");
228 
229 	pinmon = readl(sg_base + SG_PINMON0);
230 
231 	if (info->boot_device_is_sd)
232 		printf("SD Boot:  %s\n",
233 		       info->boot_device_is_sd(pinmon) ? "ON" : "OFF");
234 
235 	if (info->boot_device_is_usb)
236 		printf("USB Boot:  %s\n",
237 		       info->boot_device_is_usb(pinmon) ? "ON" : "OFF");
238 
239 	boot_device_count = *info->boot_device_count;
240 
241 	boot_sel = pinmon >> info->boot_device_sel_shift;
242 	boot_sel &= boot_device_count - 1;
243 
244 	printf("\nBoot Mode Sel:\n");
245 	for (i = 0; i < boot_device_count; i++)
246 		printf(" %c %02x %s\n", i == boot_sel ? '*' : ' ', i,
247 		       info->boot_device_table[i].desc);
248 
249 	return CMD_RET_SUCCESS;
250 }
251 
252 U_BOOT_CMD(
253 	pinmon,	1,	1,	do_pinmon,
254 	"pin monitor",
255 	""
256 );
257 
258 #endif /* !CONFIG_SPL_BUILD */
259