/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2007-2008 coresystems GmbH
 *
 * 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; version 2 of the License.
 *
 * 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.
 */

#include <console/console.h>
#include <arch/io.h>
#include "raminit.h"
#include "i945.h"

/**
 * sample the strobes signal
 */
static u32 sample_strobes(int channel_offset, struct sys_info *sysinfo)
{
	u32 reg32, addr;
	int i;

	MCHBAR32(C0DRC1 + channel_offset) |= (1 << 6);

	MCHBAR32(C0DRC1 + channel_offset) &= ~(1 << 6);

	addr = 0;

	if (channel_offset != 0) {	/* must be dual channel */
		if (sysinfo->interleaved == 1)
			addr |= (1 << 6);
		else
			addr = ((u32)MCHBAR8(C0DRB3)) << 25;
	}

	for (i = 0; i < 28; i++) {
		read32((void *)addr);
		read32((void *)(addr + 0x80));
	}

	reg32 = MCHBAR32(RCVENMT);
	if (channel_offset == 0)
		reg32 = reg32 << 2;

	/**
	 * [19] = 1: all bits are high
	 * [18] = 1: all bits are low
	 * [19:18] = 00: bits are mixed high, low
	 */
	return reg32;
}

/**
 * This function sets receive enable coarse and medium timing parameters
 */

static void set_receive_enable(int channel_offset, u8 medium, u8 coarse)
{
	u32 reg32;

	printk(BIOS_SPEW, "    set_receive_enable() medium=0x%x, coarse=0x%x\n", medium, coarse);

	reg32 = MCHBAR32(C0DRT1 + channel_offset);
	reg32 &= 0xf0ffffff;
	reg32 |= ((u32)coarse & 0x0f) << 24;
	MCHBAR32(C0DRT1 + channel_offset) = reg32;

	/* This should never happen: */
	if (coarse > 0x0f)
		printk(BIOS_DEBUG, "set_receive_enable: coarse overflow: 0x%02x.\n", coarse);

	/* medium control
	 *
	 * 00 - 1/4 clock
	 * 01 - 1/2 clock
	 * 10 - 3/4 clock
	 * 11 - 1   clock
	 */

	reg32 = MCHBAR32(RCVENMT);
	if (!channel_offset) {
		/* Channel 0 */
		reg32 &= ~(3 << 2);
		reg32 |= medium << 2;
	} else {
		/* Channel 1 */
		reg32 &= ~(3 << 0);
		reg32 |= medium;
	}
	MCHBAR32(RCVENMT) = reg32;

}

static int normalize(int channel_offset, u8 *mediumcoarse, u8 *fine)
{
	printk(BIOS_SPEW, "  normalize()\n");

	if (*fine < 0x80)
		return 0;

	*fine -= 0x80;
	*mediumcoarse += 1;

	if (*mediumcoarse >= 0x40) {
		printk(BIOS_DEBUG, "Normalize Error\n");
		return -1;
	}

	set_receive_enable(channel_offset, *mediumcoarse & 3,
			   *mediumcoarse >> 2);

	MCHBAR8(C0WL0REOST + channel_offset) = *fine;

	return 0;
}

static int find_preamble(int channel_offset, u8 *mediumcoarse,
			 struct sys_info *sysinfo)
{
	/* find start of the data phase */
	u32 reg32;

	printk(BIOS_SPEW, "  find_preamble()\n");

	do {
		if (*mediumcoarse < 4) {
			printk(BIOS_DEBUG, "No Preamble found.\n");
			return -1;
		}
		*mediumcoarse -= 4;

		set_receive_enable(channel_offset, *mediumcoarse & 3,
				   *mediumcoarse >> 2);

		reg32 = sample_strobes(channel_offset, sysinfo);

	} while (reg32 & (1 << 19));

	if (!(reg32 & (1 << 18))) {
		printk(BIOS_DEBUG, "No Preamble found (neither high nor low).\n");
		return -1;
	}

	return 0;
}

/**
 * add a quarter clock to the current receive enable settings
 */

static int add_quarter_clock(int channel_offset, u8 *mediumcoarse, u8 *fine)
{
	printk(BIOS_SPEW, "  add_quarter_clock() mediumcoarse=%02x fine=%02x\n",
			*mediumcoarse, *fine);
	if (*fine >= 0x80) {
		*fine -= 0x80;

		*mediumcoarse += 2;
		if (*mediumcoarse >= 0x40) {
			printk(BIOS_DEBUG, "clocks at max.\n");
			return -1;
		}

		set_receive_enable(channel_offset, *mediumcoarse & 3,
				   *mediumcoarse >> 2);
	} else {
		*fine += 0x80;
	}

	MCHBAR8(C0WL0REOST + channel_offset) = *fine;

	return 0;
}

static int find_strobes_low(int channel_offset, u8 *mediumcoarse, u8 *fine,
			    struct sys_info *sysinfo)
{
	u32 rcvenmt;

	printk(BIOS_SPEW, "  find_strobes_low()\n");

	for (;;) {
		MCHBAR8(C0WL0REOST + channel_offset) = *fine;

		set_receive_enable(channel_offset, *mediumcoarse & 3,
				   *mediumcoarse >> 2);

		rcvenmt = sample_strobes(channel_offset, sysinfo);

		if (((rcvenmt & (1 << 18)) != 0))
			return 0;

		*fine -= 0x80;
		if (*fine == 0)
			continue;

		*mediumcoarse -= 2;
		if (*mediumcoarse < 0xfe)
			continue;

		break;

	}

	printk(BIOS_DEBUG, "Could not find low strobe\n");
	return 0;
}

static int find_strobes_edge(int channel_offset, u8 *mediumcoarse, u8 *fine,
			     struct sys_info *sysinfo)
{

	int counter;
	u32 rcvenmt;

	printk(BIOS_SPEW, "  find_strobes_edge()\n");

	counter = 8;
	set_receive_enable(channel_offset, *mediumcoarse & 3,
			   *mediumcoarse >> 2);

	for (;;) {
		MCHBAR8(C0WL0REOST + channel_offset) = *fine;
		rcvenmt = sample_strobes(channel_offset, sysinfo);

		if ((rcvenmt & (1 << 19)) == 0) {
			counter = 8;
		} else {
			counter--;
			if (!counter)
				break;
		}

		*fine = *fine + 1;
		if (*fine < 0xf8) {
			if (*fine & (1 << 3)) {
				*fine &= ~(1 << 3);
				*fine += 0x10;
			}
			continue;
		}

		*fine = 0;
		*mediumcoarse += 2;
		if (*mediumcoarse <= 0x40) {
			set_receive_enable(channel_offset, *mediumcoarse & 3,
					   *mediumcoarse >> 2);
			continue;
		}

		printk(BIOS_DEBUG, "Could not find rising edge.\n");
		return -1;
	}

	*fine -= 7;
	if (*fine >= 0xf9) {
		*mediumcoarse -= 2;
		set_receive_enable(channel_offset, *mediumcoarse & 3,
				   *mediumcoarse >> 2);
	}

	*fine &= ~(1 << 3);
	MCHBAR8(C0WL0REOST + channel_offset) = *fine;

	return 0;
}

/**
 * Here we use a trick. The RCVEN channel 0 registers are all at an
 * offset of 0x80 to the channel 0 registers. We don't want to waste
 * a lot of if ()s so let's just pass 0 or 0x80 for the channel offset.
 */

static int receive_enable_autoconfig(int channel_offset,
				     struct sys_info *sysinfo)
{
	u8 mediumcoarse;
	u8 fine;

	printk(BIOS_SPEW, "receive_enable_autoconfig() for channel %d\n",
		    channel_offset ? 1 : 0);

	/* Set initial values */
	mediumcoarse = (sysinfo->cas << 2) | 3;
	fine = 0;

	if (find_strobes_low(channel_offset, &mediumcoarse, &fine, sysinfo))
		return -1;

	if (find_strobes_edge(channel_offset, &mediumcoarse, &fine, sysinfo))
		return -1;

	if (add_quarter_clock(channel_offset, &mediumcoarse, &fine))
		return -1;

	if (find_preamble(channel_offset, &mediumcoarse, sysinfo))
		return -1;

	if (add_quarter_clock(channel_offset, &mediumcoarse, &fine))
		return -1;

	if (normalize(channel_offset, &mediumcoarse, &fine))
		return -1;

	/* This is a debug check to see if the rcven code is fully working.
	 * It can be removed when the output message is not printed anymore
	 */
	if (MCHBAR8(C0WL0REOST + channel_offset) == 0)
		printk(BIOS_DEBUG, "Weird. No C%sWL0REOST\n", channel_offset?"1":"0");

	return 0;
}

void receive_enable_adjust(struct sys_info *sysinfo)
{
	/* Is channel 0 populated? */
	if (sysinfo->dimm[0] != SYSINFO_DIMM_NOT_POPULATED
	    || sysinfo->dimm[1] != SYSINFO_DIMM_NOT_POPULATED)
		if (receive_enable_autoconfig(0, sysinfo))
			return;

	/* Is channel 1 populated? */
	if (sysinfo->dimm[2] != SYSINFO_DIMM_NOT_POPULATED
	    || sysinfo->dimm[3] != SYSINFO_DIMM_NOT_POPULATED)
		if (receive_enable_autoconfig(0x80, sysinfo))
			return;
}
