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

#include <bootstage.h>
#include <button.h>
#include <command.h>
#include <env.h>
#include <init.h>
#include <led.h>
#include <power/regulator.h>
#include <spi.h>
#include <spi_flash.h>
#include <asm/arch/cpu.h>
#include <asm/arch/mpp.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <linux/delay.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'.
 */

DECLARE_GLOBAL_DATA_PTR;

static bool force_rescue_mode;

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
	 */
	mvebu_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;
}

enum {
	LSXL_LED_OFF,
	LSXL_LED_ALARM,
	LSXL_LED_POWER,
	LSXL_LED_INFO,
};

static void __set_led(int alarm, int info, int power)
{
	struct udevice *led;
	int ret;

	ret = led_get_by_label("lsxl:red:alarm", &led);
	if (!ret)
		led_set_state(led, alarm);
	ret = led_get_by_label("lsxl:amber:info", &led);
	if (!ret)
		led_set_state(led, info);
	ret = led_get_by_label("lsxl:blue:power", &led);
	if (!ret)
		led_set_state(led, power);
}

static void set_led(int state)
{
	switch (state) {
	case LSXL_LED_OFF:
		__set_led(0, 0, 0);
		break;
	case LSXL_LED_ALARM:
		__set_led(1, 0, 0);
		break;
	case LSXL_LED_INFO:
		__set_led(0, 1, 0);
		break;
	case LSXL_LED_POWER:
		__set_led(0, 0, 1);
		break;
	}
}

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

	set_led(LSXL_LED_POWER);

	return 0;
}

static void check_power_switch(void)
{
	struct udevice *power_button, *hdd_power, *usb_power;
	int ret;

	ret = button_get_by_label("Power-on Switch", &power_button);
	if (ret)
		goto err;

	ret = regulator_get_by_platname("HDD Power", &hdd_power);
	if (ret)
		goto err;

	ret = regulator_get_by_platname("USB Power", &usb_power);
	if (ret)
		goto err;

	if (button_get_state(power_button) == BUTTON_OFF) {
		ret = regulator_set_enable(hdd_power, false);
		if (ret)
			goto err;
		ret = regulator_set_enable(usb_power, false);
		if (ret)
			goto err;
		/* TODO: fan off */
		set_led(LSXL_LED_OFF);

		/* loop until released */
		while (button_get_state(power_button) == BUTTON_OFF)
			;

		/* turn power on again */
		ret = regulator_set_enable(hdd_power, true);
		if (ret)
			goto err;
		ret = regulator_set_enable(usb_power, true);
		if (ret)
			goto err;
		/* TODO: fan on */
		set_led(LSXL_LED_POWER);
	};

	return;
err:
	printf("error in %s\n", __func__);
}

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

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

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)
{
	printf("Entering rescue mode..\n");
	env_set("bootsource", "rescue");
}

static void check_push_button(void)
{
	struct udevice *func_button;
	int i = 0;

	int ret;

	ret = button_get_by_label("Function Button", &func_button);
	if (ret)
		goto err;

	while (button_get_state(func_button) == BUTTON_ON) {
		udelay(100000);
		i++;

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

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

	if (i >= 100)
		erase_environment();
	else if (i >= 10)
		force_rescue_mode = true;

	return;
err:
	printf("error in %s\n", __func__);
}

int board_early_init_r(void)
{
	check_push_button();

	return 0;
}

int misc_init_r(void)
{
	check_power_switch();
	check_enetaddr();
	if (force_rescue_mode)
		rescue_mode();

	return 0;
}

#if CONFIG_IS_ENABLED(BOOTSTAGE)
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(LSXL_LED_ALARM);
}
#endif
