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