/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2009 One Laptop per Child, Association, Inc.
 *
 * 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.
 *
 * 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
 */

/*
    part of this file is from cx700 port, part of is from cn700 port,
   */

#include <console/console.h>
#include <arch/io.h>
#include <stdint.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <stdlib.h>
#include <string.h>
#include <cpu/cpu.h>
#include "vx800.h"

/* !!FIXME!!  This was meant to be a CONFIG option */
#define VIACONFIG_TOP_SM_SIZE_MB 32	// Set frame buffer 32M for default
/* !!FIXME!!  I declared this to fix the build. */
u8 acpi_sleep_type = 0;

static void memctrl_init(device_t dev)
{
/*
  set VGA in uma_ram_setting.c, not in this function.
*/
#if 0
	pci_write_config8(dev, 0x85, 0x20);
	pci_write_config8(dev, 0x86, 0x2d);

	/* Set up VGA timers */
	pci_write_config8(dev, 0xa2, 0x44);

	/* Enable VGA with a 32mb framebuffer */
	pci_write_config16(dev, 0xa0, 0xd000);

	pci_write_config16(dev, 0xa4, 0x0010);

	//b0: 60 aa aa 5a 0f 00 00 00 08
	pci_write_config16(dev, 0xb0, 0xaa00);
	pci_write_config8(dev, 0xb8, 0x08);
#endif
}

static const struct device_operations memctrl_operations = {
	.read_resources = vx800_noop,
	.init = memctrl_init,
};

static const struct pci_driver memctrl_driver __pci_driver = {
	.ops = &memctrl_operations,
	.vendor = PCI_VENDOR_ID_VIA,
	.device = PCI_DEVICE_ID_VIA_VX855_MEMCTRL,
};

static void pci_domain_set_resources(device_t dev)
{
	/*
	 * the order is important to find the correct ram size.
	 */
	u8 ramregs[] = { 0x43, 0x42, 0x41, 0x40 };
	device_t mc_dev;
	u32 pci_tolm;
	u8 reg;

	printk(BIOS_SPEW, "Entering vx800 pci_domain_set_resources.\n");

	pci_tolm = find_pci_tolm(dev->link_list);
	mc_dev = dev_find_device(PCI_VENDOR_ID_VIA,
				 PCI_DEVICE_ID_VIA_VX855_MEMCTRL, 0);

	if (mc_dev) {
		unsigned long tomk, tolmk;
		unsigned char rambits;
		u8 i, idx;

		/*
		 * once the register value is not zero, the ramsize is
		 * this register's value multiply 64 * 1024 * 1024
		 */
		for (rambits = 0, i = 0; i < ARRAY_SIZE(ramregs); i++) {
			rambits = pci_read_config8(mc_dev, ramregs[i]);
			if (rambits != 0)
				break;
		}
/*
Get memory size and frame buffer from northbridge's registers.
if register with invalid value we set frame buffer size to 32M for default, but it won't happen.
*/
		reg = pci_read_config8(mc_dev, 0xa1);
		reg &= 0x70;
		reg = reg >> 4;
		/* TOP 1M SM Memory */
		if (reg == 0x0)
			tomk = (((rambits << 6) - 32 - VIACONFIG_TOP_SM_SIZE_MB) * 1024);	// Set frame buffer 32M for default
		else
			tomk =
			    (((rambits << 6) - (4 << reg) -
			      VIACONFIG_TOP_SM_SIZE_MB) * 1024);

		printk(BIOS_SPEW, "tomk is 0x%lx\n", tomk);
		/* Compute the Top Of Low Memory, in Kb */
		tolmk = pci_tolm >> 10;
		if (tolmk >= tomk) {
			/* The PCI hole does does not overlap the memory. */
			tolmk = tomk;
		}
		/* Report the memory regions */
		idx = 10;
		/* TODO: Hole needed? */
		ram_resource(dev, idx++, 0, 640);	/* first 640k */
		/* Leave a hole for vga, 0xa0000 - 0xc0000 */
		ram_resource(dev, idx++, 768, (tolmk - 768));
	}
	assign_resources(dev->link_list);
}

static struct device_operations pci_domain_ops = {
	.read_resources = pci_domain_read_resources,
	.set_resources = pci_domain_set_resources,
	.enable_resources = NULL,
	.init = NULL,
	.scan_bus = pci_domain_scan_bus,
};

static void cpu_bus_init(device_t dev)
{
	initialize_cpus(dev->link_list);
}

static void cpu_bus_noop(device_t dev)
{
}

static struct device_operations cpu_bus_ops = {
	.read_resources = cpu_bus_noop,
	.set_resources = cpu_bus_noop,
	.enable_resources = cpu_bus_noop,
	.init = cpu_bus_init,
	.scan_bus = 0,
};

static void enable_dev(struct device *dev)
{
	printk(BIOS_SPEW, "In VX800 enable_dev for device %s.\n", dev_path(dev));

	/* Set the operations if it is a special bus type */
	if (dev->path.type == DEVICE_PATH_DOMAIN) {
		dev->ops = &pci_domain_ops;
		pci_set_method(dev);
	} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
		dev->ops = &cpu_bus_ops;
	}
}

struct chip_operations northbridge_via_vx800_ops = {
	CHIP_NAME("VIA VX800 Chipset")
	    .enable_dev = enable_dev,
};
