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