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