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