1/* 2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7#include <common.h> 8#include <mmc.h> 9#include <spl.h> 10#include <linux/err.h> 11 12#include "../sbc/sbc-regs.h" 13#include "../soc-info.h" 14#include "boot-device.h" 15 16u32 spl_boot_device_raw(void) 17{ 18 if (boot_is_swapped()) 19 return BOOT_DEVICE_NOR; 20 21 switch (uniphier_get_soc_type()) { 22#if defined(CONFIG_ARCH_UNIPHIER_SLD3) 23 case SOC_UNIPHIER_SLD3: 24 return uniphier_sld3_boot_device(); 25#endif 26#if defined(CONFIG_ARCH_UNIPHIER_LD4) || defined(CONFIG_ARCH_UNIPHIER_PRO4) || \ 27 defined(CONFIG_ARCH_UNIPHIER_SLD8) 28 case SOC_UNIPHIER_LD4: 29 case SOC_UNIPHIER_PRO4: 30 case SOC_UNIPHIER_SLD8: 31 return uniphier_ld4_boot_device(); 32#endif 33#if defined(CONFIG_ARCH_UNIPHIER_PRO5) 34 case SOC_UNIPHIER_PRO5: 35 return uniphier_pro5_boot_device(); 36#endif 37#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B) 38 case SOC_UNIPHIER_PXS2: 39 case SOC_UNIPHIER_LD6B: 40 return uniphier_pxs2_boot_device(); 41#endif 42#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20) 43 case SOC_UNIPHIER_LD11: 44 case SOC_UNIPHIER_LD20: 45 return uniphier_ld20_boot_device(); 46#endif 47 default: 48 return BOOT_DEVICE_NONE; 49 } 50} 51 52u32 spl_boot_device(void) 53{ 54 u32 mode; 55 56 mode = spl_boot_device_raw(); 57 58 switch (uniphier_get_soc_type()) { 59#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B) 60 case SOC_UNIPHIER_PXS2: 61 case SOC_UNIPHIER_LD6B: 62 if (mode == BOOT_DEVICE_USB) 63 mode = BOOT_DEVICE_NOR; 64 break; 65#endif 66#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20) 67 case SOC_UNIPHIER_LD11: 68 case SOC_UNIPHIER_LD20: 69 if (mode == BOOT_DEVICE_MMC1 || mode == BOOT_DEVICE_USB) 70 mode = BOOT_DEVICE_BOARD; 71 break; 72#endif 73 default: 74 break; 75 } 76 77 return mode; 78} 79 80u32 spl_boot_mode(const u32 boot_device) 81{ 82 struct mmc *mmc; 83 84 /* 85 * work around a bug in the Boot ROM of PH1-sLD3, LD4, Pro4, and sLD8: 86 * 87 * The boot ROM in these SoCs breaks the PARTITION_CONFIG [179] of 88 * Extended CSD register; when switching to the Boot Partition 1, the 89 * Boot ROM should issue the SWITCH command (CMD6) with Set Bits for 90 * the Access Bits, but in fact it uses Write Byte for the Access Bits. 91 * As a result, the BOOT_PARTITION_ENABLE field of the PARTITION_CONFIG 92 * is lost. This bug was fixed for PH1-Pro5 and later SoCs. 93 * 94 * Fixup mmc->part_config here because it is used to determine the 95 * partition which the U-Boot image is read from. 96 */ 97 mmc = find_mmc_device(0); 98 mmc->part_config &= ~EXT_CSD_BOOT_PART_NUM(PART_ACCESS_MASK); 99 mmc->part_config |= EXT_CSD_BOOT_PARTITION_ENABLE; 100 101 return MMCSD_MODE_EMMCBOOT; 102} 103 104#if defined(CONFIG_DM_MMC) && !defined(CONFIG_SPL_BUILD) 105static int find_first_mmc_device(void) 106{ 107 struct mmc *mmc; 108 int i; 109 110 for (i = 0; (mmc = find_mmc_device(i)); i++) { 111 if (!mmc_init(mmc) && IS_MMC(mmc)) 112 return i; 113 } 114 115 return -ENODEV; 116} 117 118int mmc_get_env_dev(void) 119{ 120 return find_first_mmc_device(); 121} 122 123static int do_mmcsetn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 124{ 125 int dev; 126 127 dev = find_first_mmc_device(); 128 if (dev < 0) 129 return CMD_RET_FAILURE; 130 131 setenv_ulong("mmc_first_dev", dev); 132 return CMD_RET_SUCCESS; 133} 134 135U_BOOT_CMD( 136 mmcsetn, 1, 1, do_mmcsetn, 137 "Set the first MMC (not SD) dev number to \"mmc_first_dev\" environment", 138 "" 139); 140#endif 141