]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
f214a20e MW |
2 | /* |
3 | * Copyright (c) 2012 Michael Walle | |
4 | * Michael Walle <[email protected]> | |
5 | * | |
6 | * Based on sheevaplug/sheevaplug.c by | |
7 | * Marvell Semiconductor <www.marvell.com> | |
f214a20e MW |
8 | */ |
9 | ||
10 | #include <common.h> | |
52f24238 | 11 | #include <bootstage.h> |
09140113 | 12 | #include <command.h> |
9fb625ce | 13 | #include <env.h> |
f3998fdc | 14 | #include <env_internal.h> |
b79fdc76 | 15 | #include <flash.h> |
691d719d | 16 | #include <init.h> |
f214a20e MW |
17 | #include <net.h> |
18 | #include <malloc.h> | |
19 | #include <netdev.h> | |
20 | #include <miiphy.h> | |
ff0960f9 SG |
21 | #include <spi.h> |
22 | #include <spi_flash.h> | |
3dc23f78 | 23 | #include <asm/arch/soc.h> |
f214a20e MW |
24 | #include <asm/arch/cpu.h> |
25 | #include <asm/arch/mpp.h> | |
26 | #include <asm/arch/gpio.h> | |
401d1c4f | 27 | #include <asm/global_data.h> |
c05ed00a | 28 | #include <linux/delay.h> |
f214a20e MW |
29 | |
30 | #include "lsxl.h" | |
31 | ||
32 | /* | |
33 | * Rescue mode | |
34 | * | |
35 | * Selected by holding the push button for 3 seconds, while powering on | |
36 | * the device. | |
37 | * | |
38 | * These linkstations don't have a (populated) serial port. There is no | |
39 | * way to access an (unmodified) board other than using the netconsole. If | |
40 | * you want to recover from a bad environment setting or an empty environment, | |
41 | * you can do this only with a working network connection. Therefore, a random | |
42 | * ethernet address is generated if none is set and a DHCP request is sent. | |
43 | * After a successful DHCP response is received, the network settings are | |
23c9946a MW |
44 | * configured and the ncip is unset. Therefore, all netconsole packets are |
45 | * broadcasted. | |
f214a20e MW |
46 | * Additionally, the bootsource is set to 'rescue'. |
47 | */ | |
48 | ||
49 | #ifndef CONFIG_ENV_OVERWRITE | |
50 | # error "You need to set CONFIG_ENV_OVERWRITE" | |
51 | #endif | |
52 | ||
53 | DECLARE_GLOBAL_DATA_PTR; | |
54 | ||
55 | int board_early_init_f(void) | |
56 | { | |
57 | /* | |
58 | * default gpio configuration | |
59 | * There are maximum 64 gpios controlled through 2 sets of registers | |
60 | * the below configuration configures mainly initial LED status | |
61 | */ | |
d5c5132f SR |
62 | mvebu_config_gpio(LSXL_OE_VAL_LOW, |
63 | LSXL_OE_VAL_HIGH, | |
64 | LSXL_OE_LOW, LSXL_OE_HIGH); | |
f214a20e MW |
65 | |
66 | /* | |
67 | * Multi-Purpose Pins Functionality configuration | |
68 | * These strappings are taken from the original vendor uboot port. | |
69 | */ | |
9d86f0c3 | 70 | static const u32 kwmpp_config[] = { |
f214a20e MW |
71 | MPP0_SPI_SCn, |
72 | MPP1_SPI_MOSI, | |
73 | MPP2_SPI_SCK, | |
74 | MPP3_SPI_MISO, | |
75 | MPP4_UART0_RXD, | |
76 | MPP5_UART0_TXD, | |
77 | MPP6_SYSRST_OUTn, | |
78 | MPP7_GPO, | |
79 | MPP8_GPIO, | |
80 | MPP9_GPIO, | |
81 | MPP10_GPO, /* HDD power */ | |
82 | MPP11_GPIO, /* USB Vbus enable */ | |
83 | MPP12_SD_CLK, | |
84 | MPP13_SD_CMD, | |
85 | MPP14_SD_D0, | |
86 | MPP15_SD_D1, | |
87 | MPP16_SD_D2, | |
88 | MPP17_SD_D3, | |
89 | MPP18_GPO, /* fan speed high */ | |
90 | MPP19_GPO, /* fan speed low */ | |
91 | MPP20_GE1_0, | |
92 | MPP21_GE1_1, | |
93 | MPP22_GE1_2, | |
94 | MPP23_GE1_3, | |
95 | MPP24_GE1_4, | |
96 | MPP25_GE1_5, | |
97 | MPP26_GE1_6, | |
98 | MPP27_GE1_7, | |
99 | MPP28_GPIO, | |
100 | MPP29_GPIO, | |
101 | MPP30_GE1_10, | |
102 | MPP31_GE1_11, | |
103 | MPP32_GE1_12, | |
104 | MPP33_GE1_13, | |
105 | MPP34_GPIO, | |
106 | MPP35_GPIO, | |
107 | MPP36_GPIO, /* function LED */ | |
108 | MPP37_GPIO, /* alarm LED */ | |
109 | MPP38_GPIO, /* info LED */ | |
110 | MPP39_GPIO, /* power LED */ | |
111 | MPP40_GPIO, /* fan alarm */ | |
112 | MPP41_GPIO, /* funtion button */ | |
113 | MPP42_GPIO, /* power switch */ | |
114 | MPP43_GPIO, /* power auto switch */ | |
115 | MPP44_GPIO, | |
116 | MPP45_GPIO, | |
117 | MPP46_GPIO, | |
118 | MPP47_GPIO, | |
119 | MPP48_GPIO, /* function red LED */ | |
120 | MPP49_GPIO, | |
121 | 0 | |
122 | }; | |
123 | ||
124 | kirkwood_mpp_conf(kwmpp_config, NULL); | |
125 | ||
126 | return 0; | |
127 | } | |
128 | ||
129 | #define LED_OFF 0 | |
130 | #define LED_ALARM_ON 1 | |
131 | #define LED_ALARM_BLINKING 2 | |
132 | #define LED_POWER_ON 3 | |
133 | #define LED_POWER_BLINKING 4 | |
134 | #define LED_INFO_ON 5 | |
135 | #define LED_INFO_BLINKING 6 | |
136 | ||
137 | static void __set_led(int blink_alarm, int blink_info, int blink_power, | |
138 | int value_alarm, int value_info, int value_power) | |
139 | { | |
140 | kw_gpio_set_blink(GPIO_ALARM_LED, blink_alarm); | |
141 | kw_gpio_set_blink(GPIO_INFO_LED, blink_info); | |
142 | kw_gpio_set_blink(GPIO_POWER_LED, blink_power); | |
143 | kw_gpio_set_value(GPIO_ALARM_LED, value_alarm); | |
144 | kw_gpio_set_value(GPIO_INFO_LED, value_info); | |
145 | kw_gpio_set_value(GPIO_POWER_LED, value_power); | |
146 | } | |
147 | ||
148 | static void set_led(int state) | |
149 | { | |
150 | switch (state) { | |
151 | case LED_OFF: | |
a9f1a489 | 152 | __set_led(0, 0, 0, 1, 1, 1); |
f214a20e MW |
153 | break; |
154 | case LED_ALARM_ON: | |
155 | __set_led(0, 0, 0, 0, 1, 1); | |
156 | break; | |
157 | case LED_ALARM_BLINKING: | |
158 | __set_led(1, 0, 0, 1, 1, 1); | |
159 | break; | |
160 | case LED_INFO_ON: | |
161 | __set_led(0, 0, 0, 1, 0, 1); | |
162 | break; | |
163 | case LED_INFO_BLINKING: | |
164 | __set_led(0, 1, 0, 1, 1, 1); | |
165 | break; | |
166 | case LED_POWER_ON: | |
167 | __set_led(0, 0, 0, 1, 1, 0); | |
168 | break; | |
169 | case LED_POWER_BLINKING: | |
170 | __set_led(0, 0, 1, 1, 1, 1); | |
171 | break; | |
172 | } | |
173 | } | |
174 | ||
175 | int board_init(void) | |
176 | { | |
177 | /* address of boot parameters */ | |
96c5f081 | 178 | gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100; |
f214a20e MW |
179 | |
180 | set_led(LED_POWER_BLINKING); | |
181 | ||
182 | return 0; | |
183 | } | |
184 | ||
185 | #ifdef CONFIG_MISC_INIT_R | |
a9f1a489 MW |
186 | static void check_power_switch(void) |
187 | { | |
188 | if (kw_gpio_get_value(GPIO_POWER_SWITCH)) { | |
9bd2317b | 189 | /* turn off fan, HDD and USB power */ |
a9f1a489 MW |
190 | kw_gpio_set_value(GPIO_HDD_POWER, 0); |
191 | kw_gpio_set_value(GPIO_USB_VBUS, 0); | |
9bd2317b MW |
192 | kw_gpio_set_value(GPIO_FAN_HIGH, 1); |
193 | kw_gpio_set_value(GPIO_FAN_LOW, 1); | |
a9f1a489 MW |
194 | set_led(LED_OFF); |
195 | ||
196 | /* loop until released */ | |
197 | while (kw_gpio_get_value(GPIO_POWER_SWITCH)) | |
198 | ; | |
199 | ||
200 | /* turn power on again */ | |
201 | kw_gpio_set_value(GPIO_HDD_POWER, 1); | |
202 | kw_gpio_set_value(GPIO_USB_VBUS, 1); | |
9bd2317b MW |
203 | kw_gpio_set_value(GPIO_FAN_HIGH, 0); |
204 | kw_gpio_set_value(GPIO_FAN_LOW, 0); | |
a9f1a489 MW |
205 | set_led(LED_POWER_BLINKING); |
206 | } | |
207 | } | |
208 | ||
f214a20e MW |
209 | void check_enetaddr(void) |
210 | { | |
211 | uchar enetaddr[6]; | |
212 | ||
35affd7a | 213 | if (!eth_env_get_enetaddr("ethaddr", enetaddr)) { |
f214a20e MW |
214 | /* signal unset/invalid ethaddr to user */ |
215 | set_led(LED_INFO_BLINKING); | |
216 | } | |
217 | } | |
218 | ||
219 | static void erase_environment(void) | |
220 | { | |
221 | struct spi_flash *flash; | |
222 | ||
223 | printf("Erasing environment..\n"); | |
224 | flash = spi_flash_probe(0, 0, 1000000, SPI_MODE_3); | |
225 | if (!flash) { | |
226 | printf("Erasing flash failed\n"); | |
227 | return; | |
228 | } | |
229 | ||
230 | spi_flash_erase(flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE); | |
231 | spi_flash_free(flash); | |
232 | do_reset(NULL, 0, 0, NULL); | |
233 | } | |
234 | ||
235 | static void rescue_mode(void) | |
236 | { | |
f214a20e | 237 | printf("Entering rescue mode..\n"); |
382bee57 | 238 | env_set("bootsource", "rescue"); |
f214a20e MW |
239 | } |
240 | ||
241 | static void check_push_button(void) | |
242 | { | |
243 | int i = 0; | |
244 | ||
245 | while (!kw_gpio_get_value(GPIO_FUNC_BUTTON)) { | |
246 | udelay(100000); | |
247 | i++; | |
248 | ||
249 | if (i == 10) | |
250 | set_led(LED_INFO_ON); | |
251 | ||
252 | if (i >= 100) { | |
253 | set_led(LED_INFO_BLINKING); | |
254 | break; | |
255 | } | |
256 | } | |
257 | ||
258 | if (i >= 100) | |
259 | erase_environment(); | |
260 | else if (i >= 10) | |
261 | rescue_mode(); | |
262 | } | |
263 | ||
264 | int misc_init_r(void) | |
265 | { | |
a9f1a489 | 266 | check_power_switch(); |
f214a20e MW |
267 | check_enetaddr(); |
268 | check_push_button(); | |
269 | ||
270 | return 0; | |
271 | } | |
272 | #endif | |
273 | ||
274 | #ifdef CONFIG_SHOW_BOOT_PROGRESS | |
275 | void show_boot_progress(int progress) | |
276 | { | |
277 | if (progress > 0) | |
278 | return; | |
279 | ||
280 | /* this is not an error, eg. bootp with autoload=no will trigger this */ | |
281 | if (progress == -BOOTSTAGE_ID_NET_LOADED) | |
282 | return; | |
283 | ||
284 | set_led(LED_ALARM_BLINKING); | |
285 | } | |
286 | #endif |