/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2013 Rudolf Marek <r.marek@assembler.cz>
 * Copyright (C) 2013 Stefan Tauner
 *
 * 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.
 */

#include "flash.h"
#include "programmer.h"
#include "hwaccess_x86_io.h"
#include "spi.h"
#include "platform/pci.h"

/* same as serverengines */
static void enter_conf_mode_ec(uint16_t port)
{
	OUTB(0x5a, port);
}

static void exit_conf_mode_ec(uint16_t port)
{
	OUTB(0xa5, port);
}

static uint16_t get_sio_port(struct pci_dev *dev)
{
	uint16_t ec_port;

	if (!dev) {
		return 0;
	}

	ec_port = pci_read_word(dev, 0xa4);

	/* EcPortActive? */
	if (!(ec_port & 0x1))
		return 0;

	ec_port &= ~0x1;

	return ec_port;
}

/* Wait for up to 10 ms for a response. */
static int mbox_wait_ack(uint16_t mbox_port)
{
	int i = 10;
	while (sio_read(mbox_port, 0x82) != 0xfa) {
		if (--i == 0) {
			msg_pwarn("IMC MBOX: Timeout!\n");
			return 1;
		}
		programmer_delay(1000);
	}
	return 0;
}

static uint16_t mbox_get_port(uint16_t sio_port)
{
	uint16_t mbox_port;

	enter_conf_mode_ec(sio_port);

	/* Go to LDN 9, mailbox */
	sio_write(sio_port, 7, 9);

	/* MBOX inactive? */
	if ((sio_read(sio_port, 0x30) & 1) == 0) {
		exit_conf_mode_ec(sio_port);
		return 0;
	}

	mbox_port = sio_read(sio_port, 0x60) << 8;
	mbox_port |= sio_read(sio_port, 0x61);

	exit_conf_mode_ec(sio_port);
	return mbox_port;
}

/* Returns negative values when IMC is inactive, positive values on errors */
static int imc_send_cmd(struct pci_dev *dev, uint8_t cmd)
{
	uint16_t sio_port;
	uint16_t mbox_port;

	/* IntegratedEcPresent? */
	if (!(pci_read_byte(dev, 0x40) & (1 << 7)))
		return -1;

	sio_port = get_sio_port(dev);
	if (!sio_port)
		return -1;

	msg_pdbg2("IMC SIO is at 0x%x.\n", sio_port);
	mbox_port = mbox_get_port(sio_port);
	if (!mbox_port)
		return -1;
	msg_pdbg2("IMC MBOX is at 0x%x.\n", mbox_port);

	sio_write(mbox_port, 0x82, 0x0);
	sio_write(mbox_port, 0x83, cmd);
	sio_write(mbox_port, 0x84, 0x0);
	/* trigger transfer 0x96 with subcommand cmd */
	sio_write(mbox_port, 0x80, 0x96);

	return mbox_wait_ack(mbox_port);
}

static int imc_resume(void *data)
{
	struct pci_dev *dev = data;
	int ret = imc_send_cmd(dev, 0xb5);

	if (ret != 0)
		msg_pinfo("Resuming IMC failed.\n");
	else
		msg_pdbg2("IMC resumed.\n");
	return ret;
}

int amd_imc_shutdown(struct pci_dev *dev)
{
	/* Try to put IMC to sleep */
	int ret = imc_send_cmd(dev, 0xb4);

	/* No IMC activity detectable, assume we are fine */
	if (ret < 0) {
		msg_pdbg2("No IMC found.\n");
		return 0;
	}

	if (ret != 0) {
		msg_perr("Shutting down IMC failed.\n");
		return ret;
	}
	msg_pdbg2("Shutting down IMC successful.\n");

	if (register_shutdown(imc_resume, dev))
		return 1;

	return ret;
}
