/*
 * 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.
 *
 * 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
 */

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

#include <stdlib.h>
#include "flash.h"
#include "programmer.h"

#define PCI_VENDOR_ID_SII	0x1095

#define SATASII_MEMMAP_SIZE	0x100

uint8_t *sii_bar;
static uint16_t id;

const struct pcidev_status 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"},

	{},
};

static int satasii_shutdown(void *data)
{
	physunmap(sii_bar, SATASII_MEMMAP_SIZE);
	pci_cleanup(pacc);
	release_io_perms();
	return 0;
}

int satasii_init(void)
{
	uint32_t addr;
	uint16_t reg_offset;

	get_io_perms();

	pcidev_init(PCI_BASE_ADDRESS_0, satas_sii);

	id = pcidev_dev->device_id;

	if ((id == 0x3132) || (id == 0x3124)) {
		addr = pci_read_long(pcidev_dev, PCI_BASE_ADDRESS_0) & ~0x07;
		reg_offset = 0x70;
	} else {
		addr = pci_read_long(pcidev_dev, PCI_BASE_ADDRESS_5) & ~0x07;
		reg_offset = 0x50;
	}

	sii_bar = physmap("SATA SIL registers", addr, SATASII_MEMMAP_SIZE) +
		  reg_offset;

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

	buses_supported = CHIP_BUSTYPE_PARALLEL;

	if (register_shutdown(satasii_shutdown, NULL))
		return 1;
	return 0;
}

void satasii_chip_writeb(uint8_t val, chipaddr addr)
{
	uint32_t ctrl_reg, data_reg;

	while ((ctrl_reg = pci_mmio_readl(sii_bar)) & (1 << 25)) ;

	/* 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);

	while (pci_mmio_readl(sii_bar) & (1 << 25)) ;
}

uint8_t satasii_chip_readb(const chipaddr addr)
{
	uint32_t ctrl_reg;

	while ((ctrl_reg = pci_mmio_readl(sii_bar)) & (1 << 25)) ;

	/* 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);

	while (pci_mmio_readl(sii_bar) & (1 << 25)) ;

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