/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2007 Advanced Micro Devices, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <console/console.h>
#include <arch/io.h>
#include "cs5536.h"
#include "smbus.h"

#define SMBUS_ERROR -1
#define SMBUS_WAIT_UNTIL_READY_TIMEOUT -2
#define SMBUS_WAIT_UNTIL_DONE_TIMEOUT  -3
#define SMBUS_TIMEOUT (1000)

static void smbus_delay(void)
{
	/* inb(0x80); */
}

static int smbus_wait(unsigned smbus_io_base)
{
	unsigned long loops = SMBUS_TIMEOUT;
	unsigned char val;

	do {
		smbus_delay();
		val = inb(smbus_io_base + SMB_STS);
		if ((val & SMB_STS_SDAST) != 0)
			break;
		if (val & (SMB_STS_BER | SMB_STS_NEGACK)) {
			/*printk(BIOS_DEBUG, "SMBUS WAIT ERROR %x\n", val); */
			return SMBUS_ERROR;
		}
	} while (--loops);
	return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}

/* generate a smbus start condition */
int smbus_start_condition(unsigned smbus_io_base)
{
	unsigned char val;

	/* issue a START condition */
	val = inb(smbus_io_base + SMB_CTRL1);
	outb(val | SMB_CTRL1_START, smbus_io_base + SMB_CTRL1);

	/* check for bus conflict */
	val = inb(smbus_io_base + SMB_STS);
	if ((val & SMB_STS_BER) != 0)
		return SMBUS_ERROR;

	return smbus_wait(smbus_io_base);
}

int smbus_check_stop_condition(unsigned smbus_io_base)
{
	unsigned char val;
	unsigned long loops;
	loops = SMBUS_TIMEOUT;
	/* check for SDA status */
	do {
		smbus_delay();
		val = inb(smbus_io_base + SMB_CTRL1);
		if ((val & SMB_CTRL1_STOP) == 0) {
			break;
		}
		outb((0x7F << 1) | SMB_CTRL2_ENABLE, smbus_io_base + SMB_CTRL2);
	} while (--loops);
	return loops ? 0 : SMBUS_WAIT_UNTIL_READY_TIMEOUT;
}

int smbus_stop_condition(unsigned smbus_io_base)
{
	outb(SMB_CTRL1_STOP, smbus_io_base + SMB_CTRL1);
	return smbus_wait(smbus_io_base);
}

static int smbus_ack(unsigned smbus_io_base, int state)
{
	unsigned char val = inb(smbus_io_base + SMB_CTRL1);

/*	if (state) */
	outb(val | SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1);
/*	else
		outb(val & ~SMB_CTRL1_ACK, smbus_io_base + SMB_CTRL1);
*/
	return 0;
}

int smbus_send_slave_address(unsigned smbus_io_base,
				    unsigned char device)
{
	unsigned char val;

	/* send the slave address */
	outb(device, smbus_io_base + SMB_SDA);

	/* check for bus conflict and NACK */
	val = inb(smbus_io_base + SMB_STS);
	if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0)) {
		/* printk(BIOS_DEBUG, "SEND SLAVE ERROR (%x)\n", val); */
		return SMBUS_ERROR;
	}
	return smbus_wait(smbus_io_base);
}

int smbus_send_command(unsigned smbus_io_base, unsigned char command)
{
	unsigned char val;

	/* send the command */
	outb(command, smbus_io_base + SMB_SDA);

	/* check for bus conflict and NACK */
	val = inb(smbus_io_base + SMB_STS);
	if (((val & SMB_STS_BER) != 0) || ((val & SMB_STS_NEGACK) != 0))
		return SMBUS_ERROR;

	return smbus_wait(smbus_io_base);
}

static unsigned char smbus_get_result(unsigned smbus_io_base)
{
	return inb(smbus_io_base + SMB_SDA);
}

unsigned char do_smbus_read_byte(unsigned smbus_io_base,
					unsigned char device,
					unsigned char address)
{
	unsigned char error = 0;

	if ((smbus_check_stop_condition(smbus_io_base))) {
		error = 1;
		goto err;
	}

	if ((smbus_start_condition(smbus_io_base))) {
		error = 2;
		goto err;
	}

	if ((smbus_send_slave_address(smbus_io_base, device << 1))) {
		error = 3;
		goto err;
	}

	smbus_ack(smbus_io_base, 1);

	if ((smbus_send_command(smbus_io_base, address))) {
		error = 4;
		goto err;
	}

	if ((smbus_start_condition(smbus_io_base))) {
		error = 5;
		goto err;
	}

	if ((smbus_send_slave_address(smbus_io_base, (device << 1) | 0x01))) {
		error = 6;
		goto err;
	}

	if ((smbus_stop_condition(smbus_io_base))) {
		error = 7;
		goto err;
	}

	return smbus_get_result(smbus_io_base);

err:
	print_debug("SMBUS READ ERROR:");
	print_debug_hex8(error);
	print_debug(" device:");
	print_debug_hex8(device);
	print_debug("\n");
	/* stop, clean up the error, and leave */
	smbus_stop_condition(smbus_io_base);
	outb(inb(smbus_io_base + SMB_STS), smbus_io_base + SMB_STS);
	outb(0x0, smbus_io_base + SMB_STS);
	return 0xFF;
}
 
