/*
 * (C) Copyright 2003
 * MuLogic B.V.
 *
 * (C) Copyright 2002
 * Simple Network Magic Corporation, dnevil@snmc.com
 *
 * (C) Copyright 2000
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * 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/u-boot.h>
#include <commproc.h>
#include "mpc8xx.h"

/* ------------------------------------------------------------------------- */

static long  int dram_size (long int, long int *, long int);

/* ------------------------------------------------------------------------- */

const uint sdram_table[] =
{
	/*
	 * Single Read. (Offset 0 in UPMA RAM)
	 */
	0x0f07cc04,  0x00adcc04,  0x00a74c00,  0x00bfcc04,
	0x1fffcc05,  0xffffcc05,  0xffffcc05,  0xffffcc05,
	/*
	 * Burst Read. (Offset 8 in UPMA RAM)
	 */
	0x0ff7fc04,  0x0ffffc04,  0x00bdfc04,  0x00fffc00,
	0x00fffc00,  0x00fffc00,  0x0ff77c00,  0x1ffffc05,
	0x1ffffc05,  0x1ffffc05,  0x1ffffc05,  0x1ffffc05,
	0x1ffffc05,  0x1ffffc05,  0x1ffffc05,  0x1ffffc05,
	/*
	 * Single Write. (Offset 18 in UPMA RAM)
	 */
	0x0f07cc04,  0x0fafcc00,  0x01ad0c04,  0x1ff74c07,
	0xffffcc05,  0xffffcc05,  0xffffcc05,  0xffffcc05,
	/*
	 * Burst Write. (Offset 20 in UPMA RAM)
	 */
	0x0ff7fc04,  0x0ffffc00,  0x00bd7c00,  0x00fffc00,
	0x00fffc00,  0x00fffc00,  0x0ffffc04,  0x0ff77c04,
	0x1ffffc05,  0x1ffffc05,  0x1ffffc05,  0x1ffffc05,
	0x1ffffc05,  0x1ffffc05,  0x1ffffc05,  0x1ffffc05,
	/*
	 * Refresh  (Offset 30 in UPMA RAM)
	 */
	0xffffcc04,  0x1ff5cc84,  0xffffcc04,  0xffffcc04,
	0xffffcc84,  0xffffcc05,  0xffffcc04,  0xffffcc04,
	0xffffcc04,  0xffffcc04,  0xffffcc04,  0xffffcc04,
	/*
	 * Exception. (Offset 3c in UPMA RAM)
	 */
	0x1ff74c04,  0xffffcc07,  0xffffaa34,  0x1fb54a37
};

/* ------------------------------------------------------------------------- */


/*
 * Check Board Identity:
 *
 * Test ID string (QS850, QS823, ...)
 *
 * Always return 1
 */
#if defined(CONFIG_QS850)
#define BOARD_IDENTITY	"QS850"
#elif defined(CONFIG_QS823)
#define BOARD_IDENTITY	"QS823"
#else
#define	BOARD_IDENTITY	"QS???"
#endif

int checkboard (void)
{
	char *s, *e;
	char buf[64];
	int i;

	i = getenv_r("serial#", buf, sizeof(buf));
	s = (i>0) ? buf : NULL;

	if (!s || strncmp(s, BOARD_IDENTITY, 5)) {
		puts ("### No HW ID - assuming " BOARD_IDENTITY);
	} else {
		for (e=s; *e; ++e) {
		if (*e == ' ')
		break;
	}

	for ( ; s<e; ++s) {
		putc (*s);
		}
	}
	putc ('\n');

	return (0);
}

/* ------------------------------------------------------------------------- */
/* SDRAM Mode Register Definitions */

/* Set SDRAM Burst Length to 4 (010) */
/* See Motorola MPC850 User Manual, Page 13-14 */
#define SDRAM_BURST_LENGTH      (2)

/* Set Wrap Type to Sequential (0) */
/* See Motorola MPC850 User Manual, Page 13-14 */
#define SDRAM_WRAP_TYPE         (0 << 3)

/* Set /CAS Latentcy to 2 clocks */
#define SDRAM_CAS_LATENTCY      (2 << 4)

/* The Mode Register value must be shifted left by 2, since it is */
/* placed on the address bus, and the 2 LSBs are ignored for 32-bit accesses */
#define SDRAM_MODE_REG  ((SDRAM_BURST_LENGTH|SDRAM_WRAP_TYPE|SDRAM_CAS_LATENTCY) << 2)

#define UPMA_RUN(loops,index)   (0x80002000 + (loops<<8) + index)

/* Please note a value of zero = 16 loops */
#define REFRESH_INIT_LOOPS (0)


phys_size_t initdram (int board_type)
{
	volatile immap_t     *immap  = (immap_t *)CONFIG_SYS_IMMR;
	volatile memctl8xx_t *memctl = &immap->im_memctl;
	long int size;

	upmconfig(UPMA, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint));

	/*
	* Prescaler for refresh
	*/
	memctl->memc_mptpr = CONFIG_SYS_MPTPR;

	/*
	* Map controller bank 1 to the SDRAM address
	*/
	memctl->memc_or1 = CONFIG_SYS_OR1;
	memctl->memc_br1 = CONFIG_SYS_BR1;
	udelay(1000);

	/* perform SDRAM initialization sequence */
	memctl->memc_mamr = CONFIG_SYS_16M_MAMR;
	udelay(100);

	/* Program the SDRAM's Mode Register */
	memctl->memc_mar  = SDRAM_MODE_REG;

	/* Run the Prechard Pattern at 0x3C */
	memctl->memc_mcr  = UPMA_RUN(1,0x3c);
	udelay(1);

	/* Run the Refresh program residing at MAD index 0x30 */
	/* This contains the CBR Refresh command with a loop */
	/* The SDRAM must be refreshed at least 2 times */
	/* Please note a value of zero = 16 loops */
	memctl->memc_mcr  = UPMA_RUN(REFRESH_INIT_LOOPS,0x30);
	udelay(1);

	/* Run the Exception program residing at MAD index 0x3E */
	/* This contains the Write Mode Register command */
	/* The Write Mode Register command uses the value written to MAR */
	memctl->memc_mcr  = UPMA_RUN(1,0x3e);

	udelay (1000);

	/*
	* Check for 32M SDRAM Memory Size
	*/
	size = dram_size(CONFIG_SYS_32M_MAMR|MAMR_PTAE,
	(long *)SDRAM_BASE, SDRAM_32M_MAX_SIZE);
	udelay (1000);

	/*
	* Check for 16M SDRAM Memory Size
	*/
	if (size != SDRAM_32M_MAX_SIZE) {
	size = dram_size(CONFIG_SYS_16M_MAMR|MAMR_PTAE,
	(long *)SDRAM_BASE, SDRAM_16M_MAX_SIZE);
	udelay (1000);
	}

	udelay(10000);
	return (size);
}

/* ------------------------------------------------------------------------- */

/*
 * Check memory range for valid RAM. A simple memory test determines
 * the actually available RAM size between addresses `base' and
 * `base + maxsize'. Some (not all) hardware errors are detected:
 * - short between address lines
 * - short between data lines
 */

static long int dram_size (long int mamr_value, long int *base, long int maxsize)
{
	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
	volatile memctl8xx_t *memctl = &immap->im_memctl;

	memctl->memc_mamr = mamr_value;

	return (get_ram_size(base, maxsize));
}
