/*
 * 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 "early_ht.h"
#include <inttypes.h>
#include <device/pci_ops.h>
#include <device/pci_def.h>

// For SB HT chain only
// mmconf is not ready yet
void set_bsp_node_CHtExtNodeCfgEn(void)
{
#if IS_ENABLED(CONFIG_EXT_RT_TBL_SUPPORT)
	u32 dword;
	dword = pci_io_read_config32(PCI_DEV(0, 0x18, 0), 0x68);
	dword |= (1<<27) | (1<<25);
	/* CHtExtNodeCfgEn: coherent link extended node configuration enable,
	   Nodes[31:0] will be 0xff:[31:0], Nodes[63:32] will be 0xfe:[31:0]
	      ---- 32 nodes now only
	   It can be used even nodes less than 8 nodes.
	   We can have 8 more device on bus 0 in that case
	 */

	/* CHtExtAddrEn */
	pci_io_write_config32(PCI_DEV(0, 0x18, 0), 0x68, dword);
	// CPU on bus 0xff and 0xfe now. For now on we can use CONFIG_CBB and CONFIG_CDB.
#endif
}

void enumerate_ht_chain(void)
{
#if CONFIG_HT_CHAIN_UNITID_BASE != 0
/* CONFIG_HT_CHAIN_UNITID_BASE could be 0 (only one ht device in the ht chain),
   if so, don't need to go through the chain  */

	/* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
	 * On most boards this just happens.  If a CPU has multiple
	 * non Coherent links the appropriate bus registers for the
	 * links needs to be programed to point at bus 0.
	 */
	unsigned next_unitid, last_unitid = 0;
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
	// let't record the device of last ht device, So we can set the
	// Unitid to CONFIG_HT_CHAIN_END_UNITID_BASE
	unsigned real_last_unitid = 0;
	u8 real_last_pos = 0;
	int ht_dev_num = 0; // except host_bridge
	u8 end_used = 0;
#endif

	next_unitid = CONFIG_HT_CHAIN_UNITID_BASE;
	do {
		u32 id;
		u8 hdr_type, pos;
		last_unitid = next_unitid;

		id = pci_io_read_config32(PCI_DEV(0,0,0), PCI_VENDOR_ID);
		/* If the chain is enumerated quit */
		if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
			(((id >> 16) & 0xffff) == 0xffff) ||
			(((id >> 16) & 0xffff) == 0x0000))
		{
			break;
		}

		hdr_type = pci_io_read_config8(PCI_DEV(0,0,0), PCI_HEADER_TYPE);
		pos = 0;
		hdr_type &= 0x7f;

		if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
			(hdr_type == PCI_HEADER_TYPE_BRIDGE))
		{
			pos = pci_io_read_config8(PCI_DEV(0,0,0), PCI_CAPABILITY_LIST);
		}
		while (pos != 0) {
			u8 cap;
			cap = pci_io_read_config8(PCI_DEV(0,0,0), pos + PCI_CAP_LIST_ID);
			if (cap == PCI_CAP_ID_HT) {
				u16 flags;
				/* Read and write and reread flags so the link
				 * direction bit is valid.
				 */
				flags = pci_io_read_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS);
				pci_io_write_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS, flags);
				flags = pci_io_read_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS);
				if ((flags >> 13) == 0) {
					unsigned count;
					unsigned ctrl, ctrl_off;
					pci_devfn_t devx;

#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
					if (next_unitid >= 0x18) {
						if (!end_used) {
							next_unitid = CONFIG_HT_CHAIN_END_UNITID_BASE;
							end_used = 1;
						} else {
							goto out;
						}
					}
					real_last_unitid = next_unitid;
					real_last_pos = pos;
					ht_dev_num++;
#endif
		#if !CONFIG_HT_CHAIN_END_UNITID_BASE
					if (!next_unitid)
						goto out;
		#endif
					flags &= ~0x1f;
					flags |= next_unitid & 0x1f;
					count = (flags >> 5) & 0x1f;
					devx = PCI_DEV(0, next_unitid, 0);
					next_unitid += count;

					pci_io_write_config16(PCI_DEV(0, 0, 0), pos + PCI_CAP_FLAGS, flags);

					/* Test for end of chain */
					ctrl_off = ((flags >> 10) & 1)?
						PCI_HT_CAP_SLAVE_CTRL0 : PCI_HT_CAP_SLAVE_CTRL1;

					do {
						ctrl = pci_io_read_config16(devx, pos + ctrl_off);
						/* Is this the end of the hypertransport chain? */
						if (ctrl & (1 << 6)) {
							goto out;
						}

						if (ctrl & ((1 << 4) | (1 << 8))) {
							/*
							 * Either the link has failed, or we have
							 * a CRC error.
							 * Sometimes this can happen due to link
							 * retrain, so lets knock it down and see
							 * if its transient
							 */
							ctrl |= ((1 << 4) | (1 <<8)); // Link fail + Crc
							pci_io_write_config16(devx, pos + ctrl_off, ctrl);
							ctrl = pci_io_read_config16(devx, pos + ctrl_off);
							if (ctrl & ((1 << 4) | (1 << 8))) {
								// can not clear the error
								break;
							}
						}
					} while ((ctrl & (1 << 5)) == 0);

					break;
				}
			}
			pos = pci_io_read_config8(PCI_DEV(0, 0, 0), pos + PCI_CAP_LIST_NEXT);
		}
	} while (last_unitid != next_unitid);

out:	;
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
	if ((ht_dev_num > 1) && (real_last_unitid != CONFIG_HT_CHAIN_END_UNITID_BASE) && !end_used) {
		u16 flags;
		flags = pci_io_read_config16(PCI_DEV(0,real_last_unitid,0), real_last_pos + PCI_CAP_FLAGS);
		flags &= ~0x1f;
		flags |= CONFIG_HT_CHAIN_END_UNITID_BASE & 0x1f;
		pci_io_write_config16(PCI_DEV(0, real_last_unitid, 0), real_last_pos + PCI_CAP_FLAGS, flags);
	}
#endif

#endif
}
