/*
 * Copyright (c) 2012 Michael Walle
 * Michael Walle <michael@walle.cc>
 *
 * Based on sheevaplug/sheevaplug.c by
 *   Marvell Semiconductor <www.marvell.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <net.h>
#include <malloc.h>
#include <netdev.h>
#include <miiphy.h>
#include <asm/arch/kirkwood.h>
#include <asm/arch/cpu.h>
#include <asm/arch/mpp.h>
#include <asm/arch/gpio.h>
#include <spi_flash.h>

#include "lsxl.h"

/*
 * Rescue mode
 *
 * Selected by holding the push button for 3 seconds, while powering on
 * the device.
 *
 * These linkstations don't have a (populated) serial port. There is no
 * way to access an (unmodified) board other than using the netconsole. If
 * you want to recover from a bad environment setting or an empty environment,
 * you can do this only with a working network connection. Therefore, a random
 * ethernet address is generated if none is set and a DHCP request is sent.
 * After a successful DHCP response is received, the network settings are
 * configured and the ncip is unset. Therefore, all netconsole packets are
 * broadcasted.
 * Additionally, the bootsource is set to 'rescue'.
 */

#ifndef CONFIG_ENV_OVERWRITE
# error "You need to set CONFIG_ENV_OVERWRITE"
#endif

DECLARE_GLOBAL_DATA_PTR;

int board_early_init_f(void)
{
	/*
	 * default gpio configuration
	 * There are maximum 64 gpios controlled through 2 sets of registers
	 * the below configuration configures mainly initial LED status
	 */
	kw_config_gpio(LSXL_OE_VAL_LOW,
			LSXL_OE_VAL_HIGH,
			LSXL_OE_LOW, LSXL_OE_HIGH);

	/*
	 * Multi-Purpose Pins Functionality configuration
	 * These strappings are taken from the original vendor uboot port.
	 */
	static const u32 kwmpp_config[] = {
		MPP0_SPI_SCn,
		MPP1_SPI_MOSI,
		MPP2_SPI_SCK,
		MPP3_SPI_MISO,
		MPP4_UART0_RXD,
		MPP5_UART0_TXD,
		MPP6_SYSRST_OUTn,
		MPP7_GPO,
		MPP8_GPIO,
		MPP9_GPIO,
		MPP10_GPO,		/* HDD power */
		MPP11_GPIO,		/* USB Vbus enable */
		MPP12_SD_CLK,
		MPP13_SD_CMD,
		MPP14_SD_D0,
		MPP15_SD_D1,
		MPP16_SD_D2,
		MPP17_SD_D3,
		MPP18_GPO,		/* fan speed high */
		MPP19_GPO,		/* fan speed low */
		MPP20_GE1_0,
		MPP21_GE1_1,
		MPP22_GE1_2,
		MPP23_GE1_3,
		MPP24_GE1_4,
		MPP25_GE1_5,
		MPP26_GE1_6,
		MPP27_GE1_7,
		MPP28_GPIO,
		MPP29_GPIO,
		MPP30_GE1_10,
		MPP31_GE1_11,
		MPP32_GE1_12,
		MPP33_GE1_13,
		MPP34_GPIO,
		MPP35_GPIO,
		MPP36_GPIO,		/* function LED */
		MPP37_GPIO,		/* alarm LED */
		MPP38_GPIO,		/* info LED */
		MPP39_GPIO,		/* power LED */
		MPP40_GPIO,		/* fan alarm */
		MPP41_GPIO,		/* funtion button */
		MPP42_GPIO,		/* power switch */
		MPP43_GPIO,		/* power auto switch */
		MPP44_GPIO,
		MPP45_GPIO,
		MPP46_GPIO,
		MPP47_GPIO,
		MPP48_GPIO,		/* function red LED */
		MPP49_GPIO,
		0
	};

	kirkwood_mpp_conf(kwmpp_config, NULL);

	return 0;
}

#define LED_OFF             0
#define LED_ALARM_ON        1
#define LED_ALARM_BLINKING  2
#define LED_POWER_ON        3
#define LED_POWER_BLINKING  4
#define LED_INFO_ON         5
#define LED_INFO_BLINKING   6

static void __set_led(int blink_alarm, int blink_info, int blink_power,
		int value_alarm, int value_info, int value_power)
{
	kw_gpio_set_blink(GPIO_ALARM_LED, blink_alarm);
	kw_gpio_set_blink(GPIO_INFO_LED, blink_info);
	kw_gpio_set_blink(GPIO_POWER_LED, blink_power);
	kw_gpio_set_value(GPIO_ALARM_LED, value_alarm);
	kw_gpio_set_value(GPIO_INFO_LED, value_info);
	kw_gpio_set_value(GPIO_POWER_LED, value_power);
}

static void set_led(int state)
{
	switch (state) {
	case LED_OFF:
		__set_led(0, 0, 0, 1, 1, 1);
		break;
	case LED_ALARM_ON:
		__set_led(0, 0, 0, 0, 1, 1);
		break;
	case LED_ALARM_BLINKING:
		__set_led(1, 0, 0, 1, 1, 1);
		break;
	case LED_INFO_ON:
		__set_led(0, 0, 0, 1, 0, 1);
		break;
	case LED_INFO_BLINKING:
		__set_led(0, 1, 0, 1, 1, 1);
		break;
	case LED_POWER_ON:
		__set_led(0, 0, 0, 1, 1, 0);
		break;
	case LED_POWER_BLINKING:
		__set_led(0, 0, 1, 1, 1, 1);
		break;
	}
}

int board_init(void)
{
	/* address of boot parameters */
	gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;

	set_led(LED_POWER_BLINKING);

	return 0;
}

#ifdef CONFIG_MISC_INIT_R
static void check_power_switch(void)
{
	if (kw_gpio_get_value(GPIO_POWER_SWITCH)) {
		/* turn off fan, HDD and USB power */
		kw_gpio_set_value(GPIO_HDD_POWER, 0);
		kw_gpio_set_value(GPIO_USB_VBUS, 0);
		kw_gpio_set_value(GPIO_FAN_HIGH, 1);
		kw_gpio_set_value(GPIO_FAN_LOW, 1);
		set_led(LED_OFF);

		/* loop until released */
		while (kw_gpio_get_value(GPIO_POWER_SWITCH))
			;

		/* turn power on again */
		kw_gpio_set_value(GPIO_HDD_POWER, 1);
		kw_gpio_set_value(GPIO_USB_VBUS, 1);
		kw_gpio_set_value(GPIO_FAN_HIGH, 0);
		kw_gpio_set_value(GPIO_FAN_LOW, 0);
		set_led(LED_POWER_BLINKING);
	}
}

void check_enetaddr(void)
{
	uchar enetaddr[6];

	if (!eth_getenv_enetaddr("ethaddr", enetaddr)) {
		/* signal unset/invalid ethaddr to user */
		set_led(LED_INFO_BLINKING);
	}
}

static void erase_environment(void)
{
	struct spi_flash *flash;

	printf("Erasing environment..\n");
	flash = spi_flash_probe(0, 0, 1000000, SPI_MODE_3);
	if (!flash) {
		printf("Erasing flash failed\n");
		return;
	}

	spi_flash_erase(flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE);
	spi_flash_free(flash);
	do_reset(NULL, 0, 0, NULL);
}

static void rescue_mode(void)
{
	uchar enetaddr[6];

	printf("Entering rescue mode..\n");
#ifdef CONFIG_RANDOM_MACADDR
	if (!eth_getenv_enetaddr("ethaddr", enetaddr)) {
		eth_random_addr(enetaddr);
		if (eth_setenv_enetaddr("ethaddr", enetaddr)) {
			printf("Failed to set ethernet address\n");
				set_led(LED_ALARM_BLINKING);
			return;
		}
	}
#endif
	setenv("bootsource", "rescue");
}

static void check_push_button(void)
{
	int i = 0;

	while (!kw_gpio_get_value(GPIO_FUNC_BUTTON)) {
		udelay(100000);
		i++;

		if (i == 10)
			set_led(LED_INFO_ON);

		if (i >= 100) {
			set_led(LED_INFO_BLINKING);
			break;
		}
	}

	if (i >= 100)
		erase_environment();
	else if (i >= 10)
		rescue_mode();
}

int misc_init_r(void)
{
	check_power_switch();
	check_enetaddr();
	check_push_button();

	return 0;
}
#endif

#ifdef CONFIG_SHOW_BOOT_PROGRESS
void show_boot_progress(int progress)
{
	if (progress > 0)
		return;

	/* this is not an error, eg. bootp with autoload=no will trigger this */
	if (progress == -BOOTSTAGE_ID_NET_LOADED)
		return;

	set_led(LED_ALARM_BLINKING);
}
#endif
