xref: /rk3399_rockchip-uboot/arch/arm/mach-uniphier/boot-device/boot-device.c (revision 81afa9c9a3a9c006a6555e4abf7a75875eb3e926)
1784548efSMasahiro Yamada /*
2784548efSMasahiro Yamada  * Copyright (C) 2015-2017 Socionext Inc.
3784548efSMasahiro Yamada  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
4784548efSMasahiro Yamada  *
5784548efSMasahiro Yamada  * SPDX-License-Identifier:	GPL-2.0+
6784548efSMasahiro Yamada  */
7784548efSMasahiro Yamada 
8784548efSMasahiro Yamada #include <common.h>
9784548efSMasahiro Yamada #include <spl.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_SLD3)
30784548efSMasahiro Yamada 	{
31784548efSMasahiro Yamada 		.soc_id = UNIPHIER_SLD3_ID,
32784548efSMasahiro Yamada 		.boot_device_sel_shift = 0,
33784548efSMasahiro Yamada 		.boot_device_table = uniphier_sld3_boot_device_table,
34784548efSMasahiro Yamada 		.boot_device_count = &uniphier_sld3_boot_device_count,
3563754842SMasahiro Yamada 		.have_internal_stm = 0,
36784548efSMasahiro Yamada 	},
37784548efSMasahiro Yamada #endif
38784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_LD4)
39784548efSMasahiro Yamada 	{
40784548efSMasahiro Yamada 		.soc_id = UNIPHIER_LD4_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 = 1,
45784548efSMasahiro Yamada 	},
46784548efSMasahiro Yamada #endif
47784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_PRO4)
48784548efSMasahiro Yamada 	{
49784548efSMasahiro Yamada 		.soc_id = UNIPHIER_PRO4_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 = 0,
54784548efSMasahiro Yamada 	},
55784548efSMasahiro Yamada #endif
56784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_SLD8)
57784548efSMasahiro Yamada 	{
58784548efSMasahiro Yamada 		.soc_id = UNIPHIER_SLD8_ID,
59784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
60784548efSMasahiro Yamada 		.boot_device_table = uniphier_ld4_boot_device_table,
61784548efSMasahiro Yamada 		.boot_device_count = &uniphier_ld4_boot_device_count,
6263754842SMasahiro Yamada 		.have_internal_stm = 1,
63784548efSMasahiro Yamada 	},
64784548efSMasahiro Yamada #endif
65784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_PRO5)
66784548efSMasahiro Yamada 	{
67784548efSMasahiro Yamada 		.soc_id = UNIPHIER_PRO5_ID,
68784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
69784548efSMasahiro Yamada 		.boot_device_table = uniphier_pro5_boot_device_table,
70784548efSMasahiro Yamada 		.boot_device_count = &uniphier_pro5_boot_device_count,
7163754842SMasahiro Yamada 		.have_internal_stm = 0,
72784548efSMasahiro Yamada 	},
73784548efSMasahiro Yamada #endif
74784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_PXS2)
75784548efSMasahiro Yamada 	{
76784548efSMasahiro Yamada 		.soc_id = UNIPHIER_PXS2_ID,
77784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
78784548efSMasahiro Yamada 		.boot_device_table = uniphier_pxs2_boot_device_table,
79784548efSMasahiro Yamada 		.boot_device_count = &uniphier_pxs2_boot_device_count,
80784548efSMasahiro Yamada 		.boot_device_is_usb = uniphier_pxs2_boot_device_is_usb,
81784548efSMasahiro Yamada 		.boot_device_fixup = uniphier_pxs2_boot_device_fixup,
8263754842SMasahiro Yamada 		.have_internal_stm = 0,
83784548efSMasahiro Yamada 	},
84784548efSMasahiro Yamada #endif
85784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_LD6B)
86784548efSMasahiro Yamada 	{
87784548efSMasahiro Yamada 		.soc_id = UNIPHIER_LD6B_ID,
88784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
89784548efSMasahiro Yamada 		.boot_device_table = uniphier_pxs2_boot_device_table,
90784548efSMasahiro Yamada 		.boot_device_count = &uniphier_pxs2_boot_device_count,
91784548efSMasahiro Yamada 		.boot_device_is_usb = uniphier_pxs2_boot_device_is_usb,
92784548efSMasahiro Yamada 		.boot_device_fixup = uniphier_pxs2_boot_device_fixup,
9363754842SMasahiro Yamada 		.have_internal_stm = 1,	/* STM on A-chip */
94784548efSMasahiro Yamada 	},
95784548efSMasahiro Yamada #endif
96784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_LD11)
97784548efSMasahiro Yamada 	{
98784548efSMasahiro Yamada 		.soc_id = UNIPHIER_LD11_ID,
99784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
100784548efSMasahiro Yamada 		.boot_device_table = uniphier_ld11_boot_device_table,
101784548efSMasahiro Yamada 		.boot_device_count = &uniphier_ld11_boot_device_count,
102784548efSMasahiro Yamada 		.boot_device_is_usb = uniphier_ld11_boot_device_is_usb,
103784548efSMasahiro Yamada 		.boot_device_fixup = uniphier_ld11_boot_device_fixup,
10463754842SMasahiro Yamada 		.have_internal_stm = 1,
105784548efSMasahiro Yamada 	},
106784548efSMasahiro Yamada #endif
107784548efSMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_LD20)
108784548efSMasahiro Yamada 	{
109784548efSMasahiro Yamada 		.soc_id = UNIPHIER_LD20_ID,
110784548efSMasahiro Yamada 		.boot_device_sel_shift = 1,
111784548efSMasahiro Yamada 		.boot_device_table = uniphier_ld11_boot_device_table,
112784548efSMasahiro Yamada 		.boot_device_count = &uniphier_ld11_boot_device_count,
113784548efSMasahiro Yamada 		.boot_device_is_usb = uniphier_ld20_boot_device_is_usb,
114784548efSMasahiro Yamada 		.boot_device_fixup = uniphier_ld11_boot_device_fixup,
11563754842SMasahiro Yamada 		.have_internal_stm = 1,
116784548efSMasahiro Yamada 	},
117784548efSMasahiro Yamada #endif
118*81afa9c9SMasahiro Yamada #if defined(CONFIG_ARCH_UNIPHIER_PXS3)
119*81afa9c9SMasahiro Yamada 	{
120*81afa9c9SMasahiro Yamada 		.soc_id = UNIPHIER_PXS3_ID,
121*81afa9c9SMasahiro Yamada 		.boot_device_sel_shift = 1,
122*81afa9c9SMasahiro Yamada 		.boot_device_table = uniphier_pxs3_boot_device_table,
123*81afa9c9SMasahiro Yamada 		.boot_device_count = &uniphier_pxs3_boot_device_count,
124*81afa9c9SMasahiro Yamada 		.boot_device_is_usb = uniphier_pxs3_boot_device_is_usb,
125*81afa9c9SMasahiro Yamada 		.have_internal_stm = 0,
126*81afa9c9SMasahiro Yamada 	},
127*81afa9c9SMasahiro Yamada #endif
128784548efSMasahiro Yamada };
129784548efSMasahiro Yamada UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info,
130784548efSMasahiro Yamada 			     uniphier_boot_device_info)
131784548efSMasahiro Yamada 
132784548efSMasahiro Yamada static unsigned int __uniphier_boot_device_raw(
133784548efSMasahiro Yamada 				const struct uniphier_boot_device_info *info)
134784548efSMasahiro Yamada {
135784548efSMasahiro Yamada 	u32 pinmon;
136784548efSMasahiro Yamada 	unsigned int boot_sel;
137784548efSMasahiro Yamada 
138784548efSMasahiro Yamada 	if (boot_is_swapped())
139784548efSMasahiro Yamada 		return BOOT_DEVICE_NOR;
140784548efSMasahiro Yamada 
141784548efSMasahiro Yamada 	pinmon = readl(SG_PINMON0);
142784548efSMasahiro Yamada 
143784548efSMasahiro Yamada 	if (info->boot_device_is_usb && info->boot_device_is_usb(pinmon))
144784548efSMasahiro Yamada 		return BOOT_DEVICE_USB;
145784548efSMasahiro Yamada 
146784548efSMasahiro Yamada 	boot_sel = pinmon >> info->boot_device_sel_shift;
147784548efSMasahiro Yamada 
148784548efSMasahiro Yamada 	BUG_ON(!is_power_of_2(*info->boot_device_count));
149784548efSMasahiro Yamada 	boot_sel &= *info->boot_device_count - 1;
150784548efSMasahiro Yamada 
151784548efSMasahiro Yamada 	return info->boot_device_table[boot_sel].boot_device;
152784548efSMasahiro Yamada }
153784548efSMasahiro Yamada 
154784548efSMasahiro Yamada unsigned int uniphier_boot_device_raw(void)
155784548efSMasahiro Yamada {
156784548efSMasahiro Yamada 	const struct uniphier_boot_device_info *info;
157784548efSMasahiro Yamada 
158784548efSMasahiro Yamada 	info = uniphier_get_boot_device_info();
159784548efSMasahiro Yamada 	if (!info) {
160784548efSMasahiro Yamada 		pr_err("unsupported SoC\n");
161784548efSMasahiro Yamada 		return BOOT_DEVICE_NONE;
162784548efSMasahiro Yamada 	}
163784548efSMasahiro Yamada 
164784548efSMasahiro Yamada 	return __uniphier_boot_device_raw(info);
165784548efSMasahiro Yamada }
166784548efSMasahiro Yamada 
167784548efSMasahiro Yamada u32 spl_boot_device(void)
168784548efSMasahiro Yamada {
169784548efSMasahiro Yamada 	const struct uniphier_boot_device_info *info;
170784548efSMasahiro Yamada 	u32 raw_mode;
171784548efSMasahiro Yamada 
172784548efSMasahiro Yamada 	info = uniphier_get_boot_device_info();
173784548efSMasahiro Yamada 	if (!info) {
174784548efSMasahiro Yamada 		pr_err("unsupported SoC\n");
175784548efSMasahiro Yamada 		return BOOT_DEVICE_NONE;
176784548efSMasahiro Yamada 	}
177784548efSMasahiro Yamada 
178784548efSMasahiro Yamada 	raw_mode = __uniphier_boot_device_raw(info);
179784548efSMasahiro Yamada 
180784548efSMasahiro Yamada 	return info->boot_device_fixup ?
181784548efSMasahiro Yamada 				info->boot_device_fixup(raw_mode) : raw_mode;
182784548efSMasahiro Yamada }
183784548efSMasahiro Yamada 
18463754842SMasahiro Yamada int uniphier_have_internal_stm(void)
18563754842SMasahiro Yamada {
18663754842SMasahiro Yamada 	const struct uniphier_boot_device_info *info;
18763754842SMasahiro Yamada 
18863754842SMasahiro Yamada 	info = uniphier_get_boot_device_info();
18963754842SMasahiro Yamada 	if (!info) {
19063754842SMasahiro Yamada 		pr_err("unsupported SoC\n");
19163754842SMasahiro Yamada 		return -ENOTSUPP;
19263754842SMasahiro Yamada 	}
19363754842SMasahiro Yamada 
19463754842SMasahiro Yamada 	return info->have_internal_stm;
19563754842SMasahiro Yamada }
19663754842SMasahiro Yamada 
19763754842SMasahiro Yamada int uniphier_boot_from_backend(void)
19863754842SMasahiro Yamada {
19963754842SMasahiro Yamada 	return !!(readl(SG_PINMON0) & BIT(27));
20063754842SMasahiro Yamada }
20163754842SMasahiro Yamada 
202784548efSMasahiro Yamada #ifndef CONFIG_SPL_BUILD
203784548efSMasahiro Yamada 
204784548efSMasahiro Yamada static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
205784548efSMasahiro Yamada {
206784548efSMasahiro Yamada 	const struct uniphier_boot_device_info *info;
207784548efSMasahiro Yamada 	u32 pinmon;
208784548efSMasahiro Yamada 	unsigned int boot_device_count, boot_sel;
209784548efSMasahiro Yamada 	int i;
210784548efSMasahiro Yamada 
211784548efSMasahiro Yamada 	info = uniphier_get_boot_device_info();
212784548efSMasahiro Yamada 	if (!info) {
213784548efSMasahiro Yamada 		pr_err("unsupported SoC\n");
214784548efSMasahiro Yamada 		return CMD_RET_FAILURE;
215784548efSMasahiro Yamada 	}
216784548efSMasahiro Yamada 
21763754842SMasahiro Yamada 	if (uniphier_have_internal_stm())
21863754842SMasahiro Yamada 		printf("STB Micon: %s\n",
21963754842SMasahiro Yamada 		       uniphier_boot_from_backend() ? "OFF" : "ON");
22063754842SMasahiro Yamada 
22163754842SMasahiro Yamada 	printf("Boot Swap: %s\n", boot_is_swapped() ? "ON" : "OFF");
222784548efSMasahiro Yamada 
223784548efSMasahiro Yamada 	pinmon = readl(SG_PINMON0);
224784548efSMasahiro Yamada 
225784548efSMasahiro Yamada 	if (info->boot_device_is_usb)
22663754842SMasahiro Yamada 		printf("USB Boot:  %s\n",
227784548efSMasahiro Yamada 		       info->boot_device_is_usb(pinmon) ? "ON" : "OFF");
228784548efSMasahiro Yamada 
229784548efSMasahiro Yamada 	boot_device_count = *info->boot_device_count;
230784548efSMasahiro Yamada 
231784548efSMasahiro Yamada 	boot_sel = pinmon >> info->boot_device_sel_shift;
232784548efSMasahiro Yamada 	boot_sel &= boot_device_count - 1;
233784548efSMasahiro Yamada 
23463754842SMasahiro Yamada 	printf("\nBoot Mode Sel:\n");
235784548efSMasahiro Yamada 	for (i = 0; i < boot_device_count; i++)
236784548efSMasahiro Yamada 		printf(" %c %02x %s\n", i == boot_sel ? '*' : ' ', i,
237784548efSMasahiro Yamada 		       info->boot_device_table[i].desc);
238784548efSMasahiro Yamada 
239784548efSMasahiro Yamada 	return CMD_RET_SUCCESS;
240784548efSMasahiro Yamada }
241784548efSMasahiro Yamada 
242784548efSMasahiro Yamada U_BOOT_CMD(
243784548efSMasahiro Yamada 	pinmon,	1,	1,	do_pinmon,
244784548efSMasahiro Yamada 	"pin monitor",
245784548efSMasahiro Yamada 	""
246784548efSMasahiro Yamada );
247784548efSMasahiro Yamada 
248784548efSMasahiro Yamada #endif /* !CONFIG_SPL_BUILD */
249