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 109