1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2784548efSMasahiro Yamada /*
3784548efSMasahiro Yamada  * Copyright (C) 2015-2017 Socionext Inc.
4784548efSMasahiro Yamada  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
5784548efSMasahiro Yamada  */
6784548efSMasahiro Yamada 
7784548efSMasahiro Yamada #include <common.h>
8784548efSMasahiro Yamada #include <spl.h>
9dd74b945SMasahiro Yamada #include <stdio.h>
10784548efSMasahiro Yamada #include <linux/log2.h>
11784548efSMasahiro Yamada 
12784548efSMasahiro Yamada #include "../init.h"
13784548efSMasahiro Yamada #include "../sbc/sbc-regs.h"
14784548efSMasahiro Yamada #include "../sg-regs.h"
15784548efSMasahiro Yamada #include "../soc-info.h"
16784548efSMasahiro Yamada #include "boot-device.h"
17784548efSMasahiro Yamada 
18784548efSMasahiro Yamada struct uniphier_boot_device_info {
19784548efSMasahiro Yamada 	unsigned int soc_id;
20784548efSMasahiro Yamada 	unsigned int boot_device_sel_shift;
21784548efSMasahiro Yamada 	const struct uniphier_boot_device *boot_device_table;
22784548efSMasahiro Yamada 	const unsigned int *boot_device_count;
23784548efSMasahiro Yamada 	int (*boot_device_is_usb)(u32 pinmon);
24784548efSMasahiro Yamada 	unsigned int (*boot_device_fixup)(unsigned int mode);
2563754842SMasahiro Yamada 	int have_internal_stm;
26784548efSMasahiro Yamada };
27784548efSMasahiro Yamada 
28784548efSMasahiro Yamada static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
29784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_LD4)
30784548efSMasahiro Yamada 	{
31784548efSMasahiro Yamada 		.soc_id = UNIPHIER_LD4_ID,
32784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
33784548efSMasahiro Yamada 		.boot_device_table = uniphier_ld4_boot_device_table,
34784548efSMasahiro Yamada 		.boot_device_count = &uniphier_ld4_boot_device_count,
3563754842SMasahiro Yamada 		.have_internal_stm = 1,
36784548efSMasahiro Yamada 	},
37784548efSMasahiro Yamada #endif
38784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_PRO4)
39784548efSMasahiro Yamada 	{
40784548efSMasahiro Yamada 		.soc_id = UNIPHIER_PRO4_ID,
41784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
42784548efSMasahiro Yamada 		.boot_device_table = uniphier_ld4_boot_device_table,
43784548efSMasahiro Yamada 		.boot_device_count = &uniphier_ld4_boot_device_count,
4463754842SMasahiro Yamada 		.have_internal_stm = 0,
45784548efSMasahiro Yamada 	},
46784548efSMasahiro Yamada #endif
47784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_SLD8)
48784548efSMasahiro Yamada 	{
49784548efSMasahiro Yamada 		.soc_id = UNIPHIER_SLD8_ID,
50784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
51784548efSMasahiro Yamada 		.boot_device_table = uniphier_ld4_boot_device_table,
52784548efSMasahiro Yamada 		.boot_device_count = &uniphier_ld4_boot_device_count,
5363754842SMasahiro Yamada 		.have_internal_stm = 1,
54784548efSMasahiro Yamada 	},
55784548efSMasahiro Yamada #endif
56784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_PRO5)
57784548efSMasahiro Yamada 	{
58784548efSMasahiro Yamada 		.soc_id = UNIPHIER_PRO5_ID,
59784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
60784548efSMasahiro Yamada 		.boot_device_table = uniphier_pro5_boot_device_table,
61784548efSMasahiro Yamada 		.boot_device_count = &uniphier_pro5_boot_device_count,
6263754842SMasahiro Yamada 		.have_internal_stm = 0,
63784548efSMasahiro Yamada 	},
64784548efSMasahiro Yamada #endif
65784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_PXS2)
66784548efSMasahiro Yamada 	{
67784548efSMasahiro Yamada 		.soc_id = UNIPHIER_PXS2_ID,
68784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
69784548efSMasahiro Yamada 		.boot_device_table = uniphier_pxs2_boot_device_table,
70784548efSMasahiro Yamada 		.boot_device_count = &uniphier_pxs2_boot_device_count,
71784548efSMasahiro Yamada 		.boot_device_is_usb = uniphier_pxs2_boot_device_is_usb,
72784548efSMasahiro Yamada 		.boot_device_fixup = uniphier_pxs2_boot_device_fixup,
7363754842SMasahiro Yamada 		.have_internal_stm = 0,
74784548efSMasahiro Yamada 	},
75784548efSMasahiro Yamada #endif
76784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_LD6B)
77784548efSMasahiro Yamada 	{
78784548efSMasahiro Yamada 		.soc_id = UNIPHIER_LD6B_ID,
79784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
80784548efSMasahiro Yamada 		.boot_device_table = uniphier_pxs2_boot_device_table,
81784548efSMasahiro Yamada 		.boot_device_count = &uniphier_pxs2_boot_device_count,
82784548efSMasahiro Yamada 		.boot_device_is_usb = uniphier_pxs2_boot_device_is_usb,
83784548efSMasahiro Yamada 		.boot_device_fixup = uniphier_pxs2_boot_device_fixup,
8463754842SMasahiro Yamada 		.have_internal_stm = 1,	/* STM on A-chip */
85784548efSMasahiro Yamada 	},
86784548efSMasahiro Yamada #endif
87784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_LD11)
88784548efSMasahiro Yamada 	{
89784548efSMasahiro Yamada 		.soc_id = UNIPHIER_LD11_ID,
90784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
91784548efSMasahiro Yamada 		.boot_device_table = uniphier_ld11_boot_device_table,
92784548efSMasahiro Yamada 		.boot_device_count = &uniphier_ld11_boot_device_count,
93784548efSMasahiro Yamada 		.boot_device_is_usb = uniphier_ld11_boot_device_is_usb,
94784548efSMasahiro Yamada 		.boot_device_fixup = uniphier_ld11_boot_device_fixup,
9563754842SMasahiro Yamada 		.have_internal_stm = 1,
96784548efSMasahiro Yamada 	},
97784548efSMasahiro Yamada #endif
98784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_LD20)
99784548efSMasahiro Yamada 	{
100784548efSMasahiro Yamada 		.soc_id = UNIPHIER_LD20_ID,
101784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
102784548efSMasahiro Yamada 		.boot_device_table = uniphier_ld11_boot_device_table,
103784548efSMasahiro Yamada 		.boot_device_count = &uniphier_ld11_boot_device_count,
104784548efSMasahiro Yamada 		.boot_device_is_usb = uniphier_ld20_boot_device_is_usb,
105784548efSMasahiro Yamada 		.boot_device_fixup = uniphier_ld11_boot_device_fixup,
10663754842SMasahiro Yamada 		.have_internal_stm = 1,
107784548efSMasahiro Yamada 	},
108784548efSMasahiro Yamada #endif
10981afa9c9SMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_PXS3)
11081afa9c9SMasahiro Yamada 	{
11181afa9c9SMasahiro Yamada 		.soc_id = UNIPHIER_PXS3_ID,
11281afa9c9SMasahiro Yamada 		.boot_device_sel_shift = 1,
11381afa9c9SMasahiro Yamada 		.boot_device_table = uniphier_pxs3_boot_device_table,
11481afa9c9SMasahiro Yamada 		.boot_device_count = &uniphier_pxs3_boot_device_count,
11581afa9c9SMasahiro Yamada 		.boot_device_is_usb = uniphier_pxs3_boot_device_is_usb,
11681afa9c9SMasahiro Yamada 		.have_internal_stm = 0,
11781afa9c9SMasahiro Yamada 	},
11881afa9c9SMasahiro Yamada #endif
119784548efSMasahiro Yamada };
UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info,uniphier_boot_device_info)120784548efSMasahiro Yamada UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info,
121784548efSMasahiro Yamada 			     uniphier_boot_device_info)
122784548efSMasahiro Yamada 
123784548efSMasahiro Yamada static unsigned int __uniphier_boot_device_raw(
124784548efSMasahiro Yamada 				const struct uniphier_boot_device_info *info)
125784548efSMasahiro Yamada {
126784548efSMasahiro Yamada 	u32 pinmon;
127784548efSMasahiro Yamada 	unsigned int boot_sel;
128784548efSMasahiro Yamada 
129784548efSMasahiro Yamada 	if (boot_is_swapped())
130784548efSMasahiro Yamada 		return BOOT_DEVICE_NOR;
131784548efSMasahiro Yamada 
132784548efSMasahiro Yamada 	pinmon = readl(SG_PINMON0);
133784548efSMasahiro Yamada 
134784548efSMasahiro Yamada 	if (info->boot_device_is_usb && info->boot_device_is_usb(pinmon))
135784548efSMasahiro Yamada 		return BOOT_DEVICE_USB;
136784548efSMasahiro Yamada 
137784548efSMasahiro Yamada 	boot_sel = pinmon >> info->boot_device_sel_shift;
138784548efSMasahiro Yamada 
139784548efSMasahiro Yamada 	BUG_ON(!is_power_of_2(*info->boot_device_count));
140784548efSMasahiro Yamada 	boot_sel &= *info->boot_device_count - 1;
141784548efSMasahiro Yamada 
142784548efSMasahiro Yamada 	return info->boot_device_table[boot_sel].boot_device;
143784548efSMasahiro Yamada }
144784548efSMasahiro Yamada 
uniphier_boot_device_raw(void)145784548efSMasahiro Yamada unsigned int uniphier_boot_device_raw(void)
146784548efSMasahiro Yamada {
147784548efSMasahiro Yamada 	const struct uniphier_boot_device_info *info;
148784548efSMasahiro Yamada 
149784548efSMasahiro Yamada 	info = uniphier_get_boot_device_info();
150784548efSMasahiro Yamada 	if (!info) {
151784548efSMasahiro Yamada 		pr_err("unsupported SoC\n");
152784548efSMasahiro Yamada 		return BOOT_DEVICE_NONE;
153784548efSMasahiro Yamada 	}
154784548efSMasahiro Yamada 
155784548efSMasahiro Yamada 	return __uniphier_boot_device_raw(info);
156784548efSMasahiro Yamada }
157784548efSMasahiro Yamada 
spl_boot_device(void)158784548efSMasahiro Yamada u32 spl_boot_device(void)
159784548efSMasahiro Yamada {
160784548efSMasahiro Yamada 	const struct uniphier_boot_device_info *info;
161784548efSMasahiro Yamada 	u32 raw_mode;
162784548efSMasahiro Yamada 
163784548efSMasahiro Yamada 	info = uniphier_get_boot_device_info();
164784548efSMasahiro Yamada 	if (!info) {
165784548efSMasahiro Yamada 		pr_err("unsupported SoC\n");
166784548efSMasahiro Yamada 		return BOOT_DEVICE_NONE;
167784548efSMasahiro Yamada 	}
168784548efSMasahiro Yamada 
169784548efSMasahiro Yamada 	raw_mode = __uniphier_boot_device_raw(info);
170784548efSMasahiro Yamada 
171784548efSMasahiro Yamada 	return info->boot_device_fixup ?
172784548efSMasahiro Yamada 				info->boot_device_fixup(raw_mode) : raw_mode;
173784548efSMasahiro Yamada }
174784548efSMasahiro Yamada 
uniphier_have_internal_stm(void)17563754842SMasahiro Yamada int uniphier_have_internal_stm(void)
17663754842SMasahiro Yamada {
17763754842SMasahiro Yamada 	const struct uniphier_boot_device_info *info;
17863754842SMasahiro Yamada 
17963754842SMasahiro Yamada 	info = uniphier_get_boot_device_info();
18063754842SMasahiro Yamada 	if (!info) {
18163754842SMasahiro Yamada 		pr_err("unsupported SoC\n");
18263754842SMasahiro Yamada 		return -ENOTSUPP;
18363754842SMasahiro Yamada 	}
18463754842SMasahiro Yamada 
18563754842SMasahiro Yamada 	return info->have_internal_stm;
18663754842SMasahiro Yamada }
18763754842SMasahiro Yamada 
uniphier_boot_from_backend(void)18863754842SMasahiro Yamada int uniphier_boot_from_backend(void)
18963754842SMasahiro Yamada {
19063754842SMasahiro Yamada 	return !!(readl(SG_PINMON0) & BIT(27));
19163754842SMasahiro Yamada }
19263754842SMasahiro Yamada 
193784548efSMasahiro Yamada #ifndef CONFIG_SPL_BUILD
194784548efSMasahiro Yamada 
do_pinmon(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])195784548efSMasahiro Yamada static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
196784548efSMasahiro Yamada {
197784548efSMasahiro Yamada 	const struct uniphier_boot_device_info *info;
198784548efSMasahiro Yamada 	u32 pinmon;
199784548efSMasahiro Yamada 	unsigned int boot_device_count, boot_sel;
200784548efSMasahiro Yamada 	int i;
201784548efSMasahiro Yamada 
202784548efSMasahiro Yamada 	info = uniphier_get_boot_device_info();
203784548efSMasahiro Yamada 	if (!info) {
204784548efSMasahiro Yamada 		pr_err("unsupported SoC\n");
205784548efSMasahiro Yamada 		return CMD_RET_FAILURE;
206784548efSMasahiro Yamada 	}
207784548efSMasahiro Yamada 
20863754842SMasahiro Yamada 	if (uniphier_have_internal_stm())
20963754842SMasahiro Yamada 		printf("STB Micon: %s\n",
21063754842SMasahiro Yamada 		       uniphier_boot_from_backend() ? "OFF" : "ON");
21163754842SMasahiro Yamada 
21263754842SMasahiro Yamada 	printf("Boot Swap: %s\n", boot_is_swapped() ? "ON" : "OFF");
213784548efSMasahiro Yamada 
214784548efSMasahiro Yamada 	pinmon = readl(SG_PINMON0);
215784548efSMasahiro Yamada 
216784548efSMasahiro Yamada 	if (info->boot_device_is_usb)
21763754842SMasahiro Yamada 		printf("USB Boot:  %s\n",
218784548efSMasahiro Yamada 		       info->boot_device_is_usb(pinmon) ? "ON" : "OFF");
219784548efSMasahiro Yamada 
220784548efSMasahiro Yamada 	boot_device_count = *info->boot_device_count;
221784548efSMasahiro Yamada 
222784548efSMasahiro Yamada 	boot_sel = pinmon >> info->boot_device_sel_shift;
223784548efSMasahiro Yamada 	boot_sel &= boot_device_count - 1;
224784548efSMasahiro Yamada 
22563754842SMasahiro Yamada 	printf("\nBoot Mode Sel:\n");
226784548efSMasahiro Yamada 	for (i = 0; i < boot_device_count; i++)
227784548efSMasahiro Yamada 		printf(" %c %02x %s\n", i == boot_sel ? '*' : ' ', i,
228784548efSMasahiro Yamada 		       info->boot_device_table[i].desc);
229784548efSMasahiro Yamada 
230784548efSMasahiro Yamada 	return CMD_RET_SUCCESS;
231784548efSMasahiro Yamada }
232784548efSMasahiro Yamada 
233784548efSMasahiro Yamada U_BOOT_CMD(
234784548efSMasahiro Yamada 	pinmon,	1,	1,	do_pinmon,
235784548efSMasahiro Yamada 	"pin monitor",
236784548efSMasahiro Yamada 	""
237784548efSMasahiro Yamada );
238784548efSMasahiro Yamada 
239784548efSMasahiro Yamada #endif /* !CONFIG_SPL_BUILD */
240