1 /*
2  * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <stdbool.h>
9 #include <stddef.h>
10 
11 #include <lib/mmio.h>
12 #include <lib/utils_def.h>
13 
14 #include "uniphier.h"
15 
16 #define UNIPHIER_PINMON0		0x0
17 #define UNIPHIER_PINMON2		0x8
18 
19 static const uintptr_t uniphier_pinmon_base[] = {
20 	[UNIPHIER_SOC_LD11] = 0x5f900100,
21 	[UNIPHIER_SOC_LD20] = 0x5f900100,
22 	[UNIPHIER_SOC_PXS3] = 0x5f900100,
23 };
24 
uniphier_ld11_is_usb_boot(uint32_t pinmon)25 static bool uniphier_ld11_is_usb_boot(uint32_t pinmon)
26 {
27 	return !!(~pinmon & 0x00000080);
28 }
29 
uniphier_ld20_is_usb_boot(uint32_t pinmon)30 static bool uniphier_ld20_is_usb_boot(uint32_t pinmon)
31 {
32 	return !!(~pinmon & 0x00000780);
33 }
34 
uniphier_pxs3_is_usb_boot(uint32_t pinmon)35 static bool uniphier_pxs3_is_usb_boot(uint32_t pinmon)
36 {
37 	uintptr_t pinmon_base = uniphier_pinmon_base[UNIPHIER_SOC_PXS3];
38 	uint32_t pinmon2 = mmio_read_32(pinmon_base + UNIPHIER_PINMON2);
39 
40 	return !!(pinmon2 & BIT(31));
41 }
42 
43 static const unsigned int uniphier_ld11_boot_device_table[] = {
44 	UNIPHIER_BOOT_DEVICE_NAND,
45 	UNIPHIER_BOOT_DEVICE_NAND,
46 	UNIPHIER_BOOT_DEVICE_NAND,
47 	UNIPHIER_BOOT_DEVICE_NAND,
48 	UNIPHIER_BOOT_DEVICE_NAND,
49 	UNIPHIER_BOOT_DEVICE_NAND,
50 	UNIPHIER_BOOT_DEVICE_NAND,
51 	UNIPHIER_BOOT_DEVICE_NAND,
52 	UNIPHIER_BOOT_DEVICE_NAND,
53 	UNIPHIER_BOOT_DEVICE_NAND,
54 	UNIPHIER_BOOT_DEVICE_NAND,
55 	UNIPHIER_BOOT_DEVICE_NAND,
56 	UNIPHIER_BOOT_DEVICE_NAND,
57 	UNIPHIER_BOOT_DEVICE_NAND,
58 	UNIPHIER_BOOT_DEVICE_NAND,
59 	UNIPHIER_BOOT_DEVICE_NAND,
60 	UNIPHIER_BOOT_DEVICE_NAND,
61 	UNIPHIER_BOOT_DEVICE_NAND,
62 	UNIPHIER_BOOT_DEVICE_NAND,
63 	UNIPHIER_BOOT_DEVICE_NAND,
64 	UNIPHIER_BOOT_DEVICE_NAND,
65 	UNIPHIER_BOOT_DEVICE_NAND,
66 	UNIPHIER_BOOT_DEVICE_NAND,
67 	UNIPHIER_BOOT_DEVICE_NAND,
68 	UNIPHIER_BOOT_DEVICE_EMMC,
69 	UNIPHIER_BOOT_DEVICE_EMMC,
70 	UNIPHIER_BOOT_DEVICE_EMMC,
71 	UNIPHIER_BOOT_DEVICE_EMMC,
72 	UNIPHIER_BOOT_DEVICE_EMMC,
73 	UNIPHIER_BOOT_DEVICE_EMMC,
74 	UNIPHIER_BOOT_DEVICE_EMMC,
75 	UNIPHIER_BOOT_DEVICE_NOR,
76 };
77 
uniphier_ld11_get_boot_device(uint32_t pinmon)78 static unsigned int uniphier_ld11_get_boot_device(uint32_t pinmon)
79 {
80 	unsigned int boot_sel = (pinmon >> 1) & 0x1f;
81 
82 	assert(boot_sel < ARRAY_SIZE(uniphier_ld11_boot_device_table));
83 
84 	return uniphier_ld11_boot_device_table[boot_sel];
85 }
86 
87 static const unsigned int uniphier_pxs3_boot_device_table[] = {
88 	UNIPHIER_BOOT_DEVICE_NAND,
89 	UNIPHIER_BOOT_DEVICE_NAND,
90 	UNIPHIER_BOOT_DEVICE_NAND,
91 	UNIPHIER_BOOT_DEVICE_NAND,
92 	UNIPHIER_BOOT_DEVICE_NAND,
93 	UNIPHIER_BOOT_DEVICE_NAND,
94 	UNIPHIER_BOOT_DEVICE_NAND,
95 	UNIPHIER_BOOT_DEVICE_NAND,
96 	UNIPHIER_BOOT_DEVICE_EMMC,
97 	UNIPHIER_BOOT_DEVICE_EMMC,
98 	UNIPHIER_BOOT_DEVICE_EMMC,
99 	UNIPHIER_BOOT_DEVICE_EMMC,
100 	UNIPHIER_BOOT_DEVICE_EMMC,
101 	UNIPHIER_BOOT_DEVICE_EMMC,
102 	UNIPHIER_BOOT_DEVICE_NAND,
103 	UNIPHIER_BOOT_DEVICE_NAND,
104 };
105 
uniphier_pxs3_get_boot_device(uint32_t pinmon)106 static unsigned int uniphier_pxs3_get_boot_device(uint32_t pinmon)
107 {
108 	unsigned int boot_sel = (pinmon >> 1) & 0xf;
109 
110 	assert(boot_sel < ARRAY_SIZE(uniphier_pxs3_boot_device_table));
111 
112 	return uniphier_pxs3_boot_device_table[boot_sel];
113 }
114 
115 struct uniphier_boot_device_info {
116 	bool have_boot_swap;
117 	bool (*is_sd_boot)(uint32_t pinmon);
118 	bool (*is_usb_boot)(uint32_t pinmon);
119 	unsigned int (*get_boot_device)(uint32_t pinmon);
120 };
121 
122 static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
123 	[UNIPHIER_SOC_LD11] = {
124 		.have_boot_swap = true,
125 		.is_usb_boot = uniphier_ld11_is_usb_boot,
126 		.get_boot_device = uniphier_ld11_get_boot_device,
127 	},
128 	[UNIPHIER_SOC_LD20] = {
129 		.have_boot_swap = true,
130 		.is_usb_boot = uniphier_ld20_is_usb_boot,
131 		.get_boot_device = uniphier_ld11_get_boot_device,
132 	},
133 	[UNIPHIER_SOC_PXS3] = {
134 		.have_boot_swap = true,
135 		.is_usb_boot = uniphier_pxs3_is_usb_boot,
136 		.get_boot_device = uniphier_pxs3_get_boot_device,
137 	},
138 };
139 
uniphier_get_boot_device(unsigned int soc)140 unsigned int uniphier_get_boot_device(unsigned int soc)
141 {
142 	const struct uniphier_boot_device_info *info;
143 	uintptr_t pinmon_base;
144 	uint32_t pinmon;
145 
146 	assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
147 	info = &uniphier_boot_device_info[soc];
148 
149 	assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
150 	pinmon_base = uniphier_pinmon_base[soc];
151 
152 	pinmon = mmio_read_32(pinmon_base + UNIPHIER_PINMON0);
153 
154 	if (info->have_boot_swap && !(pinmon & BIT(29)))
155 		return UNIPHIER_BOOT_DEVICE_NOR;
156 
157 	if (info->is_sd_boot && info->is_sd_boot(pinmon))
158 		return UNIPHIER_BOOT_DEVICE_SD;
159 
160 	if (info->is_usb_boot && info->is_usb_boot(pinmon))
161 		return UNIPHIER_BOOT_DEVICE_USB;
162 
163 	return info->get_boot_device(pinmon);
164 }
165 
166 static const bool uniphier_have_onchip_scp[] = {
167 	[UNIPHIER_SOC_LD11] = true,
168 	[UNIPHIER_SOC_LD20] = true,
169 	[UNIPHIER_SOC_PXS3] = false,
170 };
171 
uniphier_get_boot_master(unsigned int soc)172 unsigned int uniphier_get_boot_master(unsigned int soc)
173 {
174 	assert(soc < ARRAY_SIZE(uniphier_have_onchip_scp));
175 
176 	if (uniphier_have_onchip_scp[soc]) {
177 		uintptr_t pinmon_base;
178 
179 		assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
180 		pinmon_base = uniphier_pinmon_base[soc];
181 
182 		if (mmio_read_32(pinmon_base + UNIPHIER_PINMON0) & BIT(27))
183 			return UNIPHIER_BOOT_MASTER_THIS;
184 		else
185 			return UNIPHIER_BOOT_MASTER_SCP;
186 	} else {
187 		return UNIPHIER_BOOT_MASTER_EXT;
188 	}
189 }
190