/*
 * 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_programmer lpc_programmer_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 ? "suceeded" : "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_programmer(&lpc_programmer_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;
}
