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