/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
 * Copyright (C) 2007-2008 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 <cpu/x86/msr.h>
#include <console/console.h>
#include <northbridge/amd/amdfam10/amdfam10.h>

#include "ht_wrapper.h"

/*----------------------------------------------------------------------------
 *			TYPEDEFS, DEFINITIONS AND MACROS
 *
 *----------------------------------------------------------------------------
 */

/* Single CPU system? */
#if (CONFIG_MAX_PHYSICAL_CPUS == 1)
	/* FIXME
         * This #define is used by other #included .c files
	 * When set, multiprocessor support is completely disabled
         */
	#define HT_BUILD_NC_ONLY 1
#endif

/* Debugging Options */
#define AMD_DEBUG 1
//#define AMD_DEBUG_ERROR_STOP 1

/*----------------------------------------------------------------------------
 *				MODULES USED
 *
 *----------------------------------------------------------------------------
 */

#undef FILECODE
#define FILECODE 0xFF01
#include "comlib.h"
#include "h3gtopo.h"
#include "h3finit.h"

/* include the main HT source file */
#include "h3finit.c"


/*----------------------------------------------------------------------------
 *			LOCAL FUNCTIONS
 *
 *----------------------------------------------------------------------------
 */

/* FIXME: Find a better place for these pre-ram functions. */
#define NODE_HT(x) NODE_PCI(x,0)
#define NODE_MP(x) NODE_PCI(x,1)
#define NODE_MC(x) NODE_PCI(x,3)
#define NODE_LC(x) NODE_PCI(x,4)

static  u32 get_nodes(void)
{
	device_t dev;
	u32 nodes;

	dev = PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0);
	nodes = ((pci_read_config32(dev, 0x60)>>4) & 7) ;
#if CONFIG_MAX_PHYSICAL_CPUS > 8
	nodes += (((pci_read_config32(dev, 0x160)>>4) & 7)<<3);
#endif
	nodes++;

	return nodes;
}


/**
 * void AMD_CB_EventNotify (u8 evtClass, u16 event, const u8 *pEventData0)
 */
static void AMD_CB_EventNotify (u8 evtClass, u16 event, const u8 *pEventData0)
{
	u8 i;

	printk(BIOS_DEBUG, "AMD_CB_EventNotify()\n");
	printk(BIOS_DEBUG, " event class: %02x\n event: %04x\n data: ", evtClass, event);

	for (i = 0; i < *pEventData0; i++) {
		printk(BIOS_DEBUG, " %02x ", *(pEventData0 + i));
	}
	printk(BIOS_DEBUG, "\n");

}

/**
 * void getAmdTopolist(u8 ***p)
 *
 *  point to the stock topo list array
 *
 */
void getAmdTopolist(u8 ***p)
{
	*p = (u8 **)amd_topo_list;
}

/**
 * BOOL AMD_CB_IgnoreLink(u8 Node, u8 Link)
 * Description:
 *	This routine is used to ignore connected yet faulty HT links,
 *	such as those present in a G34 processor package.
 *
 * Parameters:
 *	@param[in]  node   = The node on which this chain is located
 *	@param[in]  link   = The link on the host for this chain
 */
static BOOL AMD_CB_IgnoreLink (u8 node, u8 link)
{
	return 0;
}

/**
 * void amd_ht_init(struct sys_info *sysinfo)
 *
 *  AMD HT init coreboot wrapper
 *
 */
static void amd_ht_init(struct sys_info *sysinfo)
{

	AMD_HTBLOCK ht_wrapper = {
		NULL,	// u8 **topolist;
		0,	// u8 AutoBusStart;
		32,	// u8 AutoBusMax;
		6,	// u8 AutoBusIncrement;
		AMD_CB_IgnoreLink,		// BOOL (*AMD_CB_IgnoreLink)();
		NULL,	// BOOL (*AMD_CB_OverrideBusNumbers)();
		AMD_CB_ManualBUIDSwapList,	// BOOL (*AMD_CB_ManualBUIDSwapList)();
		NULL,	// void (*AMD_CB_DeviceCapOverride)();
		NULL,	// void (*AMD_CB_Cpu2CpuPCBLimits)();
		NULL,	// void (*AMD_CB_IOPCBLimits)();
		NULL,	// BOOL (*AMD_CB_SkipRegang)();
		NULL,	// BOOL (*AMD_CB_CustomizeTrafficDistribution)();
		NULL,	// BOOL (*AMD_CB_CustomizeBuffers)();
		NULL,	// void (*AMD_CB_OverrideDevicePort)();
		NULL,	// void (*AMD_CB_OverrideCpuPort)();
		AMD_CB_EventNotify,	// void (*AMD_CB_EventNotify) ();
		&sysinfo->ht_link_cfg // struct ht_link_config*
	};

	printk(BIOS_DEBUG, "Enter amd_ht_init()\n");
	amdHtInitialize(&ht_wrapper);
	printk(BIOS_DEBUG, "Exit amd_ht_init()\n");
}

/**
 * void amd_ht_fixup(struct sys_info *sysinfo)
 *
 *  AMD HT fixup
 *
 */
void amd_ht_fixup(struct sys_info *sysinfo) {
	printk(BIOS_DEBUG, "amd_ht_fixup()\n");
	if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX)) {
		uint8_t rev_gte_d = 0;
		uint8_t fam15h = 0;
		uint8_t dual_node = 0;
		uint32_t f3xe8;
		uint32_t family;
		uint32_t model;

		family = model = cpuid_eax(0x80000001);
		model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
		family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);

		if (family >= 0x6f)
			/* Family 15h or later */
			fam15h = 1;

		if ((model >= 0x8) || fam15h)
			/* Family 10h Revision D or later */
			rev_gte_d = 1;

		if (rev_gte_d) {
			f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);

			/* Check for dual node capability */
			if (f3xe8 & 0x20000000)
				dual_node = 1;

			if (dual_node) {
				/* Each G34 processor contains a defective HT link.
				* See the Family 10h BKDG Rev 3.62 section 2.7.1.5 for details
				* For Family 15h see the BKDG Rev. 3.14 section 2.12.1.5 for details.
				*/
				uint8_t node;
				uint8_t node_count = get_nodes();
				uint32_t dword;
				for (node = 0; node < node_count; node++) {
					f3xe8 = pci_read_config32(NODE_PCI(node, 3), 0xe8);
					uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 30);
					printk(BIOS_DEBUG, "amd_ht_fixup(): node %d (internal node ID %d): disabling defective HT link\n", node, internal_node_number);
					if (internal_node_number == 0) {
						uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x98:0xd8) & 0x1;
						if (package_link_3_connected) {
							/* Set WidthIn and WidthOut to 0 */
							dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x84:0xc4);
							dword &= ~0x77000000;
							pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x84:0xc4, dword);
							/* Set Ganged to 1 */
							dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x170:0x178);
							dword |= 0x00000001;
							pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x170:0x178, dword);
						} else {
							/* Set ConnDly to 1 */
							dword = pci_read_config32(NODE_PCI(node, 0), 0x16c);
							dword |= 0x00000100;
							pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
							/* Set TransOff and EndOfChain to 1 */
							dword = pci_read_config32(NODE_PCI(node, 4), (fam15h)?0x84:0xc4);
							dword |= 0x000000c0;
							pci_write_config32(NODE_PCI(node, 4), (fam15h)?0x84:0xc4, dword);
						}
					} else if (internal_node_number == 1) {
						uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0xf8:0xb8) & 0x1;
						if (package_link_3_connected) {
							/* Set WidthIn and WidthOut to 0 */
							dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0xe4:0xa4);
							dword &= ~0x77000000;
							pci_write_config32(NODE_PCI(node, 0), (fam15h)?0xe4:0xa4, dword);
							/* Set Ganged to 1 */
							dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x18c:0x174);
							dword |= 0x00000001;
							pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x18c:0x174, dword);
						} else {
							/* Set ConnDly to 1 */
							dword = pci_read_config32(NODE_PCI(node, 0), 0x16c);
							dword |= 0x00000100;
							pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
							/* Set TransOff and EndOfChain to 1 */
							dword = pci_read_config32(NODE_PCI(node, 4), (fam15h)?0xe4:0xa4);
							dword |= 0x000000c0;
							pci_write_config32(NODE_PCI(node, 4), (fam15h)?0xe4:0xa4, dword);
						}
					}
				}
			}
		}
	}
}
