/*
 * Copyright (C) Freescale Semiconductor, Inc. 2006-2007
 * Copyright (C) Sheldon Instruments, Inc. 2008
 *
 * Author: Ron Madrid <info@sheldoninst.com>
 *
 * (C) Copyright 2006
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <mpc83xx.h>
#include <spd_sdram.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/mmu.h>

DECLARE_GLOBAL_DATA_PTR;

static long fixed_sdram(void);

#if defined(CONFIG_NAND_SPL)
void si_wait_i2c(void)
{
	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;

	while (!(__raw_readb(&im->i2c[0].sr) & 0x02))
		;

	__raw_writeb(0x00, &im->i2c[0].sr);

	sync();

	return;
}

void si_read_i2c(u32 lbyte, int count, u8 *buffer)
{
	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
	u32 i;
	u8 chip = 0x50 << 1; /* boot sequencer I2C */
	u32 ubyte = (lbyte & 0xff00) >> 8;

	lbyte &= 0xff;

	/*
	 * Set up controller
	 */
	__raw_writeb(0x3f, &im->i2c[0].fdr);
	__raw_writeb(0x00, &im->i2c[0].adr);
	__raw_writeb(0x00, &im->i2c[0].sr);
	__raw_writeb(0x00, &im->i2c[0].dr);

	while (__raw_readb(&im->i2c[0].sr) & 0x20)
		;

	/*
	 * Writing address to device
	 */
	__raw_writeb(0xb0, &im->i2c[0].cr);
	sync();
	__raw_writeb(chip, &im->i2c[0].dr);
	si_wait_i2c();

	__raw_writeb(0xb0, &im->i2c[0].cr);
	sync();
	__raw_writeb(ubyte, &im->i2c[0].dr);
	si_wait_i2c();

	__raw_writeb(lbyte, &im->i2c[0].dr);
	si_wait_i2c();

	__raw_writeb(0xb4, &im->i2c[0].cr);
	sync();
	__raw_writeb(chip + 1, &im->i2c[0].dr);
	si_wait_i2c();

	__raw_writeb(0xa0, &im->i2c[0].cr);
	sync();

	/*
	 * Dummy read
	 */
	__raw_readb(&im->i2c[0].dr);

	si_wait_i2c();

	/*
	 * Read actual data
	 */
	for (i = 0; i < count; i++)
	{
		if (i == (count - 2))	/* Reached next to last byte, No ACK */
			__raw_writeb(0xa8, &im->i2c[0].cr);
		if (i == (count - 1))	/* Reached last byte, STOP */
			__raw_writeb(0x88, &im->i2c[0].cr);

		/* Read byte of data */
		buffer[i] = __raw_readb(&im->i2c[0].dr);

		if (i == (count - 1))
			break;
		si_wait_i2c();
	}

	return;
}
#endif /* CONFIG_NAND_SPL */

phys_size_t initdram(int board_type)
{
	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
	volatile fsl_lbc_t *lbc = &im->im_lbc;
	u32 msize;

	if ((__raw_readl(&im->sysconf.immrbar) & IMMRBAR_BASE_ADDR) != (u32) im)
		return -1;

	/* DDR SDRAM - Main SODIMM */
	__raw_writel(CONFIG_SYS_DDR_BASE & LAWBAR_BAR, &im->sysconf.ddrlaw[0].bar);

	msize = fixed_sdram();

	/* Local Bus setup lbcr and mrtpr */
	__raw_writel(CONFIG_SYS_LBC_LBCR, &lbc->lbcr);
	__raw_writel(CONFIG_SYS_LBC_MRTPR, &lbc->mrtpr);
	sync();

	/* return total bus SDRAM size(bytes)  -- DDR */
	return (msize * 1024 * 1024);
}

/*************************************************************************
 *  fixed sdram init -- reads values from boot sequencer I2C
 ************************************************************************/
static long fixed_sdram(void)
{
	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
	u32 msizelog2, msize = 1;
#if defined(CONFIG_NAND_SPL)
	u32 i;
	const u8 bytecount = 135;
	u8 buffer[bytecount];
	u32 addr, data;

	si_read_i2c(0, bytecount, buffer);

	for (i = 18; i < bytecount; i += 7){
		addr = (u32)buffer[i];
		addr <<= 8;
		addr |= (u32)buffer[i + 1];
		addr <<= 2;
		data = (u32)buffer[i + 2];
		data <<= 8;
		data |= (u32)buffer[i + 3];
		data <<= 8;
		data |= (u32)buffer[i + 4];
		data <<= 8;
		data |= (u32)buffer[i + 5];

		__raw_writel(data, (u32 *)(CONFIG_SYS_IMMR + addr));
	}

	sync();

	/* enable DDR controller */
	__raw_writel((__raw_readl(&im->ddr.sdram_cfg) | SDRAM_CFG_MEM_EN), &im->ddr.sdram_cfg);
#endif /* (CONFIG_NAND_SPL) */

	msizelog2 = ((__raw_readl(&im->sysconf.ddrlaw[0].ar) & LAWAR_SIZE) + 1);
	msize <<= (msizelog2 - 20);

	return msize;
}
