]> git.sur5r.net Git - u-boot/blob - arch/arm/mach-uniphier/boot-device/boot-device.c
Merge git://git.denx.de/u-boot-sunxi
[u-boot] / arch / arm / mach-uniphier / boot-device / boot-device.c
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 };
119 UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info,
120                              uniphier_boot_device_info)
121
122 static unsigned int __uniphier_boot_device_raw(
123                                 const struct uniphier_boot_device_info *info)
124 {
125         u32 pinmon;
126         unsigned int boot_sel;
127
128         if (boot_is_swapped())
129                 return BOOT_DEVICE_NOR;
130
131         pinmon = readl(SG_PINMON0);
132
133         if (info->boot_device_is_usb && info->boot_device_is_usb(pinmon))
134                 return BOOT_DEVICE_USB;
135
136         boot_sel = pinmon >> info->boot_device_sel_shift;
137
138         BUG_ON(!is_power_of_2(*info->boot_device_count));
139         boot_sel &= *info->boot_device_count - 1;
140
141         return info->boot_device_table[boot_sel].boot_device;
142 }
143
144 unsigned int uniphier_boot_device_raw(void)
145 {
146         const struct uniphier_boot_device_info *info;
147
148         info = uniphier_get_boot_device_info();
149         if (!info) {
150                 pr_err("unsupported SoC\n");
151                 return BOOT_DEVICE_NONE;
152         }
153
154         return __uniphier_boot_device_raw(info);
155 }
156
157 u32 spl_boot_device(void)
158 {
159         const struct uniphier_boot_device_info *info;
160         u32 raw_mode;
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         raw_mode = __uniphier_boot_device_raw(info);
169
170         return info->boot_device_fixup ?
171                                 info->boot_device_fixup(raw_mode) : raw_mode;
172 }
173
174 int uniphier_have_internal_stm(void)
175 {
176         const struct uniphier_boot_device_info *info;
177
178         info = uniphier_get_boot_device_info();
179         if (!info) {
180                 pr_err("unsupported SoC\n");
181                 return -ENOTSUPP;
182         }
183
184         return info->have_internal_stm;
185 }
186
187 int uniphier_boot_from_backend(void)
188 {
189         return !!(readl(SG_PINMON0) & BIT(27));
190 }
191
192 #ifndef CONFIG_SPL_BUILD
193
194 static int do_pinmon(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
195 {
196         const struct uniphier_boot_device_info *info;
197         u32 pinmon;
198         unsigned int boot_device_count, boot_sel;
199         int i;
200
201         info = uniphier_get_boot_device_info();
202         if (!info) {
203                 pr_err("unsupported SoC\n");
204                 return CMD_RET_FAILURE;
205         }
206
207         if (uniphier_have_internal_stm())
208                 printf("STB Micon: %s\n",
209                        uniphier_boot_from_backend() ? "OFF" : "ON");
210
211         printf("Boot Swap: %s\n", boot_is_swapped() ? "ON" : "OFF");
212
213         pinmon = readl(SG_PINMON0);
214
215         if (info->boot_device_is_usb)
216                 printf("USB Boot:  %s\n",
217                        info->boot_device_is_usb(pinmon) ? "ON" : "OFF");
218
219         boot_device_count = *info->boot_device_count;
220
221         boot_sel = pinmon >> info->boot_device_sel_shift;
222         boot_sel &= boot_device_count - 1;
223
224         printf("\nBoot Mode Sel:\n");
225         for (i = 0; i < boot_device_count; i++)
226                 printf(" %c %02x %s\n", i == boot_sel ? '*' : ' ', i,
227                        info->boot_device_table[i].desc);
228
229         return CMD_RET_SUCCESS;
230 }
231
232 U_BOOT_CMD(
233         pinmon, 1,      1,      do_pinmon,
234         "pin monitor",
235         ""
236 );
237
238 #endif /* !CONFIG_SPL_BUILD */