blob: 1f38b0c0320296024d121cce9e7ca811bc08ce53 [file] [log] [blame]
Marc Jones8ae8c882007-12-19 01:32:08 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Marc Jones8ae8c882007-12-19 01:32:08 +00003 *
Timothy Pearson88d213a2015-01-23 20:28:13 -06004 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Marc Jonesda4ce6b2008-04-22 22:11:31 +00005 * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
Marc Jones8ae8c882007-12-19 01:32:08 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Marc Jones8ae8c882007-12-19 01:32:08 +000015 */
16
Patrick Georgi3d5bb232010-05-09 21:15:13 +000017#include <cpu/x86/msr.h>
18#include <console/console.h>
19#include <northbridge/amd/amdfam10/amdfam10.h>
Marc Jones8ae8c882007-12-19 01:32:08 +000020
Timothy Pearson1c4508e2015-09-05 17:50:29 -050021#include "ht_wrapper.h"
22
Marc Jones8ae8c882007-12-19 01:32:08 +000023/*----------------------------------------------------------------------------
24 * TYPEDEFS, DEFINITIONS AND MACROS
25 *
26 *----------------------------------------------------------------------------
27 */
28
29/* Single CPU system? */
Timothy Pearson88d213a2015-01-23 20:28:13 -060030#if (CONFIG_MAX_PHYSICAL_CPUS == 1)
31 /* FIXME
32 * This #define is used by other #included .c files
33 * When set, multiprocessor support is completely disabled
34 */
Marc Jones8ae8c882007-12-19 01:32:08 +000035 #define HT_BUILD_NC_ONLY 1
36#endif
37
38/* Debugging Options */
39#define AMD_DEBUG 1
40//#define AMD_DEBUG_ERROR_STOP 1
41
42/*----------------------------------------------------------------------------
43 * MODULES USED
44 *
45 *----------------------------------------------------------------------------
46 */
47
48#undef FILECODE
49#define FILECODE 0xFF01
50#include "comlib.h"
51#include "h3gtopo.h"
52#include "h3finit.h"
53
54/* include the main HT source file */
55#include "h3finit.c"
56
57
58/*----------------------------------------------------------------------------
59 * LOCAL FUNCTIONS
60 *
61 *----------------------------------------------------------------------------
62 */
63
64/* FIXME: Find a better place for these pre-ram functions. */
65#define NODE_HT(x) NODE_PCI(x,0)
66#define NODE_MP(x) NODE_PCI(x,1)
67#define NODE_MC(x) NODE_PCI(x,3)
68#define NODE_LC(x) NODE_PCI(x,4)
Marc Jonesda4ce6b2008-04-22 22:11:31 +000069
Marc Jones8ae8c882007-12-19 01:32:08 +000070static u32 get_nodes(void)
71{
72 device_t dev;
73 u32 nodes;
74
Stefan Reinauer08670622009-06-30 15:17:49 +000075 dev = PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0);
Marc Jones8ae8c882007-12-19 01:32:08 +000076 nodes = ((pci_read_config32(dev, 0x60)>>4) & 7) ;
77#if CONFIG_MAX_PHYSICAL_CPUS > 8
78 nodes += (((pci_read_config32(dev, 0x160)>>4) & 7)<<3);
79#endif
80 nodes++;
81
82 return nodes;
83}
84
Marc Jones8ae8c882007-12-19 01:32:08 +000085
86/**
87 * void AMD_CB_EventNotify (u8 evtClass, u16 event, const u8 *pEventData0)
Marc Jones8ae8c882007-12-19 01:32:08 +000088 */
Myles Watson075fbe82010-04-15 05:19:29 +000089static void AMD_CB_EventNotify (u8 evtClass, u16 event, const u8 *pEventData0)
Marc Jones8ae8c882007-12-19 01:32:08 +000090{
Marc Joneseafcedd2008-07-17 19:54:06 +000091 u8 i;
92
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000093 printk(BIOS_DEBUG, "AMD_CB_EventNotify()\n");
94 printk(BIOS_DEBUG, " event class: %02x\n event: %04x\n data: ", evtClass, event);
Marc Joneseafcedd2008-07-17 19:54:06 +000095
96 for (i = 0; i < *pEventData0; i++) {
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000097 printk(BIOS_DEBUG, " %02x ", *(pEventData0 + i));
Marc Joneseafcedd2008-07-17 19:54:06 +000098 }
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000099 printk(BIOS_DEBUG, "\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000100
101}
102
103/**
104 * void getAmdTopolist(u8 ***p)
105 *
106 * point to the stock topo list array
107 *
108 */
109void getAmdTopolist(u8 ***p)
110{
111 *p = (u8 **)amd_topo_list;
112}
113
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500114/**
115 * BOOL AMD_CB_IgnoreLink(u8 Node, u8 Link)
116 * Description:
117 * This routine is used to ignore connected yet faulty HT links,
118 * such as those present in a G34 processor package.
119 *
120 * Parameters:
121 * @param[in] node = The node on which this chain is located
122 * @param[in] link = The link on the host for this chain
123 */
124static BOOL AMD_CB_IgnoreLink (u8 node, u8 link)
125{
126 return 0;
127}
Marc Jones8ae8c882007-12-19 01:32:08 +0000128
129/**
130 * void amd_ht_init(struct sys_info *sysinfo)
131 *
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000132 * AMD HT init coreboot wrapper
Marc Jones8ae8c882007-12-19 01:32:08 +0000133 *
134 */
Myles Watson075fbe82010-04-15 05:19:29 +0000135static void amd_ht_init(struct sys_info *sysinfo)
Marc Jones8ae8c882007-12-19 01:32:08 +0000136{
Marc Joneseafcedd2008-07-17 19:54:06 +0000137
Marc Jones8ae8c882007-12-19 01:32:08 +0000138 AMD_HTBLOCK ht_wrapper = {
139 NULL, // u8 **topolist;
140 0, // u8 AutoBusStart;
141 32, // u8 AutoBusMax;
142 6, // u8 AutoBusIncrement;
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500143 AMD_CB_IgnoreLink, // BOOL (*AMD_CB_IgnoreLink)();
Marc Jones8ae8c882007-12-19 01:32:08 +0000144 NULL, // BOOL (*AMD_CB_OverrideBusNumbers)();
Marc Joneseafcedd2008-07-17 19:54:06 +0000145 AMD_CB_ManualBUIDSwapList, // BOOL (*AMD_CB_ManualBUIDSwapList)();
Marc Jones8ae8c882007-12-19 01:32:08 +0000146 NULL, // void (*AMD_CB_DeviceCapOverride)();
147 NULL, // void (*AMD_CB_Cpu2CpuPCBLimits)();
148 NULL, // void (*AMD_CB_IOPCBLimits)();
149 NULL, // BOOL (*AMD_CB_SkipRegang)();
150 NULL, // BOOL (*AMD_CB_CustomizeTrafficDistribution)();
151 NULL, // BOOL (*AMD_CB_CustomizeBuffers)();
152 NULL, // void (*AMD_CB_OverrideDevicePort)();
153 NULL, // void (*AMD_CB_OverrideCpuPort)();
Timothy Pearson586d6e22015-02-16 14:57:06 -0600154 AMD_CB_EventNotify, // void (*AMD_CB_EventNotify) ();
155 &sysinfo->ht_link_cfg // struct ht_link_config*
Marc Jones8ae8c882007-12-19 01:32:08 +0000156 };
157
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000158 printk(BIOS_DEBUG, "Enter amd_ht_init()\n");
Marc Jones8ae8c882007-12-19 01:32:08 +0000159 amdHtInitialize(&ht_wrapper);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000160 printk(BIOS_DEBUG, "Exit amd_ht_init()\n");
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500161}
Marc Jones8ae8c882007-12-19 01:32:08 +0000162
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500163/**
164 * void amd_ht_fixup(struct sys_info *sysinfo)
165 *
166 * AMD HT fixup
167 *
168 */
169void amd_ht_fixup(struct sys_info *sysinfo) {
170 printk(BIOS_DEBUG, "amd_ht_fixup()\n");
171 if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX)) {
172 uint8_t rev_gte_d = 0;
Timothy Pearson730a0432015-10-16 13:51:51 -0500173 uint8_t fam15h = 0;
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500174 uint8_t dual_node = 0;
175 uint32_t f3xe8;
176 uint32_t family;
177 uint32_t model;
Marc Jones8ae8c882007-12-19 01:32:08 +0000178
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500179 family = model = cpuid_eax(0x80000001);
Timothy Pearson730a0432015-10-16 13:51:51 -0500180 model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
181 family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500182
Timothy Pearson730a0432015-10-16 13:51:51 -0500183 if (family >= 0x6f)
184 /* Family 15h or later */
185 fam15h = 1;
186
187 if ((model >= 0x8) || fam15h)
188 /* Family 10h Revision D or later */
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500189 rev_gte_d = 1;
190
191 if (rev_gte_d) {
192 f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
193
194 /* Check for dual node capability */
195 if (f3xe8 & 0x20000000)
196 dual_node = 1;
197
198 if (dual_node) {
199 /* Each G34 processor contains a defective HT link.
Timothy Pearson730a0432015-10-16 13:51:51 -0500200 * See the Family 10h BKDG Rev 3.62 section 2.7.1.5 for details
201 * For Family 15h see the BKDG Rev. 3.14 section 2.12.1.5 for details.
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500202 */
203 uint8_t node;
204 uint8_t node_count = get_nodes();
205 uint32_t dword;
206 for (node = 0; node < node_count; node++) {
207 f3xe8 = pci_read_config32(NODE_PCI(node, 3), 0xe8);
208 uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 30);
209 printk(BIOS_DEBUG, "amd_ht_fixup(): node %d (internal node ID %d): disabling defective HT link\n", node, internal_node_number);
210 if (internal_node_number == 0) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500211 uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x98:0xd8) & 0x1;
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500212 if (package_link_3_connected) {
213 /* Set WidthIn and WidthOut to 0 */
Timothy Pearson730a0432015-10-16 13:51:51 -0500214 dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x84:0xc4);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500215 dword &= ~0x77000000;
Timothy Pearson730a0432015-10-16 13:51:51 -0500216 pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x84:0xc4, dword);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500217 /* Set Ganged to 1 */
Timothy Pearson730a0432015-10-16 13:51:51 -0500218 dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x170:0x178);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500219 dword |= 0x00000001;
Timothy Pearson730a0432015-10-16 13:51:51 -0500220 pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x170:0x178, dword);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500221 } else {
222 /* Set ConnDly to 1 */
223 dword = pci_read_config32(NODE_PCI(node, 0), 0x16c);
224 dword |= 0x00000100;
225 pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
226 /* Set TransOff and EndOfChain to 1 */
Timothy Pearson730a0432015-10-16 13:51:51 -0500227 dword = pci_read_config32(NODE_PCI(node, 4), (fam15h)?0x84:0xc4);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500228 dword |= 0x000000c0;
Timothy Pearson730a0432015-10-16 13:51:51 -0500229 pci_write_config32(NODE_PCI(node, 4), (fam15h)?0x84:0xc4, dword);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500230 }
231 } else if (internal_node_number == 1) {
Timothy Pearson730a0432015-10-16 13:51:51 -0500232 uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0xf8:0xb8) & 0x1;
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500233 if (package_link_3_connected) {
234 /* Set WidthIn and WidthOut to 0 */
Timothy Pearson730a0432015-10-16 13:51:51 -0500235 dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0xe4:0xa4);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500236 dword &= ~0x77000000;
Timothy Pearson730a0432015-10-16 13:51:51 -0500237 pci_write_config32(NODE_PCI(node, 0), (fam15h)?0xe4:0xa4, dword);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500238 /* Set Ganged to 1 */
Timothy Pearson730a0432015-10-16 13:51:51 -0500239 dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x18c:0x174);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500240 dword |= 0x00000001;
Timothy Pearson730a0432015-10-16 13:51:51 -0500241 pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x18c:0x174, dword);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500242 } else {
243 /* Set ConnDly to 1 */
244 dword = pci_read_config32(NODE_PCI(node, 0), 0x16c);
245 dword |= 0x00000100;
246 pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
247 /* Set TransOff and EndOfChain to 1 */
Timothy Pearson730a0432015-10-16 13:51:51 -0500248 dword = pci_read_config32(NODE_PCI(node, 4), (fam15h)?0xe4:0xa4);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500249 dword |= 0x000000c0;
Timothy Pearson730a0432015-10-16 13:51:51 -0500250 pci_write_config32(NODE_PCI(node, 4), (fam15h)?0xe4:0xa4, dword);
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500251 }
252 }
253 }
254 }
255 }
256 }
Marc Jones8ae8c882007-12-19 01:32:08 +0000257}