/*
 * Copyright 2009-2011 eXMeritus, A Boeing Company
 * Copyright 2007-2009 Freescale Semiconductor, Inc.
 *
 * SPDX-License-Identifier:	GPL-2.0+ 
 */

#include <common.h>
#include <command.h>
#include <pci.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/cache.h>
#include <asm/immap_85xx.h>
#include <asm/fsl_pci.h>
#include <asm/fsl_ddr_sdram.h>
#include <asm/io.h>
#include <miiphy.h>
#include <libfdt.h>
#include <linux/ctype.h>
#include <fdt_support.h>
#include <fsl_mdio.h>
#include <tsec.h>
#include <asm/fsl_law.h>
#include <netdev.h>
#include <malloc.h>
#include <i2c.h>
#include <pca953x.h>

#include "gpios.h"

DECLARE_GLOBAL_DATA_PTR;

int checkboard(void)
{
	unsigned int gpio_high = 0;
	unsigned int gpio_low  = 0;
	unsigned int gpio_in   = 0;
	unsigned int i;

	puts("Board: HWW-1U-1A ");

	/*
	 * First just figure out which CPU we're on, then use that to
	 * configure the lists of other GPIOs to be programmed.
	 */
	mpc85xx_gpio_set_in(GPIO_CPU_ID);
	if (hww1u1a_is_cpu_a()) {
		puts("CPU A\n");

		/* We want to turn on some LEDs */
		gpio_high |= GPIO_CPUA_CPU_READY;
		gpio_low  |= GPIO_CPUA_DEBUG_LED1;
		gpio_low  |= GPIO_CPUA_DEBUG_LED2;

		/* Disable the unused transmitters */
		gpio_low  |= GPIO_CPUA_TDIS1A;
		gpio_high |= GPIO_CPUA_TDIS1B;
		gpio_low  |= GPIO_CPUA_TDIS2A;
		gpio_high |= GPIO_CPUA_TDIS2B;
	} else {
		puts("CPU B\n");

		/* We want to turn on some LEDs */
		gpio_high |= GPIO_CPUB_CPU_READY;
		gpio_low  |= GPIO_CPUB_DEBUG_LED1;
		gpio_low  |= GPIO_CPUB_DEBUG_LED2;

		/* Enable the appropriate receivers */
		gpio_high |= GPIO_CPUB_RMUX_SEL0A;
		gpio_high |= GPIO_CPUB_RMUX_SEL0B;
		gpio_low  |= GPIO_CPUB_RMUX_SEL1A;
		gpio_low  |= GPIO_CPUB_RMUX_SEL1B;
	}

	/* These GPIOs are common */
	gpio_in   |= IRQ_I2CINT | IRQ_FANINT | IRQ_DIMM_EVENT;
	gpio_low  |= GPIO_RS422_RE;
	gpio_high |= GPIO_RS422_DE;

	/* Ok, now go ahead and program all of those in one go */
	mpc85xx_gpio_set(gpio_high|gpio_low|gpio_in,
			 gpio_high|gpio_low,
			 gpio_high);

	/*
	 * If things have been taken out of reset early (for example, by one
	 * of the BDI3000 debuggers), then we need to put them back in reset
	 * and delay a while before we continue.
	 */
	if (mpc85xx_gpio_get(GPIO_RESETS)) {
		ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;

		puts("Debugger detected... extra device reset enabled!\n");

		/* Put stuff into reset and disable the DDR controller */
		mpc85xx_gpio_set_low(GPIO_RESETS);
		out_be32(&ddr->sdram_cfg, 0x00000000);

		puts("    Waiting 1 sec for reset...");
		for (i = 0; i < 10; i++) {
			udelay(100000);
			puts(".");
		}
		puts("\n");
	}

	/* Now bring everything back out of reset again */
	mpc85xx_gpio_set_high(GPIO_RESETS);
	return 0;
}

/*
 * This little shell function just returns whether or not it's CPU A.
 * It can be used to select the right device-tree when booting, etc.
 */
int do_hww1u1a_test_cpu_a(cmd_tbl_t *cmdtp, int flag,
		int argc, char * const argv[])
{
	if (argc > 1)
		cmd_usage(cmdtp);

	if (hww1u1a_is_cpu_a())
		return 0;
	else
		return 1;
}
U_BOOT_CMD(
	test_cpu_a, 1, 0, do_hww1u1a_test_cpu_a,
	"Test if this is CPU A (versus B) on the eXMeritus HWW-1U-1A board",
	""
);

/* Create a prompt-like string: "uboot@HOSTNAME% " */
#define PROMPT_PREFIX "uboot@exm"
#define PROMPT_SUFFIX "% "

/* This function returns a PS1 prompt based on the serial number */
static char *hww1u1a_prompt;
const char *hww1u1a_get_ps1(void)
{
	unsigned long len, i, j;
	const char *serialnr;

	/* If our prompt was already set, just use that */
	if (hww1u1a_prompt)
		return hww1u1a_prompt;

	/* Use our serial number if present, otherwise a default */
	serialnr = getenv("serial#");
	if (!serialnr || !serialnr[0])
		serialnr = "999999-X";

	/*
	 * We will turn the serial number into a hostname by:
	 *   (A) Delete all non-alphanumerics.
	 *   (B) Lowercase all letters.
	 *   (C) Prefix "exm".
	 *   (D) Suffix "a" for CPU A and "b" for CPU B.
	 */
	for (i = 0, len = 0; serialnr[i]; i++) {
		if (isalnum(serialnr[i]))
			len++;
	}

	len += sizeof(PROMPT_PREFIX PROMPT_SUFFIX) + 1; /* Includes NUL */
	hww1u1a_prompt = malloc(len);
	if (!hww1u1a_prompt)
		return PROMPT_PREFIX "UNKNOWN(ENOMEM)" PROMPT_SUFFIX;

	/* Now actually fill it in */
	i = 0;

	/* Handle the prefix */
	for (j = 0; j < sizeof(PROMPT_PREFIX) - 1; j++)
		hww1u1a_prompt[i++] = PROMPT_PREFIX[j];

	/* Now the serial# part of the hostname */
	for (j = 0; serialnr[j]; j++)
		if (isalnum(serialnr[j]))
			hww1u1a_prompt[i++] = tolower(serialnr[j]);

	/* Now the CPU id ("a" or "b") */
	hww1u1a_prompt[i++] = hww1u1a_is_cpu_a() ? 'a' : 'b';

	/* Finally the suffix */
	for (j = 0; j < sizeof(PROMPT_SUFFIX); j++)
		hww1u1a_prompt[i++] = PROMPT_SUFFIX[j];

	/* This should all have added up, but just in case */
	hww1u1a_prompt[len - 1] = '\0';

	/* Now we're done */
	return hww1u1a_prompt;
}

void pci_init_board(void)
{
	fsl_pcie_init_board(0);
}

int board_early_init_r(void)
{
	const unsigned int flashbase = CONFIG_SYS_FLASH_BASE;
	const u8 flash_esel = find_tlb_idx((void *)flashbase, 1);

	/*
	 * Remap bootflash region to caching-inhibited
	 * so that flash can be erased properly.
	 */

	/* Flush d-cache and invalidate i-cache of any FLASH data */
	flush_dcache();
	invalidate_icache();

	/* invalidate existing TLB entry for FLASH */
	disable_tlb(flash_esel);

	set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS,
			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
			0, flash_esel, BOOKE_PAGESZ_256M, 1);

	return 0;
}

int board_eth_init(bd_t *bis)
{
	struct tsec_info_struct tsec_info[4];
	struct fsl_pq_mdio_info mdio_info;

	SET_STD_TSEC_INFO(tsec_info[0], 1);
	SET_STD_TSEC_INFO(tsec_info[1], 2);
	SET_STD_TSEC_INFO(tsec_info[2], 3);

	if (hww1u1a_is_cpu_a())
		tsec_info[2].phyaddr = TSEC3_PHY_ADDR_CPUA;
	else
		tsec_info[2].phyaddr = TSEC3_PHY_ADDR_CPUB;

	mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
	mdio_info.name = DEFAULT_MII_NAME;
	fsl_pq_mdio_init(bis, &mdio_info);

	tsec_eth_init(bis, tsec_info, 3);
	return pci_eth_init(bis);
}

void ft_board_setup(void *blob, bd_t *bd)
{
	phys_addr_t base;
	phys_size_t size;

	ft_cpu_setup(blob, bd);

	base = getenv_bootm_low();
	size = getenv_bootm_size();

	fdt_fixup_memory(blob, (u64)base, (u64)size);

	FT_FSL_PCI_SETUP;
}
