/*
 * (C) Copyright 2008
 * Graeme Russ, graeme.russ@gmail.com.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <asm/io.h>
#include <asm/arch/sc520.h>
#include <net.h>
#include <netdev.h>

#ifdef CONFIG_HW_WATCHDOG
#include <watchdog.h>
#endif

#include "hardware.h"

DECLARE_GLOBAL_DATA_PTR;

unsigned long monitor_flash_len = CONFIG_SYS_MONITOR_LEN;

static void enet_timer_isr(void);
static void enet_toggle_run_led(void);
static void enet_setup_pars(void);

/*
 * Miscellaneous platform dependent initializations
 */
int board_early_init_f(void)
{
	u16 pio_out_cfg = 0x0000;

	/* Configure General Purpose Bus timing */
	writeb(CONFIG_SYS_SC520_GPCSRT, &sc520_mmcr->gpcsrt);
	writeb(CONFIG_SYS_SC520_GPCSPW, &sc520_mmcr->gpcspw);
	writeb(CONFIG_SYS_SC520_GPCSOFF, &sc520_mmcr->gpcsoff);
	writeb(CONFIG_SYS_SC520_GPRDW, &sc520_mmcr->gprdw);
	writeb(CONFIG_SYS_SC520_GPRDOFF, &sc520_mmcr->gprdoff);
	writeb(CONFIG_SYS_SC520_GPWRW, &sc520_mmcr->gpwrw);
	writeb(CONFIG_SYS_SC520_GPWROFF, &sc520_mmcr->gpwroff);

	/* Configure Programmable Input/Output Pins */
	writew(CONFIG_SYS_SC520_PIODIR15_0, &sc520_mmcr->piodir15_0);
	writew(CONFIG_SYS_SC520_PIODIR31_16, &sc520_mmcr->piodir31_16);
	writew(CONFIG_SYS_SC520_PIOPFS31_16, &sc520_mmcr->piopfs31_16);
	writew(CONFIG_SYS_SC520_PIOPFS15_0, &sc520_mmcr->piopfs15_0);
	writeb(CONFIG_SYS_SC520_CSPFS, &sc520_mmcr->cspfs);
	writeb(CONFIG_SYS_SC520_CLKSEL, &sc520_mmcr->clksel);

	/*
	 * Turn off top board
	 * Set StrataFlash chips to 16-bit width
	 * Set StrataFlash chips to normal (non reset/power down) mode
	 */
	pio_out_cfg |= CONFIG_SYS_ENET_TOP_BRD_PWR;
	pio_out_cfg |= CONFIG_SYS_ENET_SF_WIDTH;
	pio_out_cfg |= CONFIG_SYS_ENET_SF1_MODE;
	pio_out_cfg |= CONFIG_SYS_ENET_SF2_MODE;
	writew(pio_out_cfg, &sc520_mmcr->pioset15_0);

	/* Turn off auxiliary power output */
	writew(CONFIG_SYS_ENET_AUX_PWR, &sc520_mmcr->pioclr15_0);

	/* Clear FPGA program mode */
	writew(CONFIG_SYS_ENET_FPGA_PROG, &sc520_mmcr->pioset31_16);

	enet_setup_pars();

	/* Disable Watchdog */
	writew(0x3333, &sc520_mmcr->wdtmrctl);
	writew(0xcccc, &sc520_mmcr->wdtmrctl);
	writew(0x0000, &sc520_mmcr->wdtmrctl);

	/* Chip Select Configuration */
	writew(CONFIG_SYS_SC520_BOOTCS_CTRL, &sc520_mmcr->bootcsctl);
	writew(CONFIG_SYS_SC520_ROMCS1_CTRL, &sc520_mmcr->romcs1ctl);
	writew(CONFIG_SYS_SC520_ROMCS2_CTRL, &sc520_mmcr->romcs2ctl);

	writeb(CONFIG_SYS_SC520_ADDDECCTL, &sc520_mmcr->adddecctl);
	writeb(CONFIG_SYS_SC520_UART1CTL, &sc520_mmcr->uart1ctl);
	writeb(CONFIG_SYS_SC520_UART2CTL, &sc520_mmcr->uart2ctl);

	writeb(CONFIG_SYS_SC520_SYSARBCTL, &sc520_mmcr->sysarbctl);
	writew(CONFIG_SYS_SC520_SYSARBMENB, &sc520_mmcr->sysarbmenb);

	/* enable posted-writes */
	writeb(CONFIG_SYS_SC520_HBCTL, &sc520_mmcr->hbctl);

	return 0;
}

static void enet_setup_pars(void)
{
	/*
	 * PARs 11 and 12 are 2MB SRAM @ 0x19000000
	 *
	 * These are setup now because older version of U-Boot have them
	 * mapped to a different PAR which gets clobbered which prevents
	 * using SRAM for warm-booting a new image
	 */
	writel(CONFIG_SYS_SC520_SRAM1_PAR, &sc520_mmcr->par[11]);
	writel(CONFIG_SYS_SC520_SRAM2_PAR, &sc520_mmcr->par[12]);

	/* PARs 0 and 1 are Compact Flash slots (4kB each) */
	writel(CONFIG_SYS_SC520_CF1_PAR, &sc520_mmcr->par[0]);
	writel(CONFIG_SYS_SC520_CF2_PAR, &sc520_mmcr->par[1]);

	/* PAR 2 is used for Cache-As-RAM */

	/*
	 * PARs 5 through 8 are additional NS16550 UARTS
	 * 8 bytes each @ 0x013f8, 0x012f8, 0x011f8 and 0x010f8
	 */
	writel(CONFIG_SYS_SC520_UARTA_PAR, &sc520_mmcr->par[5]);
	writel(CONFIG_SYS_SC520_UARTB_PAR, &sc520_mmcr->par[6]);
	writel(CONFIG_SYS_SC520_UARTC_PAR, &sc520_mmcr->par[7]);
	writel(CONFIG_SYS_SC520_UARTD_PAR, &sc520_mmcr->par[8]);

	/* PARs 9 and 10 are 32MB StrataFlash @ 0x10000000 */
	writel(CONFIG_SYS_SC520_SF1_PAR, &sc520_mmcr->par[9]);
	writel(CONFIG_SYS_SC520_SF2_PAR, &sc520_mmcr->par[10]);

	/* PAR 13 is 4kB DPRAM @ 0x18100000 (implemented in FPGA) */
	writel(CONFIG_SYS_SC520_DPRAM_PAR, &sc520_mmcr->par[13]);

	/*
	 * PAR 14 is Low Level I/O (LEDs, Hex Switches etc)
	 * Already configured in board_init16 (eNET_start16.S)
	 *
	 * PAR 15 is Boot ROM
	 * Already configured in board_init16 (eNET_start16.S)
	 */
}


int board_early_init_r(void)
{
	/* CPU Speed to 100MHz */
	gd->cpu_clk = 100000000;

	/* Crystal is 33.000MHz */
	gd->bus_clk = 33000000;

	return 0;
}

void show_boot_progress(int val)
{
	uchar led_mask;

	led_mask = 0x00;

	if (val < 0)
		led_mask |= LED_ERR_BITMASK;

	led_mask |= (uchar)(val & 0x001f);
	outb(led_mask, LED_LATCH_ADDRESS);
}


int last_stage_init(void)
{
	int minor;
	int major;

	major = minor = 0;

	outb(0x00, LED_LATCH_ADDRESS);

	register_timer_isr(enet_timer_isr);

	printf("Serck Controls eNET\n");

	return 0;
}

ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
{
	if (banknum == 0) {	/* non-CFI boot flash */
		info->portwidth = FLASH_CFI_8BIT;
		info->chipwidth = FLASH_CFI_BY8;
		info->interface = FLASH_CFI_X8;
		return 1;
	} else {
		return 0;
	}
}

int board_eth_init(bd_t *bis)
{
	return pci_eth_init(bis);
}

void setup_pcat_compatibility()
{
	/* disable global interrupt mode */
	writeb(0x40, &sc520_mmcr->picicr);

	/* set all irqs to edge */
	writeb(0x00, &sc520_mmcr->pic_mode[0]);
	writeb(0x00, &sc520_mmcr->pic_mode[1]);
	writeb(0x00, &sc520_mmcr->pic_mode[2]);

	/*
	 *  active low polarity on PIC interrupt pins,
	 *  active high polarity on all other irq pins
	 */
	writew(0x0000, &sc520_mmcr->intpinpol);

	/*
	 * PIT 0 -> IRQ0
	 * RTC -> IRQ8
	 * FP error -> IRQ13
	 * UART1 -> IRQ4
	 * UART2 -> IRQ3
	 */
	writeb(SC520_IRQ0, &sc520_mmcr->pit_int_map[0]);
	writeb(SC520_IRQ8, &sc520_mmcr->rtcmap);
	writeb(SC520_IRQ13, &sc520_mmcr->ferrmap);
	writeb(SC520_IRQ4, &sc520_mmcr->uart_int_map[0]);
	writeb(SC520_IRQ3, &sc520_mmcr->uart_int_map[1]);

	/* Disable all other interrupt sources */
	writeb(SC520_IRQ_DISABLED, &sc520_mmcr->gp_tmr_int_map[0]);
	writeb(SC520_IRQ_DISABLED, &sc520_mmcr->gp_tmr_int_map[1]);
	writeb(SC520_IRQ_DISABLED, &sc520_mmcr->gp_tmr_int_map[2]);
	writeb(SC520_IRQ_DISABLED, &sc520_mmcr->pit_int_map[1]);
	writeb(SC520_IRQ_DISABLED, &sc520_mmcr->pit_int_map[2]);
	writeb(SC520_IRQ_DISABLED, &sc520_mmcr->ssimap);
	writeb(SC520_IRQ_DISABLED, &sc520_mmcr->wdtmap);
	writeb(SC520_IRQ_DISABLED, &sc520_mmcr->wpvmap);
	writeb(SC520_IRQ_DISABLED, &sc520_mmcr->icemap);
}

void enet_timer_isr(void)
{
	static long enet_ticks;

	enet_ticks++;

	/* Toggle Watchdog every 100ms */
	if ((enet_ticks % 100) == 0)
		hw_watchdog_reset();

	/* Toggle Run LED every 500ms */
	if ((enet_ticks % 500) == 0)
		enet_toggle_run_led();
}

void hw_watchdog_reset(void)
{
	/* Watchdog Reset must be atomic */
	long flag = disable_interrupts();

	if (sc520_mmcr->piodata15_0 & WATCHDOG_PIO_BIT)
		sc520_mmcr->pioclr15_0 = WATCHDOG_PIO_BIT;
	else
		sc520_mmcr->pioset15_0 = WATCHDOG_PIO_BIT;

	if (flag)
		enable_interrupts();
}

void enet_toggle_run_led(void)
{
	unsigned char leds_state = inb(LED_LATCH_ADDRESS);
	if (leds_state & LED_RUN_BITMASK)
		outb(leds_state & ~LED_RUN_BITMASK, LED_LATCH_ADDRESS);
	else
		outb(leds_state | LED_RUN_BITMASK, LED_LATCH_ADDRESS);
}
