
#include <linux/init.h>
#include <linux/mm.h>
#include <asm/bootinfo.h>

#include <prjconfig.h>
#include <pnx833x.h>
#include <gpio.h>

/* endianess twiddlers */
#define PNX8335_DEBUG0 0x5400
#define PNX8335_DEBUG1 0x5404
#define PNX8335_DEBUG2 0x5408
#define PNX8335_DEBUG3 0x540c
#define PNX8335_DEBUG4 0x5410
#define PNX8335_DEBUG5 0x5414
#define PNX8335_DEBUG6 0x5418
#define PNX8335_DEBUG7 0x541c

#define PNX8335_DEBUG2_SATA_DMA_DESC_ENDIAN	(1 << 11)
#define PNX8335_DEBUG2_SATA_DMA_READ_ENDIAN	(1 << 7)
#define PNX8335_DEBUG5_SATA_DMA_WRITE_ENDIAN	(1 << 30)

#define ENB_POWER_5V 14
#define LED1 21
#define LED2 22

int prom_argc = 0;
char **prom_argv = 0, **prom_envp = 0;

static unsigned int keep_gpio_sel=0;
static unsigned int keep_gpio_dir=0;
static unsigned int keep_gpio_out=0;

extern void prom_init_cmdline(void);
extern char *prom_getenv(char *envname);

const char *get_system_type(void)
{
	return "BrightSign \"Monaco\"";
}

static inline unsigned long env_or_default(char *env, unsigned long dfl)
{
	char *str = prom_getenv(env);
	return str ? simple_strtol(str, 0, 0) : dfl;
}

void __init prom_init(void)
{
	unsigned long memsize;
	unsigned long memstart;

	prom_argc = fw_arg0;
	prom_argv = (char **)fw_arg1;
	prom_envp = (char **)fw_arg2;

	prom_init_cmdline();

	/* We are using for the MAIN MIPS
	   board memory size - CONFIG_DSP_MIPS_MEM_SIZE - CONFIG_RESERVED_HIGH_MEM_SIZE
	   and we 'assume' that the DSP MIPS memory starts at
	   256MB - CONFIG_DSP_MIPS_MEM_SIZE - CONFIG_RESERVED_HIGH_MEM_SIZE.
	   This would make use of the 'feature' that access to non-existant
	   memory 'wraps around' to lower 128MB / 64MB memory banks.
	*/

	/* Proper memory size (e.g. 64mb for stb220t3) should be passed
	   by bootloader */
	memsize = env_or_default("memsize", 0x55);
	if (memsize == 0x55) 
	{
		// Monaco has 256Mbytes of available SDRAM
		memsize = 256 * 1024 * 1024;
	}

#ifdef CONFIG_SOC_PNX8335
#ifdef CONFIG_PNX8335_AUDIO_MIPS
        /* Memory start is calculated from load address - standard 0x1000 */
        memstart = ((unsigned long)CONFIG_DSP_MIPS_LOAD_ADDR) - CAC_BASE - 0x1000;
        memsize = (unsigned long)CONFIG_DSP_MIPS_MEM_SIZE;
#else
        /* Main CPU always runs from 0MB upwards. */
        memstart = 0UL;
        /* Upperlimit is by autosensing memsize - dsp memsize - reserved memsize. */
        memsize -= (CONFIG_DSP_MIPS_MEM_SIZE + CONFIG_RESERVED_HIGH_MEM_SIZE);
#endif
#else
        /* Main CPU always runs from 0MB upwards. */
        memstart = 0UL;
        /* Upperlimit is by autosensing memsize - reserved memsize. */
        memsize -= CONFIG_RESERVED_HIGH_MEM_SIZE;
#endif
	add_memory_region(memstart, memsize, BOOT_MEM_RAM);
}

void __init pnx833x_board_setup(void)
{
	/*
	 * Note: MIU setup for NAND or NOR is assumed to have already have
	 * been completed by the bootloader (exact setup may be platform
	 * specific and we want to avoid platform specific code in the
	 * kernel if possible). Flash related GPIOs such as NAND RDY and WP
	 * are also left to the bootloader, for the same reason.
	 */

#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE)
	// On Monaco GPIO25 is used to enable the hub chip or our USB
	// device via VBUS_DET. GPIO26 does nothing.
#if defined (CONFIG_KERNEL_GPIO_INIT_USB)
	gpio_select_output(25);
	gpio_write(1, 25);
#endif
#endif

#if defined(CONFIG_IP3902) || defined(CONFIG_IP3902_MODULE)
	/* Configure GPIOs 28-33 for MII interface to Ethernet phy */
	gpio_select_function_alt(27);
	gpio_select_function_alt(28);
#if defined(CONFIG_NETPHY_RESET_PIO_29)
	/* Do Nothing, let gpio function as pio */
#else
	gpio_select_function_alt(29);
#endif
	gpio_select_function_alt(30);
	gpio_select_function_alt(31);
	gpio_select_function_alt(32);
	gpio_select_function_alt(33);

#ifdef CONFIG_MOCA_PHY
	gpio_select_function_io(13);
	gpio_select_output(13);
	gpio_select_function_io(14);
	gpio_select_output(14);
	gpio_write(0, 13);
	gpio_write(0, 14);
#endif

#endif

#if defined(CONFIG_SATA_PNX833X) || defined(CONFIG_SATA_PNX833X_MODULE)
	{
		u32 val;
		val = PNX833X_REG(PNX8335_DEBUG2);
#ifdef __LITTLE_ENDIAN
		val |= PNX8335_DEBUG2_SATA_DMA_DESC_ENDIAN;
#else
		val &= ~PNX8335_DEBUG2_SATA_DMA_DESC_ENDIAN;
#endif
		val |= PNX8335_DEBUG2_SATA_DMA_READ_ENDIAN;
		PNX833X_REG(PNX8335_DEBUG2) = val;
		val = PNX833X_REG(PNX8335_DEBUG5);
		val |= PNX8335_DEBUG5_SATA_DMA_WRITE_ENDIAN;
		PNX833X_REG(PNX8335_DEBUG5) = val;
	}
#endif

#if defined (CONFIG_HDMI_PRESENT)
	gpio_setup_irq (GPIO_INT_LEVEL_LOW, CONFIG_HDMI_GPIO_PIN);
#endif

#ifndef CONFIG_PNX8335_AUDIO_MIPS
	printk(KERN_INFO "PNX833x DDR PLL configuration: M=0x%08lx, NP=0x%08lx\n",
	       PNX8335_CLOCK_PLL_DDR_M_CTL,
	       PNX8335_CLOCK_PLL_DDR_NP_CTL);
#endif
}

/* This function is called before the system goes into standby */

void pnx833x_pm_board_standby(void)
{
#ifdef CONFIG_NXP_STB225
	/* keep original gpio state */
	keep_gpio_sel=PNX833X_PIO_SEL;
	keep_gpio_dir=PNX833X_PIO_DIR;
	keep_gpio_out=PNX833X_PIO_OUT;
	
#if 0
	/* switch off leds */
	PNX833X_PIO_SEL &= ~((1 << LED1) | (1 << LED2));
	PNX833X_PIO_DIR |= (1 << LED1) | (1 << LED2);
	PNX833X_PIO_OUT |= (1 << LED1) | (1 << LED2);
#endif
#endif	
}

/* This function is called soon after the system has come out of standby */

void pnx833x_pm_board_resume(void)
{
#ifdef CONFIG_NXP_STB225
	/* restore pre standby gpio state */
	PNX833X_PIO_OUT=keep_gpio_out;
	PNX833X_PIO_DIR=keep_gpio_dir;
	PNX833X_PIO_SEL=keep_gpio_sel;
#endif
}
