summaryrefslogtreecommitdiff
path: root/arch/arm/mach-uniphier/boot-mode/boot-mode.c
blob: a5527704df3d58464b29ec95711c4a79a64196ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <mmc.h>
#include <spl.h>
#include <linux/errno.h>

#include "../sbc/sbc-regs.h"
#include "../soc-info.h"
#include "boot-device.h"

u32 spl_boot_device_raw(void)
{
	if (boot_is_swapped())
		return BOOT_DEVICE_NOR;

	switch (uniphier_get_soc_id()) {
#if defined(CONFIG_ARCH_UNIPHIER_SLD3)
	case UNIPHIER_SLD3_ID:
		return uniphier_sld3_boot_device();
#endif
#if defined(CONFIG_ARCH_UNIPHIER_LD4) || defined(CONFIG_ARCH_UNIPHIER_PRO4) || \
	defined(CONFIG_ARCH_UNIPHIER_SLD8)
	case UNIPHIER_LD4_ID:
	case UNIPHIER_PRO4_ID:
	case UNIPHIER_SLD8_ID:
		return uniphier_ld4_boot_device();
#endif
#if defined(CONFIG_ARCH_UNIPHIER_PRO5)
	case UNIPHIER_PRO5_ID:
		return uniphier_pro5_boot_device();
#endif
#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B)
	case UNIPHIER_PXS2_ID:
	case UNIPHIER_LD6B_ID:
		return uniphier_pxs2_boot_device();
#endif
#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20)
	case UNIPHIER_LD11_ID:
	case UNIPHIER_LD20_ID:
		return uniphier_ld20_boot_device();
#endif
	default:
		return BOOT_DEVICE_NONE;
	}
}

u32 spl_boot_device(void)
{
	u32 mode;

	mode = spl_boot_device_raw();

	switch (uniphier_get_soc_id()) {
#if defined(CONFIG_ARCH_UNIPHIER_PXS2) || defined(CONFIG_ARCH_UNIPHIER_LD6B)
	case UNIPHIER_PXS2_ID:
	case UNIPHIER_LD6B_ID:
		if (mode == BOOT_DEVICE_USB)
			mode = BOOT_DEVICE_NOR;
		break;
#endif
#if defined(CONFIG_ARCH_UNIPHIER_LD11) || defined(CONFIG_ARCH_UNIPHIER_LD20)
	case UNIPHIER_LD11_ID:
	case UNIPHIER_LD20_ID:
		if (mode == BOOT_DEVICE_MMC1 || mode == BOOT_DEVICE_USB)
			mode = BOOT_DEVICE_BOARD;
		break;
#endif
	default:
		break;
	}

	return mode;
}

u32 spl_boot_mode(const u32 boot_device)
{
	struct mmc *mmc;

	/*
	 * work around a bug in the Boot ROM of PH1-sLD3, LD4, Pro4, and sLD8:
	 *
	 * The boot ROM in these SoCs breaks the PARTITION_CONFIG [179] of
	 * Extended CSD register; when switching to the Boot Partition 1, the
	 * Boot ROM should issue the SWITCH command (CMD6) with Set Bits for
	 * the Access Bits, but in fact it uses Write Byte for the Access Bits.
	 * As a result, the BOOT_PARTITION_ENABLE field of the PARTITION_CONFIG
	 * is lost.  This bug was fixed for PH1-Pro5 and later SoCs.
	 *
	 * Fixup mmc->part_config here because it is used to determine the
	 * partition which the U-Boot image is read from.
	 */
	mmc = find_mmc_device(0);
	mmc->part_config &= ~EXT_CSD_BOOT_PART_NUM(PART_ACCESS_MASK);
	mmc->part_config |= EXT_CSD_BOOT_PARTITION_ENABLE;

	return MMCSD_MODE_EMMCBOOT;
}

#if defined(CONFIG_DM_MMC) && !defined(CONFIG_SPL_BUILD)
static int find_first_mmc_device(void)
{
	struct mmc *mmc;
	int i;

	for (i = 0; (mmc = find_mmc_device(i)); i++) {
		if (!mmc_init(mmc) && IS_MMC(mmc))
			return i;
	}

	return -ENODEV;
}

int mmc_get_env_dev(void)
{
	return find_first_mmc_device();
}

static int do_mmcsetn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	int dev;

	dev = find_first_mmc_device();
	if (dev < 0)
		return CMD_RET_FAILURE;

	setenv_ulong("mmc_first_dev", dev);
	return CMD_RET_SUCCESS;
}

U_BOOT_CMD(
	   mmcsetn,	1,	1,	do_mmcsetn,
	"Set the first MMC (not SD) dev number to \"mmc_first_dev\" environment",
	""
);
#endif