command: Remove the cmd_tbl_t typedef
[oweals/u-boot.git] / arch / arm / mach-uniphier / boot-device / boot-device.c
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 <command.h>
9 #include <spl.h>
10 #include <stdio.h>
11 #include <linux/io.h>
12 #include <linux/log2.h>
13
14 #include "../init.h"
15 #include "../sbc/sbc-regs.h"
16 #include "../sg-regs.h"
17 #include "../soc-info.h"
18 #include "boot-device.h"
19
20 struct uniphier_boot_device_info {
21         unsigned int soc_id;
22         unsigned int boot_device_sel_shift;
23         const struct uniphier_boot_device *boot_device_table;
24         const unsigned int *boot_device_count;
25         int (*boot_device_is_sd)(u32 pinmon);
26         int (*boot_device_is_usb)(u32 pinmon);
27         unsigned int (*boot_device_fixup)(unsigned int mode);
28         int (*boot_is_swapped)(void);
29         bool have_internal_stm;
30 };
31
32 static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
33 #if defined(CONFIG_ARCH_UNIPHIER_LD4)
34         {
35                 .soc_id = UNIPHIER_LD4_ID,
36                 .boot_device_sel_shift = 1,
37                 .boot_device_table = uniphier_ld4_boot_device_table,
38                 .boot_device_count = &uniphier_ld4_boot_device_count,
39                 .boot_is_swapped = uniphier_sbc_boot_is_swapped,
40                 .have_internal_stm = true,
41         },
42 #endif
43 #if defined(CONFIG_ARCH_UNIPHIER_PRO4)
44         {
45                 .soc_id = UNIPHIER_PRO4_ID,
46                 .boot_device_sel_shift = 1,
47                 .boot_device_table = uniphier_ld4_boot_device_table,
48                 .boot_device_count = &uniphier_ld4_boot_device_count,
49                 .boot_is_swapped = uniphier_sbc_boot_is_swapped,
50                 .have_internal_stm = false,
51         },
52 #endif
53 #if defined(CONFIG_ARCH_UNIPHIER_SLD8)
54         {
55                 .soc_id = UNIPHIER_SLD8_ID,
56                 .boot_device_sel_shift = 1,
57                 .boot_device_table = uniphier_ld4_boot_device_table,
58                 .boot_device_count = &uniphier_ld4_boot_device_count,
59                 .boot_is_swapped = uniphier_sbc_boot_is_swapped,
60                 .have_internal_stm = true,
61         },
62 #endif
63 #if defined(CONFIG_ARCH_UNIPHIER_PRO5)
64         {
65                 .soc_id = UNIPHIER_PRO5_ID,
66                 .boot_device_sel_shift = 1,
67                 .boot_device_table = uniphier_pro5_boot_device_table,
68                 .boot_device_count = &uniphier_pro5_boot_device_count,
69                 .boot_is_swapped = uniphier_sbc_boot_is_swapped,
70                 .have_internal_stm = false,
71         },
72 #endif
73 #if defined(CONFIG_ARCH_UNIPHIER_PXS2)
74         {
75                 .soc_id = UNIPHIER_PXS2_ID,
76                 .boot_device_sel_shift = 1,
77                 .boot_device_table = uniphier_pxs2_boot_device_table,
78                 .boot_device_count = &uniphier_pxs2_boot_device_count,
79                 .boot_device_is_usb = uniphier_pxs2_boot_device_is_usb,
80                 .boot_device_fixup = uniphier_pxs2_boot_device_fixup,
81                 .boot_is_swapped = uniphier_sbc_boot_is_swapped,
82                 .have_internal_stm = false,
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                 .boot_is_swapped = uniphier_sbc_boot_is_swapped,
94                 .have_internal_stm = true,      /* STM on A-chip */
95         },
96 #endif
97 #if defined(CONFIG_ARCH_UNIPHIER_LD11)
98         {
99                 .soc_id = UNIPHIER_LD11_ID,
100                 .boot_device_sel_shift = 1,
101                 .boot_device_table = uniphier_ld11_boot_device_table,
102                 .boot_device_count = &uniphier_ld11_boot_device_count,
103                 .boot_device_is_usb = uniphier_ld11_boot_device_is_usb,
104                 .boot_is_swapped = uniphier_sbc_boot_is_swapped,
105                 .have_internal_stm = true,
106         },
107 #endif
108 #if defined(CONFIG_ARCH_UNIPHIER_LD20)
109         {
110                 .soc_id = UNIPHIER_LD20_ID,
111                 .boot_device_sel_shift = 1,
112                 .boot_device_table = uniphier_ld11_boot_device_table,
113                 .boot_device_count = &uniphier_ld11_boot_device_count,
114                 .boot_device_is_usb = uniphier_ld20_boot_device_is_usb,
115                 .boot_is_swapped = uniphier_sbc_boot_is_swapped,
116                 .have_internal_stm = true,
117         },
118 #endif
119 #if defined(CONFIG_ARCH_UNIPHIER_PXS3)
120         {
121                 .soc_id = UNIPHIER_PXS3_ID,
122                 .boot_device_sel_shift = 1,
123                 .boot_device_table = uniphier_pxs3_boot_device_table,
124                 .boot_device_count = &uniphier_pxs3_boot_device_count,
125                 .boot_device_is_usb = uniphier_pxs3_boot_device_is_usb,
126                 .boot_is_swapped = uniphier_sbc_boot_is_swapped,
127                 .have_internal_stm = false,
128         },
129 #endif
130 };
131 UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_boot_device_info,
132                              uniphier_boot_device_info)
133
134 static unsigned int __uniphier_boot_device_raw(
135                                 const struct uniphier_boot_device_info *info)
136 {
137         u32 pinmon;
138         unsigned int boot_sel;
139
140         if (info->boot_is_swapped && info->boot_is_swapped())
141                 return BOOT_DEVICE_NOR;
142
143         pinmon = readl(sg_base + SG_PINMON0);
144
145         if (info->boot_device_is_sd && info->boot_device_is_sd(pinmon))
146                 return BOOT_DEVICE_MMC2;
147
148         if (info->boot_device_is_usb && info->boot_device_is_usb(pinmon))
149                 return BOOT_DEVICE_USB;
150
151         boot_sel = pinmon >> info->boot_device_sel_shift;
152
153         BUG_ON(!is_power_of_2(*info->boot_device_count));
154         boot_sel &= *info->boot_device_count - 1;
155
156         return info->boot_device_table[boot_sel].boot_device;
157 }
158
159 unsigned int uniphier_boot_device_raw(void)
160 {
161         const struct uniphier_boot_device_info *info;
162
163         info = uniphier_get_boot_device_info();
164         if (!info) {
165                 pr_err("unsupported SoC\n");
166                 return BOOT_DEVICE_NONE;
167         }
168
169         return __uniphier_boot_device_raw(info);
170 }
171
172 u32 spl_boot_device(void)
173 {
174         const struct uniphier_boot_device_info *info;
175         u32 raw_mode;
176
177         info = uniphier_get_boot_device_info();
178         if (!info) {
179                 pr_err("unsupported SoC\n");
180                 return BOOT_DEVICE_NONE;
181         }
182
183         raw_mode = __uniphier_boot_device_raw(info);
184
185         return info->boot_device_fixup ?
186                                 info->boot_device_fixup(raw_mode) : raw_mode;
187 }
188
189 int uniphier_have_internal_stm(void)
190 {
191         const struct uniphier_boot_device_info *info;
192
193         info = uniphier_get_boot_device_info();
194         if (!info) {
195                 pr_err("unsupported SoC\n");
196                 return -ENOTSUPP;
197         }
198
199         return info->have_internal_stm;
200 }
201
202 int uniphier_boot_from_backend(void)
203 {
204         return !!(readl(sg_base + SG_PINMON0) & BIT(27));
205 }
206
207 #ifndef CONFIG_SPL_BUILD
208
209 static int do_pinmon(struct cmd_tbl *cmdtp, int flag, int argc,
210                      char *const argv[])
211 {
212         const struct uniphier_boot_device_info *info;
213         u32 pinmon;
214         unsigned int boot_device_count, boot_sel;
215         int i;
216
217         info = uniphier_get_boot_device_info();
218         if (!info) {
219                 pr_err("unsupported SoC\n");
220                 return CMD_RET_FAILURE;
221         }
222
223         if (uniphier_have_internal_stm())
224                 printf("STB Micon: %s\n",
225                        uniphier_boot_from_backend() ? "OFF" : "ON");
226
227         if (info->boot_is_swapped)
228                 printf("Boot Swap: %s\n",
229                        info->boot_is_swapped() ? "ON" : "OFF");
230
231         pinmon = readl(sg_base + SG_PINMON0);
232
233         if (info->boot_device_is_sd)
234                 printf("SD Boot:  %s\n",
235                        info->boot_device_is_sd(pinmon) ? "ON" : "OFF");
236
237         if (info->boot_device_is_usb)
238                 printf("USB Boot:  %s\n",
239                        info->boot_device_is_usb(pinmon) ? "ON" : "OFF");
240
241         boot_device_count = *info->boot_device_count;
242
243         boot_sel = pinmon >> info->boot_device_sel_shift;
244         boot_sel &= boot_device_count - 1;
245
246         printf("\nBoot Mode Sel:\n");
247         for (i = 0; i < boot_device_count; i++)
248                 printf(" %c %02x %s\n", i == boot_sel ? '*' : ' ', i,
249                        info->boot_device_table[i].desc);
250
251         return CMD_RET_SUCCESS;
252 }
253
254 U_BOOT_CMD(
255         pinmon, 1,      1,      do_pinmon,
256         "pin monitor",
257         ""
258 );
259
260 #endif /* !CONFIG_SPL_BUILD */