Correct SPL uses of FASTBOOT
[platform/kernel/u-boot.git] / arch / arm / mach-rockchip / board.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2019 Rockchip Electronics Co., Ltd.
4  */
5 #include <common.h>
6 #include <clk.h>
7 #include <cpu_func.h>
8 #include <dm.h>
9 #include <efi_loader.h>
10 #include <fastboot.h>
11 #include <init.h>
12 #include <log.h>
13 #include <mmc.h>
14 #include <part.h>
15 #include <ram.h>
16 #include <syscon.h>
17 #include <uuid.h>
18 #include <asm/cache.h>
19 #include <asm/global_data.h>
20 #include <asm/io.h>
21 #include <asm/arch-rockchip/boot_mode.h>
22 #include <asm/arch-rockchip/clock.h>
23 #include <asm/arch-rockchip/periph.h>
24 #include <asm/arch-rockchip/misc.h>
25 #include <power/regulator.h>
26
27 DECLARE_GLOBAL_DATA_PTR;
28
29 #if defined(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) && defined(CONFIG_EFI_PARTITION)
30
31 #define DFU_ALT_BUF_LEN                 SZ_1K
32
33 static struct efi_fw_image *fw_images;
34
35 static bool updatable_image(struct disk_partition *info)
36 {
37         int i;
38         bool ret = false;
39         efi_guid_t image_type_guid;
40
41         uuid_str_to_bin(info->type_guid, image_type_guid.b,
42                         UUID_STR_FORMAT_GUID);
43
44         for (i = 0; i < num_image_type_guids; i++) {
45                 if (!guidcmp(&fw_images[i].image_type_id, &image_type_guid)) {
46                         ret = true;
47                         break;
48                 }
49         }
50
51         return ret;
52 }
53
54 static void set_image_index(struct disk_partition *info, int index)
55 {
56         int i;
57         efi_guid_t image_type_guid;
58
59         uuid_str_to_bin(info->type_guid, image_type_guid.b,
60                         UUID_STR_FORMAT_GUID);
61
62         for (i = 0; i < num_image_type_guids; i++) {
63                 if (!guidcmp(&fw_images[i].image_type_id, &image_type_guid)) {
64                         fw_images[i].image_index = index;
65                         break;
66                 }
67         }
68 }
69
70 static int get_mmc_desc(struct blk_desc **desc)
71 {
72         int ret;
73         struct mmc *mmc;
74         struct udevice *dev;
75
76         /*
77          * For now the firmware images are assumed to
78          * be on the SD card
79          */
80         ret = uclass_get_device(UCLASS_MMC, 1, &dev);
81         if (ret)
82                 return -1;
83
84         mmc = mmc_get_mmc_dev(dev);
85         if (!mmc)
86                 return -ENODEV;
87
88         if ((ret = mmc_init(mmc)))
89                 return ret;
90
91         *desc = mmc_get_blk_desc(mmc);
92         if (!*desc)
93                 return -1;
94
95         return 0;
96 }
97
98 void set_dfu_alt_info(char *interface, char *devstr)
99 {
100         const char *name;
101         bool first = true;
102         int p, len, devnum, ret;
103         char buf[DFU_ALT_BUF_LEN];
104         struct disk_partition info;
105         struct blk_desc *desc = NULL;
106
107         ret = get_mmc_desc(&desc);
108         if (ret) {
109                 log_err("Unable to get mmc desc\n");
110                 return;
111         }
112
113         memset(buf, 0, sizeof(buf));
114         name = blk_get_uclass_name(desc->uclass_id);
115         devnum = desc->devnum;
116         len = strlen(buf);
117
118         len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
119                          "%s %d=", name, devnum);
120
121         for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
122                 if (part_get_info(desc, p, &info))
123                         continue;
124
125                 /* Add entry to dfu_alt_info only for updatable images */
126                 if (updatable_image(&info)) {
127                         if (!first)
128                                 len += snprintf(buf + len,
129                                                 DFU_ALT_BUF_LEN - len, ";");
130
131                         len += snprintf(buf + len, DFU_ALT_BUF_LEN - len,
132                                         "%s%d_%s part %d %d",
133                                         name, devnum, info.name, devnum, p);
134                         first = false;
135                 }
136         }
137
138         log_debug("dfu_alt_info => %s\n", buf);
139         env_set("dfu_alt_info", buf);
140 }
141
142 static void gpt_capsule_update_setup(void)
143 {
144         int p, i, ret;
145         struct disk_partition info;
146         struct blk_desc *desc = NULL;
147
148         fw_images = update_info.images;
149         rockchip_capsule_update_board_setup();
150
151         ret = get_mmc_desc(&desc);
152         if (ret) {
153                 log_err("Unable to get mmc desc\n");
154                 return;
155         }
156
157         for (p = 1, i = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
158                 if (part_get_info(desc, p, &info))
159                         continue;
160
161                 /*
162                  * Since we have a GPT partitioned device, the updatable
163                  * images could be stored in any order. Populate the
164                  * image_index at runtime.
165                  */
166                 if (updatable_image(&info)) {
167                         set_image_index(&info, i);
168                         i++;
169                 }
170         }
171 }
172 #endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT && CONFIG_EFI_PARTITION */
173
174 __weak int rk_board_late_init(void)
175 {
176 #if defined(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) && defined(CONFIG_EFI_PARTITION)
177         gpt_capsule_update_setup();
178 #endif
179
180         return 0;
181 }
182
183 int board_late_init(void)
184 {
185         setup_boot_mode();
186
187         return rk_board_late_init();
188 }
189
190 int board_init(void)
191 {
192         int ret;
193
194 #ifdef CONFIG_DM_REGULATOR
195         ret = regulators_enable_boot_on(false);
196         if (ret)
197                 debug("%s: Cannot enable boot on regulator\n", __func__);
198 #endif
199
200         return 0;
201 }
202
203 #if !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_ARM64)
204 void enable_caches(void)
205 {
206         /* Enable D-cache. I-cache is already enabled in start.S */
207         dcache_enable();
208 }
209 #endif
210
211 #if defined(CONFIG_USB_GADGET)
212 #include <usb.h>
213
214 #if defined(CONFIG_USB_GADGET_DWC2_OTG)
215 #include <usb/dwc2_udc.h>
216
217 static struct dwc2_plat_otg_data otg_data = {
218         .rx_fifo_sz     = 512,
219         .np_tx_fifo_sz  = 16,
220         .tx_fifo_sz     = 128,
221 };
222
223 int board_usb_init(int index, enum usb_init_type init)
224 {
225         ofnode node;
226         const char *mode;
227         bool matched = false;
228
229         /* find the usb_otg node */
230         node = ofnode_by_compatible(ofnode_null(), "snps,dwc2");
231         while (ofnode_valid(node)) {
232                 mode = ofnode_read_string(node, "dr_mode");
233                 if (mode && strcmp(mode, "otg") == 0) {
234                         matched = true;
235                         break;
236                 }
237
238                 node = ofnode_by_compatible(node, "snps,dwc2");
239         }
240         if (!matched) {
241                 debug("Not found usb_otg device\n");
242                 return -ENODEV;
243         }
244         otg_data.regs_otg = ofnode_get_addr(node);
245
246 #ifdef CONFIG_ROCKCHIP_USB2_PHY
247         int ret;
248         u32 phandle, offset;
249         ofnode phy_node;
250
251         ret = ofnode_read_u32(node, "phys", &phandle);
252         if (ret)
253                 return ret;
254
255         node = ofnode_get_by_phandle(phandle);
256         if (!ofnode_valid(node)) {
257                 debug("Not found usb phy device\n");
258                 return -ENODEV;
259         }
260
261         phy_node = ofnode_get_parent(node);
262         if (!ofnode_valid(node)) {
263                 debug("Not found usb phy device\n");
264                 return -ENODEV;
265         }
266
267         otg_data.phy_of_node = phy_node;
268         ret = ofnode_read_u32(node, "reg", &offset);
269         if (ret)
270                 return ret;
271         otg_data.regs_phy =  offset +
272                 (u32)syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
273 #endif
274         return dwc2_udc_probe(&otg_data);
275 }
276
277 int board_usb_cleanup(int index, enum usb_init_type init)
278 {
279         return 0;
280 }
281 #endif /* CONFIG_USB_GADGET_DWC2_OTG */
282
283 #if defined(CONFIG_USB_DWC3_GADGET) && !defined(CONFIG_DM_USB_GADGET)
284 #include <dwc3-uboot.h>
285
286 static struct dwc3_device dwc3_device_data = {
287         .maximum_speed = USB_SPEED_HIGH,
288         .base = 0xfe800000,
289         .dr_mode = USB_DR_MODE_PERIPHERAL,
290         .index = 0,
291         .dis_u2_susphy_quirk = 1,
292         .hsphy_mode = USBPHY_INTERFACE_MODE_UTMIW,
293 };
294
295 int usb_gadget_handle_interrupts(int index)
296 {
297         dwc3_uboot_handle_interrupt(0);
298         return 0;
299 }
300
301 int board_usb_init(int index, enum usb_init_type init)
302 {
303         return dwc3_uboot_init(&dwc3_device_data);
304 }
305 #endif /* CONFIG_USB_DWC3_GADGET */
306
307 #endif /* CONFIG_USB_GADGET */
308
309 #if IS_ENABLED(CONFIG_FASTBOOT)
310 int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason)
311 {
312         if (reason != FASTBOOT_REBOOT_REASON_BOOTLOADER)
313                 return -ENOTSUPP;
314
315         printf("Setting reboot to fastboot flag ...\n");
316         /* Set boot mode to fastboot */
317         writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG);
318
319         return 0;
320 }
321 #endif
322
323 #ifdef CONFIG_MISC_INIT_R
324 __weak int misc_init_r(void)
325 {
326         const u32 cpuid_offset = 0x7;
327         const u32 cpuid_length = 0x10;
328         u8 cpuid[cpuid_length];
329         int ret;
330
331         ret = rockchip_cpuid_from_efuse(cpuid_offset, cpuid_length, cpuid);
332         if (ret)
333                 return ret;
334
335         ret = rockchip_cpuid_set(cpuid, cpuid_length);
336         if (ret)
337                 return ret;
338
339         ret = rockchip_setup_macaddr();
340
341         return ret;
342 }
343 #endif