| /* $NoKeywords:$ */ |
| /** |
| * @file |
| * |
| * SubLink management Routines. |
| * |
| * Contains routines for subLink frequency ratios. |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: HyperTransport |
| * @e \$Revision: 44324 $ @e \$Date: 2010-12-22 17:16:51 +0800 (Wed, 22 Dec 2010) $ |
| * |
| */ |
| /* |
| ***************************************************************************** |
| * |
| * Copyright (c) 2011, Advanced Micro Devices, Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * * Neither the name of Advanced Micro Devices, Inc. nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * *************************************************************************** |
| * |
| */ |
| |
| /* |
| *---------------------------------------------------------------------------- |
| * MODULES USED |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| |
| |
| |
| #include "AGESA.h" |
| #include "Ids.h" |
| #include "amdlib.h" |
| #include "Topology.h" |
| #include "htFeat.h" |
| #include "IdsHt.h" |
| #include "htFeatSublinks.h" |
| #include "Filecode.h" |
| CODE_GROUP (G1_PEICC) |
| RDATA_GROUP (G1_PEICC) |
| |
| #define FILECODE PROC_HT_FEATURES_HTFEATSUBLINKS_FILECODE |
| /*---------------------------------------------------------------------------- |
| * DEFINITIONS AND MACROS |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| |
| /*---------------------------------------------------------------------------- |
| * TYPEDEFS AND STRUCTURES |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| |
| typedef struct { |
| UINT8 HiFreq; |
| UINT8 LoFreq; |
| } VALID_RATIO_ITEM; |
| |
| STATIC CONST VALID_RATIO_ITEM ROMDATA ValidRatioList[] = |
| { |
| {HT_FREQUENCY_3200M, HT_FREQUENCY_1600M}, // 3200MHz / 1600MHz 2:1 |
| {HT_FREQUENCY_3200M, HT_FREQUENCY_800M}, // 3200MHz / 800MHz 4:1 |
| {HT_FREQUENCY_3200M, HT_FREQUENCY_400M}, // 3200MHz / 400MHz 8:1 |
| {HT_FREQUENCY_2800M, HT_FREQUENCY_1400M}, // 2800MHz / 1400MHz 2:1 |
| {HT_FREQUENCY_2400M, HT_FREQUENCY_1200M}, // 2400MHz / 1200MHz 2:1 |
| {HT_FREQUENCY_2400M, HT_FREQUENCY_600M}, // 2400MHz / 600MHz 4:1 |
| {HT_FREQUENCY_2400M, HT_FREQUENCY_400M}, // 2400MHz / 400MHz 6:1 |
| {HT_FREQUENCY_2000M, HT_FREQUENCY_1000M}, // 2000MHz / 1000MHz 2:1 |
| {HT_FREQUENCY_1600M, HT_FREQUENCY_800M}, // 1600MHz / 800MHz 2:1 |
| {HT_FREQUENCY_1600M, HT_FREQUENCY_400M}, // 1600MHz / 400MHz 4:1 |
| {HT_FREQUENCY_1600M, HT_FREQUENCY_200M}, // 1600MHz / 200Mhz 8:1 |
| {HT_FREQUENCY_1200M, HT_FREQUENCY_600M}, // 1200MHz / 600MHz 2:1 |
| {HT_FREQUENCY_1200M, HT_FREQUENCY_200M}, // 1200MHz / 200MHz 6:1 |
| {HT_FREQUENCY_800M, HT_FREQUENCY_400M}, // 800MHz / 400MHz 2:1 |
| {HT_FREQUENCY_800M, HT_FREQUENCY_200M}, // 800MHz / 200MHz 4:1 |
| {HT_FREQUENCY_400M, HT_FREQUENCY_200M} // 400MHz / 200MHz 2:1 |
| }; |
| |
| /*---------------------------------------------------------------------------- |
| * PROTOTYPES OF LOCAL FUNCTIONS |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| |
| /*---------------------------------------------------------------------------- |
| * EXPORTED FUNCTIONS |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| |
| /*---------------------------------------------------------------------------- |
| * LOCAL FUNCTIONS |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| |
| /*************************************************************************** |
| *** Link Optimization *** |
| ***************************************************************************/ |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /** |
| * Iterate through all Links, checking the frequency of each subLink pair. |
| * |
| * @HtFeatMethod{::F_SUBLINK_RATIO_FIXUP} |
| * |
| * Make the adjustment to the port list data so that the frequencies |
| * are at a valid ratio, reducing frequency as needed to achieve |
| * this. (All Links support the minimum 200 MHz frequency.) Repeat |
| * the above until no adjustments are needed. |
| * @note no hardware state changes in this routine. |
| * |
| * @param[in,out] State Link state and port list |
| * |
| */ |
| VOID |
| SubLinkRatioFixup ( |
| IN OUT STATE_DATA *State |
| ) |
| { |
| UINT8 i; |
| UINT8 j; |
| UINT8 ValidRatioItem; |
| BOOLEAN Changes; |
| BOOLEAN Downgrade; |
| UINT8 HiIndex; |
| UINT8 HiFreq; |
| UINT8 LoFreq; |
| |
| UINT32 Temp; |
| |
| do { |
| Changes = FALSE; |
| for (i = 0; i < State->TotalLinks*2; i++) { |
| // Must be a CPU Link |
| if ((*State->PortList)[i].Type != PORTLIST_TYPE_CPU) { |
| continue; |
| } |
| // Only look for subLink1's |
| if ((*State->PortList)[i].Link < 4) { |
| continue; |
| } |
| |
| for (j = 0; j < State->TotalLinks*2; j++) { |
| // Step 1. Find the matching subLink0 |
| if ((*State->PortList)[j].Type != PORTLIST_TYPE_CPU) { |
| continue; |
| } |
| if ((*State->PortList)[j].NodeID != (*State->PortList)[i].NodeID) { |
| continue; |
| } |
| if ((*State->PortList)[j].Link != ((*State->PortList)[i].Link & 0x03)) { |
| continue; |
| } |
| |
| // Step 2. Check for an illegal frequency ratio |
| if ((*State->PortList)[i].SelFrequency >= (*State->PortList)[j].SelFrequency) { |
| HiIndex = i; |
| HiFreq = (*State->PortList)[i].SelFrequency; |
| LoFreq = (*State->PortList)[j].SelFrequency; |
| } else { |
| HiIndex = j; |
| HiFreq = (*State->PortList)[j].SelFrequency; |
| LoFreq = (*State->PortList)[i].SelFrequency; |
| } |
| |
| // The frequencies are 1:1, no need to do anything |
| if (HiFreq == LoFreq) { |
| break; |
| } |
| |
| Downgrade = TRUE; |
| |
| for (ValidRatioItem = 0; ValidRatioItem < (sizeof (ValidRatioList) / sizeof (VALID_RATIO_ITEM)); ValidRatioItem++) { |
| if ((HiFreq == ValidRatioList[ValidRatioItem].HiFreq) && |
| (LoFreq == ValidRatioList[ValidRatioItem].LoFreq)) { |
| Downgrade = FALSE; |
| break; |
| } |
| } |
| |
| // Step 3. Downgrade the higher of the two frequencies, and set Changes to FALSE |
| if (Downgrade) { |
| // Although the problem was with the port specified by hiIndex, we need to |
| // Downgrade both ends of the Link. |
| HiIndex = HiIndex & 0xFE; // Select the 'upstream' (i.e. even) port |
| |
| Temp = (*State->PortList)[HiIndex].CompositeFrequencyCap; |
| |
| // Remove HiFreq from the list of valid frequencies |
| Temp = Temp & ~((UINT32)1 << HiFreq); |
| ASSERT (Temp != 0); |
| (*State->PortList)[HiIndex].CompositeFrequencyCap = (UINT32)Temp; |
| (*State->PortList)[HiIndex + 1].CompositeFrequencyCap = (UINT32)Temp; |
| |
| HiFreq = LibAmdBitScanReverse (Temp); |
| |
| (*State->PortList)[HiIndex].SelFrequency = HiFreq; |
| (*State->PortList)[HiIndex + 1].SelFrequency = HiFreq; |
| |
| Changes = TRUE; |
| } |
| } |
| } |
| } while (Changes); // Repeat until a valid configuration is reached |
| } |