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