uniphier_boot_device.c 4.77 KB
Newer Older
1
/*
2
 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
3
4
5
6
7
8
9
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
10
11
12

#include <lib/mmio.h>
#include <lib/utils_def.h>
13
14
15

#include "uniphier.h"

16
17
18
19
20
21
22
23
#define UNIPHIER_PINMON0		0x0
#define UNIPHIER_PINMON2		0x8

static const uintptr_t uniphier_pinmon_base[] = {
	[UNIPHIER_SOC_LD11] = 0x5f900100,
	[UNIPHIER_SOC_LD20] = 0x5f900100,
	[UNIPHIER_SOC_PXS3] = 0x5f900100,
};
24

25
static bool uniphier_ld11_is_usb_boot(uint32_t pinmon)
26
27
28
29
{
	return !!(~pinmon & 0x00000080);
}

30
static bool uniphier_ld20_is_usb_boot(uint32_t pinmon)
31
32
33
34
{
	return !!(~pinmon & 0x00000780);
}

35
static bool uniphier_pxs3_is_usb_boot(uint32_t pinmon)
36
{
37
38
	uintptr_t pinmon_base = uniphier_pinmon_base[UNIPHIER_SOC_PXS3];
	uint32_t pinmon2 = mmio_read_32(pinmon_base + UNIPHIER_PINMON2);
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

	return !!(pinmon2 & BIT(31));
}

static const unsigned int uniphier_ld11_boot_device_table[] = {
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_NOR,
};

static unsigned int uniphier_ld11_get_boot_device(uint32_t pinmon)
{
	unsigned int boot_sel = (pinmon >> 1) & 0x1f;

	assert(boot_sel < ARRAY_SIZE(uniphier_ld11_boot_device_table));

	return uniphier_ld11_boot_device_table[boot_sel];
}

static const unsigned int uniphier_pxs3_boot_device_table[] = {
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_EMMC,
	UNIPHIER_BOOT_DEVICE_NAND,
	UNIPHIER_BOOT_DEVICE_NAND,
};

static unsigned int uniphier_pxs3_get_boot_device(uint32_t pinmon)
{
	unsigned int boot_sel = (pinmon >> 1) & 0xf;

	assert(boot_sel < ARRAY_SIZE(uniphier_pxs3_boot_device_table));

	return uniphier_pxs3_boot_device_table[boot_sel];
}

struct uniphier_boot_device_info {
116
117
	bool have_boot_swap;
	bool (*is_sd_boot)(uint32_t pinmon);
118
	bool (*is_usb_boot)(uint32_t pinmon);
119
120
121
122
123
	unsigned int (*get_boot_device)(uint32_t pinmon);
};

static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
	[UNIPHIER_SOC_LD11] = {
124
		.have_boot_swap = true,
125
126
127
128
		.is_usb_boot = uniphier_ld11_is_usb_boot,
		.get_boot_device = uniphier_ld11_get_boot_device,
	},
	[UNIPHIER_SOC_LD20] = {
129
		.have_boot_swap = true,
130
131
132
133
		.is_usb_boot = uniphier_ld20_is_usb_boot,
		.get_boot_device = uniphier_ld11_get_boot_device,
	},
	[UNIPHIER_SOC_PXS3] = {
134
		.have_boot_swap = true,
135
136
137
138
139
140
141
142
		.is_usb_boot = uniphier_pxs3_is_usb_boot,
		.get_boot_device = uniphier_pxs3_get_boot_device,
	},
};

unsigned int uniphier_get_boot_device(unsigned int soc)
{
	const struct uniphier_boot_device_info *info;
143
	uintptr_t pinmon_base;
144
145
146
147
148
	uint32_t pinmon;

	assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
	info = &uniphier_boot_device_info[soc];

149
150
151
152
	assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
	pinmon_base = uniphier_pinmon_base[soc];

	pinmon = mmio_read_32(pinmon_base + UNIPHIER_PINMON0);
153

154
	if (info->have_boot_swap && !(pinmon & BIT(29)))
155
156
		return UNIPHIER_BOOT_DEVICE_NOR;

157
158
159
160
	if (info->is_sd_boot && info->is_sd_boot(pinmon))
		return UNIPHIER_BOOT_DEVICE_SD;

	if (info->is_usb_boot && info->is_usb_boot(pinmon))
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
		return UNIPHIER_BOOT_DEVICE_USB;

	return info->get_boot_device(pinmon);
}

static const bool uniphier_have_onchip_scp[] = {
	[UNIPHIER_SOC_LD11] = true,
	[UNIPHIER_SOC_LD20] = true,
	[UNIPHIER_SOC_PXS3] = false,
};

unsigned int uniphier_get_boot_master(unsigned int soc)
{
	assert(soc < ARRAY_SIZE(uniphier_have_onchip_scp));

	if (uniphier_have_onchip_scp[soc]) {
177
178
179
180
181
182
		uintptr_t pinmon_base;

		assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
		pinmon_base = uniphier_pinmon_base[soc];

		if (mmio_read_32(pinmon_base + UNIPHIER_PINMON0) & BIT(27))
183
184
185
186
187
188
189
			return UNIPHIER_BOOT_MASTER_THIS;
		else
			return UNIPHIER_BOOT_MASTER_SCP;
	} else {
		return UNIPHIER_BOOT_MASTER_EXT;
	}
}