/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
 * Copyright (C) 2011 Jonathan Kollasch <jakllsch@kollasch.net>
 * Copyright (C) 2012-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.
 *
 * 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 <stdlib.h>
#include <string.h>
#include "flash.h"
#include "programmer.h"
#include "hwaccess.h"

#define PCI_VENDOR_ID_VIA	0x1106

#define VIA_MAX_RETRIES		300

#define BROM_ADDR		0x60

#define BROM_DATA		0x64

#define BROM_ACCESS		0x68
#define BROM_TRIGGER		0x80
#define BROM_WRITE		0x40
#define BROM_SIZE_MASK		0x30
#define BROM_SIZE_64K		0x00
#define BROM_SIZE_32K		0x10
#define BROM_SIZE_16K		0x20
#define BROM_SIZE_0K		0x30
#define BROM_BYTE_ENABLE_MASK	0x0f

#define BROM_STATUS		0x69
#define BROM_ERROR_STATUS	0x80

/* Select the byte we want to access. This is done by clearing the bit corresponding to the byte we want to
 * access, leaving the others set (yes, really). */
#define ENABLE_BYTE(address)	((~(1 << ((address) & 3))) & BROM_BYTE_ENABLE_MASK)
#define BYTE_OFFSET(address)	(((addr) & 3) * 8)

const struct dev_entry ata_via[] = {
	{PCI_VENDOR_ID_VIA, 0x3249, DEP, "VIA", "VT6421A"},

	{},
};

static void atavia_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr);
static uint8_t atavia_chip_readb(const struct flashctx *flash, const chipaddr addr);
static const struct par_master lpc_master_atavia = {
		.chip_readb		= atavia_chip_readb,
		.chip_readw		= fallback_chip_readw,
		.chip_readl		= fallback_chip_readl,
		.chip_readn		= fallback_chip_readn,
		.chip_writeb		= atavia_chip_writeb,
		.chip_writew		= fallback_chip_writew,
		.chip_writel		= fallback_chip_writel,
		.chip_writen		= fallback_chip_writen,
};

static void *atavia_offset = NULL;
static struct pci_dev *dev = NULL;

static void atavia_prettyprint_access(uint8_t access)
{
	uint8_t bmask = access & BROM_BYTE_ENABLE_MASK;
	uint8_t size = access & BROM_SIZE_MASK;

	msg_pspew("Accessing byte(s):%s%s%s%s\n",
		  ((bmask & (1<<3)) == 0) ? " 3" : "",
		  ((bmask & (1<<2)) == 0) ? " 2" : "",
		  ((bmask & (1<<1)) == 0) ? " 1" : "",
		  ((bmask & (1<<0)) == 0) ? " 0" : "");
	if (size == BROM_SIZE_0K) {
		msg_pspew("No ROM device found.\n");
	} else
		msg_pspew("ROM device with %s kB attached.\n",
			  (size == BROM_SIZE_64K) ? ">=64" :
			  (size == BROM_SIZE_32K) ? "32" : "16");
	msg_pspew("Access is a %s.\n", (access & BROM_WRITE) ? "write" : "read");
	msg_pspew("Device is %s.\n", (access & BROM_TRIGGER) ? "busy" : "ready");
}

static bool atavia_ready(struct pci_dev *pcidev_dev)
{
	int try;
	uint8_t access, status;
	bool ready = false;

	for (try = 0; try < VIA_MAX_RETRIES; try++) {
		access = pci_read_byte(pcidev_dev, BROM_ACCESS);
		status = pci_read_byte(pcidev_dev, BROM_STATUS);
		if (((access & BROM_TRIGGER) == 0) && (status & BROM_ERROR_STATUS) == 0) {
			ready = true;
			break;
		} else {
			programmer_delay(1);
			continue;
		}
	}

	msg_pdbg2("\n%s: %s after %d tries (access=0x%02x, status=0x%02x)\n",
		  __func__, ready ? "succeeded" : "failed", try, access, status);
	atavia_prettyprint_access(access);
	return ready;
}

void *atavia_map(const char *descr, uintptr_t phys_addr, size_t len)
{
	return (atavia_offset != 0) ? atavia_offset : (void *)phys_addr;
}

int atavia_init(void)
{
	char *arg = extract_programmer_param("offset");
	if (arg) {
		if (strlen(arg) == 0) {
			msg_perr("Missing argument for offset.\n");
			free(arg);
			return ERROR_FATAL;
		}
		char *endptr;
		atavia_offset = (void *)strtoul(arg, &endptr, 0);
		if (*endptr) {
			msg_perr("Error: Invalid offset specified: \"%s\".\n", arg);
			free(arg);
			return ERROR_FATAL;
		}
		msg_pinfo("Mapping addresses to base %p.\n", atavia_offset);
	}
	free(arg);

	if (rget_io_perms())
		return 1;

	dev = pcidev_init(ata_via, PCI_ROM_ADDRESS); /* Acutally no BAR setup needed at all. */
	if (!dev)
		return 1;

	/* Test if a flash chip is attached. */
	pci_write_long(dev, PCI_ROM_ADDRESS, (uint32_t)PCI_ROM_ADDRESS_MASK);
	programmer_delay(90);
	uint32_t base = pci_read_long(dev, PCI_ROM_ADDRESS);
	msg_pdbg2("BROM base=0x%08x\n", base);
	if ((base & PCI_ROM_ADDRESS_MASK) == 0) {
		msg_pwarn("Controller thinks there is no ROM attached.\n");
	}

	if (!atavia_ready(dev)) {
		msg_perr("Controller not ready.\n");
		return 1;
	}

	register_par_master(&lpc_master_atavia, BUS_LPC);

	return 0;
}

static void atavia_chip_writeb(const struct flashctx *flash, uint8_t val, const chipaddr addr)
{
	msg_pspew("%s: 0x%02x to 0x%*" PRIxPTR ".\n", __func__, val, PRIxPTR_WIDTH, addr);
	pci_write_long(dev, BROM_ADDR, (addr & ~3));
	pci_write_long(dev, BROM_DATA, val << BYTE_OFFSET(addr));
	pci_write_byte(dev, BROM_ACCESS, BROM_TRIGGER | BROM_WRITE | ENABLE_BYTE(addr));

	if (!atavia_ready(dev)) {
		msg_perr("not ready after write\n");
	}
}

static uint8_t atavia_chip_readb(const struct flashctx *flash, const chipaddr addr)
{
	pci_write_long(dev, BROM_ADDR, (addr & ~3));
	pci_write_byte(dev, BROM_ACCESS, BROM_TRIGGER | ENABLE_BYTE(addr));

	if (!atavia_ready(dev)) {
		msg_perr("not ready after read\n");
	}

	uint8_t val = (pci_read_long(dev, BROM_DATA) >> BYTE_OFFSET(addr)) & 0xff;
	msg_pspew("%s: 0x%02x from 0x%*" PRIxPTR ".\n", __func__, val, PRIxPTR_WIDTH, addr);
	return val;
}
