]>
Commit | Line | Data |
---|---|---|
9b0bc593 PT |
1 | /* |
2 | * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <dm.h> | |
9 | #include <mmc.h> | |
10 | #include <spl.h> | |
11 | ||
12 | #if CONFIG_IS_ENABLED(OF_CONTROL) | |
13 | static int spl_node_to_boot_device(int node) | |
14 | { | |
15 | struct udevice *parent; | |
16 | ||
17 | /* | |
18 | * This should eventually move into the SPL code, once SPL becomes | |
19 | * aware of the block-device layer. Until then (and to avoid unneeded | |
20 | * delays in getting this feature out, it lives at the board-level). | |
21 | */ | |
22 | if (!uclass_get_device_by_of_offset(UCLASS_MMC, node, &parent)) { | |
23 | struct udevice *dev; | |
24 | struct blk_desc *desc = NULL; | |
25 | ||
26 | for (device_find_first_child(parent, &dev); | |
27 | dev; | |
28 | device_find_next_child(&dev)) { | |
29 | if (device_get_uclass_id(dev) == UCLASS_BLK) { | |
30 | desc = dev_get_uclass_platdata(dev); | |
31 | break; | |
32 | } | |
33 | } | |
34 | ||
35 | if (!desc) | |
36 | return -ENOENT; | |
37 | ||
38 | switch (desc->devnum) { | |
39 | case 0: | |
40 | return BOOT_DEVICE_MMC1; | |
41 | case 1: | |
42 | return BOOT_DEVICE_MMC2; | |
43 | default: | |
44 | return -ENOSYS; | |
45 | } | |
46 | } | |
47 | ||
48 | /* | |
49 | * SPL doesn't differentiate SPI flashes, so we keep the detection | |
50 | * brief and inaccurate... hopefully, the common SPL layer can be | |
51 | * extended with awareness of the BLK layer (and matching OF_CONTROL) | |
52 | * soon. | |
53 | */ | |
54 | if (!uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, &parent)) | |
55 | return BOOT_DEVICE_SPI; | |
56 | ||
57 | return -1; | |
58 | } | |
59 | ||
60 | void board_boot_order(u32 *spl_boot_list) | |
61 | { | |
62 | const void *blob = gd->fdt_blob; | |
63 | int chosen_node = fdt_path_offset(blob, "/chosen"); | |
64 | int idx = 0; | |
65 | int elem; | |
66 | int boot_device; | |
67 | int node; | |
68 | const char *conf; | |
69 | ||
70 | if (chosen_node < 0) { | |
71 | debug("%s: /chosen not found, using spl_boot_device()\n", | |
72 | __func__); | |
73 | spl_boot_list[0] = spl_boot_device(); | |
74 | return; | |
75 | } | |
76 | ||
77 | for (elem = 0; | |
78 | (conf = fdt_stringlist_get(blob, chosen_node, | |
79 | "u-boot,spl-boot-order", elem, NULL)); | |
80 | elem++) { | |
81 | /* First check if the list element is an alias */ | |
82 | const char *alias = fdt_get_alias(blob, conf); | |
83 | if (alias) | |
84 | conf = alias; | |
85 | ||
86 | /* Try to resolve the config item (or alias) as a path */ | |
87 | node = fdt_path_offset(blob, conf); | |
88 | if (node < 0) { | |
89 | debug("%s: could not find %s in FDT", __func__, conf); | |
90 | continue; | |
91 | } | |
92 | ||
93 | /* Try to map this back onto SPL boot devices */ | |
94 | boot_device = spl_node_to_boot_device(node); | |
95 | if (boot_device < 0) { | |
96 | debug("%s: could not map node @%x to a boot-device\n", | |
97 | __func__, node); | |
98 | continue; | |
99 | } | |
100 | ||
101 | spl_boot_list[idx++] = boot_device; | |
102 | } | |
103 | ||
104 | /* If we had no matches, fall back to spl_boot_device */ | |
105 | if (idx == 0) | |
106 | spl_boot_list[0] = spl_boot_device(); | |
107 | } | |
108 | #endif |