| /* $NoKeywords:$ */ |
| /** |
| * @file |
| * |
| * Initialize PP/DPM fuse table. |
| * |
| * |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: GNB |
| * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $ |
| * |
| */ |
| /* |
| ***************************************************************************** |
| * |
| * Copyright (c) 2008 - 2013, 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. |
| * *************************************************************************** |
| * |
| */ |
| |
| /*---------------------------------------------------------------------------------------- |
| * M O D U L E S U S E D |
| *---------------------------------------------------------------------------------------- |
| */ |
| #include "AGESA.h" |
| #include "amdlib.h" |
| #include "Ids.h" |
| #include "Gnb.h" |
| #include "GnbPcieConfig.h" |
| #include "GnbCommonLib.h" |
| #include "GnbRegisterAccKB.h" |
| #include "GnbRegistersKB.h" |
| #include "GnbSmuInitLibV7.h" |
| #include "Filecode.h" |
| #define FILECODE PROC_GNB_MODULES_GNBINITKB_GNBREGISTERACCKB_FILECODE |
| /*---------------------------------------------------------------------------------------- |
| * D E F I N I T I O N S A N D M A C R O S |
| *---------------------------------------------------------------------------------------- |
| */ |
| #define GNB_IGNORED_PARAM 0xFF |
| #define ORB_WRITE_ENABLE 0x100 |
| #define IOMMU_L1_WRITE_ENABLE 0x80000000ul |
| #define IOMMU_L2_WRITE_ENABLE 0x100 |
| |
| |
| /*---------------------------------------------------------------------------------------- |
| * T Y P E D E F S A N D S T R U C T U R E S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| |
| /*---------------------------------------------------------------------------------------- |
| * P R O T O T Y P E S O F L O C A L F U N C T I O N S |
| *---------------------------------------------------------------------------------------- |
| */ |
| |
| VOID |
| GnbRegisterWriteKBDump ( |
| IN UINT8 RegisterSpaceType, |
| IN UINT32 Address, |
| IN VOID *Value |
| ); |
| |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /* |
| * Routine to read all register spaces. |
| * |
| * |
| * |
| * @param[in] RegisterSpaceType Register space type |
| * @param[in] Address Register offset, but PortDevice |
| * @param[out] Value Return value |
| * @param[in] Flags Flags - BIT0 indicates S3 save/restore |
| * @param[in] StdHeader Standard configuration header |
| */ |
| AGESA_STATUS |
| GnbRegisterReadKB ( |
| IN GNB_HANDLE *GnbHandle, |
| IN UINT8 RegisterSpaceType, |
| IN UINT32 Address, |
| OUT VOID *Value, |
| IN UINT32 Flags, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| ACCESS_WIDTH Width; |
| UINT32 TempValue; |
| UINT32 TempAddress; |
| PCI_ADDR GnbPciAddress; |
| |
| GnbPciAddress = GnbGetHostPciAddress (GnbHandle); |
| Width = (Flags == GNB_REG_ACC_FLAG_S3SAVE) ? AccessS3SaveWidth32 : AccessWidth32; |
| TempAddress = 0; |
| TempValue = 0; |
| |
| |
| switch (RegisterSpaceType) { |
| case 0x1: |
| GnbLibPciRead ( |
| GnbPciAddress.AddressValue | Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case 0x8: |
| GnbPciAddress.Address.Function = 2; |
| GnbLibPciRead ( |
| GnbPciAddress.AddressValue | Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case 0x6: ///@todo has to be DxFx |
| GnbLibPciRead ( |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F0: |
| GnbLibPciRead ( |
| MAKE_SBDFO (0, 0, 0x18, 0, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F1: |
| GnbLibPciRead ( |
| MAKE_SBDFO (0, 0, 0x18, 1, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F2: |
| case TYPE_D18F2_dct0: |
| GnbLibPciRead ( |
| MAKE_SBDFO (0, 0, 0x18, 2, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F3: |
| GnbLibPciRead ( |
| MAKE_SBDFO (0, 0, 0x18, 3, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F4: |
| GnbLibPciRead ( |
| MAKE_SBDFO (0, 0, 0x18, 4, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F5: |
| GnbLibPciRead ( |
| MAKE_SBDFO (0, 0, 0x18, 5, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x2: |
| // Miscellaneous Index Data, access the registers D0F0x64_x[FF:00] |
| GnbLibPciIndirectRead ( |
| GnbPciAddress.AddressValue | D0F0x60_ADDRESS, |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x3: |
| // Northbridge ORB Configuration Offset, access D0F0x98_x[FF:00] |
| GnbLibPciIndirectRead ( |
| GnbPciAddress.AddressValue | D0F0x94_ADDRESS, |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x4: |
| { |
| UINT64 TempData; |
| GnbLibPciIndirectRead ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| (Address & (~0x3ull)), |
| Width, |
| &TempData, |
| StdHeader |
| ); |
| if ((Address & 0x3) != 0) { |
| //Non aligned access allowed to fuse block |
| GnbLibPciIndirectRead ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| (Address & (~0x3ull)) + 4, |
| Width, |
| ((UINT32 *) &TempData) + 1, |
| StdHeader |
| ); |
| } |
| * ((UINT32*) Value) = (UINT32) (TempData >> ((Address & 0x3) * 8)); |
| break; |
| } |
| case 0x22: |
| // D0F0xD0 Link Index Address, access D0F0xD4_x[0130_14BF:0109_0000] |
| GnbLibPciIndirectRead ( |
| GnbPciAddress.AddressValue | 0xD0, |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x5: |
| // D0F0xE0 Link Index Address, access D0F0xE4_x[FFFF_FFFF:0000_0000] |
| GnbLibPciIndirectRead ( |
| GnbPciAddress.AddressValue | D0F0xE0_ADDRESS, |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x9: |
| GnbPciAddress.Address.Function = 2; |
| GnbLibPciIndirectRead ( |
| GnbPciAddress.AddressValue | 0xF0, |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0xa: |
| GnbPciAddress.Address.Function = 2; |
| GnbLibPciIndirectRead ( |
| GnbPciAddress.AddressValue | 0xF8, |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case TYPE_MSR: |
| LibAmdMsrRead (Address, Value, StdHeader); |
| break; |
| |
| case 0x12: |
| ASSERT (Address < 0x40000); |
| // SRBM |
| GnbLibPciIndirectRead ( |
| MAKE_SBDFO (0, 0, 0, 0, 0xB8), |
| (0x80080000 | (Address & 0x3FFFF)), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| default: |
| ASSERT (FALSE); |
| break; |
| } |
| return AGESA_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /* |
| * Routine to write all register spaces. |
| * |
| * |
| * @param[in] GnbHandle GnbHandle |
| * @param[in] RegisterSpaceType Register space type |
| * @param[in] Address Register offset, but PortDevice |
| * @param[out] Value The value to write |
| * @param[in] Flags Flags - BIT0 indicates S3 save/restore |
| * @param[in] StdHeader Standard configuration header |
| */ |
| AGESA_STATUS |
| GnbRegisterWriteKB ( |
| IN GNB_HANDLE *GnbHandle, |
| IN UINT8 RegisterSpaceType, |
| IN UINT32 Address, |
| IN VOID *Value, |
| IN UINT32 Flags, |
| IN AMD_CONFIG_PARAMS *StdHeader |
| ) |
| { |
| |
| ACCESS_WIDTH Width; |
| UINT32 TempValue; |
| UINT32 TempAddress; |
| PCI_ADDR GnbPciAddress; |
| DEV_OBJECT DevObject; |
| |
| GnbPciAddress = GnbGetHostPciAddress (GnbHandle); |
| Width = (Flags == GNB_REG_ACC_FLAG_S3SAVE) ? AccessS3SaveWidth32 : AccessWidth32; |
| TempAddress = 0; |
| TempValue = 0; |
| |
| GNB_DEBUG_CODE ( |
| GnbRegisterWriteKBDump (RegisterSpaceType, Address, Value); |
| ); |
| |
| switch (RegisterSpaceType) { |
| case 0x1: |
| GnbLibPciWrite ( |
| GnbPciAddress.AddressValue | Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case 0x8: |
| GnbPciAddress.Address.Function = 2; |
| GnbLibPciWrite ( |
| GnbPciAddress.AddressValue | Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case 0x6: /// @todo needs to be DxFx |
| GnbLibPciWrite ( |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F0: |
| GnbLibPciWrite ( |
| MAKE_SBDFO (0, 0, 0x18, 0, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F1: |
| GnbLibPciWrite ( |
| MAKE_SBDFO (0, 0, 0x18, 1, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F2: |
| case TYPE_D18F2_dct0: |
| GnbLibPciWrite ( |
| MAKE_SBDFO (0, 0, 0x18, 2, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F3: |
| GnbLibPciWrite ( |
| MAKE_SBDFO (0, 0, 0x18, 3, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F4: |
| GnbLibPciWrite ( |
| MAKE_SBDFO (0, 0, 0x18, 4, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| case TYPE_D18F5: |
| GnbLibPciWrite ( |
| MAKE_SBDFO (0, 0, 0x18, 5, Address), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x2: |
| // Miscellaneous Index Data, access the registers D0F0x64_x[FF:00] |
| GnbLibPciIndirectWrite ( |
| GnbPciAddress.AddressValue | D0F0x60_ADDRESS, |
| Address | IOC_WRITE_ENABLE, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x3: |
| // Northbridge ORB Configuration Offset, access D0F0x98_x[FF:00] |
| GnbLibPciIndirectWrite ( |
| GnbPciAddress.AddressValue | D0F0x94_ADDRESS, |
| Address | ORB_WRITE_ENABLE, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x4: |
| //SMU, access D0F0xBC_x[FFFFFFFF:00000000] |
| GnbLibPciIndirectWrite ( |
| GnbPciAddress.AddressValue | D0F0xB8_ADDRESS, |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x22: |
| // D0F0xD0 Link Index Address, access D0F0xD4_x[0130_14BF:0109_0000] |
| GnbLibPciIndirectWrite ( |
| GnbPciAddress.AddressValue | 0xD0, |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x5: |
| // D0F0xE0 Link Index Address, access D0F0xE4_x[FFFF_FFFF:0000_0000] |
| GnbLibPciIndirectWrite ( |
| GnbPciAddress.AddressValue | D0F0xE0_ADDRESS, |
| Address, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0x9: |
| // IOMMU L2 Config Index, to access the registers D0F2xF4_x[FF:00]. |
| GnbPciAddress.Address.Function = 2; |
| GnbLibPciIndirectWrite ( |
| GnbPciAddress.AddressValue | 0xF0, |
| Address | IOMMU_L2_WRITE_ENABLE, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case 0xa: |
| GnbPciAddress.Address.Function = 2; |
| GnbLibPciIndirectWrite ( |
| GnbPciAddress.AddressValue | 0xF8, |
| Address | IOMMU_L1_WRITE_ENABLE, |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case TYPE_MSR: |
| LibAmdMsrWrite (Address, Value, StdHeader); |
| break; |
| |
| case 0x12: |
| ASSERT (Address < 0x40000); |
| // SRBM |
| GnbLibPciIndirectWrite ( |
| MAKE_SBDFO (0, 0, 0, 0, 0xB8), |
| (0x80080000 | (Address & 0x3FFFF)), |
| Width, |
| Value, |
| StdHeader |
| ); |
| break; |
| |
| case TYPE_SMU_MSG: |
| DevObject.StdHeader = StdHeader; |
| DevObject.GnbHandle = GnbGetHandle (StdHeader); |
| DevObject.DevPciAddress.AddressValue = MAKE_SBDFO (0, 0, 0, 0, 0); |
| GnbSmuServiceRequestV7 (&DevObject, (UINT8) Address, *((UINT32 *)Value), Flags); |
| break; |
| |
| default: |
| ASSERT (FALSE); |
| break; |
| } |
| |
| return AGESA_SUCCESS; |
| } |
| |
| /*----------------------------------------------------------------------------------------*/ |
| /* |
| * Routine to dump all write register spaces. |
| * |
| * |
| * |
| * @param[in] RegisterSpaceType Register space type |
| * @param[in] Address Register offset |
| * @param[in] Value The value to write |
| */ |
| VOID |
| GnbRegisterWriteKBDump ( |
| IN UINT8 RegisterSpaceType, |
| IN UINT32 Address, |
| IN VOID *Value |
| ) |
| { |
| IDS_HDT_CONSOLE (NB_MISC, " R WRITE Space %s Address 0x%04x, Value 0x%04x\n", |
| (RegisterSpaceType == 0x1) ? "0x1" : ( |
| (RegisterSpaceType == 0x2) ? "0x2" : ( |
| (RegisterSpaceType == 0x3) ? "0x3" : ( |
| (RegisterSpaceType == 0x4) ? "0x4" : ( |
| (RegisterSpaceType == 0x22) ? "0x22" : ( |
| (RegisterSpaceType == 0x5) ? "0x5" : ( |
| (RegisterSpaceType == 0x6) ? "0x6" : ( |
| (RegisterSpaceType == TYPE_D18F0) ? "TYPE_D18F0" : ( |
| (RegisterSpaceType == TYPE_D18F1) ? "TYPE_D18F1" : ( |
| (RegisterSpaceType == TYPE_D18F2) ? "TYPE_D18F2" : ( |
| (RegisterSpaceType == TYPE_D18F3) ? "TYPE_D18F3" : ( |
| (RegisterSpaceType == TYPE_D18F4) ? "TYPE_D18F4" : ( |
| (RegisterSpaceType == TYPE_D18F5) ? "TYPE_D18F5" : ( |
| (RegisterSpaceType == TYPE_MSR) ? "TYPE_MSR" : ( |
| (RegisterSpaceType == TYPE_D1F0) ? "TYPE_D1F0" : ( |
| (RegisterSpaceType == TYPE_D1F1) ? "TYPE_D1F1" : ( |
| (RegisterSpaceType == 0x12) ? "0x12" : ( |
| (RegisterSpaceType == TYPE_D18F2x9C_dct0) ? "TYPE_D18F2x9C_dct0" : ( |
| (RegisterSpaceType == TYPE_D18F2x9C_dct0_mp0) ? "TYPE_D18F2x9C_dct0_mp0" : ( |
| (RegisterSpaceType == TYPE_D18F2x9C_dct0_mp1) ? "TYPE_D18F2x9C_dct0_mp1" : ( |
| (RegisterSpaceType == TYPE_D18F2x9C_dct1) ? "TYPE_D18F2x9C_dct1" : ( |
| (RegisterSpaceType == TYPE_D18F2x9C_dct1_mp0) ? "TYPE_D18F2x9C_dct1_mp0" : ( |
| (RegisterSpaceType == TYPE_D18F2x9C_dct1_mp1) ? "TYPE_D18F2x9C_dct1_mp1" : ( |
| (RegisterSpaceType == TYPE_D18F2_dct0) ? "TYPE_D18F2_dct0" : ( |
| (RegisterSpaceType == TYPE_D18F2_dct0_mp0) ? "TYPE_D18F2_dct0_mp0" : ( |
| (RegisterSpaceType == TYPE_D18F2_dct0_mp1) ? "TYPE_D18F2_dct0_mp1" : ( |
| (RegisterSpaceType == TYPE_D18F2_dct1) ? "TYPE_D18F2_dct1" : ( |
| (RegisterSpaceType == TYPE_D18F2_dct1_mp0) ? "TYPE_D18F2_dct1_mp0" : ( |
| (RegisterSpaceType == TYPE_SMU_MSG) ? "TYPE_SMU_MSG" : ( |
| (RegisterSpaceType == TYPE_D18F2_dct1_mp1) ? "TYPE_D18F2_dct1_mp1" : "Invalid"))))))))))))))))))))))))))))), |
| Address, |
| *((UINT32*)Value) |
| ); |
| } |