/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2007 Advanced Micro Devices, 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.
 */

#include <stdint.h>
#include <cpu/x86/lapic.h>
#include "amdfam10.h"

#define NODE_ID		0x60
#define HT_INIT_CONTROL	0x6c
#define HTIC_ColdR_Detect	(1<<4)
#define HTIC_BIOSR_Detect	(1<<5)
#define HTIC_INIT_Detect	(1<<6)

/* mmconf is not ready */
/* io_ext is not ready */
u32 cpu_init_detected(u8 nodeid)
{
	u32 htic;
	pci_devfn_t dev;

	dev = NODE_PCI(nodeid, 0);
	htic = pci_io_read_config32(dev, HT_INIT_CONTROL);

	return !!(htic & HTIC_INIT_Detect);
}

u32 bios_reset_detected(void)
{
	u32 htic;
	htic = pci_io_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), HT_INIT_CONTROL);

	return (htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect);
}

u32 cold_reset_detected(void)
{
	u32 htic;
	htic = pci_io_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), HT_INIT_CONTROL);

	return !(htic & HTIC_ColdR_Detect);
}

u32 other_reset_detected(void)	// other warm reset not started by BIOS
{
	u32 htic;
	htic = pci_io_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), HT_INIT_CONTROL);

	return (htic & HTIC_ColdR_Detect) && (htic & HTIC_BIOSR_Detect);
}

static void distinguish_cpu_resets(u8 nodeid)
{
	u32 htic;
	pci_devfn_t device;
	device = NODE_PCI(nodeid, 0);
	htic = pci_io_read_config32(device, HT_INIT_CONTROL);
	htic |= HTIC_ColdR_Detect | HTIC_BIOSR_Detect | HTIC_INIT_Detect;
	pci_io_write_config32(device, HT_INIT_CONTROL, htic);
}

static u32 warm_reset_detect(u8 nodeid)
{
	u32 htic;
	pci_devfn_t device;
	device = NODE_PCI(nodeid, 0);
	htic = pci_io_read_config32(device, HT_INIT_CONTROL);
	return (htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect);
}

void set_bios_reset(void);
void set_bios_reset(void)
{

	u32 nodes;
	u32 htic;
	pci_devfn_t dev;
	int i;

	nodes = ((pci_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), 0x60) >> 4) & 7) + 1;

	for (i = 0; i < nodes; i++) {
		dev = NODE_PCI(i,0);
		htic = pci_read_config32(dev, HT_INIT_CONTROL);
		htic &= ~HTIC_BIOSR_Detect;
		pci_write_config32(dev, HT_INIT_CONTROL, htic);
	}
}


/* Look up a which bus a given node/link combination is on.
 * return 0 when we can't find the answer.
 */
static u8 node_link_to_bus(u8 node, u8 link) // node are 6 bit, and link three bit
{
	u32 reg;
	u32 val;

	// put node and link in correct bit
	val = ((node & 0x0f)<<4) | ((node & 0x30)<< (12-4)) | ((link & 0x07)<<8) ;

	for (reg = 0xE0; reg < 0xF0; reg += 0x04) {
		u32 config_map;
		config_map = pci_io_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 1), reg);
		if ((config_map & 3) != 3) {
			continue;
		}
		if ((config_map & (((63 & 0x0f)<<4) | ((63 & 0x30)<< (12-4)) | ((7 & 0x07)<<8))
			) == val)
		{
			return (config_map >> 16) & 0xff;
		}
	}

	return 0;
}

u32 get_sblk(void)
{
	u32 reg;
	/* read PCI_DEV(CONFIG_CBB,CONFIG_CDB,0) 0x64 bit [8:9] to find out SbLink m */
	reg = pci_io_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), 0x64);
	return ((reg>>8) & 3) ;
}


u8 get_sbbusn(u8 sblk)
{
	return node_link_to_bus(0, sblk);
}
