/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2004 Tyan Computer
 * Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
 *
 * 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; version 2 of the License.
 *
 * 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 <console/console.h>
#include <arch/io.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include "chip.h"

static u32 final_reg;

static device_t find_lpc_dev(device_t dev, unsigned devfn)
{
	device_t lpc_dev;

	lpc_dev = dev_find_slot(dev->bus->secondary, devfn);
	if (!lpc_dev)
		return lpc_dev;

	if ((lpc_dev->vendor != PCI_VENDOR_ID_NVIDIA)
		|| ((lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_LPC)
		&& (lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_PRO)
		&& (lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_SLAVE)))
	{
		u32 id;
		id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
		if ((id != (PCI_VENDOR_ID_NVIDIA |
		      (PCI_DEVICE_ID_NVIDIA_CK804_LPC << 16)))
		    && (id != (PCI_VENDOR_ID_NVIDIA |
			 (PCI_DEVICE_ID_NVIDIA_CK804_PRO << 16)))
		    && (id != (PCI_VENDOR_ID_NVIDIA |
			 (PCI_DEVICE_ID_NVIDIA_CK804_SLAVE << 16))))
		{
			lpc_dev = 0;
		}
	}

	return lpc_dev;
}

static void ck804_enable(device_t dev)
{
	device_t lpc_dev;
	unsigned index = 0, index2 = 0, deviceid, vendorid, devfn;
	u32 reg_old, reg;
	u8 byte;

	struct southbridge_nvidia_ck804_config *conf;
	conf = dev->chip_info;

	if (dev->device == 0x0000) {
		vendorid = pci_read_config32(dev, PCI_VENDOR_ID);
		deviceid = (vendorid >> 16) & 0xffff;
		/* vendorid &= 0xffff; */
	} else {
		/* vendorid = dev->vendor; */
		deviceid = dev->device;
	}

	devfn = (dev->path.pci.devfn) & ~7;
	switch (deviceid) {
	case PCI_DEVICE_ID_NVIDIA_CK804_SM:
		index = 16;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_USB:
		devfn -= (1 << 3);
		index = 8;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_USB2:
		devfn -= (1 << 3);
		index = 20;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_NIC:
		devfn -= (9 << 3);
		index = 10;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_NIC_BRIDGE:
		devfn -= (9 << 3);
		index = 10;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_ACI:
		devfn -= (3 << 3);
		index = 12;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_MCI:
		devfn -= (3 << 3);
		index = 13;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_IDE:
		devfn -= (5 << 3);
		index = 14;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_SATA0:
		devfn -= (6 << 3);
		index = 22;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_SATA1:
		devfn -= (7 << 3);
		index = 18;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_PCI:
		devfn -= (8 << 3);
		index = 15;
		break;
	case PCI_DEVICE_ID_NVIDIA_CK804_PCI_E:
		devfn -= (0xa << 3);
		index2 = 19;
		break;
	default:
		index = 0;
	}

	if (index2 != 0) {
		int i;
		for (i = 0; i < 4; i++) {
			lpc_dev = find_lpc_dev(dev, devfn - (i << 3));
			if (!lpc_dev)
				continue;
			index2 -= i;
			break;
		}

		if (lpc_dev) {
			reg_old = reg = pci_read_config32(lpc_dev, 0xe4);
			if (!dev->enabled)
				reg |= (1 << index2);
			if (reg != reg_old)
				pci_write_config32(lpc_dev, 0xe4, reg);
		}

		index2 = 0;
		return;
	}

	lpc_dev = find_lpc_dev(dev, devfn);
	if (!lpc_dev)
		return;

	if (index == 0) {
		final_reg = pci_read_config32(lpc_dev, 0xe8);
		final_reg &= ~((1 << 16) | (1 << 8) | (1 << 20) | (1 << 10)
			| (1 << 12) | (1 << 13) | (1 << 14) | (1 << 22)
			| (1 << 18) | (1 << 15));
		pci_write_config32(lpc_dev, 0xe8, final_reg);

		reg_old = reg = pci_read_config32(lpc_dev, 0xe4);
		reg |= (1 << 20);
		if (reg != reg_old)
			pci_write_config32(lpc_dev, 0xe4, reg);

		byte = pci_read_config8(lpc_dev, 0x74);
		byte |= ((1 << 1));
		pci_write_config8(dev, 0x74, byte);

		byte = pci_read_config8(lpc_dev, 0xdd);
		byte |= ((1 << 0) | (1 << 3));
		pci_write_config8(dev, 0xdd, byte);

		return;
	}

	if (!dev->enabled)
		final_reg |= (1 << index);

	if (index == 10) {
		reg_old = pci_read_config32(lpc_dev, 0xe8);
		if (final_reg != reg_old)
			pci_write_config32(lpc_dev, 0xe8, final_reg);
	}
}

static void ck804_set_subsystem(device_t dev, unsigned vendor, unsigned device)
{
	pci_write_config32(dev, 0x40,
			   ((device & 0xffff) << 16) | (vendor & 0xffff));
}

struct pci_operations ck804_pci_ops = {
	.set_subsystem = ck804_set_subsystem,
};

struct chip_operations southbridge_nvidia_ck804_ops = {
	CHIP_NAME("NVIDIA CK804 Southbridge")
	.enable_dev = ck804_enable,
};
