/*
 * (C) Copyright 2007-2009, NXP Semiconductors
 *
 * 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 <command.h>
#include <stb225_gpio.h>
#include <asm/arch/regaccess.h>

#include <configs/STB225v1.h>

#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#include <linux/mtd/nand.h>
#endif

/*
   MIU "type" register definitions
*/
#define MIU_TYPE_CLK_DIV_6		(3 << 18)
#define MIU_TYPE_CLK_DIV_4		(2 << 18)
#define MIU_TYPE_CLK_DIV_2		(1 << 18)
#define MIU_TYPE_CLK_DIV_1		(0 << 18)
#define MIU_TYPE_PCMCIA_IO		(1 << 17)
#define MIU_TYPE_PCMCIA 		(1 << 16)
#define MIU_TYPE_ST_BURST_FLASH		(1 << 15)
#define MIU_TYPE_SPI			(1 << 14)
#define MIU_TYPE_SYNC			(1 << 13)	/* disable double sync between MIU_CLK_EXT and FCP domains */
#define MIU_TYPE_BURST_128		(7 <<  9)
#define MIU_TYPE_BURST_64		(6 <<  9)
#define MIU_TYPE_BURST_32		(5 <<  9)
#define MIU_TYPE_BURST_16		(4 <<  9)
#define MIU_TYPE_BURST_8		(3 <<  9)
#define MIU_TYPE_BURST_4		(2 <<  9)
#define MIU_TYPE_BURST_2		(1 <<  9)
#define MIU_TYPE_BURST_1		(0 <<  9)
#define MIU_TYPE_PAGE_READ		(1 <<  8)
#define MIU_TYPE_BURST_READ		(1 <<  7)
#define MIU_TYPE_NOE_MOTOROLA_LIKE	(1 <<  6)
#define MIU_TYPE_RDY_ACK_MODE		(1 <<  5)
#define MIU_TYPE_HANDSHAKE		(1 <<  4)	/* use RDY signal to stretch individal accesses (ie NOT the same use and NAND or NOR RDY !!!) */
#define MIU_TYPE_ADDR_INC_DISABLE	(1 <<  3)
#define MIU_TYPE_WRITE_PROTECT		(1 <<  2)
#define MIU_TYPE_DATA_SWAP16		(1 <<  1)	/* swap bytes in 16bit mode */
#define MIU_TYPE_16BIT			(1 <<  0)
#define MIU_TYPE_8BIT			(0 <<  0)

/*
   MIU "timing" register definitions
*/
#define MIU_TIMING_DELAYRI_SHIFT	(30)		/* DelayRI   : RD or WR strobe high to CS high at end of access (0..3 clocks) */
#define MIU_TIMING_DELAYCS_SHIFT	(28)		/* DelayCS   : Address setup to falling CS at start of access (0..3 clocks) */
#define MIU_TIMING_SETWRITE_SHIFT	(26)		/* SetWrite  : Falling CS to falling WR at start of access (0..3 clocks) */
#define MIU_TIMING_SETREAD_SHIFT	(24)		/* SetRead   : Falling CS to falling RD at start of access (0..3 clocks) */
#define MIU_TIMING_WAITBURST_SHIFT	(18)		/* WaitBurst : burst mode only... */
#define MIU_TIMING_WAIT_SHIFT		(12)		/* Wait      : RD or WR strobe low cycles (1..63 clocks, 0 is invalid) */
#define MIU_TIMING_RECOVERY_SHIFT	(6)		/* Recovery  : Read cycles only : idle cycles after CS high at end of access (0..63 clocks ?) */
#define MIU_TIMING_INTER_SHIFT		(0)		/* Inter     : Write cycles only : data and address hold cycles after CS high at end of access (0..63 clocks ?) */

#define MIU_TIMING_DELAYRI_MASK 	(0x03 << MIU_TIMING_DELAYRI_SHIFT)
#define MIU_TIMING_DELAYCS_MASK 	(0x03 << MIU_TIMING_DELAYCS_SHIFT)
#define MIU_TIMING_SETWRITE_MASK	(0x03 << MIU_TIMING_SETWRITE_SHIFT)
#define MIU_TIMING_SETREAD_MASK 	(0x03 << MIU_TIMING_SETREAD_SHIFT)
#define MIU_TIMING_WAITBURST_MASK	(0x3F << MIU_TIMING_WAITBURST_SHIFT)
#define MIU_TIMING_WAIT_MASK		(0x3F << MIU_TIMING_WAIT_SHIFT)
#define MIU_TIMING_RECOVERY_MASK	(0x3F << MIU_TIMING_RECOVERY_SHIFT)
#define MIU_TIMING_INTER_MASK		(0x3F << MIU_TIMING_INTER_SHIFT)


/* Default configuration for the MIU,
 *
 * These values may need updating (in addition to the polyfuse map) if
 * you switch to a new flash device with different structure or
 * timing.
 */

#define MIU_TYPE_CONFIG_BASE		(MIU_TYPE_CLK_DIV_1 | MIU_TYPE_SYNC)

#define MIU_TYPE_CONFIG_NOR8		(MIU_TYPE_CONFIG_BASE | MIU_TYPE_8BIT)
#define MIU_TYPE_CONFIG_NOR16		(MIU_TYPE_CONFIG_BASE | MIU_TYPE_16BIT)
#define MIU_TYPE_CONFIG_NAND		(MIU_TYPE_CONFIG_BASE | MIU_TYPE_ADDR_INC_DISABLE | MIU_TYPE_8BIT)

#define MIU_TYPE_CONFIG_SMSC911X	(MIU_TYPE_CONFIG_BASE | MIU_TYPE_16BIT)

#define MIU_TYPE_CONFIG_SPI		0x00044E80	/* fixme: decode */


/*******************************************************************************
*******************************************************************************/

/*
   Original Soton timing for NOR (0x6A08C082)... glacial, but safe in all cases.
*/
#define MIU_TIMING_NOR_SLOW		(( 1 << MIU_TIMING_DELAYRI_SHIFT)	| \
					 ( 2 << MIU_TIMING_DELAYCS_SHIFT)	| \
					 ( 2 << MIU_TIMING_SETWRITE_SHIFT)	| \
					 ( 2 << MIU_TIMING_SETREAD_SHIFT)	| \
					 ( 2 << MIU_TIMING_WAITBURST_SHIFT)	| \
					 (12 << MIU_TIMING_WAIT_SHIFT)		| \
					 ( 2 << MIU_TIMING_RECOVERY_SHIFT)	| \
					 ( 2 << MIU_TIMING_INTER_SHIFT))

/*
   Original Soton timing for NOR with WAIT changed from 12 to 8. Still slow
   and in need of proper tuning... (Note: WAIT == 6 causes trouble on the
   STB225 board...).
*/
#define MIU_TIMING_NOR_FAST		(( 1 << MIU_TIMING_DELAYRI_SHIFT)	| \
					 ( 2 << MIU_TIMING_DELAYCS_SHIFT)	| \
					 ( 2 << MIU_TIMING_SETWRITE_SHIFT)	| \
					 ( 2 << MIU_TIMING_SETREAD_SHIFT)	| \
					 ( 2 << MIU_TIMING_WAITBURST_SHIFT)	| \
					 ( 8 << MIU_TIMING_WAIT_SHIFT)		| \
					 ( 2 << MIU_TIMING_RECOVERY_SHIFT)	| \
					 ( 2 << MIU_TIMING_INTER_SHIFT))

#define MIU_TIMING_NOR_DEFAULT		MIU_TIMING_NOR_FAST


/*******************************************************************************
*******************************************************************************/

/*
   Fast timing + 2 clocks for all stages. Needs tuning.
*/
#define MIU_TIMING_NAND_SLOW		(( 2 << MIU_TIMING_DELAYRI_SHIFT)	| \
					 ( 2 << MIU_TIMING_DELAYCS_SHIFT)	| \
					 ( 3 << MIU_TIMING_SETWRITE_SHIFT)	| \
					 ( 3 << MIU_TIMING_SETREAD_SHIFT)	| \
					 ( 0 << MIU_TIMING_WAITBURST_SHIFT)	| \
					 ( 5 << MIU_TIMING_WAIT_SHIFT)		| \
					 ( 3 << MIU_TIMING_RECOVERY_SHIFT)	| \
					 ( 3 << MIU_TIMING_INTER_SHIFT))

/*
   Reasonably optimal, but still safe for expected "worse case" (ie 80 MHz PI-Bus == 12.5 nsec / MIU clock).
   Cycle time is 5 clocks (62.5 nsec), read access time is 3 clocks (ie 37.5 nsec), etc.
   Some recent NAND devices (eg Large page devices) can probably be accessed even more quickly.
*/
#define MIU_TIMING_NAND_FAST		(( 0 << MIU_TIMING_DELAYRI_SHIFT)	| \
					 ( 0 << MIU_TIMING_DELAYCS_SHIFT)	| \
					 ( 1 << MIU_TIMING_SETWRITE_SHIFT)	| \
					 ( 1 << MIU_TIMING_SETREAD_SHIFT)	| \
					 ( 0 << MIU_TIMING_WAITBURST_SHIFT)	| \
					 ( 3 << MIU_TIMING_WAIT_SHIFT)		| \
					 ( 1 << MIU_TIMING_RECOVERY_SHIFT)	| \
					 ( 1 << MIU_TIMING_INTER_SHIFT))

#define MIU_TIMING_NAND_DEFAULT 	MIU_TIMING_NAND_FAST


/*******************************************************************************
*******************************************************************************/

/*
   Fixme: add specific details of timing requirements...
*/
#define MIU_TIMING_SMSC911X		(( 0 << MIU_TIMING_DELAYRI_SHIFT)	| \
					 ( 0 << MIU_TIMING_DELAYCS_SHIFT)	| \
					 ( 0 << MIU_TIMING_SETWRITE_SHIFT)	| \
					 ( 0 << MIU_TIMING_SETREAD_SHIFT)	| \
					 ( 1 << MIU_TIMING_WAITBURST_SHIFT)	| \
					 ( 2 << MIU_TIMING_WAIT_SHIFT)		| \
					 ( 1 << MIU_TIMING_RECOVERY_SHIFT)	| \
					 ( 1 << MIU_TIMING_INTER_SHIFT))


/*******************************************************************************
*******************************************************************************/

/*
   Original Soton timing for SPI (0x00000082)... details unclear.
*/
#define MIU_TIMING_SPI_DEFAULT		0x00000082


/*******************************************************************************
*******************************************************************************/

/* On STB22x, DRAM is already initialized at this point.
   So we will just run a simple check for actual memory size. */
long int initdram (int board_type)
{
    volatile unsigned long *baddr, *addr;

    /* We check in KSEG1, to avoid influence of caches */
    unsigned long base = 0xA0000000;
    unsigned long size = 0x00400000;    /* start at 4 mbytes */
    unsigned long step = 0x00400000;    /* step is 4 mbytes */
    unsigned long save, save2;

    baddr = (volatile unsigned long *)base;
    save2 = *baddr;
    *baddr = 0x55555555;
    /* Don't test beyond 256MB - that's the size of our DRAM controller memory aperture */
    for (; size < 0x10000000; size += step) {
        /* detect no more memory at addresses > base + (size - step) */
        addr = (volatile unsigned long *)(base + size - 4);
        save = *addr;
        *addr = 0x55555555;
        if (*addr != 0x55555555) {
            *addr = save;
            *baddr = save2;
            return size - step;
        }
        *addr = 0xAAAAAAAA;
        if (*addr != 0xAAAAAAAA) {
            *addr = save;
            *baddr = save2;
            return size - step;
        }
        *addr = save;
        /* detect situation when base + size maps at base */
        addr = (volatile unsigned long *)(base + size);
        save = *addr;
        *addr = 0xAAAAAAAA;
        if (*baddr != 0x55555555) {
            *addr = save;
            *baddr = save2;
            return size;
        }
        *addr = save;
    }

    *baddr = save2;

    /* We've reached our DRAM controller limited max size of 256MB (which is plenty!) */
    return size;
}

int stb225_bootmode (void)
{
	unsigned int config_flash_config;
	unsigned int config_boot_mode = PNX8335_REGFIELD(CONFIG_POLYFUSE_9, FLASH_CONFIG);

	if (CPU_IS_PNX8335_M0) {
		if (config_boot_mode == BOOTMODE_NAND_8)
			return BOOTMODE_NAND_8;
		return BOOTMODE_NOR_16;
	}

	if (CPU_IS_PNX8335_M1) {
		config_flash_config = PNX8335_REGFIELD(CONFIG_POLYFUSE_9, FLASH_CONFIG);
		if (config_flash_config != BOOTMODE_OMNIBOOT)
			return config_flash_config;
		config_boot_mode = *((unsigned int *) 0xB7E070B4);
		switch (config_boot_mode & 0x03) {
			case 0: return BOOTMODE_NOR_8;
			case 1: return BOOTMODE_NOR_16;
			case 2: return BOOTMODE_NAND_8;
			case 3: return BOOTMODE_NAND_16;
		}
	}

	return -1;
}

int stb225_bootmode_is_nand (void)
{
	unsigned int bootmode = stb225_bootmode();

	if ((bootmode == BOOTMODE_NAND_8) || (bootmode == BOOTMODE_NAND_16))
		return 1;

	return 0;
}

int stb225_bootmode_is_nor (void)
{
	return ! stb225_bootmode_is_nand();
}

int stb225_board_rev (void)
{
	int rev = -1;		/* -1 : unknown / unsupported */

#if defined (BOOT_TARGET_CINDYKATE) || defined (BOOT_TARGET_CINDYKATE_RESCUE)
	rev = 0;
	rev = (rev << 1) | gpio_get_value (GPIO_ID5);
	rev = (rev << 1) | gpio_get_value (GPIO_ID4);
	rev = (rev << 1) | gpio_get_value (GPIO_ID3);
	rev = (rev << 1) | gpio_get_value (GPIO_ID2);
	rev = (rev << 1) | gpio_get_value (GPIO_ID1);
	rev = (rev << 1) | gpio_get_value (GPIO_ID0);
#else
	/* Add cases for other platforms here... */
#endif

	return rev;
}

/*
   Init GPIO_USB_PWE and GPIO_USB_FLG pins. There are 3 cases:

   1) USB functionality is not used : pins should be left alone.
      We don't have a way to select this case yet. If required, it could
      either be determined from BOOT_TARGET_xxx definitions or generalised
      via prjconfig.

   2) USB functionality is used, VBus power enable and over-current work
      in the same way as on STB225 boards. This is the most common case.
      Historically this has been handled by putting both GPIO_USB_PWE and
      GPIO_USB_FLG pins in function mode (init performed in the kernel).

   3) USB functionality is used, VBus power enabled and over-current work
      differently... fixme: describe !!

   Fixme: what if sense of GPIO_USB_FLG is inverted ?
*/
static int stb225_setup_usb_power_control (int board_rev)
{
#if defined (BOOT_TARGET_CINDYKATE) || defined (BOOT_TARGET_CINDYKATE_RESCUE)
	/*
	   Rev 3 and below: compatible with STB225
	   Rev 4 and above: MP6223 USB VBus controller, behaves differently...
	*/
	if (board_rev < 4) {
		gpio_set_as_function (GPIO_USB_PWE);
		gpio_set_as_function (GPIO_USB_FLG);
	}
	else {
		gpio_set_as_output (GPIO_USB_PWE, 1);
		gpio_set_as_input (GPIO_USB_FLG);
	}
#elif defined (BOOT_TARGET_MONACO)
	gpio_set_as_output(GPIO_USB_PWE, 1);
	gpio_set_as_input(GPIO_USB_FLG);
#else
	gpio_set_as_function (GPIO_USB_PWE);
	gpio_set_as_function (GPIO_USB_FLG);
#endif

	return 0;
}

static int stb225_setup_clkout (int board_rev)
{
#if defined (STB225_ETHERNET_OSCILLATOR)
	/* write 0x80 to disable oscillator output */
	*((volatile unsigned int *) 0xB7E09330) = 0x80;
#else
	/* write 1 to enable oscillator output */
	*((volatile unsigned int *) 0xB7E09330) = 1;
#endif

	return 0;
}

/* Configure the flash memory interface
 *
 * This duplicates some setup normally done by the onchip ROM during
 * boot. We repeat it here to guarantee that rescue images work,
 * regardless of what happened during boot (e.g. even if the links are
 * incorrectly configured).
 */
int setup_miu (void)
{
	unsigned int bootmode = stb225_bootmode();

	switch (bootmode)
	{
		case BOOTMODE_NAND_8:
			PNX833X_MIU_SEL0 = MIU_TYPE_CONFIG_NAND;
			PNX833X_MIU_SEL0_TIMING = MIU_TIMING_NAND_DEFAULT;
			break;

		case BOOTMODE_NOR_8:
			PNX833X_MIU_SEL0 = MIU_TYPE_CONFIG_NOR8;
			PNX833X_MIU_SEL0_TIMING = MIU_TIMING_NOR_DEFAULT;
			break;

		case BOOTMODE_NOR_16:
		case BOOTMODE_EXTERNAL:
			PNX833X_MIU_SEL0 = MIU_TYPE_CONFIG_NOR16;
			PNX833X_MIU_SEL0_TIMING = MIU_TIMING_NOR_DEFAULT;
			break;

		case BOOTMODE_SPINOR:
			PNX833X_MIU_SEL0 = MIU_TYPE_CONFIG_SPI;
			PNX833X_MIU_SEL0_TIMING = MIU_TIMING_SPI_DEFAULT;
			break;

		default:
			/*
			   Leave MIU alone and hope for the best...
			*/
			printf ("Error: Unexpected bootmode: %d\n", bootmode);
			break;
	}

	/*
	   Duplicate nCS0 config for nCS1
	   This is required for NOR (to allow access to devices larger
	   than 32 MBytes which span both nCS0 and nCS1 address ranges).
	   It does no harm for NAND.
	*/
	PNX833X_MIU_SEL1 = PNX833X_MIU_SEL0;
	PNX833X_MIU_SEL1_TIMING = PNX833X_MIU_SEL0_TIMING;

	gpio_set_as_function (GPIO_MIU_CSN1);	/* Note: GPIO_MIU_CSN1 == GPIO_0 */

#if (CONFIG_COMMANDS & CFG_CMD_NAND)
	/*
	   Dual NOR / NAND boards connect NOR to nCS0 + nCS1 and NAND to nCS2.
	   If NAND support is enabled and we booted from NOR, setup nCS2 so
	   that we can use it to access NAND...
	*/
	if (stb225_bootmode_is_nor()) {
		PNX833X_MIU_SEL2 = MIU_TYPE_CONFIG_NAND;
		PNX833X_MIU_SEL2_TIMING = MIU_TIMING_NAND_SLOW;
	}
#endif

#if defined (CONFIG_SMSC911X)
	if (CFG_SMSC911X_IOBASE == MIU_CS3_BASE_UNCACHED) {
		PNX833X_MIU_SEL3 = MIU_TYPE_CONFIG_SMSC911X;
		PNX833X_MIU_SEL3_TIMING = MIU_TIMING_SMSC911X;
	}
#endif

#if defined (GPIO_NAND_RDY)
	gpio_set_as_input (GPIO_NAND_RDY);
#endif
#if defined (GPIO_NAND_WP)
	gpio_set_as_output (GPIO_NAND_WP, 1);	/* NAND WP: (0 == write disabled), (1 == write enabled) */
#endif
#if defined (GPIO_NOR_WP)
	gpio_set_as_output (GPIO_NOR_WP, 1);	/* NOR WP: (0 == write disabled), (1 == write enabled) */
#endif

	return 0;
}

int stb225_secure_boot (void)
{
#if defined (CFG_FORCE_SECURE_GPIO)
	if (! gpio_is_input (GPIO_FORCE_SECURE)) {
		gpio_set_as_input (GPIO_FORCE_SECURE);
		udelay (10 * 1000);
	}
	if (gpio_get_value (GPIO_FORCE_SECURE) == 0) {
//		printf ("GPIO_FORCE_SECURE pin is low: forcing secure boot\n");
		return 1;
	}
#endif

	return PNX8335_CONFIG_SECURE_BOOT;	/* return raw polyfuse bit: 1 == secure boot enabled */
}

static char *stb225_part_number_string (void)
{
	unsigned int tcb_reg = *((unsigned int *) 0xB7E0A018);

	switch ((tcb_reg >> 18) & 0x07)
	{
//		case 0x00: return ??;
		case 0x01: return "8932";
		case 0x02: return "8935";
//		case 0x03: return ??;
		case 0x04: return "8335";
//		case 0x05: return ??;
//		case 0x06: return ??;
		case 0x07: return "8332";

		default: return "????";
	}
}

char *stb225_pibus_mhz_string (void)
{
	unsigned int pcp_ctl_reg = *((unsigned int *) 0xB7E09204);

	switch ((pcp_ctl_reg >> 0) & 0x03)
	{
		case 0x00:
		case 0x02:
			return "0";	/* clock disabled... */

		case 0x01:
			return "25";	/* clock taken directly from xtal */

		case 0x03:		/* clock taken from USB PLL, with choice of dividers */
			switch ((pcp_ctl_reg >> 2) & 0x03)
			{
				case 0x00: return "80"; 	/* usb_pll_mhz / 6 */
				case 0x01: return "68.571";	/* usb_pll_mhz / 7 */
				case 0x02: return "60"; 	/* usb_pll_mhz / 8 */
				case 0x03: return "53.333";	/* usb_pll_mhz / 9 */
			}
	}

	return "?";
}

int checkboard (void)
{
	int board_rev;

	printf ("CPU: PNX%s\n", stb225_part_number_string());
	printf ("Secure boot: %sabled\n", stb225_secure_boot() ? "en" : "dis");

	board_rev = stb225_board_rev();
	stb225_setup_usb_power_control (board_rev);
	stb225_setup_clkout (board_rev);

#if defined (GPIO_EXT_PHY_RESET)
	/*
	   External Phy reset: generate a short reset pulse then de-assert.
	   Note: If the Phy is clocked by the PNX8335 clock output, then
	   stb225_setup_clkout() should be called before this point !
	*/
	gpio_set_as_output (GPIO_EXT_PHY_RESET, 0);	/* drive low to assert */
	udelay (200);
	gpio_set_as_output (GPIO_EXT_PHY_RESET, 1);	/* drive high to de-assert */
#endif

#if defined (BOOT_TARGET_GRIFFIN)
	gpio_set_as_output (GPIO_14, 1);		/* drive high to turn on Griffin LED */
#endif

	return 0;
}

#ifdef CFG_ENV_IS_NOWHERE
char *env_name_spec = "NOWHERE";
int saveenv (void)
{
	puts("Are you joking?\n");
	return 0;
}
#endif

unsigned int stb225_get_cpu_clock_mhz (void)
{
	return 90 + (10 * (*((volatile unsigned int *) 0xB7E09020) & 0x1F));
}

unsigned int stb225_get_cpu_clock_hz (void)
{
	return (stb225_get_cpu_clock_mhz() * (1 * 1000 * 1000));
}

unsigned long sdram_size (void)
{
	DECLARE_GLOBAL_DATA_PTR;
	return gd->ram_size;
}

static int selftest_miu (void)
{
	int i;
	unsigned int timing;

	for (i = 0; i < 3; i++) {
		timing = (i == 0) ? PNX833X_MIU_SEL0_TIMING :
			 (i == 1) ? PNX833X_MIU_SEL1_TIMING :
			 (i == 2) ? PNX833X_MIU_SEL2_TIMING : 0;

		printf ("\n");
		printf ("nCS%d : DELAYRI  : %2d\n", i, (timing & MIU_TIMING_DELAYRI_MASK   ) >> MIU_TIMING_DELAYRI_SHIFT   );
		printf ("       DELAYCS  : %2d\n", (timing & MIU_TIMING_DELAYCS_MASK   ) >> MIU_TIMING_DELAYCS_SHIFT   );
		printf ("       SETWRITE : %2d\n", (timing & MIU_TIMING_SETWRITE_MASK  ) >> MIU_TIMING_SETWRITE_SHIFT  );
		printf ("       SETREAD  : %2d\n", (timing & MIU_TIMING_SETREAD_MASK   ) >> MIU_TIMING_SETREAD_SHIFT   );
//		printf ("       WAITBURST: %2d\n", (timing & MIU_TIMING_WAITBURST_MASK ) >> MIU_TIMING_WAITBURST_SHIFT );
		printf ("       WAIT     : %2d\n", (timing & MIU_TIMING_WAIT_MASK      ) >> MIU_TIMING_WAIT_SHIFT      );
		printf ("       RECOVERY : %2d\n", (timing & MIU_TIMING_RECOVERY_MASK  ) >> MIU_TIMING_RECOVERY_SHIFT  );
		printf ("       INTER    : %2d\n", (timing & MIU_TIMING_INTER_MASK     ) >> MIU_TIMING_INTER_SHIFT     );
	}

	printf ("\n");

	return 0;
}

U_BOOT_CMD(
	st_miu, 1, 1, (int (*)(struct cmd_tbl_s *, int, int, char *[])) selftest_miu,
	"st_miu  - dump MIU timing\n",
	" - dump MIU timing\n"
);

