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