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

/* Datasheets can be found on http://www.siliconimage.com. Great thanks! */

#include "programmer.h"
#include "hwaccess.h"

#define PCI_VENDOR_ID_SII	0x1095

#define SATASII_MEMMAP_SIZE	0x100

static uint8_t *sii_bar;
static uint16_t id;

static const struct dev_entry satas_sii[] = {
	{0x1095, 0x0680, OK, "Silicon Image", "PCI0680 Ultra ATA-133 Host Ctrl"},
	{0x1095, 0x3112, OK, "Silicon Image", "SiI 3112 [SATALink/SATARaid] SATA Ctrl"},
	{0x1095, 0x3114, OK, "Silicon Image", "SiI 3114 [SATALink/SATARaid] SATA Ctrl"},
	{0x1095, 0x3124, OK, "Silicon Image", "SiI 3124 PCI-X SATA Ctrl"},
	{0x1095, 0x3132, OK, "Silicon Image", "SiI 3132 SATA Raid II Ctrl"},
	{0x1095, 0x3512, OK, "Silicon Image", "SiI 3512 [SATALink/SATARaid] SATA Ctrl"},

	{0},
};

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

static uint32_t satasii_wait_done(void)
{
	uint32_t ctrl_reg;
	int i = 0;
	while ((ctrl_reg = pci_mmio_readl(sii_bar)) & (1 << 25)) {
		if (++i > 10000) {
			msg_perr("%s: control register stuck at %08x, ignoring.\n",
				 __func__, pci_mmio_readl(sii_bar));
			break;
		}
	}
	return ctrl_reg;
}

static int satasii_init(void)
{
	struct pci_dev *dev = NULL;
	uint32_t addr;
	uint16_t reg_offset;

	if (rget_io_perms())
		return 1;

	dev = pcidev_init(satas_sii, PCI_BASE_ADDRESS_0);
	if (!dev)
		return 1;

	id = dev->device_id;

	if ((id == 0x3132) || (id == 0x3124)) {
		addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0);
		if (!addr)
			return 1;
		reg_offset = 0x70;
	} else {
		addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_5);
		if (!addr)
			return 1;
		reg_offset = 0x50;
	}

	sii_bar = rphysmap("SATA SiI registers", addr, SATASII_MEMMAP_SIZE);
	if (sii_bar == ERROR_PTR)
		return 1;
	sii_bar += reg_offset;

	/* Check if ROM cycle are OK. */
	if ((id != 0x0680) && (!(pci_mmio_readl(sii_bar) & (1 << 26))))
		msg_pwarn("Warning: Flash seems unconnected.\n");

	register_par_master(&par_master_satasii, BUS_PARALLEL, NULL);

	return 0;
}

static void satasii_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
{
	uint32_t data_reg;
	uint32_t ctrl_reg = satasii_wait_done();

	/* Mask out unused/reserved bits, set writes and start transaction. */
	ctrl_reg &= 0xfcf80000;
	ctrl_reg |= (1 << 25) | (0 << 24) | ((uint32_t) addr & 0x7ffff);

	data_reg = (pci_mmio_readl((sii_bar + 4)) & ~0xff) | val;
	pci_mmio_writel(data_reg, (sii_bar + 4));
	pci_mmio_writel(ctrl_reg, sii_bar);

	satasii_wait_done();
}

static uint8_t satasii_chip_readb(const struct flashctx *flash, const chipaddr addr)
{
	uint32_t ctrl_reg = satasii_wait_done();

	/* Mask out unused/reserved bits, set reads and start transaction. */
	ctrl_reg &= 0xfcf80000;
	ctrl_reg |= (1 << 25) | (1 << 24) | ((uint32_t) addr & 0x7ffff);

	pci_mmio_writel(ctrl_reg, sii_bar);

	satasii_wait_done();

	return (pci_mmio_readl(sii_bar + 4)) & 0xff;
}

const struct programmer_entry programmer_satasii = {
	.name			= "satasii",
	.type			= PCI,
	.devs.dev		= satas_sii,
	.init			= satasii_init,
	.map_flash_region	= fallback_map,
	.unmap_flash_region	= fallback_unmap,
	.delay			= internal_delay,
};
