diff options
author | Marc Jones <marc.jones@amd.com> | 2007-12-19 01:32:08 +0000 |
---|---|---|
committer | Marc Jones <marc.jones@amd.com> | 2007-12-19 01:32:08 +0000 |
commit | 8ae8c8822068ef1722c08073ffa4ecc25633cbee (patch) | |
tree | 8c7bbf2f7b791081e486439a9b7ffb2fd6e649ac /src/northbridge/amd/amdfam10 | |
parent | 2006b38fed2f5f3680de1736f7fc878823f2f93b (diff) |
Initial AMD Barcelona support for rev Bx.
These are the core files for HyperTransport, DDR2 Memory, and multi-core initialization.
Signed-off-by: Marc Jones <marc.jones@amd.com>
Reviewed-by: Jordan Crouse <jordan.crouse@amd.com>
Acked-by: Myles Watson <myles@pel.cs.byu.edu>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3014 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge/amd/amdfam10')
28 files changed, 6578 insertions, 0 deletions
diff --git a/src/northbridge/amd/amdfam10/Config.lb b/src/northbridge/amd/amdfam10/Config.lb new file mode 100644 index 0000000000..96619b23c6 --- /dev/null +++ b/src/northbridge/amd/amdfam10/Config.lb @@ -0,0 +1,79 @@ +# +# This file is part of the LinuxBIOS 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +uses CONFIG_CHIP_NAME +uses AGP_APERTURE_SIZE +uses HAVE_ACPI_TABLES + +default AGP_APERTURE_SIZE=0x4000000 + +if CONFIG_CHIP_NAME + config chip.h +end + +object northbridge.o +driver misc_control.o + +if HAVE_ACPI_TABLES + object amdfam10_acpi.o + makerule ssdt.c + depends "$(TOP)/src/northbridge/amd/amdfam10/ssdt.dsl" + action "iasl -tc $(TOP)/src/northbridge/amd/amdfam10/ssdt.dsl" + action "perl -pi -e 's/AmlCode/AmlCode_ssdt/g' ssdt.hex" + action "mv ssdt.hex ssdt.c" + end + object ./ssdt.o + makerule sspr1.c + depends "$(TOP)/src/northbridge/amd/amdfam10/sspr1.dsl" + action "iasl -tc $(TOP)/src/northbridge/amd/amdfam10/sspr1.dsl" + action "perl -pi -e 's/AmlCode/AmlCode_sspr1/g' sspr1.hex" + action "mv sspr1.hex sspr1.c" + end + object ./sspr1.o + makerule sspr2.c + depends "$(TOP)/src/northbridge/amd/amdfam10/sspr2.dsl" + action "iasl -tc $(TOP)/src/northbridge/amd/amdfam10/sspr2.dsl" + action "perl -pi -e 's/AmlCode/AmlCode_sspr2/g' sspr2.hex" + action "mv sspr2.hex sspr2.c" + end + object ./sspr2.o + makerule sspr3.c + depends "$(TOP)/src/northbridge/amd/amdfam10/sspr3.dsl" + action "iasl -tc $(TOP)/src/northbridge/amd/amdfam10/sspr3.dsl" + action "perl -pi -e 's/AmlCode/AmlCode_sspr3/g' sspr3.hex" + action "mv sspr3.hex sspr3.c" + end + object ./sspr3.o + makerule sspr4.c + depends "$(TOP)/src/northbridge/amd/amdfam10/sspr4.dsl" + action "iasl -tc $(TOP)/src/northbridge/amd/amdfam10/sspr4.dsl" + action "perl -pi -e 's/AmlCode/AmlCode_sspr4/g' sspr4.hex" + action "mv sspr4.hex sspr4.c" + end + object ./sspr4.o + makerule sspr5.c + depends "$(TOP)/src/northbridge/amd/amdfam10/sspr5.dsl" + action "iasl -tc $(TOP)/src/northbridge/amd/amdfam10/sspr5.dsl" + action "perl -pi -e 's/AmlCode/AmlCode_sspr5/g' sspr5.hex" + action "mv sspr5.hex sspr5.c" + end + object ./sspr5.o +end + +object get_pci1234.o diff --git a/src/northbridge/amd/amdfam10/amdfam10.h b/src/northbridge/amd/amdfam10/amdfam10.h new file mode 100644 index 0000000000..369f8dde20 --- /dev/null +++ b/src/northbridge/amd/amdfam10/amdfam10.h @@ -0,0 +1,1164 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AMDFAM10_H + +#define AMDFAM10_H +/* Definitions of various FAM10 registers */ +/* Function 0 */ +#define HT_TRANSACTION_CONTROL 0x68 +#define HTTC_DIS_RD_B_P (1 << 0) +#define HTTC_DIS_RD_DW_P (1 << 1) +#define HTTC_DIS_WR_B_P (1 << 2) +#define HTTC_DIS_WR_DW_P (1 << 3) +#define HTTC_DIS_MTS (1 << 4) +#define HTTC_CPU1_EN (1 << 5) +#define HTTC_CPU_REQ_PASS_PW (1 << 6) +#define HTTC_CPU_RD_RSP_PASS_PW (1 << 7) +#define HTTC_DIS_P_MEM_C (1 << 8) +#define HTTC_DIS_RMT_MEM_C (1 << 9) +#define HTTC_DIS_FILL_P (1 << 10) +#define HTTC_RSP_PASS_PW (1 << 11) +#define HTTC_BUF_REL_PRI_SHIFT 13 +#define HTTC_BUF_REL_PRI_MASK 3 +#define HTTC_BUF_REL_PRI_64 0 +#define HTTC_BUF_REL_PRI_16 1 +#define HTTC_BUF_REL_PRI_8 2 +#define HTTC_BUF_REL_PRI_2 3 +#define HTTC_LIMIT_CLDT_CFG (1 << 15) +#define HTTC_LINT_EN (1 << 16) +#define HTTC_APIC_EXT_BRD_CST (1 << 17) +#define HTTC_APIC_EXT_ID (1 << 18) +#define HTTC_APIC_EXT_SPUR (1 << 19) +#define HTTC_SEQ_ID_SRC_NODE_EN (1 << 20) +#define HTTC_DS_NP_REQ_LIMIT_SHIFT 21 +#define HTTC_DS_NP_REQ_LIMIT_MASK 3 +#define HTTC_DS_NP_REQ_LIMIT_NONE 0 +#define HTTC_DS_NP_REQ_LIMIT_1 1 +#define HTTC_DS_NP_REQ_LIMIT_4 2 +#define HTTC_DS_NP_REQ_LIMIT_8 3 + + +/* Function 1 */ +#define PCI_IO_BASE0 0xc0 +#define PCI_IO_BASE1 0xc8 +#define PCI_IO_BASE2 0xd0 +#define PCI_IO_BASE3 0xd8 +#define PCI_IO_BASE_VGA_EN (1 << 4) +#define PCI_IO_BASE_NO_ISA (1 << 5) + +/* Function 2 */ +// 0x1xx is for DCT1 +#define DRAM_CSBASE 0x40 +#define DRAM_CSMASK 0x60 +#define DRAM_BANK_ADDR_MAP 0x80 + +#define DRAM_CTRL 0x78 +#define DC_RdPtrInit_SHIFT 0 +#define DC_RdPrtInit_MASK 0xf +#define DC_Twrrd3_2_SHIFT 8 /*DDR3 */ +#define DC_Twrrd3_2_MASK 3 +#define DC_Twrwr3_2_SHIFT 10 /*DDR3 */ +#define DC_Twrwr3_2_MASK 3 +#define DC_Trdrd3_2_SHIFT 12 /*DDR3 */ +#define DC_Trdrd3_2_MASK 3 +#define DC_AltVidC3MemClkTriEn (1<<16) +#define DC_DqsRcvEnTrain (1<<18) +#define DC_MaxRdLatency_SHIFT 22 +#define DC_MaxRdLatency_MASK 0x3ff + +#define DRAM_INIT 0x7c +#define DI_MrsAddress_SHIFT 0 +#define DI_MrsAddress_MASK 0xffff +#define DI_MrsBank_SHIFT 16 +#define DI_MrsBank_MASK 7 +#define DI_MrsChipSel_SHIFT 20 +#define DI_MrsChipSel_MASK 7 +#define DI_SendRchgAll (1<<24) +#define DI_SendAutoRefresh (1<<25) +#define DI_SendMrsCmd (1<<26) +#define DI_DeassertMemRstX (1<<27) +#define DI_AssertCke (1<<28) +#define DI_SendZQCmd (1<<29) /*DDR3 */ +#define DI_EnMrsCmd (1<<30) +#define DI_EnDramInit (1<<31) + +#define DRAM_MRS 0x84 +#define DM_BurstCtrl_SHIFT 0 +#define DM_BurstCtrl_MASK 3 +#define DM_DrvImpCtrl_SHIFT 2 /* DDR3 */ +#define DM_DrvImpCtrl_MASK 3 +#define DM_Twr_SHIFT 4 /* DDR3 */ +#define DM_Twr_MASK 7 +#define DM_Twr_BASE 4 +#define DM_Twr_MIN 5 +#define DM_Twr_MAX 12 +#define DM_DramTerm_SHIFT 7 /*DDR3 */ +#define DM_DramTerm_MASK 7 +#define DM_DramTermDyn_SHIFT 10 /* DDR3 */ +#define DM_DramTermDyn_MASK 3 +#define DM_Ooff (1<<13) +#define DM_ASR (1<<18) +#define DM_SRT (1<<19) +#define DM_Tcwl_SHIFT 20 +#define DM_Tcwl_MASK 7 +#define DM_PchgPDModeSel (1<<23) /* DDR3 */ +#define DM_MPrLoc_SHIFT 24 /* DDR3 */ +#define DM_MPrLoc_MASK 3 +#define DM_MprEn (1<<26) /* DDR3 */ + +#define DRAM_TIMING_LOW 0x88 +#define DTL_TCL_SHIFT 0 +#define DTL_TCL_MASK 0xf +#define DTL_TCL_BASE 1 /* DDR3 =4 */ +#define DTL_TCL_MIN 3 /* DDR3 =4 */ +#define DTL_TCL_MAX 6 /* DDR3 =12 */ +#define DTL_TRCD_SHIFT 4 +#define DTL_TRCD_MASK 3 /* DDR3 =7 */ +#define DTL_TRCD_BASE 3 /* DDR3 =5 */ +#define DTL_TRCD_MIN 3 /* DDR3 =5 */ +#define DTL_TRCD_MAX 6 /* DDR3 =12 */ +#define DTL_TRP_SHIFT 8 /* DDR3 =7 */ +#define DTL_TRP_MASK 3 /* DDR3 =7 */ +#define DTL_TRP_BASE 3 /* DDR3 =5 */ +#define DTL_TRP_MIN 3 /* DDR3 =5 */ +#define DTL_TRP_MAX 6 /* DDR3 =12 */ +#define DTL_TRTP_SHIFT 11 /*DDR3 =10 */ +#define DTL_TRTP_MASK 1 /*DDR3 =3 */ +#define DTL_TRTP_BASE 2 /* DDR3 =4 */ +#define DTL_TRTP_MIN 2 /* 4 for 64 bytes*/ /* DDR3 =4 for 32bytes or 64bytes */ +#define DTL_TRTP_MAX 3 /* 5 for 64 bytes */ /* DDR3 =7 for 32Bytes or 64bytes */ +#define DTL_TRAS_SHIFT 12 +#define DTL_TRAS_MASK 0xf +#define DTL_TRAS_BASE 3 /* DDR3 =15 */ +#define DTL_TRAS_MIN 5 /* DDR3 =15 */ +#define DTL_TRAS_MAX 18 /*DDR3 =30 */ +#define DTL_TRC_SHIFT 16 +#define DTL_TRC_MASK 0xf /* DDR3 =0x1f */ +#define DTL_TRC_BASE 11 +#define DTL_TRC_MIN 11 +#define DTL_TRC_MAX 26 /* DDR3 =43 */ +#define DTL_TWR_SHIFT 20 /* only for DDR2, DDR3's is on DC */ +#define DTL_TWR_MASK 3 +#define DTL_TWR_BASE 3 +#define DTL_TWR_MIN 3 +#define DTL_TWR_MAX 6 +#define DTL_TRRD_SHIFT 22 +#define DTL_TRRD_MASK 3 +#define DTL_TRRD_BASE 2 /* DDR3 =4 */ +#define DTL_TRRD_MIN 2 /* DDR3 =4 */ +#define DTL_TRRD_MAX 5 /* DDR3 =7 */ +#define DTL_MemClkDis_SHIFT 24 /* Channel A */ +#define DTL_MemClkDis3 (1 << 26) +#define DTL_MemClkDis2 (1 << 27) +#define DTL_MemClkDis1 (1 << 28) +#define DTL_MemClkDis0 (1 << 29) +/* DTL_MemClkDis for m2 and s1g1 is different */ + +#define DRAM_TIMING_HIGH 0x8c +#define DTH_TRWTWB_SHIFT 0 +#define DTH_TRWTWB_MASK 3 +#define DTH_TRWTWB_BASE 3 /* DDR3 =4 */ +#define DTH_TRWTWB_MIN 3 /* DDR3 =5 */ +#define DTH_TRWTWB_MAX 10 /* DDR3 =11 */ +#define DTH_TRWTTO_SHIFT 4 +#define DTH_TRWTTO_MASK 7 +#define DTH_TRWTTO_BASE 2 /* DDR3 =3 */ +#define DTH_TRWTTO_MIN 2 /* DDR3 =3 */ +#define DTH_TRWTTO_MAX 9 /* DDR3 =10 */ +#define DTH_TWTR_SHIFT 8 +#define DTH_TWTR_MASK 3 +#define DTH_TWTR_BASE 0 /* DDR3 =4 */ +#define DTH_TWTR_MIN 1 /* DDR3 =4 */ +#define DTH_TWTR_MAX 3 /* DDR3 =7 */ +#define DTH_TWRRD_SHIFT 10 +#define DTH_TWRRD_MASK 3 /* For DDR3 3_2 is at 0x78 DC */ +#define DTH_TWRRD_BASE 0 /* DDR3 =0 */ +#define DTH_TWRRD_MIN 0 /* DDR3 =2 */ +#define DTH_TWRRD_MAX 3 /* DDR3 =12 */ +#define DTH_TWRWR_SHIFT 12 +#define DTH_TWRWR_MASK 3 /* For DDR3 3_2 is at 0x78 DC */ +#define DTH_TWRWR_BASE 1 +#define DTH_TWRWR_MIN 1 /* DDR3 =3 */ +#define DTH_TWRWR_MAX 3 /* DDR3 =12 */ +#define DTH_TRDRD_SHIFT 14 +#define DTH_TRDRD_MASK 3 /* For DDR3 3_2 is at 0x78 DC */ +#define DTH_TRDRD_BASE 2 +#define DTH_TRDRD_MIN 2 +#define DTH_TRDRD_MAX 5 /* DDR3 =10 */ +#define DTH_TREF_SHIFT 16 +#define DTH_TREF_MASK 3 +#define DTH_TREF_7_8_US 2 +#define DTH_TREF_3_9_US 3 +#define DTH_DisAutoRefresh (1<<18) +#define DTH_TRFC0_SHIFT 20 /* for Logical DIMM0 */ +#define DTH_TRFC_MASK 7 +#define DTH_TRFC_75_256M 0 +#define DTH_TRFC_105_512M 1 +#define DTH_TRFC_127_5_1G 2 +#define DTH_TRFC_195_2G 3 +#define DTH_TRFC_327_5_4G 4 +#if 0 +//DDR3 +#define DTH_TRFC_90_512M 1 +#define DTH_TRFC_110_5_1G 2 +#define DTH_TRFC_160_2G 3 +#define DTH_TRFC_300_4G 4 +#define DTH_TRFC_UNDEFINED_8G 5 +#endif +#define DTH_TRFC1_SHIFT 23 /*for Logical DIMM1 */ +#define DTH_TRFC2_SHIFT 26 /*for Logical DIMM2 */ +#define DTH_TRFC3_SHIFT 29 /*for Logical DIMM3 */ + +#define DRAM_CONFIG_LOW 0x90 +#define DCL_InitDram (1<<0) +#define DCL_ExitSelfRef (1<<1) +#define DCL_PllLockTime_SHIFT 2 +#define DCL_PllLockTime_MASK 3 +#define DCL_PllLockTime_15US 0 +#define DCL_PllLockTime_6US 1 +#define DCL_DramTerm_SHIFT 4 +#define DCL_DramTerm_MASK 3 +#define DCL_DramTerm_No 0 +#define DCL_DramTerm_75_OH 1 +#define DCL_DramTerm_150_OH 2 +#define DCL_DramTerm_50_OH 3 +#define DCL_DisDqsBar (1<<6) /* only for DDR2 */ +#define DCL_DramDrvWeak (1<<7) /* only for DDR2 */ +#define DCL_ParEn (1<<8) +#define DCL_SelfRefRateEn (1<<9) /* only for DDR2 */ +#define DCL_BurstLength32 (1<<10) /* only for DDR3 */ +#define DCL_Width128 (1<<11) +#define DCL_X4Dimm_SHIFT 12 +#define DCL_X4Dimm_MASK 0xf +#define DCL_UnBuffDimm (1<<16) +#define DCL_EnPhyDqsRcvEnTr (1<<18) +#define DCL_DimmEccEn (1<<19) +#define DCL_DynPageCloseEn (1<<20) +#define DCL_IdleCycInit_SHIFT 21 +#define DCL_IdleCycInit_MASK 3 +#define DCL_IdleCycInit_16CLK 0 +#define DCL_IdleCycInit_32CLK 1 +#define DCL_IdleCycInit_64CLK 2 +#define DCL_IdleCycInit_96CLK 3 +#define DCL_ForceAutoPchg (1<<23) + +#define DRAM_CONFIG_HIGH 0x94 +#define DCH_MemClkFreq_SHIFT 0 +#define DCH_MemClkFreq_MASK 7 +#define DCH_MemClkFreq_200MHz 0 /* DDR2 */ +#define DCH_MemClkFreq_266MHz 1 /* DDR2 */ +#define DCH_MemClkFreq_333MHz 2 /* DDR2 */ +#define DCH_MemClkFreq_400MHz 3 /* DDR2 and DDR 3*/ +#define DCH_MemClkFreq_533MHz 4 /* DDR 3 */ +#define DCH_MemClkFreq_667MHz 5 /* DDR 3 */ +#define DCH_MemClkFreq_800MHz 6 /* DDR 3 */ +#define DCH_MemClkFreqVal (1<<3) +#define DCH_Ddr3Mode (1<<8) +#define DCH_LegacyBiosMode (1<<9) +#define DCH_ZqcsInterval_SHIFT 10 +#define DCH_ZqcsInterval_MASK 3 +#define DCH_ZqcsInterval_DIS 0 +#define DCH_ZqcsInterval_64MS 1 +#define DCH_ZqcsInterval_128MS 2 +#define DCH_ZqcsInterval_256MS 3 +#define DCH_RDqsEn (1<<12) /* only for DDR2 */ +#define DCH_DisSimulRdWr (1<<13) +#define DCH_DisDramInterface (1<<14) +#define DCH_PowerDownEn (1<<15) +#define DCH_PowerDownMode_SHIFT 16 +#define DCH_PowerDownMode_MASK 1 +#define DCH_PowerDownMode_Channel_CKE 0 +#define DCH_PowerDownMode_ChipSelect_CKE 1 +#define DCH_FourRankSODimm (1<<17) +#define DCH_FourRankRDimm (1<<18) +#define DCH_SlowAccessMode (1<<20) +#define DCH_BankSwizzleMode (1<<22) +#define DCH_DcqBypassMax_SHIFT 24 +#define DCH_DcqBypassMax_MASK 0xf +#define DCH_DcqBypassMax_BASE 0 +#define DCH_DcqBypassMax_MIN 0 +#define DCH_DcqBypassMax_MAX 15 +#define DCH_FourActWindow_SHIFT 28 +#define DCH_FourActWindow_MASK 0xf +#define DCH_FourActWindow_BASE 7 /* DDR3 15 */ +#define DCH_FourActWindow_MIN 8 /* DDR3 16 */ +#define DCH_FourActWindow_MAX 20 /* DDR3 30 */ + + +// for 0x98 index and 0x9c data for DCT0 +// for 0x198 index and 0x19c data for DCT1 +// even at ganged mode, 0x198/0x19c will be used for channnel B + +#define DRAM_CTRL_ADDI_DATA_OFFSET 0x98 +#define DCAO_DctOffset_SHIFT 0 +#define DCAO_DctOffset_MASK 0x3fffffff +#define DCAO_DctAccessWrite (1<<30) +#define DCAO_DctAccessDone (1<<31) + +#define DRAM_CTRL_ADDI_DATA_PORT 0x9c + +#define DRAM_OUTPUT_DRV_COMP_CTRL 0x00 +#define DODCC_CkeDrvStren_SHIFT 0 +#define DODCC_CkeDrvStren_MASK 3 +#define DODCC_CkeDrvStren_1_0X 0 +#define DODCC_CkeDrvStren_1_25X 1 +#define DODCC_CkeDrvStren_1_5X 2 +#define DODCC_CkeDrvStren_2_0X 3 +#define DODCC_CsOdtDrvStren_SHIFT 4 +#define DODCC_CsOdtDrvStren_MASK 3 +#define DODCC_CsOdtDrvStren_1_0X 0 +#define DODCC_CsOdtDrvStren_1_25X 1 +#define DODCC_CsOdtDrvStren_1_5X 2 +#define DODCC_CsOdtDrvStren_2_0X 3 +#define DODCC_AddrCmdDrvStren_SHIFT 8 +#define DODCC_AddrCmdDrvStren_MASK 3 +#define DODCC_AddrCmdDrvStren_1_0X 0 +#define DODCC_AddrCmdDrvStren_1_25X 1 +#define DODCC_AddrCmdDrvStren_1_5X 2 +#define DODCC_AddrCmdDrvStren_2_0X 3 +#define DODCC_ClkDrvStren_SHIFT 12 +#define DODCC_ClkDrvStren_MASK 3 +#define DODCC_ClkDrvStren_0_75X 0 +#define DODCC_ClkDrvStren_1_0X 1 +#define DODCC_ClkDrvStren_1_25X 2 +#define DODCC_ClkDrvStren_1_5X 3 +#define DODCC_DataDrvStren_SHIFT 16 +#define DODCC_DataDrvStren_MASK 3 +#define DODCC_DataDrvStren_0_75X 0 +#define DODCC_DataDrvStren_1_0X 1 +#define DODCC_DataDrvStren_1_25X 2 +#define DODCC_DataDrvStren_1_5X 3 +#define DODCC_DqsDrvStren_SHIFT 20 +#define DODCC_DqsDrvStren_MASK 3 +#define DODCC_DqsDrvStren_0_75X 0 +#define DODCC_DqsDrvStren_1_0X 1 +#define DODCC_DqsDrvStren_1_25X 2 +#define DODCC_DqsDrvStren_1_5X 3 +#define DODCC_ProcOdt_SHIFT 28 +#define DODCC_ProcOdt_MASK 3 +#define DODCC_ProcOdt_300_OHMS 0 +#define DODCC_ProcOdt_150_OHMS 1 +#define DODCC_ProcOdt_75_OHMS 2 +#if 0 +//DDR3 +#define DODCC_ProcOdt_240_OHMS 0 +#define DODCC_ProcOdt_120_OHMS 1 +#define DODCC_ProcOdt_60_OHMS 2 +#endif + +/* + for DDR2 400, 533, 667, F2x[1,0]9C_x[02:01], [03], [06:05], [07] controll timing of all DIMMs + for DDR2 800, DDR3 800, 1067, 1333, 1600, F2x[1,0]9C_x[02:01], [03], [06:05], [07] controll timing of DIMM0 + F2x[1,0]9C_x[102:101], [103], [106:105], [107] controll timing of DIMM1 + So Socket F with Four Logical DIMM will only support DDR2 800 ? +*/ +/* there are index +100 ===> for DIMM1 +that are corresponding to 0x01, 0x02, 0x03, 0x05, 0x06, 0x07 +*/ +//02/15/2006 18:37 +#define DRAM_WRITE_DATA_TIMING_CTRL_LOW 0x01 +#define DWDTC_WrDatFineDlyByte0_SHIFT 0 +#define DWDTC_WrDatFineDlyByte_MASK 0x1f +#define DWDTC_WrDatFineDlyByte_BASE 0 +#define DWDTC_WrDatFineDlyByte_MIN 0 +#define DWDTC_WrDatFineDlyByte_MAX 31 // 1/64 MEMCLK +#define DWDTC_WrDatGrossDlyByte0_SHIFT 5 +#define DWDTC_WrDatGrossDlyByte_MASK 0x3 +#define DWDTC_WrDatGrossDlyByte_NO_DELAY 0 +#define DWDTC_WrDatGrossDlyByte_0_5_ 1 +#define DWDTC_WrDatGrossDlyByte_1 2 +#define DWDTC_WrDatFineDlyByte1_SHIFT 8 +#define DWDTC_WrDatGrossDlyByte1_SHIFT 13 +#define DWDTC_WrDatFineDlyByte2_SHIFT 16 +#define DWDTC_WrDatGrossDlyByte2_SHIFT 21 +#define DWDTC_WrDatFineDlyByte3_SHIFT 24 +#define DWDTC_WrDatGrossDlyByte3_SHIFT 29 + +#define DRAM_WRITE_DATA_TIMING_CTRL_HIGH 0x02 +#define DWDTC_WrDatFineDlyByte4_SHIFT 0 +#define DWDTC_WrDatGrossDlyByte4_SHIFT 5 +#define DWDTC_WrDatFineDlyByte5_SHIFT 8 +#define DWDTC_WrDatGrossDlyByte5_SHIFT 13 +#define DWDTC_WrDatFineDlyByte6_SHIFT 16 +#define DWDTC_WrDatGrossDlyByte6_SHIFT 21 +#define DWDTC_WrDatFineDlyByte7_SHIFT 24 +#define DWDTC_WrDatGrossDlyByte7_SHIFT 29 + +#define DRAM_WRITE_ECC_TIMING_CTRL 0x03 +#define DWETC_WrChkFinDly_SHIFT 0 +#define DWETC_WrChkGrossDly_SHIFT 5 + +#define DRAM_ADDR_CMD_TIMING_CTRL 0x04 +#define DACTC_CkeFineDelay_SHIFT 0 +#define DACTC_CkeFineDelay_MASK 0x1f +#define DACTC_CkeFineDelay_BASE 0 +#define DACTC_CkeFineDelay_MIN 0 +#define DACTC_CkeFineDelay_MAX 31 +#define DACTC_CkeSetup (1<<5) +#define DACTC_CsOdtFineDelay_SHIFT 8 +#define DACTC_CsOdtFineDelay_MASK 0x1f +#define DACTC_CsOdtFineDelay_BASE 0 +#define DACTC_CsOdtFineDelay_MIN 0 +#define DACTC_CsOdtFineDelay_MAX 31 +#define DACTC_CsOdtSetup (1<<13) +#define DACTC_AddrCmdFineDelay_SHIFT 16 +#define DACTC_AddrCmdFineDelay_MASK 0x1f +#define DACTC_AddrCmdFineDelay_BASE 0 +#define DACTC_AddrCmdFineDelay_MIN 0 +#define DACTC_AddrCmdFineDelay_MAX 31 +#define DACTC_AddrCmdSetup (1<<21) + +#define DRAM_READ_DQS_TIMING_CTRL_LOW 0x05 +#define DRDTC_RdDqsTimeByte0_SHIFT 0 +#define DRDTC_RdDqsTimeByte_MASK 0x3f +#define DRDTC_RdDqsTimeByte_BASE 0 +#define DRDTC_RdDqsTimeByte_MIN 0 +#define DRDTC_RdDqsTimeByte_MAX 63 // 1/128 MEMCLK +#define DRDTC_RdDqsTimeByte1_SHIFT 8 +#define DRDTC_RdDqsTimeByte2_SHIFT 16 +#define DRDTC_RdDqsTimeByte3_SHIFT 24 + +#define DRAM_READ_DQS_TIMING_CTRL_HIGH 0x06 +#define DRDTC_RdDqsTimeByte4_SHIFT 0 +#define DRDTC_RdDqsTimeByte5_SHIFT 8 +#define DRDTC_RdDqsTimeByte6_SHIFT 16 +#define DRDTC_RdDqsTimeByte7_SHIFT 24 + +#define DRAM_READ_DQS_ECC_TIMING_CTRL 0x07 +#define DRDETC_RdDqsTimeCheck_SHIFT 0 + +#define DRAM_PHY_CTRL 0x08 +#define DPC_WrtLvTrEn (1<<0) +#define DPC_WrtLvTrMode (1<<1) +#define DPC_TrNibbleSel (1<<2) +#define DPC_TrDimmSel_SHIFT 4 +#define DPC_TrDimmSel_MASK 3 /* 0-->dimm0, 1-->dimm1, 2--->dimm2, 3--->dimm3 */ +#define DPC_WrLvOdt_SHIFT 8 +#define DPC_WrLvOdt_MASK 0xf /* bit 0-->odt 0, ...*/ +#define DPC_WrLvODtEn (1<<12) +#define DPC_DqsRcvTrEn (1<<13) +#define DPC_DisAutoComp (1<<30) +#define DPC_AsyncCompUpdate (1<<31) + +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_0_0 0x10 //DIMM0 Channel A +#define DDRETC_DqsRcvEnFineDelayByte0_SHIFT 0 +#define DDRETC_DqsRcvEnFineDelayByte0_MASK 0x1f +#define DDRETC_DqsRcvEnGrossDelayByte0_SHIFT 5 +#define DDRETC_DqsRcvEnGrossDelayByte0_MASK 0x3 +#define DDRETC_DqsRcvEnFineDelayByte1_SHIFT 8 +#define DDRETC_DqsRcvEnGrossDelayByte1_SHIFT 13 +#define DDRETC_DqsRcvEnFineDelayByte2_SHIFT 16 +#define DDRETC_DqsRcvEnGrossDelayByte2_SHIFT 21 +#define DDRETC_DqsRcvEnFineDelayByte3_SHIFT 24 +#define DDRETC_DqsRcvEnGrossDelayByte3_SHIFT 29 + +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_0_1 0x11 //DIMM0 Channel A +#define DDRETC_DqsRcvEnFineDelayByte4_SHIFT 0 +#define DDRETC_DqsRcvEnGrossDelayByte4_SHIFT 5 +#define DDRETC_DqsRcvEnFineDelayByte5_SHIFT 8 +#define DDRETC_DqsRcvEnGrossDelayByte5_SHIFT 13 +#define DDRETC_DqsRcvEnFineDelayByte6_SHIFT 16 +#define DDRETC_DqsRcvEnGrossDelayByte6_SHIFT 21 +#define DDRETC_DqsRcvEnFineDelayByte7_SHIFT 24 +#define DDRETC_DqsRcvEnGrossDelayByte7_SHIFT 29 + +#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_0_0 0x12 +#define DDRETCE_WrChkFineDlyByte0_SHIFT 0 +#define DDRETCE_WrChkGrossDlyByte0_SHIFT 5 + +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_0_2 0x20 //DIMM0 channel B +#define DDRETC_DqsRcvEnFineDelayByte8_SHIFT 0 +#define DDRETC_DqsRcvEnGrossDelayByte8_SHIFT 5 +#define DDRETC_DqsRcvEnFineDelayByte9_SHIFT 8 +#define DDRETC_DqsRcvEnGrossDelayByte9_SHIFT 13 +#define DDRETC_DqsRcvEnFineDelayByte10_SHIFT 16 +#define DDRETC_DqsRcvEnGrossDelayByte10_SHIFT 21 +#define DDRETC_DqsRcvEnFineDelayByte11_SHIFT 24 +#define DDRETC_DqsRcvEnGrossDelayByte11_SHIFT 29 + +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_0_3 0x21 // DIMM0 Channel B +#define DDRETC_DqsRcvEnFineDelayByte12_SHIFT 0 +#define DDRETC_DqsRcvEnGrossDelayByte12_SHIFT 5 +#define DDRETC_DqsRcvEnFineDelayByte13_SHIFT 8 +#define DDRETC_DqsRcvEnGrossDelayByte13_SHIFT 13 +#define DDRETC_DqsRcvEnFineDelayByte14_SHIFT 16 +#define DDRETC_DqsRcvEnGrossDelayByte14_SHIFT 21 +#define DDRETC_DqsRcvEnFineDelayByte15_SHIFT 24 +#define DDRETC_DqsRcvEnGrossDelayByte15_SHIFT 29 + +#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_0_1 0x22 +#define DDRETCE_WrChkFineDlyByte1_SHIFT 0 +#define DDRETCE_WrChkGrossDlyByte1_SHIFT 5 + +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_1_0 0x13 //DIMM1 +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_1_1 0x14 +#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_1_0 0x15 +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_1_2 0x23 +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_1_3 0x24 +#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_1_1 0x25 + +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_2_0 0x16 // DIMM2 +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_2_1 0x17 +#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_2_0 0x18 +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_2_2 0x26 +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_2_3 0x27 +#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_2_1 0x28 + +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_3_0 0x19 // DIMM3 +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_3_1 0x1a +#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_3_0 0x1b +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_3_2 0x29 +#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_3_3 0x2a +#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_3_1 0x2b + +/* 04.06.2006 19:12 */ + +#if 0 +//DDR3 +#define DRAM_DQS_WRITE_TIME_CTRL_0_0 0x30 //DIMM0 Channel A +#define DDWTC_WrDqsFineDlyByte0_SHIFT 0 +#define DDWTC_WrDqsFineDlyByte0_MASK 0x1f +#define DDWTC_WrDqsGrossDlyByte0_SHIFT 5 +#define DDWTC_WrDqsGrossDlyByte0_MASK 0x3 +#define DDWTC_WrDqsFineDlyByte1_SHIFT 8 +#define DDWTC_WrDqsGrossDlyByte1_SHIFT 13 +#define DDWTC_WrDqsFineDlyByte2_SHIFT 16 +#define DDWTC_WrDqsGrossDlyByte2_SHIFT 21 +#define DDWTC_WrDqsFineDlyByte3_SHIFT 24 +#define DDWTC_WrDqsGrossDlyByte3_SHIFT 29 + +#define DRAM_DQS_WRTIE_TIME_CTRL_0_1 0x31 //DIMM0 Channel A +#define DDWTC_WrDqsFineDlyByte4_SHIFT 0 +#define DDWTC_WrDqsGrossDlyByte4_SHIFT 5 +#define DDWTC_WrDqsFineDlyByte5_SHIFT 8 +#define DDWTC_WrDqsGrossDlyByte5_SHIFT 13 +#define DDWTC_WrDqsFineDlyByte6_SHIFT 16 +#define DDWTC_WrDqsGrossDlyByte6_SHIFT 21 +#define DDWTC_WrDqsFineDlyByte7_SHIFT 24 +#define DDWTC_WrDqsGrossDlyByte7_SHIFT 29 + +#define DRAM_DQS_WRITE_TIMING_CTRL_ECC_0_0 0x32 +#define DDWTCE_WrDqsChkFineDlyByte0_SHIFT 0 +#define DDWTCE_WrDqsChkGrossDlyByte0_SHIFT 5 + +#define DRAM_DQS_WRITE_TIME_CTRL_0_2 0x40 //DIMM0 Channel B +#define DDWTC_WrDqsFineDlyByte8_SHIFT 0 +#define DDWTC_WrDqsGrossDlyByte8_SHIFT 5 +#define DDWTC_WrDqsFineDlyByte9_SHIFT 8 +#define DDWTC_WrDqsGrossDlyByte9_SHIFT 13 +#define DDWTC_WrDqsFineDlyByte10_SHIFT 16 +#define DDWTC_WrDqsGrossDlyByte10_SHIFT 21 +#define DDWTC_WrDqsFineDlyByte11_SHIFT 24 +#define DDWTC_WrDqsGrossDlyByte11_SHIFT 29 + +#define DRAM_DQS_WRTIE_TIME_CTRL_0_3 0x41 //DIMM0 Channel B +#define DDWTC_WrDqsFineDlyByte12_SHIFT 0 +#define DDWTC_WrDqsGrossDlyByte12_SHIFT 5 +#define DDWTC_WrDqsFineDlyByte13_SHIFT 8 +#define DDWTC_WrDqsGrossDlyByte13_SHIFT 13 +#define DDWTC_WrDqsFineDlyByte14_SHIFT 16 +#define DDWTC_WrDqsGrossDlyByte14_SHIFT 21 +#define DDWTC_WrDqsFineDlyByte15_SHIFT 24 +#define DDWTC_WrDqsGrossDlyByte15_SHIFT 29 + +#define DRAM_DQS_WRITE_TIMING_CTRL_ECC_0_1 0x42 +#define DDWTCE_WrDqsChkFineDlyByte1_SHIFT 0 +#define DDWTCE_WrDqsChkGrossDlyByte1_SHIFT 5 + +#define DRAM_DQS_WRITE_TIME_CTRL_1_0 0x33 //DIMM1 Channel A +#define DRAM_DQS_WRTIE_TIME_CTRL_1_1 0x34 //DIMM1 Channel A +#define DRAM_DQS_WRITE_TIMING_CTRL_ECC_1_0 0x35 +#define DRAM_DQS_WRITE_TIME_CTRL_1_2 0x43 //DIMM1 Channel B +#define DRAM_DQS_WRTIE_TIME_CTRL_1_3 0x44 //DIMM1 Channel B +#define DRAM_DQS_WRITE_TIMING_CTRL_ECC_1_1 0x45 +#endif + +#define DRAM_PHASE_RECOVERY_CTRL_0 0x50 +#define DPRC_PhRecFineDlyByte0_SHIFT 0 +#define DDWTC_PhRecFineDlyByte0_MASK 0x1f +#define DDWTC_PhRecGrossDlyByte0_SHIFT 5 +#define DDWTC_PhRecGrossDlyByte0_MASK 0x3 +#define DDWTC_PhRecFineDlyByte1_SHIFT 8 +#define DDWTC_PhRecGrossDlyByte1_SHIFT 13 +#define DDWTC_PhRecFineDlyByte2_SHIFT 16 +#define DDWTC_PhRecGrossDlyByte2_SHIFT 21 +#define DDWTC_PhRecFineDlyByte3_SHIFT 24 +#define DDWTC_PhRecGrossDlyByte3_SHIFT 29 + +#define DRAM_PHASE_RECOVERY_CTRL_1 0x51 +#define DPRC_PhRecFineDlyByte4_SHIFT 0 +#define DDWTC_PhRecGrossDlyByte4_SHIFT 5 +#define DDWTC_PhRecFineDlyByte5_SHIFT 8 +#define DDWTC_PhRecGrossDlyByte5_SHIFT 13 +#define DDWTC_PhRecFineDlyByte6_SHIFT 16 +#define DDWTC_PhRecGrossDlyByte6_SHIFT 21 +#define DDWTC_PhRecFineDlyByte7_SHIFT 24 +#define DDWTC_PhRecGrossDlyByte7_SHIFT 29 + +#define DRAM_ECC_PHASE_RECOVERY_CTRL 0x52 +#define DEPRC_PhRecEccDlyByte0_SHIFT 0 +#define DEPRC_PhRecEccGrossDlyByte0_SHIFT 5 + +#define DRAM_WRITE_LEVEL_ERROR 0x53 /* read only */ +#define DWLE_WrLvErr_SHIFT 0 +#define DWLE_WrLvErr_MASK 0xff + +#define DRAM_CTRL_MISC 0xa0 +#define DCM_MemCleared (1<<0) /* RD == F2x110 [MemCleared] */ +#define DCM_DramEnabled (1<<9) /* RD == F2x110 [DramEnabled] */ + +#define NB_TIME_STAMP_COUNT_LOW 0xb0 +#define TscLow_SHIFT 0 +#define TscLow_MASK 0xffffffff + +#define NB_TIME_STAMP_COUNT_HIGH 0xb4 +#define TscHigh_SHIFT 0 +#define TscHigh_Mask 0xff + +#define DCT_DEBUG_CTRL 0xf0 /* 0xf0 for DCT0, 0x1f0 is for DCT1*/ +#define DDC_DllAdjust_SHIFT 0 +#define DDC_DllAdjust_MASK 0xff +#define DDC_DllSlower (1<<8) +#define DDC_DllFaster (1<<9) +#define DDC_WrtDqsAdjust_SHIFT 16 +#define DDC_WrtDqsAdjust_MASK 0x7 +#define DDC_WrtDqsAdjustEn (1<<19) + +#define DRAM_CTRL_SEL_LOW 0x110 +#define DCSL_DctSelHiRngEn (1<<0) +#define DCSL_DctSelHi (1<<1) +#define DCSL_DctSelIntLvEn (1<<2) +#define DCSL_MemClrInit (1<<3) /* WR only */ +#define DCSL_DctGangEn (1<<4) +#define DCSL_DctDataIntLv (1<<5) +#define DCSL_DctSelIntLvAddr_SHIFT +#define DCSL_DctSelIntLvAddr_MASK 3 +#define DCSL_DramEnable (1<<8) /* RD only */ +#define DCSL_MemClrBusy (1<<9) /* RD only */ +#define DCSL_MemCleared (1<<10) /* RD only */ +#define DCSL_DctSelBaseAddr_47_27_SHIFT 11 +#define DCSL_DctSelBaseAddr_47_27_MASK 0x1fffff + +#define DRAM_CTRL_SEL_HIGH 0x114 +#define DCSH_DctSelBaseOffset_47_26_SHIFT 10 +#define DCSH_DctSelBaseOffset_47_26_MASK 0x3fffff + +#define MEM_CTRL_CONF_LOW 0x118 +#define MCCL_MctPriCpuRd (1<<0) +#define MCCL_MctPriCpuWr (1<<1) +#define MCCL_MctPriIsocRd_SHIFT 4 +#define MCCL_MctPriIsoc_MASK 0x3 +#define MCCL_MctPriIsocWr_SHIFT 6 +#define MCCL_MctPriIsocWe_MASK 0x3 +#define MCCL_MctPriDefault_SHIFT 8 +#define MCCL_MctPriDefault_MASK 0x3 +#define MCCL_MctPriWr_SHIFT 10 +#define MCCL_MctPriWr_MASK 0x3 +#define MCCL_MctPriIsoc_SHIFT 12 +#define MCCL_MctPriIsoc_MASK 0x3 +#define MCCL_MctPriTrace_SHIFT 14 +#define MCCL_MctPriTrace_MASK 0x3 +#define MCCL_MctPriScrub_SHIFT 16 +#define MCCL_MctPriScrub_MASK 0x3 +#define MCCL_McqMedPriByPassMax_SHIFT 20 +#define MCCL_McqMedPriByPassMax_MASK 0x7 +#define MCCL_McqHiPriByPassMax_SHIFT 24 +#define MCCL_McqHiPriByPassMax_MASK 0x7 +#define MCCL_MctVarPriCntLmt_SHIFT 28 +#define MCCL_MctVarPriCntLmt_MASK 0x7 + +#define MEM_CTRL_CONF_HIGH 0x11c +#define MCCH_DctWrLimit_SHIFT 0 +#define MCCH_DctWrLimit_MASK 0x3 +#define MCCH_MctWrLimit_SHIFT 2 +#define MCCH_MctWrLimit_MASK 0x1f +#define MCCH_MctPrefReqLimit_SHIFT 7 +#define MCCH_MctPrefReqLimit_MASK 0x1f +#define MCCH_PrefCpuDis (1<<12) +#define MCCH_PrefIoDis (1<<13) +#define MCCH_PrefIoFixStrideEn (1<<14) +#define MCCH_PrefFixStrideEn (1<<15) +#define MCCH_PrefFixDist_SHIFT 16 +#define MCCH_PrefFixDist_MASK 0x3 +#define MCCH_PrefConfSat_SHIFT 18 +#define MCCH_PrefConfSat_MASK 0x3 +#define MCCH_PrefOneConf_SHIFT 20 +#define MCCH_PrefOneConf_MASK 0x3 +#define MCCH_PrefTwoConf_SHIFT 22 +#define MCCH_PrefTwoConf_MASK 0x7 +#define MCCH_PrefThreeConf_SHIFT 25 +#define MCCH_prefThreeConf_MASK 0x7 +#define MCCH_PrefDramTrainMode (1<<28) +#define MCCH_FlushWrOnStpGnt (1<<29) +#define MCCH_FlushWr (1<<30) +#define MCCH_MctScrubEn (1<<31) + + +/* Function 3 */ +#define MCA_NB_CONTROL 0x40 +#define MNCT_CorrEccEn (1<<0) +#define MNCT_UnCorrEccEn (1<<1) +#define MNCT_CrcErr0En (1<<2) /* Link 0 */ +#define MNCT_CrcErr1En (1<<3) +#define MNCT_CrcErr2En (1<<4) +#define MBCT_SyncPkt0En (1<<5) /* Link 0 */ +#define MBCT_SyncPkt1En (1<<6) +#define MBCT_SyncPkt2En (1<<7) +#define MBCT_MstrAbrtEn (1<<8) +#define MBCT_TgtAbrtEn (1<<9) +#define MBCT_GartTblEkEn (1<<10) +#define MBCT_AtomicRMWEn (1<<11) +#define MBCT_WdogTmrRptEn (1<<12) +#define MBCT_DevErrEn (1<<13) +#define MBCT_L3ArrayCorEn (1<<14) +#define MBCT_L3ArrayUncEn (1<<15) +#define MBCT_HtProtEn (1<<16) +#define MBCT_HtDataEn (1<<17) +#define MBCT_DramParEn (1<<18) +#define MBCT_RtryHt0En (1<<19) /* Link 0 */ +#define MBCT_RtryHt1En (1<<20) +#define MBCT_RtryHt2En (1<<21) +#define MBCT_RtryHt3En (1<<22) +#define MBCT_CrcErr3En (1<<23) /* Link 3*/ +#define MBCT_SyncPkt3En (1<<24) /* Link 4 */ +#define MBCT_McaUsPwDatErrEn (1<<25) +#define MBCT_NbArrayParEn (1<<26) +#define MBCT_TblWlkDatErrEn (1<<27) +#define MBCT_FbDimmCorErrEn (1<<28) +#define MBCT_FbDimmUnCorErrEn (1<<29) + + + +#define MCA_NB_CONFIG 0x44 +#define MNC_CpuRdDatErrEn (1<<1) +#define MNC_SyncOnUcEccEn (1<<2) +#define MNC_SynvPktGenDis (1<<3) +#define MNC_SyncPktPropDis (1<<4) +#define MNC_IoMstAbortDis (1<<5) +#define MNC_CpuErrDis (1<<6) +#define MNC_IoErrDis (1<<7) +#define MNC_WdogTmrDis (1<<8) +#define MNC_WdogTmrCntSel_2_0_SHIFT 9 /* 3 is ar f3x180 */ +#define MNC_WdogTmrCntSel_2_0_MASK 0x3 +#define MNC_WdogTmrBaseSel_SHIFT 12 +#define MNC_WdogTmrBaseSel_MASK 0x3 +#define MNC_LdtLinkSel_SHIFT 14 +#define MNC_LdtLinkSel_MASK 0x3 +#define MNC_GenCrcErrByte0 (1<<16) +#define MNC_GenCrcErrByte1 (1<<17) +#define MNC_SubLinkSel_SHIFT 18 +#define MNC_SubLinkSel_MASK 0x3 +#define MNC_SyncOnWdogEn (1<<20) +#define MNC_SyncOnAnyErrEn (1<<21) +#define MNC_DramEccEn (1<<22) +#define MNC_ChipKillEccEn (1<<23) +#define MNC_IoRdDatErrEn (1<<24) +#define MNC_DisPciCfgCpuErrRsp (1<<25) +#define MNC_CorrMcaExcEn (1<<26) +#define MNC_NbMcaToMstCpuEn (1<<27) +#define MNC_DisTgtAbtCpuErrRsp (1<<28) +#define MNC_DisMstAbtCpuErrRsp (1<<29) +#define MNC_SyncOnDramAdrParErrEn (1<<30) +#define MNC_NbMcaLogEn (1<<31) + +#define MCA_NB_STATUS_LOW 0x48 +#define MNSL_ErrorCode_SHIFT 0 +#define MNSL_ErrorCode_MASK 0xffff +#define MNSL_ErrorCodeExt_SHIFT 16 +#define MNSL_ErrorCodeExt_MASK 0x1f +#define MNSL_Syndrome_15_8_SHIFT 24 +#define MNSL_Syndrome_15_8_MASK 0xff + +#define MCA_NB_STATUS_HIGH 0x4c +#define MNSH_ErrCPU_SHIFT 0 +#define MNSH_ErrCPU_MASK 0xf +#define MNSH_LDTLink_SHIFT 4 +#define MNSH_LDTLink_MASK 0xf +#define MNSH_ErrScrub (1<<8) +#define MNSH_SubLink (1<<9) +#define MNSH_McaStatusSubCache_SHIFT 10 +#define MNSH_McaStatusSubCache_MASK 0x3 +#define MNSH_Deffered (1<<12) +#define MNSH_UnCorrECC (1<<13) +#define MNSH_CorrECC (1<<14) +#define MNSH_Syndrome_7_0_SHIFT 15 +#define MNSH_Syndrome_7_0_MASK 0xff +#define MNSH_PCC (1<<25) +#define MNSH_ErrAddrVal (1<<26) +#define MNSH_ErrMiscVal (1<<27) +#define MNSH_ErrEn (1<<28) +#define MNSH_ErrUnCorr (1<<29) +#define MNSH_ErrOver (1<<30) +#define MNSH_ErrValid (1<<31) + +#define MCA_NB_ADDR_LOW 0x50 +#define MNAL_ErrAddr_31_1_SHIFT 1 +#define MNAL_ErrAddr_31_1_MASK 0x7fffffff + +#define MCA_NB_ADDR_HIGH 0x54 +#define MNAL_ErrAddr_47_32_SHIFT 0 +#define MNAL_ErrAddr_47_32_MASK 0xffff + +#define DRAM_SCRUB_RATE_CTRL 0x58 +#define SCRUB_NONE 0 +#define SCRUB_40ns 1 +#define SCRUB_80ns 2 +#define SCRUB_160ns 3 +#define SCRUB_320ns 4 +#define SCRUB_640ns 5 +#define SCRUB_1_28us 6 +#define SCRUB_2_56us 7 +#define SCRUB_5_12us 8 +#define SCRUB_10_2us 9 +#define SCRUB_20_5us 0xa +#define SCRUB_41_0us 0xb +#define SCRUB_81_9us 0xc +#define SCRUB_163_8us 0xd +#define SCRUB_327_7us 0xe +#define SCRUB_655_4us 0xf +#define SCRUB_1_31ms 0x10 +#define SCRUB_2_62ms 0x11 +#define SCRUB_5_24ms 0x12 +#define SCRUB_10_49ms 0x13 +#define SCRUB_20_97ms 0x14 +#define SCRUB_42ms 0x15 +#define SCRUB_84ms 0x16 +#define DSRC_DramScrub_SHFIT 0 +#define DSRC_DramScrub_MASK 0x1f +#define DSRC_L2Scrub_SHIFT 8 +#define DSRC_L2Scrub_MASK 0x1f +#define DSRC_DcacheScrub_SHIFT 16 +#define DSRC_DcacheScrub_MASK 0x1f +#define DSRC_L3Scrub_SHIFT 24 +#define DSRC_L3Scrub_MASK 0x1f + +#define DRAM_SCRUB_ADDR_LOW 0x5C +#define DSAL_ScrubReDirEn (1<<0) +#define DSAL_ScrubAddrLo_SHIFT 6 +#define DSAL_ScrubAddrLo_MASK 0x3ffffff + +#define DRAM_SCRUB_ADDR_HIGH 0x60 +#define DSAH_ScrubAddrHi_SHIFT 0 +#define DSAH_ScrubAddrHi_MASK 0xffff + +#define HW_THERMAL_CTRL 0x64 + +#define SW_THERMAL_CTRL 0x68 + +#define DATA_BUF_CNT 0x6c + +#define SRI_XBAR_CMD_BUF_CNT 0x70 + +#define XBAR_SRI_CMD_BUF_CNT 0x74 + +#define MCT_XBAR_CMD_BUF_CNT 0x78 + +#define ACPI_PWR_STATE_CTRL 0x80 /* till 0x84 */ + +#define NB_CONFIG_LOW 0x88 +#define NB_CONFIG_HIGH 0x8c + +#define GART_APERTURE_CTRL 0x90 + +#define GART_APERTURE_BASE 0x94 + +#define GART_TBL_BASE 0x98 + +#define GART_CACHE_CTRL 0x9c + +#define PWR_CTRL_MISC 0xa0 + +#define RPT_TEMP_CTRL 0xa4 + +#define ON_LINE_SPARE_CTRL 0xb0 + +#define SBI_P_STATE_LIMIT 0xc4 + +#define CLK_PWR_TIMING_CTRL0 0xd4 +#define CLK_PWR_TIMING_CTRL1 0xd8 +#define CLK_PWR_TIMING_CTRL2 0xdc + +#define THERMTRIP_STATUS 0xE4 + + +#define NORTHBRIDGE_CAP 0xE8 +#define NBCAP_TwoChanDRAMcap (1 << 0) +#define NBCAP_DualNodeMPcap (1 << 1) +#define NBCAP_EightNodeMPcap (1 << 2) +#define NBCAP_ECCcap (1 << 3) +#define NBCAP_ChipkillECCcap (1 << 4) +#define NBCAP_DdrMaxRate_SHIFT 5 +#define NBCAP_DdrMaxRate_MASK 7 +#define NBCAP_DdrMaxRate_400 7 +#define NBCAP_DdrMaxRate_533 6 +#define NBCAP_DdrMaxRate_667 5 +#define NBCAP_DdrMaxRate_800 4 +#define NBCAP_DdrMaxRate_1067 3 +#define NBCAP_DdrMaxRate_1333 2 +#define NBCAP_DdrMaxRate_1600 1 +#define NBCAP_DdrMaxRate_3_2G 6 +#define NBCAP_DdrMaxRate_4_0G 5 +#define NBCAP_DdrMaxRate_4_8G 4 +#define NBCAP_DdrMaxRate_6_4G 3 +#define NBCAP_DdrMaxRate_8_0G 2 +#define NBCAP_DdrMaxRate_9_6G 1 +#define NBCAP_Mem_ctrl_cap (1 << 8) +#define MBCAP_SVMCap (1<<9) +#define NBCAP_HtcCap (1<<10) +#define NBCAP_CmpCap_SHIFT 12 +#define NBCAP_CmpCap_MASK 3 +#define NBCAP_MpCap_SHIFT 16 +#define NBCAP_MpCap_MASK 7 +#define NBCAP_MpCap_1N 7 +#define NBCAP_MpCap_2N 6 +#define NBCAP_MpCap_4N 5 +#define NBCAP_MpCap_8N 4 +#define NBCAP_MpCap_32N 0 +#define NBCAP_UnGangEn_SHIFT 20 +#define NBCAP_UnGangEn_MASK 0xf +#define NBCAP_L3Cap (1<<25) +#define NBCAP_HtAcCap (1<<26) + +/* 04/04/2006 18:00 */ + +#define EXT_NB_MCA_CTRL 0x180 + +#define NB_EXT_CONF 0x188 +#define DOWNCORE_CTRL 0x190 +#define DWNCC_DisCore_SHIFT 0 +#define DWNCC_DisCore_MASK 0xf + +/* Function 5 for FBDIMM */ +#define FBD_DRAM_TIMING_LOW + +#define LinkConnected (1 << 0) +#define InitComplete (1 << 1) +#define NonCoherent (1 << 2) +#define ConnectionPending (1 << 4) + + +#include "amdfam10_nums.h" + +#ifdef __ROMCC__ +#if NODE_NUMS==64 + #define NODE_PCI(x, fn) ((x<32)?(PCI_DEV(CBB,(CDB+x),fn)):(PCI_DEV((CBB-1),(CDB+x-32),fn))) +#else + #define NODE_PCI(x, fn) PCI_DEV(CBB,(CDB+x),fn) +#endif +#endif + +#include "raminit.h" + +#if CONFIG_AMDMCT == 0 + +//struct definitions + +struct dimm_size { + u8 per_rank; // it is rows + col + bank_lines + data lines */ + u8 rows; + u8 col; + u8 bank; //1, 2, 3 mean 2, 4, 8 + u8 rank; +} __attribute__((packed)); + +struct mem_info { // pernode + u32 dimm_mask; + struct dimm_size sz[DIMM_SOCKETS*2]; // for ungang support + u32 x4_mask; + u32 x16_mask; + u32 single_rank_mask; + u32 page_1k_mask; +// u32 ecc_mask; +// u32 registered_mask; + u8 is_opteron; + u8 is_registered; //don't support mixing on the same channel or between channel + u8 is_ecc; //don't support mixing on the same channel or between channel + u8 is_Width128; + u8 memclk_set; // we need to use this to retrieve the mem param, all dimms need to work at same freq for one node + u8 is_cs_interleaved[2]; //cs + u8 rsv[1]; +} __attribute__((packed)); +#else +#include "../amdmct/mct/mct_d.h" +#endif + +struct link_pair_t { + device_t udev; + u32 upos; + u32 uoffs; + device_t dev; + u32 pos; + u32 offs; + u8 host; + u8 nodeid; + u8 linkn; + u8 rsv; +} __attribute__((packed)); + +struct nodes_info_t { + u32 nodes_in_group; // could be 2, 3, 4, 5, 6, 7, 8 + u32 groups_in_plane; // could be 1, 2, 3, 4, 5 + u32 planes; // could be 1, 2 + u32 up_planes; // down planes will be [up_planes, planes) +} __attribute__((packed)); + +/* be careful with the alignment of sysinfo, bacause sysinfo may be shared by linuxbios_car and linuxbios_ram stage. and linuxbios_ram may be running at 64bit later.*/ +#if CONFIG_AMDMCT == 0 + +//#define MEM_CS_COPY 1 +#define MEM_CS_COPY NODE_NUMS + +#if MEM_TRAIN_SEQ == 0 + #define DQS_DELAY_COPY NODE_NUMS +#else +// #define DQS_DELAY_COPY 1 + #define DQS_DELAY_COPY NODE_NUMS +#endif +#endif + + +struct sys_info { + int32_t needs_reset; + + u8 ln[NODE_NUMS*NODE_NUMS];// [0, 3] link n, [4, 7] will be hop num + u16 ln_tn[NODE_NUMS*8]; // for 0x0zzz: bit [0,7] target node num, bit[8,11] respone link from target num; 0x80ff mean not inited, 0x4yyy mean non coherent and yyy is link pair index + struct nodes_info_t nodes_info; + u32 nodes; + + u8 host_link_freq[NODE_NUMS*8]; // record freq for every link from cpu, 0x0f means don't need to touch it + u16 host_link_freq_cap[NODE_NUMS*8]; //cap + + u32 segbit; + u32 sbdn; + u32 sblk; + u32 sbbusn; + + u32 ht_c_num; + u32 ht_c_conf_bus[HC_NUMS]; // 4-->32 + + struct link_pair_t link_pair[HC_NUMS*4];// enough? only in_conherent, 32 chain and every chain have 4 HT device + u32 link_pair_num; + + struct mem_controller ctrl[NODE_NUMS]; + +#if CONFIG_AMDMCT +// sMCTStruct MCTData; +// sDCTStruct *DCTNodeData[NODE_NUMS]; +// sDCTStruct DCTNodeData_a[NODE_NUMS]; + struct MCTStatStruc MCTstat; + struct DCTStatStruc DCTstatA[NODE_NUMS]; +#else + + u8 ctrl_present[NODE_NUMS]; + struct mem_info meminfo[NODE_NUMS]; + u8 mem_trained[NODE_NUMS]; //0: no dimm, 1: trained, 0x80: not started, 0x81: recv1 fail, 0x82: Pos Fail, 0x83:recv2 fail + u32 tom_m; + u32 tom2_m; + + //if we are getting tight of global space, may need to squesh following to one copy + u32 mem_base[MEM_CS_COPY][2]; // two dct + u32 cs_base[MEM_CS_COPY][2][8]; //8 cs_idx + u32 hole_startk; // 0 mean hole + + u8 dqs_delay_a[DQS_DELAY_COPY*2*4*2*9]; //8 node, channel 2, dimm 4, direction 2 , bytelane *9 + u8 dqs_rcvr_dly_a[DQS_DELAY_COPY*2*4*9]; //8 node, channel 2, dimm 4, bytelane *9 + u8 dqs_rcvr_dly_a_1[9]; //8 node, channel 2, dimm 4, bytelane *9 +#endif + +} __attribute__((packed)); + +#if CONFIG_AMDMCT == 0 + +#ifdef __ROMCC__ +static void soft_reset(void); +#endif +static void wait_all_core0_mem_trained(struct sys_info *sysinfo) +{ + int i; + u32 mask_lo = 0; + u32 mask_hi = 0; + unsigned needs_reset = 0; + + if(sysinfo->nodes == 1) return; // in case only one cpu installed + for(i=1; i<sysinfo->nodes; i++) { + /* Skip everything if I don't have any memory on this controller */ + if(sysinfo->mem_trained[i]==0x00) continue; + + if(i<32) { + mask_lo |= (1<<i); + } else { + mask_hi |= (1<<(i-32)); + } + } + + i = 1; + while(1) { + if(i<32) { + if(mask_lo & (1<<i)) { + if(sysinfo->mem_trained[i] != 0x80) { + mask_lo &= ~(1<<i); + } + } + } else { + if(mask_hi & (1<<(i-32))) { + if(sysinfo->mem_trained[i] != 0x80) { + mask_hi &= ~(1<<(i-32)); + } + } + } + + if((!mask_lo) && (!mask_hi)) break; + + i++; + i%=sysinfo->nodes; + } + + for(i=0; i<sysinfo->nodes; i++) { +#ifdef __ROMCC__ + print_debug("mem_trained["); print_debug_hex8(i); print_debug("]="); print_debug_hex8(sysinfo->mem_trained[i]); print_debug("\n"); +#else + printk_debug("mem_trained[%02x]=%02x\n", i, sysinfo->mem_trained[i]); +#endif + switch(sysinfo->mem_trained[i]) { + case 0: //don't need train + case 1: //trained + break; + case 0x81: //recv1: fail + case 0x82: //Pos :fail + case 0x83: //recv2: fail + needs_reset = 1; + break; + } + } + if(needs_reset) { +#ifdef __ROMCC__ + print_debug("mem trained failed\n"); + soft_reset(); +#else + printk_debug("mem trained failed\n"); + hard_reset(); +#endif + } + +} + +#endif + +#endif /* AMDFAM10_H */ diff --git a/src/northbridge/amd/amdfam10/amdfam10_acpi.c b/src/northbridge/amd/amdfam10/amdfam10_acpi.c new file mode 100644 index 0000000000..3c7f16b625 --- /dev/null +++ b/src/northbridge/amd/amdfam10/amdfam10_acpi.c @@ -0,0 +1,382 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <string.h> +#include <arch/acpi.h> +#include <device/pci.h> +#include <cpu/x86/msr.h> +#include <cpu/amd/mtrr.h> +#include <cpu/amd/amdfam10_sysconf.h> +#include "amdfam10.h" + +//it seems some functions can be moved arch/i386/boot/acpi.c + +unsigned long acpi_create_madt_lapics(unsigned long current) +{ + device_t cpu; + int cpu_index = 0; + + for(cpu = all_devices; cpu; cpu = cpu->next) { + if ((cpu->path.type != DEVICE_PATH_APIC) || + (cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER)) { + continue; + } + if (!cpu->enabled) { + continue; + } + current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current, cpu_index, cpu->path.u.apic.apic_id); + cpu_index++; + } + return current; +} + +unsigned long acpi_create_madt_lapic_nmis(unsigned long current, u16 flags, u8 lint) +{ + device_t cpu; + int cpu_index = 0; + + for(cpu = all_devices; cpu; cpu = cpu->next) { + if ((cpu->path.type != DEVICE_PATH_APIC) || + (cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER)) { + continue; + } + if (!cpu->enabled) { + continue; + } + current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current, cpu_index, flags, lint); + cpu_index++; + } + return current; +} + + +unsigned long acpi_create_srat_lapics(unsigned long current) +{ + device_t cpu; + int cpu_index = 0; + + for(cpu = all_devices; cpu; cpu = cpu->next) { + if ((cpu->path.type != DEVICE_PATH_APIC) || + (cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER)) { + continue; + } + if (!cpu->enabled) { + continue; + } + printk_debug("SRAT: lapic cpu_index=%02x, node_id=%02x, apic_id=%02x\n", cpu_index, cpu->path.u.apic.node_id, cpu->path.u.apic.apic_id); + current += acpi_create_srat_lapic((acpi_srat_lapic_t *)current, cpu->path.u.apic.node_id, cpu->path.u.apic.apic_id); + cpu_index++; + } + return current; +} + +static unsigned long resk(uint64_t value) +{ + unsigned long resultk; + if (value < (1ULL << 42)) { + resultk = value >> 10; + } else { + resultk = 0xffffffff; + } + return resultk; +} + + +struct acpi_srat_mem_state { + unsigned long current; +}; + +void set_srat_mem(void *gp, struct device *dev, struct resource *res) +{ + struct acpi_srat_mem_state *state = gp; + unsigned long basek, sizek; + basek = resk(res->base); + sizek = resk(res->size); + + printk_debug("set_srat_mem: dev %s, res->index=%04x startk=%08x, sizek=%08x\n", + dev_path(dev), res->index, basek, sizek); + /* + 0-640K must be on node 0 + next range is from 1M--- + So will cut off before 1M in the mem range + */ + if((basek+sizek)<1024) return; + + if(basek<1024) { + sizek -= 1024 - basek; + basek = 1024; + } + + // need to figure out NV + state->current += acpi_create_srat_mem((acpi_srat_mem_t *)state->current, (res->index & 0xf), basek, sizek, 1); +} + + +unsigned long acpi_fill_srat(unsigned long current) +{ + struct acpi_srat_mem_state srat_mem_state; + + /* create all subtables for processors */ + current = acpi_create_srat_lapics(current); + + /* create all subteble for memory range */ + + /* 0-640K must be on node 0 */ + current += acpi_create_srat_mem((acpi_srat_mem_t *)current, 0, 0, 640, 1);//enable + + srat_mem_state.current = current; + search_global_resources( + IORESOURCE_MEM | IORESOURCE_CACHEABLE, IORESOURCE_MEM | IORESOURCE_CACHEABLE, + set_srat_mem, &srat_mem_state); + + current = srat_mem_state.current; + return current; +} + +unsigned long acpi_fill_slit(unsigned long current) +{ + /* need to find out the node num at first */ + /* fill the first 8 byte with that num */ + /* fill the next num*num byte with distance, local is 10, 1 hop mean 20, and 2 hop with 30.... */ + + struct sys_info *sysinfox = (struct sys_info *)((CONFIG_LB_MEM_TOPK<<10) - DCACHE_RAM_GLOBAL_VAR_SIZE); + u8 *ln = sysinfox->ln; + + + u8 *p = (u8 *)current; + int nodes = sysconf.nodes; + int i,j; + u32 hops; + + memset(p, 0, 8+nodes*nodes); + *p = (u8) nodes; + p += 8; + + for(i=0;i<nodes;i++) { + for(j=0;j<nodes; j++) { + if(i==j) { + p[i*nodes+j] = 10; + } else { + hops = (((ln[i*NODE_NUMS+j]>>4) & 0x7)+1); + p[i*nodes+j] = hops * 2 + 10; + } + } + } + + current += 8+nodes*nodes; + return current; +} + + +// moved from mb acpi_tables.c +static void intx_to_stream(u32 val, u32 len, u8 *dest) +{ + int i; + for(i=0;i<len;i++) { + *(dest+i) = (val >> (8*i)) & 0xff; + } +} + + +static void int_to_stream(u32 val, u8 *dest) +{ + return intx_to_stream(val, 4, dest); +} + + +// used by acpi_tables.h +void update_ssdt(void *ssdt) +{ + u8 *BUSN; + u8 *MMIO; + u8 *PCIO; + u8 *SBLK; + u8 *TOM1; + u8 *SBDN; + u8 *HCLK; + u8 *HCDN; + u8 *CBST; + u8 *CBBX; + u8 *CBS2; + u8 *CBB2; + + + int i; + u32 dword; + msr_t msr; + + // the offset could be different if have different HC_NUMS, and HC_POSSIBLE_NUM and ssdt.asl + BUSN = ssdt+0x3b; //+5 will be next BUSN + MMIO = ssdt+0xe4; //+5 will be next MMIO + PCIO = ssdt+0x36d; //+5 will be next PCIO + SBLK = ssdt+0x4b2; // one byte + TOM1 = ssdt+0x4b9; // + SBDN = ssdt+0x4c3;// + HCLK = ssdt+0x4d1; //+5 will be next HCLK + HCDN = ssdt+0x57a; //+5 will be next HCDN + CBBX = ssdt+0x61f; // + CBST = ssdt+0x626; + CBB2 = ssdt+0x62d; // + CBS2 = ssdt+0x634; + + for(i=0;i<HC_NUMS;i++) { + dword = sysconf.ht_c_conf_bus[i]; + int_to_stream(dword, BUSN+i*5); + } + + for(i=0;i<(HC_NUMS*2);i++) { // FIXME: change to more chain + dword = sysconf.conf_mmio_addrx[i]; //base + int_to_stream(dword, MMIO+(i*2)*5); + dword = sysconf.conf_mmio_addr[i]; //mask + int_to_stream(dword, MMIO+(i*2+1)*5); + } + for(i=0;i<HC_NUMS;i++) { // FIXME: change to more chain + dword = sysconf.conf_io_addrx[i]; + int_to_stream(dword, PCIO+(i*2)*5); + dword = sysconf.conf_io_addr[i]; + int_to_stream(dword, PCIO+(i*2+1)*5); + } + + *SBLK = (u8)(sysconf.sblk); + + msr = rdmsr(TOP_MEM); + int_to_stream(msr.lo, TOM1); + + int_to_stream(sysconf.sbdn, SBDN); + + for(i=0;i<sysconf.hc_possible_num;i++) { + int_to_stream(sysconf.pci1234[i], HCLK + i*5); + int_to_stream(sysconf.hcdn[i], HCDN + i*5); + } + for(i=sysconf.hc_possible_num; i<HC_POSSIBLE_NUM; i++) { // in case we set array size to other than 8 + int_to_stream(0x00000000, HCLK + i*5); + int_to_stream(0x20202020, HCDN + i*5); + } + + *CBBX = (u8)(CBB); + + if(CBB == 0xff) { + *CBST = (u8) (0x0f); + } else { + if((sysconf.pci1234[0] >> 12) & 0xff) { //sb chain on other than bus 0 + *CBST = (u8) (0x0f); + } + else { + *CBST = (u8) (0x00); + } + } + + if((CBB == 0xff) && (sysconf.nodes>32)) { + *CBS2 = 0x0f; + *CBB2 = (u8)(CBB-1); + } else { + *CBS2 = 0x00; + *CBB2 = 0x00; + } + +} + + +void update_sspr(void *sspr, u32 nodeid, u32 cpuindex) +{ + u8 *CPU; + u8 *CPUIN; + u8 *COREFREQ; + u8 *POWER; + u8 *TRANSITION_LAT; + u8 *BUSMASTER_LAT; + u8 *CONTROL; + u8 *STATUS; + unsigned offset = 0x94 - 0x7f; + int i; + + CPU = sspr + 0x38; + CPUIN = sspr + 0x3a; + + COREFREQ = sspr + 0x7f; //2 byte + POWER = sspr + 0x82; //3 bytes + TRANSITION_LAT = sspr + 0x87; //two bytes + BUSMASTER_LAT = sspr + 0x8a; //two bytes + CONTROL = sspr + 0x8d; + STATUS = sspr + 0x8f; + + sprintf(CPU, "%02x", (u8)cpuindex); + *CPUIN = (u8) cpuindex; + + for(i=0;i<sysconf.p_state_num;i++) { + struct p_state_t *p_state = &sysconf.p_state[nodeid * 5 + i]; + intx_to_stream(COREFREQ + i*offset, 2, p_state->corefreq); + intx_to_stream(POWER + i*offset, 3, p_state->power); + intx_to_stream(TRANSITION_LAT + i*offset, 2, p_state->transition_lat); + intx_to_stream(BUSMASTER_LAT + i*offset, 2, p_state->busmaster_lat); + *((u8 *)(CONTROL + i*offset)) =(u8) p_state->control; + *((u8 *)(STATUS + i*offset)) =(u8) p_state->status; + } +} + +extern unsigned char AmlCode_sspr5[]; +extern unsigned char AmlCode_sspr4[]; +extern unsigned char AmlCode_sspr3[]; +extern unsigned char AmlCode_sspr2[]; +extern unsigned char AmlCode_sspr1[]; + +/* fixme: find one good way for different p_state_num */ +unsigned long acpi_add_ssdt_pstates(acpi_rsdt_t *rsdt, unsigned long current) +{ + device_t cpu; + int cpu_index = 0; + + acpi_header_t *ssdt; + + if(!sysconf.p_state_num) return current; + + u8 *AmlCode_sspr; + switch(sysconf.p_state_num) { + case 1: AmlCode_sspr = AmlCode_sspr1; break; + case 2: AmlCode_sspr = AmlCode_sspr2; break; + case 3: AmlCode_sspr = AmlCode_sspr3; break; + case 4: AmlCode_sspr = AmlCode_sspr4; break; + default: AmlCode_sspr = AmlCode_sspr5; break; + } + + for(cpu = all_devices; cpu; cpu = cpu->next) { + if ((cpu->path.type != DEVICE_PATH_APIC) || + (cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER)) { + continue; + } + if (!cpu->enabled) { + continue; + } + printk_debug("ACPI: pstate cpu_index=%02x, node_id=%02x, core_id=%02x\n", cpu_index, cpu->path.u.apic.node_id, cpu->path.u.apic.core_id); + + current = ( current + 0x0f) & -0x10; + ssdt = (acpi_header_t *)current; + current += ((acpi_header_t *)AmlCode_sspr)->length; + memcpy((void *)ssdt, (void *)AmlCode_sspr, ((acpi_header_t *)AmlCode_sspr)->length); + update_sspr((void*)ssdt,cpu->path.u.apic.node_id, cpu_index); + /* recalculate checksum */ + ssdt->checksum = 0; + ssdt->checksum = acpi_checksum((unsigned char *)ssdt,ssdt->length); + acpi_add_table(rsdt,ssdt); + + cpu_index++; + } + return current; +} diff --git a/src/northbridge/amd/amdfam10/amdfam10_conf.c b/src/northbridge/amd/amdfam10/amdfam10_conf.c new file mode 100644 index 0000000000..79d532fa3b --- /dev/null +++ b/src/northbridge/amd/amdfam10/amdfam10_conf.c @@ -0,0 +1,874 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if defined(__ROMCC__) +typedef struct sys_info sys_info_conf_t; +#else +typedef struct amdfam10_sysconf_t sys_info_conf_t; +#endif + +struct dram_base_mask_t { + u32 base; //[47:27] at [28:8] + u32 mask; //[47:27] at [28:8] and enable at bit 0 +}; + +static struct dram_base_mask_t get_dram_base_mask(u32 nodeid) +{ + device_t dev; + struct dram_base_mask_t d; +#if defined(__ROMCC__) + dev = PCI_DEV(CBB, CDB, 1); +#else + dev = __f1_dev[0]; +#endif + +#if EXT_CONF_SUPPORT == 1 + // I will use ext space only for simple + pci_write_config32(dev, 0x110, nodeid | (1<<28)); // [47:27] at [28:8] + d.mask = pci_read_config32(dev, 0x114); // enable is bit 0 + pci_write_config32(dev, 0x110, nodeid | (0<<28)); + d.base = pci_read_config32(dev, 0x114) & 0x1fffff00; //[47:27] at [28:8]; +#else + u32 temp; + temp = pci_read_config32(dev, 0x44 + (nodeid << 3)); //[39:24] at [31:16] + d.mask = ((temp & 0xfff80000)>>(8+3)); // mask out DramMask [26:24] too + temp = pci_read_config32(dev, 0x144 + (nodeid <<3)) & 0xff; //[47:40] at [7:0] + d.mask |= temp<<21; + + temp = pci_read_config32(dev, 0x40 + (nodeid << 3)); //[39:24] at [31:16] + d.mask |= (temp & 1); // enable bit + + d.base = ((temp & 0xfff80000)>>(8+3)); // mask out DramBase [26:24) too + temp = pci_read_config32(dev, 0x140 + (nodeid <<3)) & 0xff; //[47:40] at [7:0] + d.base |= temp<<21; +#endif + return d; +} + +static void set_dram_base_mask(u32 nodeid, struct dram_base_mask_t d, u32 nodes) +{ + u32 i; + device_t dev; +#if EXT_CONF_SUPPORT == 1 + // I will use ext space only for simple + u32 d_base_i, d_base_d, d_mask_i, d_mask_d; + d_base_i = nodeid | (0<<28); + d_base_d = d.base | nodeid; //[47:27] at [28:8]; + d_mask_i = nodeid | (1<<28); // [47:27] at [28:8] + d_mask_d = d.mask; // enable is bit 0 + +#else + u32 d_base_lo, d_base_hi, d_mask_lo, d_mask_hi; + u32 d_base_lo_reg, d_base_hi_reg, d_mask_lo_reg, d_mask_hi_reg; + d_mask_lo = (((d.mask<<(8+3))|(0x07<<16)) & 0xffff0000)|nodeid; // need to fill DramMask[26:24] with ones + d_mask_hi = (d.mask>>21) & 0xff; + d_base_lo = ((d.base<<(8+3)) & 0xffff0000); + if(d.mask & 1) d_base_lo |= 3; + d_base_hi = (d.base>>21) & 0xff; + d_mask_lo_reg = 0x44+(nodeid<<3); + d_mask_hi_reg = 0x144+(nodeid<<3); + d_base_lo_reg = 0x40+(nodeid<<3); + d_base_hi_reg = 0x140+(nodeid<<3); +#endif + + for(i=0;i<nodes;i++) { +#if defined(__ROMCC__) + dev = NODE_PCI(i, 1); +#else + dev = __f1_dev[i]; +#endif + +#if EXT_CONF_SUPPORT == 1 + // I will use ext space only for simple + pci_write_config32(dev, 0x110, d_base_i); + pci_write_config32(dev, 0x114, d_base_d); //[47:27] at [28:8]; + pci_write_config32(dev, 0x110, d_mask_i); // [47:27] at [28:8] + pci_write_config32(dev, 0x114, d_mask_d); // enable is bit 0 +#else + pci_write_config32(dev, d_mask_lo_reg, d_mask_lo); // need to fill DramMask[26:24] with ones + pci_write_config32(dev, d_mask_hi_reg, d_mask_hi); + pci_write_config32(dev, d_base_lo_reg, d_base_lo); + pci_write_config32(dev, d_base_hi_reg, d_base_hi); +#endif + } + +#if defined(__ROMCC__) + dev = NODE_PCI(nodeid, 1); +#else + dev = __f1_dev[nodeid]; +#endif + pci_write_config32(dev, 0x120, d.base>>8); + pci_write_config32(dev, 0x124, d.mask>>8); + +} + + +static void set_DctSelBaseAddr(u32 i, u32 sel_m) +{ + device_t dev; +#if defined(__ROMCC__) + dev = NODE_PCI(i, 2); +#else + dev = __f2_dev[i]; +#endif + u32 dcs_lo; + dcs_lo = pci_read_config32(dev, DRAM_CTRL_SEL_LOW); + dcs_lo &= ~(DCSL_DctSelBaseAddr_47_27_MASK<<DCSL_DctSelBaseAddr_47_27_SHIFT); + dcs_lo |= (sel_m<<(20+DCSL_DctSelBaseAddr_47_27_SHIFT-27)); + pci_write_config32(dev, DRAM_CTRL_SEL_LOW, dcs_lo); + +} + + +static u32 get_DctSelBaseAddr(u32 i) +{ + device_t dev; +#if defined(__ROMCC__) + dev = NODE_PCI(i, 2); +#else + dev = __f2_dev[i]; +#endif + u32 sel_m; + u32 dcs_lo; + dcs_lo = pci_read_config32(dev, DRAM_CTRL_SEL_LOW); + dcs_lo &= DCSL_DctSelBaseAddr_47_27_MASK<<DCSL_DctSelBaseAddr_47_27_SHIFT; + sel_m = dcs_lo>>(20+DCSL_DctSelBaseAddr_47_27_SHIFT-27); + return sel_m; +} + + +static void set_DctSelHiEn(u32 i, u32 val) +{ + device_t dev; +#if defined(__ROMCC__) + dev = NODE_PCI(i, 2); +#else + dev = __f2_dev[i]; +#endif + u32 dcs_lo; + dcs_lo = pci_read_config32(dev, DRAM_CTRL_SEL_LOW); + dcs_lo &= ~(7); + dcs_lo |= (val & 7); + pci_write_config32(dev, DRAM_CTRL_SEL_LOW, dcs_lo); + +} + +static u32 get_DctSelHiEn(u32 i) +{ + device_t dev; +#if defined(__ROMCC__) + dev = NODE_PCI(i, 2); +#else + dev = __f2_dev[i]; +#endif + u32 dcs_lo; + dcs_lo = pci_read_config32(dev, DRAM_CTRL_SEL_LOW); + dcs_lo &= 7; + return dcs_lo; + +} + +static void set_DctSelBaseOffset(u32 i, u32 sel_off_m) +{ + device_t dev; +#if defined(__ROMCC__) + dev = NODE_PCI(i, 2); +#else + dev = __f2_dev[i]; +#endif + u32 dcs_hi; + dcs_hi = pci_read_config32(dev, DRAM_CTRL_SEL_HIGH); + dcs_hi &= ~(DCSH_DctSelBaseOffset_47_26_MASK<<DCSH_DctSelBaseOffset_47_26_SHIFT); + dcs_hi |= sel_off_m<<(20+DCSH_DctSelBaseOffset_47_26_SHIFT-26); + pci_write_config32(dev, DRAM_CTRL_SEL_HIGH, dcs_hi); + +} + +static u32 get_DctSelBaseOffset(u32 i) +{ + device_t dev; +#if defined(__ROMCC__) + dev = NODE_PCI(i, 2); +#else + dev = __f2_dev[i]; +#endif + u32 sel_off_m; + u32 dcs_hi; + dcs_hi = pci_read_config32(dev, DRAM_CTRL_SEL_HIGH); + dcs_hi &= DCSH_DctSelBaseOffset_47_26_MASK<<DCSH_DctSelBaseOffset_47_26_SHIFT; + sel_off_m = dcs_hi>>(20+DCSH_DctSelBaseOffset_47_26_SHIFT-26); + return sel_off_m; +} +#if CONFIG_AMDMCT == 0 + +static u32 get_one_DCT(struct mem_info *meminfo) +{ + u32 one_DCT = 1; + if(meminfo->is_Width128) { + one_DCT = 1; + } else { + u32 dimm_mask = meminfo->dimm_mask; + if((dimm_mask >> DIMM_SOCKETS) && (dimm_mask & ((1<<DIMM_SOCKETS)-1))) { + one_DCT = 0; + } + } + + return one_DCT; +} +#endif +#if HW_MEM_HOLE_SIZEK != 0 + +static u32 hoist_memory(u32 hole_startk, u32 i, u32 one_DCT, u32 nodes) +{ + u32 ii; + u32 carry_over; + device_t dev; + struct dram_base_mask_t d; + u32 sel_m; + u32 sel_hi_en; + u32 hoist; + + + carry_over = (4*1024*1024) - hole_startk; + + for(ii=nodes - 1;ii>i;ii--) { + d = get_dram_base_mask(ii); + if(!(d.mask & 1)) continue; + d.base += (carry_over>>9); + d.mask += (carry_over>>9); + set_dram_base_mask(ii, d, nodes); + + if(get_DctSelHiEn(ii) & 1) { + sel_m = get_DctSelBaseAddr(ii); + sel_m += carry_over>>10; + set_DctSelBaseAddr(ii, sel_m); + } + + } + d = get_dram_base_mask(i); + d.mask += (carry_over>>9); + set_dram_base_mask(i,d, nodes); +#if defined(__ROMCC__) + dev = NODE_PCI(i, 1); +#else + dev = __f1_dev[i]; +#endif + sel_hi_en = get_DctSelHiEn(i); + if(sel_hi_en & 1) { + sel_m = get_DctSelBaseAddr(i); + } + if(d.base == (hole_startk>>9)) { + //don't need set memhole here, because hole off set will be 0, overflow + //so need to change base reg instead, new basek will be 4*1024*1024 + d.base = (4*1024*1024)>>9; + set_dram_base_mask(i, d, nodes); + + if(sel_hi_en & 1) { + sel_m += carry_over>>10; + set_DctSelBaseAddr(i, sel_m); + } + } else { + hoist = /* hole start address */ + ((hole_startk << 10) & 0xff000000) + + /* enable */ + 1; + if(one_DCT||(sel_m>=(hole_startk>>10))) { //one DCT or hole in DCT0 + hoist += + /* hole address to memory controller address */ + ((((d.base<<9) + carry_over) >> 6) & 0x0000ff00) ; + + if(sel_hi_en & 1) { + sel_m += (carry_over>>10); + set_DctSelBaseAddr(i, sel_m); + set_DctSelBaseOffset(i, sel_m); + } + } else { // hole in DCT1 range + hoist += + /* hole address to memory controller address */ + ((((sel_m<<10) + carry_over) >> 6) & 0x0000ff00) ; + // don't need to update DctSelBaseAddr + if(sel_hi_en & 1) { + set_DctSelBaseOffset(i, sel_m); + } + } + pci_write_config32(dev, 0xf0, hoist); + + } + + return carry_over; +} +#endif + + +#if EXT_CONF_SUPPORT +static void set_addr_map_reg_4_6_in_one_node(u32 nodeid, u32 cfg_map_dest, + u32 busn_min, u32 busn_max, + u32 type) +{ + device_t dev; + u32 i; + u32 tempreg; + u32 index_min, index_max; + u32 dest_min, dest_max; + index_min = busn_min>>2; dest_min = busn_min - (index_min<<2); + index_max = busn_max>>2; dest_max = busn_max - (index_max<<2); + + // three case: index_min==index_max, index_min+1=index_max; index_min+1<index_max +#if defined(__ROMCC__) + dev = NODE_PCI(nodeid, 1); +#else + dev = __f1_dev[nodeid]; +#endif + if(index_min== index_max) { + pci_write_config32(dev, 0x110, index_min | (type<<28)); + tempreg = pci_read_config32(dev, 0x114); + for(i=dest_min; i<=dest_max; i++) { + tempreg &= ~(0xff<<(i*8)); + tempreg |= (cfg_map_dest<<(i*8)); + } + pci_write_config32(dev, 0x110, index_min | (type<<28)); // do i need to write it again + pci_write_config32(dev, 0x114, tempreg); + } else if(index_min<index_max) { + pci_write_config32(dev, 0x110, index_min | (type<<28)); + tempreg = pci_read_config32(dev, 0x114); + for(i=dest_min; i<=3; i++) { + tempreg &= ~(0xff<<(i*8)); + tempreg |= (cfg_map_dest<<(i*8)); + } + pci_write_config32(dev, 0x110, index_min | (type<<28)); // do i need to write it again + pci_write_config32(dev, 0x114, tempreg); + + pci_write_config32(dev, 0x110, index_max | (type<<28)); + tempreg = pci_read_config32(dev, 0x114); + for(i=0; i<=dest_max; i++) { + tempreg &= ~(0xff<<(i*8)); + tempreg |= (cfg_map_dest<<(i*8)); + } + pci_write_config32(dev, 0x110, index_max | (type<<28)); // do i need to write it again + pci_write_config32(dev, 0x114, tempreg); + if((index_max-index_min)>1) { + tempreg = 0; + for(i=0; i<=3; i++) { + tempreg &= ~(0xff<<(i*8)); + tempreg |= (cfg_map_dest<<(i*8)); + } + for(i=index_min+1; i<index_max;i++) { + pci_write_config32(dev, 0x110, i | (type<<28)); + pci_write_config32(dev, 0x114, tempreg); + } + } + } +} +#endif + +static void set_config_map_reg(u32 nodeid, u32 linkn, u32 ht_c_index, + u32 busn_min, u32 busn_max, u32 segbit, + u32 nodes) +{ + u32 tempreg; + u32 i; + device_t dev; + + busn_min>>=segbit; + busn_max>>=segbit; + +#if EXT_CONF_SUPPORT + if(ht_c_index < 4) { +#endif + tempreg = 3 | ((nodeid&0xf)<<4) | ((nodeid & 0x30)<<(12-4))|(linkn<<8)|((busn_min & 0xff)<<16)|((busn_max&0xff)<<24); + for(i=0; i<nodes; i++) { + #if defined(__ROMCC__) + dev = NODE_PCI(i, 1); + #else + dev = __f1_dev[i]; + #endif + pci_write_config32(dev, 0xe0 + ht_c_index * 4, tempreg); + } +#if EXT_CONF_SUPPORT + + return; + } + + // if ht_c_index > 3, We should use extend space x114_x6 + u32 cfg_map_dest; + u32 j; + + // for nodeid at first + cfg_map_dest = (1<<7) | (1<<6) | (linkn<<0); + + set_addr_map_reg_4_6_in_one_node(nodeid, cfg_map_dest, busn_min, busn_max, 6); + + // all other nodes + cfg_map_dest = (1<<7) | (0<<6) | (nodeid<<0); + for(j = 0; j< nodes; j++) { + if(j== nodeid) continue; + set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, busn_min, busn_max, 6); + } +#endif +} + +static void clear_config_map_reg(u32 nodeid, u32 linkn, u32 ht_c_index, + u32 busn_min, u32 busn_max, u32 nodes) +{ + u32 i; + device_t dev; + +#if EXT_CONF_SUPPORT + if(ht_c_index<4) { +#endif + for(i=0; i<nodes; i++) { + #if defined(__ROMCC__) + dev = NODE_PCI(i, 1); + #else + dev = __f1_dev[i]; + #endif + pci_write_config32(dev, 0xe0 + ht_c_index * 4, 0); + } +#if EXT_CONF_SUPPORT + return; + } + + // if hc_c_index >3, We should use busn_min and busn_max to clear extend space + u32 cfg_map_dest; + u32 j; + + + // all nodes + cfg_map_dest = 0; + for(j = 0; j< nodes; j++) { + set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, busn_min, busn_max, 6); + } +#endif + +} + +#if PCI_BUS_SEGN_BITS +static u32 check_segn(device_t dev, u32 segbusn, u32 nodes, + sys_info_conf_t *sysinfo) +{ + //check segbusn here, We need every node have the same segn + if((segbusn & 0xff)>(0xe0-1)) {// use next segn + u32 segn = (segbusn >> 8) & 0x0f; + segn++; + segbusn = segn<<8; + } + if(segbusn>>8) { + u32 val; + val = pci_read_config32(dev, 0x160); + val &= ~(0xf<<25); + val |= (segbusn & 0xf00)<<(25-8); + pci_write_config32(dev, 0x160, val); + } + + return segbusn; +} +#endif + +#if defined(__ROMCC__) +static void set_ht_c_io_addr_reg(u32 nodeid, u32 linkn, u32 ht_c_index, + u32 io_min, u32 io_max, u32 nodes) +{ + u32 i; + u32 tempreg; + device_t dev; + +#if EXT_CONF_SUPPORT + if(ht_c_index<4) { +#endif + /* io range allocation */ + tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) | ((io_max&0xf0)<<(12-4)); //limit + for(i=0; i<nodes; i++) { + #if defined(__ROMCC__) + dev = NODE_PCI(i, 1); + #else + dev = __f1_dev[i]; + #endif + pci_write_config32(dev, 0xC4 + ht_c_index * 8, tempreg); + } + tempreg = 3 /*| ( 3<<4)*/ | ((io_min&0xf0)<<(12-4)); //base :ISA and VGA ? + for(i=0; i<nodes; i++){ + #if defined(__ROMCC__) + dev = NODE_PCI(i, 1); + #else + dev = __f1_dev[i]; + #endif + pci_write_config32(dev, 0xC0 + ht_c_index * 8, tempreg); + } +#if EXT_CONF_SUPPORT + return; + } + + u32 cfg_map_dest; + u32 j; + + // if ht_c_index > 3, We should use extend space + + if(io_min>io_max) return; + + // for nodeid at first + cfg_map_dest = (1<<7) | (1<<6) | (linkn<<0); + + set_addr_map_reg_4_6_in_one_node(nodeid, cfg_map_dest, io_min, io_max, 4); + + // all other nodes + cfg_map_dest = (1<<7) | (0<<6) | (nodeid<<0); + for(j = 0; j< nodes; j++) { + if(j== nodeid) continue; + set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, io_min, io_max, 4); + } +#endif +} + + +static void clear_ht_c_io_addr_reg(u32 nodeid, u32 linkn, u32 ht_c_index, + u32 io_min, u32 io_max, u32 nodes) +{ + u32 i; + device_t dev; +#if EXT_CONF_SUPPORT + if(ht_c_index<4) { +#endif + /* io range allocation */ + for(i=0; i<nodes; i++) { + #if defined(__ROMCC__) + dev = NODE_PCI(i, 1); + #else + dev = __f1_dev[i]; + #endif + pci_write_config32(dev, 0xC4 + ht_c_index * 8, 0); + pci_write_config32(dev, 0xC0 + ht_c_index * 8, 0); + } +#if EXT_CONF_SUPPORT + return; + } + // : if hc_c_index > 3, We should use io_min, io_max to clear extend space + u32 cfg_map_dest; + u32 j; + + + // all nodes + cfg_map_dest = 0; + for(j = 0; j< nodes; j++) { + set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, io_min, io_max, 4); + } +#endif +} +#endif + + +static void re_set_all_config_map_reg(u32 nodes, u32 segbit, + sys_info_conf_t *sysinfo) +{ + u32 ht_c_index; + device_t dev; + + set_config_map_reg(0, sysinfo->sblk, 0, 0, sysinfo->ht_c_conf_bus[0]>>20, segbit, nodes); + + /* clean others */ + for(ht_c_index=1;ht_c_index<4; ht_c_index++) { + u32 i; + for(i=0; i<nodes; i++) { + #if defined(__ROMCC__) + dev = NODE_PCI(i, 1); + #else + dev = __f1_dev[i]; + #endif + pci_write_config32(dev, 0xe0 + ht_c_index * 4, 0); + } + } +#if EXT_CONF_SUPPORT + u32 j; + // clear the extend space + for(j = 0; j< nodes; j++) { + set_addr_map_reg_4_6_in_one_node(j,0, 0, 0xff, 6); + } +#endif + + for(ht_c_index = 1; ht_c_index<sysinfo->ht_c_num; ht_c_index++) { + u32 nodeid, linkn; + u32 busn_max; + u32 busn_min; + nodeid = (sysinfo->ht_c_conf_bus[ht_c_index] >> 2) & 0x3f; + linkn = (sysinfo->ht_c_conf_bus[ht_c_index]>>8) & 0x7; + busn_max = sysinfo->ht_c_conf_bus[ht_c_index]>>20; + busn_min = (sysinfo->ht_c_conf_bus[ht_c_index]>>12) & 0xff; + busn_min |= busn_max & 0xf00; + set_config_map_reg(nodeid, linkn, ht_c_index, busn_min, busn_max, segbit, nodes); + } + +} + + +static u32 get_ht_c_index(u32 nodeid, u32 linkn, sys_info_conf_t *sysinfo) +{ + u32 tempreg; + u32 ht_c_index = 0; + +#if 0 + tempreg = 3 | ((nodeid & 0xf) <<4) | ((nodeid & 0x30)<<(12-4)) | (linkn<<8); + + for(ht_c_index=0;ht_c_index<4; ht_c_index++) { + reg = pci_read_config32(PCI_DEV(CBB, CDB, 1), 0xe0 + ht_c_index * 4); + if(((reg & 0xffff) == 0x0000)) { /*found free*/ + break; + } + } +#endif + tempreg = 3 | ((nodeid & 0x3f)<<2) | (linkn<<8); + for(ht_c_index=0; ht_c_index<32; ht_c_index++) { + if(((sysinfo->ht_c_conf_bus[ht_c_index] & 0xfff) == tempreg)){ + return ht_c_index; + } + } + + for(ht_c_index=0; ht_c_index<32; ht_c_index++) { + if((sysinfo->ht_c_conf_bus[ht_c_index] == 0)){ + return ht_c_index; + } + } + + return -1; + +} + +static void store_ht_c_conf_bus(u32 nodeid, u32 linkn, u32 ht_c_index, + u32 busn_min, u32 busn_max, + sys_info_conf_t *sysinfo) +{ + u32 val; + val = 3 | ((nodeid & 0x3f)<<2) | (linkn<<8); + sysinfo->ht_c_conf_bus[ht_c_index] = val | ((busn_min & 0xff) <<12) | (busn_max<<20); // same node need segn are same + +} + + +static void set_BusSegmentEn(u32 node, u32 segbit) +{ +#if PCI_BUS_SEGN_BITS + u32 dword; + device_t dev; + +#if defined(__ROMCC__) + dev = NODE_PCI(node, 0); +#else + dev = __f0_dev[node]; +#endif + + dword = pci_read_config32(dev, 0x68); + dword &= ~(7<<28); + dword |= (segbit<<28); /* bus segment enable */ + pci_write_config32(dev, 0x68, dword); +#endif +} + +#if !defined(__ROMCC__) +static u32 get_io_addr_index(u32 nodeid, u32 linkn) +{ + u32 index; + + for(index=0; index<256; index++) { + if((sysconf.conf_io_addrx[index+4] == 0)){ + sysconf.conf_io_addr[index+4] = (nodeid & 0x3f) ; + sysconf.conf_io_addrx[index+4] = 1 | ((linkn & 0x7)<<4); + return index; + } + } + + return 0; + +} + +static u32 get_mmio_addr_index(u32 nodeid, u32 linkn) +{ + u32 index; + + + for(index=0; index<64; index++) { + if((sysconf.conf_mmio_addrx[index+8] == 0)){ + sysconf.conf_mmio_addr[index+8] = (nodeid & 0x3f) ; + sysconf.conf_mmio_addrx[index+8] = 1 | ((linkn & 0x7)<<4); + return index; + } + } + + return 0; + +} + +static void store_conf_io_addr(u32 nodeid, u32 linkn, u32 reg, u32 index, + u32 io_min, u32 io_max) +{ + u32 val; +#if EXT_CONF_SUPPORT + if(reg!=0x110) { +#endif + /* io range allocation */ + index = (reg-0xc0)>>3; +#if EXT_CONF_SUPPORT + } else { + index+=4; + } +#endif + + val = (nodeid & 0x3f); // 6 bits used + sysconf.conf_io_addr[index] = val | ((io_max<<8) & 0xfffff000); //limit : with nodeid + val = 3 | ((linkn & 0x7)<<4) ; // 8 bits used + sysconf.conf_io_addrx[index] = val | ((io_min<<8) & 0xfffff000); // base : with enable bit + + if( sysconf.io_addr_num<(index+1)) + sysconf.io_addr_num = index+1; +} + + +static void store_conf_mmio_addr(u32 nodeid, u32 linkn, u32 reg, u32 index, + u32 mmio_min, u32 mmio_max) +{ + u32 val; +#if EXT_CONF_SUPPORT + if(reg!=0x110) { +#endif + /* io range allocation */ + index = (reg-0x80)>>3; +#if EXT_CONF_SUPPORT + } else { + index+=8; + } +#endif + + val = (nodeid & 0x3f) ; // 6 bits used + sysconf.conf_mmio_addr[index] = val | (mmio_max & 0xffffff00); //limit : with nodeid and linkn + val = 3 | ((linkn & 0x7)<<4) ; // 8 bits used + sysconf.conf_mmio_addrx[index] = val | (mmio_min & 0xffffff00); // base : with enable bit + + if( sysconf.mmio_addr_num<(index+1)) + sysconf.mmio_addr_num = index+1; +} + + +static void set_io_addr_reg(device_t dev, u32 nodeid, u32 linkn, u32 reg, + u32 io_min, u32 io_max) +{ + + u32 i; + u32 tempreg; +#if EXT_CONF_SUPPORT + if(reg!=0x110) { +#endif + /* io range allocation */ + tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) | ((io_max&0xf0)<<(12-4)); //limit + for(i=0; i<sysconf.nodes; i++) + pci_write_config32(__f1_dev[i], reg+4, tempreg); + + tempreg = 3 /*| ( 3<<4)*/ | ((io_min&0xf0)<<(12-4)); //base :ISA and VGA ? +#if 0 + // FIXME: can we use VGA reg instead? + if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) { + printk_spew("%s, enabling legacy VGA IO forwarding for %s link %s\n", + __func__, dev_path(dev), link); + tempreg |= PCI_IO_BASE_VGA_EN; + } + if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) { + tempreg |= PCI_IO_BASE_NO_ISA; + } +#endif + for(i=0; i<sysconf.nodes; i++) + pci_write_config32(__f1_dev[i], reg, tempreg); +#if EXT_CONF_SUPPORT + return; + } + + u32 cfg_map_dest; + u32 j; + // if ht_c_index > 3, We should use extend space + if(io_min>io_max) return; + // for nodeid at first + cfg_map_dest = (1<<7) | (1<<6) | (linkn<<0); + + set_addr_map_reg_4_6_in_one_node(nodeid, cfg_map_dest, io_min, io_max, 4); + + // all other nodes + cfg_map_dest = (1<<7) | (0<<6) | (nodeid<<0); + for(j = 0; j< sysconf.nodes; j++) { + if(j== nodeid) continue; + set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, io_min, io_max, 4); + } +#endif + +} +static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes) +{ + + u32 i; + u32 tempreg; +#if EXT_CONF_SUPPORT + if(reg!=0x110) { +#endif + /* io range allocation */ + tempreg = (nodeid&0xf) | (linkn<<4) | (mmio_max&0xffffff00); //limit + for(i=0; i<nodes; i++) + pci_write_config32(__f1_dev[i], reg+4, tempreg); + tempreg = 3 | (nodeid & 0x30) | (mmio_min&0xffffff00); + for(i=0; i<sysconf.nodes; i++) + pci_write_config32(__f1_dev[i], reg, tempreg); +#if EXT_CONF_SUPPORT + return; + } + + device_t dev; + u32 j; + // if ht_c_index > 3, We should use extend space + // for nodeid at first + u32 enable; + + if(mmio_min>mmio_max) { + return; + } + + enable = 1; + + dev = __f1_dev[nodeid]; + tempreg = ((mmio_min>>3) & 0x1fffff00)| (1<<6) | (linkn<<0); + pci_write_config32(dev, 0x110, index | (2<<28)); + pci_write_config32(dev, 0x114, tempreg); + + tempreg = ((mmio_max>>3) & 0x1fffff00) | enable; + pci_write_config32(dev, 0x110, index | (3<<28)); + pci_write_config32(dev, 0x114, tempreg); + + + // all other nodes + tempreg = ((mmio_min>>3) & 0x1fffff00) | (0<<6) | (nodeid<<0); + for(j = 0; j< sysconf.nodes; j++) { + if(j== nodeid) continue; + dev = __f1_dev[j]; + pci_write_config32(dev, 0x110, index | (2<<28)); + pci_write_config32(dev, 0x114, tempreg); + } + + tempreg = ((mmio_max>>3) & 0x1fffff00) | enable; + for(j = 0; j< sysconf.nodes; j++) { + if(j==nodeid) continue; + dev = __f1_dev[j]; + pci_write_config32(dev, 0x110, index | (3<<28)); + pci_write_config32(dev, 0x114, tempreg); + } +#endif +} + +#endif diff --git a/src/northbridge/amd/amdfam10/amdfam10_nums.h b/src/northbridge/amd/amdfam10/amdfam10_nums.h new file mode 100644 index 0000000000..016921ac68 --- /dev/null +++ b/src/northbridge/amd/amdfam10/amdfam10_nums.h @@ -0,0 +1,41 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AMDFAM10_NUMS_H + +#define AMDFAM10_NUMS_H + +#if CONFIG_MAX_PHYSICAL_CPUS > 8 + #if CONFIG_MAX_PHYSICAL_CPUS > 32 + #define NODE_NUMS 64 + #else + #define NODE_NUMS 32 + #endif +#else + #define NODE_NUMS 8 +#endif + +// max HC installed at the same time. ...could be bigger than (48+24) if we have 3x4x4 +#define HC_NUMS 32 + +//it could be more bigger +#define HC_POSSIBLE_NUM 32 + +#endif + diff --git a/src/northbridge/amd/amdfam10/amdfam10_pci.c b/src/northbridge/amd/amdfam10/amdfam10_pci.c new file mode 100644 index 0000000000..0c947268fb --- /dev/null +++ b/src/northbridge/amd/amdfam10/amdfam10_pci.c @@ -0,0 +1,73 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef AMDFAM10_PCI_C +#define AMDFAM10_PCI_C +/* bit [10,8] are dev func, bit[1,0] are dev index */ + + +static u32 pci_read_config32_index(device_t dev, u32 index_reg, u32 index) +{ + u32 dword; + + pci_write_config32(dev, index_reg, index); + dword = pci_read_config32(dev, index_reg+0x4); + return dword; +} + +static void pci_write_config32_index(device_t dev, u32 index_reg, u32 index, u32 data) +{ + + pci_write_config32(dev, index_reg, index); + + pci_write_config32(dev, index_reg + 0x4, data); + +} + +static u32 pci_read_config32_index_wait(device_t dev, u32 index_reg, u32 index) +{ + + u32 dword; + + index &= ~(1<<30); + pci_write_config32(dev, index_reg, index); + do { + dword = pci_read_config32(dev, index_reg); + } while (!(dword & (1<<31))); + dword = pci_read_config32(dev, index_reg+0x4); + return dword; +} + +static void pci_write_config32_index_wait(device_t dev, u32 index_reg, u32 index, u32 data) +{ + + u32 dword; + + pci_write_config32(dev, index_reg + 0x4, data); + index |= (1<<30); + pci_write_config32(dev, index_reg, index); + do { + dword = pci_read_config32(dev, index_reg); + } while (!(dword & (1<<31))); + +} +#endif + + diff --git a/src/northbridge/amd/amdfam10/chip.h b/src/northbridge/amd/amdfam10/chip.h new file mode 100644 index 0000000000..b11c2a4f62 --- /dev/null +++ b/src/northbridge/amd/amdfam10/chip.h @@ -0,0 +1,24 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +struct northbridge_amd_amdfam10_config +{ +}; + +extern struct chip_operations northbridge_amd_amdfam10_ops; diff --git a/src/northbridge/amd/amdfam10/debug.c b/src/northbridge/amd/amdfam10/debug.c new file mode 100644 index 0000000000..5240adfb8f --- /dev/null +++ b/src/northbridge/amd/amdfam10/debug.c @@ -0,0 +1,331 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Generic FAM10 debug code, used by mainboard specific car_auto.c + */ + +#include "amdfam10_pci.c" + +static void udelay_tsc(u32 us); + +static void print_debug_addr(const char *str, void *val) +{ +#if CACHE_AS_RAM_ADDRESS_DEBUG == 1 + printk_debug("------Address debug: %s%x------\n", str, val); +#endif +} + +static void print_debug_pci_dev(u32 dev) +{ +#if PCI_BUS_SEGN_BITS==0 + printk_debug("PCI: %02x:%02x.%02x", (dev>>20) & 0xff, (dev>>15) & 0x1f, (dev>>12) & 0x7); +#else + printk_debug("PCI: %04x:%02x:%02x.%02x", (dev>>28) & 0x0f, (dev>>20) & 0xff, (dev>>15) & 0x1f, (dev>>12) & 0x7); +#endif +} + +static void print_pci_devices(void) +{ + device_t dev; + for(dev = PCI_DEV(0, 0, 0); + dev <= PCI_DEV(0xff, 0x1f, 0x7); + dev += PCI_DEV(0,0,1)) { + u32 id; + id = pci_read_config32(dev, PCI_VENDOR_ID); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + print_debug_pci_dev(dev); + printk_debug(" %04x:%04x\n", (id & 0xffff), (id>>16)); + if(((dev>>12) & 0x07) == 0) { + u8 hdr_type; + hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); + if((hdr_type & 0x80) != 0x80) { + dev += PCI_DEV(0,0,7); + } + } + } +} + +static void print_pci_devices_on_bus(u32 busn) +{ + device_t dev; + for(dev = PCI_DEV(busn, 0, 0); + dev <= PCI_DEV(busn, 0x1f, 0x7); + dev += PCI_DEV(0,0,1)) { + u32 id; + id = pci_read_config32(dev, PCI_VENDOR_ID); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + print_debug_pci_dev(dev); + printk_debug(" %04x:%04x\n", (id & 0xffff), (id>>16)); + if(((dev>>12) & 0x07) == 0) { + u8 hdr_type; + hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); + if((hdr_type & 0x80) != 0x80) { + dev += PCI_DEV(0,0,7); + } + } + } +} + + + +static void dump_pci_device_range(u32 dev, u32 start_reg, u32 size) +{ + int i; + print_debug_pci_dev(dev); + int j; + int end = start_reg + size; + + for(i = start_reg; i < end; i+=4) { + u32 val; + if ((i & 0x0f) == 0) { + printk_debug("\n%04x:",i); + } + val = pci_read_config32(dev, i); + for(j=0;j<4;j++) { + printk_debug(" %02x", val & 0xff); + val >>= 8; + } + } + print_debug("\n"); +} +static void dump_pci_device(u32 dev) +{ + dump_pci_device_range(dev, 0, 4096); +} +static u32 pci_read_config32_index_wait(device_t dev, u32 index_reg, u32 index); +static void dump_pci_device_index_wait_range(u32 dev, u32 index_reg, u32 start, + u32 size) +{ + int i; + int end = start + size; + print_debug_pci_dev(dev); + print_debug(" -- index_reg="); print_debug_hex32(index_reg); + + for(i = start; i < end; i++) { + u32 val; + int j; + printk_debug("\n%02x:",i); + val = pci_read_config32_index_wait(dev, index_reg, i); + for(j=0;j<4;j++) { + printk_debug(" %02x", val & 0xff); + val >>= 8; + } + + } + print_debug("\n"); +} +static void dump_pci_device_index_wait(u32 dev, u32 index_reg) +{ + dump_pci_device_index_wait_range(dev, index_reg, 0, 0x54); + dump_pci_device_index_wait_range(dev, index_reg, 0x100, 0x08); //DIMM1 when memclk > 400Hz +// dump_pci_device_index_wait_range(dev, index_reg, 0x200, 0x08); //DIMM2 +// dump_pci_device_index_wait_range(dev, index_reg, 0x300, 0x08); //DIMM3 + +} + +static void dump_pci_device_index(u32 dev, u32 index_reg, u32 type, u32 length) +{ + int i; + print_debug_pci_dev(dev); + + print_debug(" index reg: "); print_debug_hex16(index_reg); print_debug(" type: "); print_debug_hex8(type); + + type<<=28; + + for(i = 0; i < length; i++) { + u32 val; + if ((i & 0x0f) == 0) { + printk_debug("\n%02x:",i); + } + val = pci_read_config32_index(dev, index_reg, i|type); + printk_debug(" %08x", val); + } + print_debug("\n"); +} + + +static void dump_pci_devices(void) +{ + device_t dev; + for(dev = PCI_DEV(0, 0, 0); + dev <= PCI_DEV(0xff, 0x1f, 0x7); + dev += PCI_DEV(0,0,1)) { + u32 id; + id = pci_read_config32(dev, PCI_VENDOR_ID); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + dump_pci_device(dev); + + if(((dev>>12) & 0x07) == 0) { + u8 hdr_type; + hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); + if((hdr_type & 0x80) != 0x80) { + dev += PCI_DEV(0,0,7); + } + } + } +} + + +static void dump_pci_devices_on_bus(u32 busn) +{ + device_t dev; + for(dev = PCI_DEV(busn, 0, 0); + dev <= PCI_DEV(busn, 0x1f, 0x7); + dev += PCI_DEV(0,0,1)) { + u32 id; + id = pci_read_config32(dev, PCI_VENDOR_ID); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + dump_pci_device(dev); + + if(((dev>>12) & 0x07) == 0) { + u8 hdr_type; + hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE); + if((hdr_type & 0x80) != 0x80) { + dev += PCI_DEV(0,0,7); + } + } + } +} + +#ifndef DEBUG_SMBUS +#define DEBUG_SMBUS 0 +#endif + +#if DEBUG_SMBUS == 1 + +static void dump_spd_registers(const struct mem_controller *ctrl) +{ + int i; + print_debug("\n"); + for(i = 0; i < DIMM_SOCKETS; i++) { + u32 device; + device = ctrl->spd_addr[i]; + if (device) { + int j; + printk_debug("dimm: %02x.0: %02x", i, device); + for(j = 0; j < 128; j++) { + int status; + u8 byte; + if ((j & 0xf) == 0) { + printk_debug("\n%02x: ", j); + } + status = smbus_read_byte(device, j); + if (status < 0) { + break; + } + byte = status & 0xff; + printk_debug("%02x ", byte); + } + print_debug("\n"); + } + device = ctrl->spd_addr[i+DIMM_SOCKETS]; + if (device) { + int j; + printk_debug("dimm: %02x.1: %02x", i, device); + for(j = 0; j < 128; j++) { + int status; + u8 byte; + if ((j & 0xf) == 0) { + printk_debug("\n%02x: ", j); + } + status = smbus_read_byte(device, j); + if (status < 0) { + break; + } + byte = status & 0xff; + printk_debug("%02x ", byte); + } + print_debug("\n"); + } + } +} +static void dump_smbus_registers(void) +{ + u32 device; + print_debug("\n"); + for(device = 1; device < 0x80; device++) { + int j; + if( smbus_read_byte(device, 0) < 0 ) continue; + printk_debug("smbus: %02x", device); + for(j = 0; j < 256; j++) { + int status; + u8 byte; + status = smbus_read_byte(device, j); + if (status < 0) { + break; + } + if ((j & 0xf) == 0) { + printk_debug("\n%02x: ",j); + } + byte = status & 0xff; + printk_debug("%02x ", byte); + } + print_debug("\n"); + } +} +#endif +static void dump_io_resources(u32 port) +{ + + int i; + udelay_tsc(2000); + printk_debug("%04x:\n", port); + for(i=0;i<256;i++) { + u8 val; + if ((i & 0x0f) == 0) { + printk_debug("%02x:", i); + } + val = inb(port); + printk_debug(" %02x",val); + if ((i & 0x0f) == 0x0f) { + print_debug("\n"); + } + port++; + } +} + +static void dump_mem(u32 start, u32 end) +{ + u32 i; + print_debug("dump_mem:"); + for(i=start;i<end;i++) { + if((i & 0xf)==0) { + printk_debug("\n%08x:", i); + } + printk_debug(" %02x", (u8)*((u8 *)i)); + } + print_debug("\n"); +} diff --git a/src/northbridge/amd/amdfam10/early_ht.c b/src/northbridge/amd/amdfam10/early_ht.c new file mode 100644 index 0000000000..0ddbf9993a --- /dev/null +++ b/src/northbridge/amd/amdfam10/early_ht.c @@ -0,0 +1,175 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// For SB HT chain only +// mmconf is not ready yet +static void set_bsp_node_CHtExtNodeCfgEn(void) +{ +#if EXT_RT_TBL_SUPPORT == 1 + 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 CBB and CDB. +#endif +} + +static void enumerate_ht_chain(void) +{ +#if HT_CHAIN_UNITID_BASE != 0 +/* 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 HT_CHAIN_END_UNITID_BASE != 0x20 + // let't record the device of last ht device, So we can set the + // Unitid to 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 = 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; + device_t devx; + +#if HT_CHAIN_END_UNITID_BASE != 0x20 + if(next_unitid>=0x18) { + if(!end_used) { + next_unitid = 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 HT_CHAIN_END_UNITID_BASE == 0 + 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_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_write_config16(devx, pos + ctrl_off, ctrl); + ctrl = pci_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 HT_CHAIN_END_UNITID_BASE != 0x20 + if((ht_dev_num>1) && (real_last_unitid != 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 |= 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 +} diff --git a/src/northbridge/amd/amdfam10/get_pci1234.c b/src/northbridge/amd/amdfam10/get_pci1234.c new file mode 100644 index 0000000000..0ef4b73bed --- /dev/null +++ b/src/northbridge/amd/amdfam10/get_pci1234.c @@ -0,0 +1,118 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <string.h> +#include <stdint.h> + +#include <cpu/amd/amdfam10_sysconf.h> + + +/* Need pci1234 array + * pci1234[0] will record sblink and bus range + * pci1234[i] will record ht chain i. + * It will keep the sequence when some ht io card is not installed. + * + * 1n: 8 + * 2n: 7x2 + * 3n: 6x3 + * 4n: 5x4 + * 5n: 4x5 + * 6n: 3x6 + * 7n: 2x7 + * 8n: 1x8 + * + * 8n(4x2): 8x4 + * 16n(4x4): 16*2 + * 20n(4x5): 20x1 + * 32n(4x4+4x4): 16x1 + * + * Total: xxx: I just want to use 32 instead, If you have more, you may need to + * reset HC_POSSIBLE_NUM and update ssdt.dsl (hcdn, hclk) + * + * Put all the possible ht node/link to the list tp pci1234[] in get_bus_conf.c + * on MB dir. Also, don't forget to increase the ACPI_SSDTX_NUM etc if you have + * too much SSDT. How about co-processor on socket 1 on 2 way system. + * or socket 2, and socket3 on 4 way system? treat that as one hc too! + * + */ + + +void get_pci1234(void) +{ + + int i,j; + u32 dword; + + dword = sysconf.sblk<<8; + dword |= 1; + sysconf.pci1234[0] = dword; // sblink + sysconf.hcid[0] = 0; + + /* about hardcode numbering for HT_IO support + set the node_id and link_id that could have ht chain in the one array, + then check if is enabled.... then update final value + */ + + //here we need to set hcdn + //1. hypertransport.c need to record hcdn_reg together with 0xe0, 0xe4, 0xe8, 0xec when are set + //2. so at the same time we need update hsdn with hcdn_reg here +// printk_debug("sysconf.ht_c_num = %02d\n", sysconf.ht_c_num); + + for(j=0;j<sysconf.ht_c_num;j++) { + u32 dwordx; + dwordx = sysconf.ht_c_conf_bus[j]; +// printk_debug("sysconf.ht_c_conf_bus[%02d] = %08x\n", j, sysconf.ht_c_conf_bus[j]); + dwordx &=0xfffffffd; //keep bus num, node_id, link_num, enable bits + if((dwordx & 0x7fd) == dword) { //SBLINK + sysconf.pci1234[0] = dwordx; + sysconf.hcdn[0] = sysconf.hcdn_reg[j]; + continue; + } + if((dwordx & 1)) { + // We need to find out the number of HC + // for exact match + for(i=1;i<sysconf.hc_possible_num;i++) { + if((dwordx & 0x7fc) == (sysconf.pci1234[i] & 0x7fc)) { // same node and same linkn + sysconf.pci1234[i] = dwordx; + sysconf.hcdn[i] = sysconf.hcdn_reg[j]; + break; + } + } + // for 0xffc match or same node + for(i=1;i<sysconf.hc_possible_num;i++) { + if((dwordx & 0x7fc) == (dwordx & sysconf.pci1234[i] & 0x7fc)) { + sysconf.pci1234[i] = dwordx; + sysconf.hcdn[i] = sysconf.hcdn_reg[j]; + break; + } + } + } + } + + for(i=1;i<sysconf.hc_possible_num;i++) { + if(!(sysconf.pci1234[i] & 1)) { + sysconf.pci1234[i] = 0; + sysconf.hcdn[i] = 0x20202020; + } + sysconf.hcid[i] = 0; + } +} diff --git a/src/northbridge/amd/amdfam10/misc_control.c b/src/northbridge/amd/amdfam10/misc_control.c new file mode 100644 index 0000000000..8e8f39ab8d --- /dev/null +++ b/src/northbridge/amd/amdfam10/misc_control.c @@ -0,0 +1,155 @@ +/* + * This file is part of the LinuxBIOS project. + * + * Copyright (C) 2003 by Eric Biederman + * Copyright (C) Stefan Reinauer + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Turn off machine check triggers when reading + * pci space where there are no devices. + * This is necessary when scaning the bus for + * devices which is done by the kernel + */ + +#include <console/console.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include <part/hard_reset.h> +#include <pc80/mc146818rtc.h> +#include <bitops.h> +#include <cpu/amd/model_10xxx_rev.h> + +#include "amdfam10.h" + +/** + * @brief Read resources for AGP aperture + * + * @param + * + * There is only one AGP aperture resource needed. The resoruce is added to + * the northbridge of BSP. + * + * The same trick can be used to augment legacy VGA resources which can + * be detect by generic pci reousrce allocator for VGA devices. + * BAD: it is more tricky than I think, the resource allocation code is + * implemented in a way to NOT DOING legacy VGA resource allcation on + * purpose :-(. + */ +static void mcf3_read_resources(device_t dev) +{ + struct resource *resource; + unsigned char iommu; + /* Read the generic PCI resources */ + pci_dev_read_resources(dev); + + /* If we are not the first processor don't allocate the gart apeture */ + if (dev->path.u.pci.devfn != PCI_DEVFN(CDB, 3)) { + return; + } + + iommu = 1; + get_option(&iommu, "iommu"); + + if (iommu) { + /* Add a Gart apeture resource */ + resource = new_resource(dev, 0x94); + resource->size = iommu?AGP_APERTURE_SIZE:1; + resource->align = log2(resource->size); + resource->gran = log2(resource->size); + resource->limit = 0xffffffff; /* 4G */ + resource->flags = IORESOURCE_MEM; + } +} + +static void set_agp_aperture(device_t dev) +{ + struct resource *resource; + + resource = probe_resource(dev, 0x94); + if (resource) { + device_t pdev; + u32 gart_base, gart_acr; + + /* Remember this resource has been stored */ + resource->flags |= IORESOURCE_STORED; + + /* Find the size of the GART aperture */ + gart_acr = (0<<6)|(0<<5)|(0<<4)|((resource->gran - 25) << 1)|(0<<0); + + /* Get the base address */ + gart_base = ((resource->base) >> 25) & 0x00007fff; + + /* Update the other northbriges */ + pdev = 0; + while((pdev = dev_find_device(PCI_VENDOR_ID_AMD, 0x1203, pdev))) { + /* Store the GART size but don't enable it */ + pci_write_config32(pdev, 0x90, gart_acr); + + /* Store the GART base address */ + pci_write_config32(pdev, 0x94, gart_base); + + /* Don't set the GART Table base address */ + pci_write_config32(pdev, 0x98, 0); + + /* Report the resource has been stored... */ + report_resource_stored(pdev, resource, " <gart>"); + } + } +} + +static void mcf3_set_resources(device_t dev) +{ + /* Set the gart apeture */ + set_agp_aperture(dev); + + /* Set the generic PCI resources */ + pci_dev_set_resources(dev); +} + +static void misc_control_init(struct device *dev) +{ + u32 cmd; + + printk_debug("NB: Function 3 Misc Control.. "); + + /* Disable Machine checks from Invalid Locations. + * This is needed for PC backwards compatibility. + */ + cmd = pci_read_config32(dev, 0x44); + cmd |= (1<<6) | (1<<25); + pci_write_config32(dev, 0x44, cmd ); + + printk_debug("done.\n"); +} + + +static struct device_operations mcf3_ops = { + .read_resources = mcf3_read_resources, + .set_resources = mcf3_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = misc_control_init, + .scan_bus = 0, + .ops_pci = 0, +}; + +static struct pci_driver mcf3_driver __pci_driver = { + .ops = &mcf3_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x1203, +}; diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c new file mode 100644 index 0000000000..79e52b82b8 --- /dev/null +++ b/src/northbridge/amd/amdfam10/northbridge.c @@ -0,0 +1,1477 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <console/console.h> +#include <arch/io.h> +#include <stdint.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/hypertransport.h> +#include <stdlib.h> +#include <string.h> +#include <bitops.h> +#include <cpu/cpu.h> + +#include <cpu/x86/lapic.h> + +#if CONFIG_LOGICAL_CPUS==1 +#include <cpu/amd/quadcore.h> +#include <pc80/mc146818rtc.h> +#endif + +#include "chip.h" +#include "root_complex/chip.h" +#include "northbridge.h" + +#include "amdfam10.h" + +#if HW_MEM_HOLE_SIZEK != 0 +#include <cpu/amd/model_10xxx_rev.h> +#endif + +#include <cpu/amd/amdfam10_sysconf.h> + +struct amdfam10_sysconf_t sysconf; + +#define FX_DEVS NODE_NUMS +static device_t __f0_dev[FX_DEVS]; +static device_t __f1_dev[FX_DEVS]; +static device_t __f2_dev[FX_DEVS]; +static device_t __f4_dev[FX_DEVS]; + +device_t get_node_pci(u32 nodeid, u32 fn) +{ +#if NODE_NUMS == 64 + if(nodeid<32) { + return dev_find_slot(CBB, PCI_DEVFN(CDB + nodeid, fn)); + } else { + return dev_find_slot(CBB-1, PCI_DEVFN(CDB + nodeid - 32, fn)); + } + +#else + return dev_find_slot(CBB, PCI_DEVFN(CDB + nodeid, fn)); +#endif + +} +static void get_fx_devs(void) +{ + int i; + if (__f1_dev[0]) { + return; + } + for(i = 0; i < FX_DEVS; i++) { + __f0_dev[i] = get_node_pci(i, 0); + __f1_dev[i] = get_node_pci(i, 1); + __f2_dev[i] = get_node_pci(i, 2); + __f4_dev[i] = get_node_pci(i, 4); + } + if (!__f1_dev[0]) { + printk_err("Cannot find %02x:%02x.1", CBB, CDB); + die("Cannot go on\n"); + } +} + +static u32 f1_read_config32(u32 reg) +{ + get_fx_devs(); + return pci_read_config32(__f1_dev[0], reg); +} + +static void f1_write_config32(u32 reg, u32 value) +{ + int i; + get_fx_devs(); + for(i = 0; i < FX_DEVS; i++) { + device_t dev; + dev = __f1_dev[i]; + if (dev && dev->enabled) { + pci_write_config32(dev, reg, value); + } + } +} + + +static u32 amdfam10_nodeid(device_t dev) +{ +#if NODE_NUMS == 64 + unsigned busn; + busn = dev->bus->secondary; + if(busn != CBB) { + return (dev->path.u.pci.devfn >> 3) - CDB + 32; + } else { + return (dev->path.u.pci.devfn >> 3) - CDB; + } + +#else + return (dev->path.u.pci.devfn >> 3) - CDB; +#endif +} + +#include "amdfam10_conf.c" + +static void set_vga_enable_reg(u32 nodeid, u32 linkn) +{ + u32 val; + + val = 1 | (nodeid<<4) | (linkn<<12); + /* it will routing (1)mmio 0xa0000:0xbffff (2) io 0x3b0:0x3bb, + 0x3c0:0x3df */ + f1_write_config32(0xf4, val); + +} + +static u32 amdfam10_scan_chain(device_t dev, u32 nodeid, u32 link, u32 sblink, + u32 max, u32 offset_unitid) +{ +// I want to put sb chain in bus 0 can I? + + + u32 link_type; + int i; + u32 ht_c_index; + u32 ht_unitid_base[4]; // here assume only 4 HT device on chain + u32 max_bus; + u32 min_bus; + u32 is_sublink1 = (link>3); + device_t devx; + u32 busses; + u32 segn = max>>8; + u32 busn = max&0xff; + u32 max_devfn; + +#if HT3_SUPPORT==1 + if(is_sublink1) { + u32 regpos; + u32 reg; + regpos = 0x170 + 4 * (link&3); // it is only on sublink0 + reg = pci_read_config32(dev, regpos); + if(reg & 1) return max; // already ganged no sblink1 + devx = get_node_pci(nodeid, 4); + } else +#endif + devx = dev; + + + dev->link[link].cap = 0x80 + ((link&3) *0x20); + do { + link_type = pci_read_config32(devx, dev->link[link].cap + 0x18); + } while(link_type & ConnectionPending); + if (!(link_type & LinkConnected)) { + return max; + } + do { + link_type = pci_read_config32(devx, dev->link[link].cap + 0x18); + } while(!(link_type & InitComplete)); + if (!(link_type & NonCoherent)) { + return max; + } + /* See if there is an available configuration space mapping + * register in function 1. + */ + ht_c_index = get_ht_c_index(nodeid, link, &sysconf); + +#if EXT_CONF_SUPPORT == 0 + if(ht_c_index>=4) return max; +#endif + + /* Set up the primary, secondary and subordinate bus numbers. + * We have no idea how many busses are behind this bridge yet, + * so we set the subordinate bus number to 0xff for the moment. + */ + +#if SB_HT_CHAIN_ON_BUS0 > 0 + // first chain will on bus 0 + if((nodeid == 0) && (sblink==link)) { // actually max is 0 here + min_bus = max; + } + #if SB_HT_CHAIN_ON_BUS0 > 1 + // second chain will be on 0x40, third 0x80, forth 0xc0 + // i would refined that to 2, 3, 4 ==> 0, 0x, 40, 0x80, 0xc0 + // >4 will use more segments, We can have 16 segmment and every segment have 256 bus, For that case need the kernel support mmio pci config. + else { + min_bus = ((busn>>3) + 1) << 3; // one node can have 8 link and segn is the same + } + max = min_bus | (segn<<8); + #else + //other ... + else { + min_bus = ++max; + } + #endif +#else + min_bus = ++max; +#endif + max_bus = 0xfc | (segn<<8); + + dev->link[link].secondary = min_bus; + dev->link[link].subordinate = max_bus; + /* Read the existing primary/secondary/subordinate bus + * number configuration. + */ + busses = pci_read_config32(devx, dev->link[link].cap + 0x14); + + /* Configure the bus numbers for this bridge: the configuration + * transactions will not be propagates by the bridge if it is + * not correctly configured + */ + busses &= 0xffff00ff; + busses |= ((u32)(dev->link[link].secondary) << 8); + pci_write_config32(devx, dev->link[link].cap + 0x14, busses); + + + /* set the config map space */ + + set_config_map_reg(nodeid, link, ht_c_index, dev->link[link].secondary, dev->link[link].subordinate, sysconf.segbit, sysconf.nodes); + + /* Now we can scan all of the subordinate busses i.e. the + * chain on the hypertranport link + */ + for(i=0;i<4;i++) { + ht_unitid_base[i] = 0x20; + } + + //if ext conf is enabled, only need use 0x1f + if (min_bus == 0) + max_devfn = (0x17<<3) | 7; + else + max_devfn = (0x1f<<3) | 7; + + max = hypertransport_scan_chain(&dev->link[link], 0, max_devfn, max, ht_unitid_base, offset_unitid); + + + /* We know the number of busses behind this bridge. Set the + * subordinate bus number to it's real value + */ + if(ht_c_index>3) { // clear the extend reg + clear_config_map_reg(nodeid, link, ht_c_index, (max+1)>>sysconf.segbit, (dev->link[link].subordinate)>>sysconf.segbit, sysconf.nodes); + } + + dev->link[link].subordinate = max; + set_config_map_reg(nodeid, link, ht_c_index, dev->link[link].secondary, dev->link[link].subordinate, sysconf.segbit, sysconf.nodes); + sysconf.ht_c_num++; + + { + // config config_reg, and ht_unitid_base to update hcdn_reg; + u32 temp = 0; + for(i=0;i<4;i++) { + temp |= (ht_unitid_base[i] & 0xff) << (i*8); + } + + sysconf.hcdn_reg[ht_c_index] = temp; + + } + + store_ht_c_conf_bus(nodeid, link, ht_c_index, dev->link[link].secondary, dev->link[link].subordinate, &sysconf); + + + return max; +} + +static u32 amdfam10_scan_chains(device_t dev, u32 max) +{ + u32 nodeid; + u32 link; + u32 sblink = sysconf.sblk; + u32 offset_unitid = 0; + + nodeid = amdfam10_nodeid(dev); + + +// Put sb chain in bus 0 +#if SB_HT_CHAIN_ON_BUS0 > 0 + if(nodeid==0) { + #if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) + offset_unitid = 1; + #endif + max = amdfam10_scan_chain(dev, nodeid, sblink, sblink, max, offset_unitid ); // do sb ht chain at first, in case s2885 put sb chain (8131/8111) on link2, but put 8151 on link0 + } +#endif + + +#if PCI_BUS_SEGN_BITS + max = check_segn(dev, max, sysconf.nodes, &sysconf); +#endif + + + for(link = 0; link < dev->links; link++) { +#if SB_HT_CHAIN_ON_BUS0 > 0 + if( (nodeid == 0) && (sblink == link) ) continue; //already done +#endif + offset_unitid = 0; + #if ((HT_CHAIN_UNITID_BASE != 1) || (HT_CHAIN_END_UNITID_BASE != 0x20)) + #if SB_HT_CHAIN_UNITID_OFFSET_ONLY == 1 + if((nodeid == 0) && (sblink == link)) + #endif + offset_unitid = 1; + #endif + + max = amdfam10_scan_chain(dev, nodeid, link, sblink, max, offset_unitid); + } + return max; +} + + +static int reg_useable(u32 reg,device_t goal_dev, u32 goal_nodeid, + u32 goal_link) +{ + struct resource *res; + u32 nodeid, link; + int result; + res = 0; + for(nodeid = 0; !res && (nodeid < NODE_NUMS); nodeid++) { + device_t dev; + dev = __f0_dev[nodeid]; + for(link = 0; !res && (link < 8); link++) { + res = probe_resource(dev, 0x1000 + reg + (link<<16)); // 8 links, 0x1000 man f1, + } + } + result = 2; + if (res) { + result = 0; + if ( (goal_link == (link - 1)) && + (goal_nodeid == (nodeid - 1)) && + (res->flags <= 1)) { + result = 1; + } + } + return result; +} + +static struct resource *amdfam10_find_iopair(device_t dev, u32 nodeid, u32 link) +{ + struct resource *resource; + u32 free_reg, reg; + resource = 0; + free_reg = 0; + for(reg = 0xc0; reg <= 0xd8; reg += 0x8) { + int result; + result = reg_useable(reg, dev, nodeid, link); + if (result == 1) { + /* I have been allocated this one */ + break; + } + else if (result > 1) { + /* I have a free register pair */ + free_reg = reg; + } + } + if (reg > 0xd8) { + reg = free_reg; // if no free, the free_reg still be 0 + } + + //Ext conf space + if(!reg) { + //because of Extend conf space, we will never run out of reg, but we need one index to differ them. so same node and same link can have multi range + u32 index = get_io_addr_index(nodeid, link); + reg = 0x110+ (index<<24) + (4<<20); // index could be 0, 255 + } + + resource = new_resource(dev, 0x1000 + reg + (link<<16)); + + return resource; +} + +static struct resource *amdfam10_find_mempair(device_t dev, u32 nodeid, u32 link) +{ + struct resource *resource; + u32 free_reg, reg; + resource = 0; + free_reg = 0; + for(reg = 0x80; reg <= 0xb8; reg += 0x8) { + int result; + result = reg_useable(reg, dev, nodeid, link); + if (result == 1) { + /* I have been allocated this one */ + break; + } + else if (result > 1) { + /* I have a free register pair */ + free_reg = reg; + } + } + if (reg > 0xb8) { + reg = free_reg; + } + + //Ext conf space + if(!reg) { + //because of Extend conf space, we will never run out of reg, + // but we need one index to differ them. so same node and + // same link can have multi range + u32 index = get_mmio_addr_index(nodeid, link); + reg = 0x110+ (index<<24) + (6<<20); // index could be 0, 63 + + } + resource = new_resource(dev, 0x1000 + reg + (link<<16)); + return resource; +} + + +static void amdfam10_link_read_bases(device_t dev, u32 nodeid, u32 link) +{ + struct resource *resource; + + /* Initialize the io space constraints on the current bus */ + resource = amdfam10_find_iopair(dev, nodeid, link); + if (resource) { + u32 align; +#if EXT_CONF_SUPPORT == 1 + if((resource->index & 0x1fff) == 0x1110) { // ext + align = 8; + } + else +#endif + align = log2(HT_IO_HOST_ALIGN); + resource->base = 0; + resource->size = 0; + resource->align = align; + resource->gran = align; + resource->limit = 0xffffUL; + resource->flags = IORESOURCE_IO; + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_IO, IORESOURCE_IO); + } + + /* Initialize the prefetchable memory constraints on the current bus */ + resource = amdfam10_find_mempair(dev, nodeid, link); + if (resource) { + resource->base = 0; + resource->size = 0; + resource->align = log2(HT_MEM_HOST_ALIGN); + resource->gran = log2(HT_MEM_HOST_ALIGN); + resource->limit = 0xffffffffffULL; + resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM | IORESOURCE_PREFETCH); + +#if EXT_CONF_SUPPORT == 1 + if((resource->index & 0x1fff) == 0x1110) { // ext + normalize_resource(resource); + } +#endif + + } + + /* Initialize the memory constraints on the current bus */ + resource = amdfam10_find_mempair(dev, nodeid, link); + if (resource) { + resource->base = 0; + resource->size = 0; + resource->align = log2(HT_MEM_HOST_ALIGN); + resource->gran = log2(HT_MEM_HOST_ALIGN); + resource->limit = 0xffffffffffULL; + resource->flags = IORESOURCE_MEM; + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM); + +#if EXT_CONF_SUPPORT == 1 + if((resource->index & 0x1fff) == 0x1110) { // ext + normalize_resource(resource); + } +#endif + + } +} + + +static void amdfam10_read_resources(device_t dev) +{ + u32 nodeid, link; + + nodeid = amdfam10_nodeid(dev); + for(link = 0; link < dev->links; link++) { + if (dev->link[link].children) { + amdfam10_link_read_bases(dev, nodeid, link); + } + } +} + + +static void amdfam10_set_resource(device_t dev, struct resource *resource, + u32 nodeid) +{ + resource_t rbase, rend; + unsigned reg, link; + char buf[50]; + + /* Make certain the resource has actually been set */ + if (!(resource->flags & IORESOURCE_ASSIGNED)) { + return; + } + + /* If I have already stored this resource don't worry about it */ + if (resource->flags & IORESOURCE_STORED) { + return; + } + + /* Only handle PCI memory and IO resources */ + if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO))) + return; + + /* Ensure I am actually looking at a resource of function 1 */ + if ((resource->index & 0xffff) < 0x1000) { + return; + } + /* Get the base address */ + rbase = resource->base; + + /* Get the limit (rounded up) */ + rend = resource_end(resource); + + /* Get the register and link */ + reg = resource->index & 0xfff; // 4k + link = ( resource->index>> 16)& 0x7; // 8 links + + if (resource->flags & IORESOURCE_IO) { + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_IO, IORESOURCE_IO); + + set_io_addr_reg(dev, nodeid, link, reg, rbase>>8, rend>>8); + store_conf_io_addr(nodeid, link, reg, (resource->index >> 24), rbase>>8, rend>>8); + } + else if (resource->flags & IORESOURCE_MEM) { + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_MEM | IORESOURCE_PREFETCH, + resource->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH)); + set_mmio_addr_reg(nodeid, link, reg, (resource->index >>24), rbase>>8, rend>>8, sysconf.nodes) ;// [39:8] + store_conf_mmio_addr(nodeid, link, reg, (resource->index >>24), rbase>>8, rend>>8); + } + resource->flags |= IORESOURCE_STORED; + sprintf(buf, " <node %02x link %02x>", + nodeid, link); + report_resource_stored(dev, resource, buf); +} + +/** + * + * I tried to reuse the resource allocation code in amdfam10_set_resource() + * but it is too diffcult to deal with the resource allocation magic. + */ +#if CONFIG_CONSOLE_VGA_MULTI == 1 +extern device_t vga_pri; // the primary vga device, defined in device.c +#endif + +static void amdfam10_create_vga_resource(device_t dev, unsigned nodeid) +{ + unsigned link; + + /* find out which link the VGA card is connected, + * we only deal with the 'first' vga card */ + for (link = 0; link < dev->links; link++) { + if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) { +#if CONFIG_CONSOLE_VGA_MULTI == 1 + printk_debug("VGA: vga_pri bus num = %d dev->link[link] bus range [%d,%d]\n", vga_pri->bus->secondary, + dev->link[link].secondary,dev->link[link].subordinate); + /* We need to make sure the vga_pri is under the link */ + if((vga_pri->bus->secondary >= dev->link[link].secondary ) && + (vga_pri->bus->secondary <= dev->link[link].subordinate ) + ) +#endif + break; + } + } + + /* no VGA card installed */ + if (link == dev->links) + return; + + printk_debug("VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link); + set_vga_enable_reg(nodeid, link); +} + +static void amdfam10_set_resources(device_t dev) +{ + u32 nodeid, link; + int i; + + /* Find the nodeid */ + nodeid = amdfam10_nodeid(dev); + + amdfam10_create_vga_resource(dev, nodeid); + + /* Set each resource we have found */ + for(i = 0; i < dev->resources; i++) { + amdfam10_set_resource(dev, &dev->resource[i], nodeid); + } + + for(link = 0; link < dev->links; link++) { + struct bus *bus; + bus = &dev->link[link]; + if (bus->children) { + assign_resources(bus); + } + } +} + + +static void amdfam10_enable_resources(device_t dev) +{ + pci_dev_enable_resources(dev); + enable_childrens_resources(dev); +} + +static void mcf0_control_init(struct device *dev) +{ +} + +static struct device_operations northbridge_operations = { + .read_resources = amdfam10_read_resources, + .set_resources = amdfam10_set_resources, + .enable_resources = amdfam10_enable_resources, + .init = mcf0_control_init, + .scan_bus = amdfam10_scan_chains, + .enable = 0, + .ops_pci = 0, +}; + + +static struct pci_driver mcf0_driver __pci_driver = { + .ops = &northbridge_operations, + .vendor = PCI_VENDOR_ID_AMD, + .device = 0x1200, +}; + +#if CONFIG_CHIP_NAME == 1 + +struct chip_operations northbridge_amd_amdfam10_ops = { + CHIP_NAME("AMD FAM10 Northbridge") + .enable_dev = 0, +}; + +#endif + +static void pci_domain_read_resources(device_t dev) +{ + struct resource *resource; + unsigned reg; + unsigned link; + + /* Find the already assigned resource pairs */ + get_fx_devs(); + for(reg = 0x80; reg <= 0xd8; reg+= 0x08) { + u32 base, limit; + base = f1_read_config32(reg); + limit = f1_read_config32(reg + 0x04); + /* Is this register allocated? */ + if ((base & 3) != 0) { + unsigned nodeid, link; + device_t dev; + if(reg<0xc0) { // mmio + nodeid = (limit & 0xf) + (base&0x30); + } else { // io + nodeid = (limit & 0xf) + ((base>>4)&0x30); + } + link = (limit >> 4) & 7; + dev = __f0_dev[nodeid]; + if (dev) { + /* Reserve the resource */ + struct resource *resource; + resource = new_resource(dev, 0x1000 + reg + (link<<16)); + if (resource) { + resource->flags = 1; + } + } + } + } + /* FIXME: do we need to check extend conf space? + I don't believe that much preset value */ + +#if CONFIG_PCI_64BIT_PREF_MEM == 0 + /* Initialize the system wide io space constraints */ + resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0)); + resource->base = 0x400; + resource->limit = 0xffffUL; + resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; + + /* Initialize the system wide memory resources constraints */ + resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0)); + resource->limit = 0xfcffffffffULL; + resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED; +#else + for(link=0; link<dev->links; link++) { + /* Initialize the system wide io space constraints */ + resource = new_resource(dev, 0|(link<<2)); + resource->base = 0x400; + resource->limit = 0xffffUL; + resource->flags = IORESOURCE_IO; + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_IO, IORESOURCE_IO); + + /* Initialize the system wide prefetchable memory resources constraints */ + resource = new_resource(dev, 1|(link<<2)); + resource->limit = 0xfcffffffffULL; + resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM | IORESOURCE_PREFETCH); + + /* Initialize the system wide memory resources constraints */ + resource = new_resource(dev, 2|(link<<2)); + resource->limit = 0xfcffffffffULL; + resource->flags = IORESOURCE_MEM; + compute_allocate_resource(&dev->link[link], resource, + IORESOURCE_MEM | IORESOURCE_PREFETCH, + IORESOURCE_MEM); + } +#endif +} + +static void ram_resource(device_t dev, unsigned long index, + resource_t basek, resource_t sizek) +{ + struct resource *resource; + + if (!sizek) { + return; + } + resource = new_resource(dev, index); + resource->base = basek << 10; + resource->size = sizek << 10; + resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE | \ + IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED; +} + +static void tolm_test(void *gp, struct device *dev, struct resource *new) +{ + struct resource **best_p = gp; + struct resource *best; + best = *best_p; + if (!best || (best->base > new->base)) { + best = new; + } + *best_p = best; +} + +static u32 find_pci_tolm(struct bus *bus, u32 tolm) +{ + struct resource *min; + min = 0; + search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min); + if (min && tolm > min->base) { + tolm = min->base; + } + return tolm; +} + +#if CONFIG_PCI_64BIT_PREF_MEM == 1 +#define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH) +#endif + +#if HW_MEM_HOLE_SIZEK != 0 + +struct hw_mem_hole_info { + unsigned hole_startk; + int node_id; +}; + +static struct hw_mem_hole_info get_hw_mem_hole_info(void) +{ + struct hw_mem_hole_info mem_hole; + int i; + + mem_hole.hole_startk = HW_MEM_HOLE_SIZEK; + mem_hole.node_id = -1; + + for (i = 0; i < sysconf.nodes; i++) { + struct dram_base_mask_t d; + u32 hole; + d = get_dram_base_mask(i); + if(!(d.mask & 1)) continue; // no memory on this node + + hole = pci_read_config32(__f1_dev[i], 0xf0); + if(hole & 1) { // we find the hole + mem_hole.hole_startk = (hole & (0xff<<24)) >> 10; + mem_hole.node_id = i; // record the node No with hole + break; // only one hole + } + } + + //We need to double check if there is speical set on base reg and limit reg are not continous instead of hole, it will find out it's hole_startk + if(mem_hole.node_id==-1) { + resource_t limitk_pri = 0; + for(i=0; i<sysconf.nodes; i++) { + struct dram_base_mask_t d; + resource_t base_k, limit_k; + d = get_dram_base_mask(i); + if(!(d.base & 1)) continue; + + base_k = ((resource_t)(d.base & 0x1fffff00)) <<9; + if(base_k > 4 *1024 * 1024) break; // don't need to go to check + if(limitk_pri != base_k) { // we find the hole + mem_hole.hole_startk = (unsigned)limitk_pri; // must beblow 4G + mem_hole.node_id = i; + break; //only one hole + } + + limit_k = ((resource_t)((d.mask + 0x00000100) & 0x1fffff00)) << 9; + limitk_pri = limit_k; + } + } + return mem_hole; +} + + +#if CONFIG_AMDMCT == 0 +static void disable_hoist_memory(unsigned long hole_startk, int i) +{ + int ii; + device_t dev; + struct dram_base_mask_t d; + u32 sel_m; + u32 sel_hi_en; + u32 hoist; + u32 hole_sizek; + + u32 one_DCT; + struct sys_info *sysinfox = (struct sys_info *)((CONFIG_LB_MEM_TOPK<<10) - DCACHE_RAM_GLOBAL_VAR_SIZE); // in RAM + struct mem_info *meminfo; + meminfo = &sysinfox->meminfo[i]; + + one_DCT = get_one_DCT(meminfo); + + // 1. find which node has hole + // 2. change limit in that node. + // 3. change base and limit in later node + // 4. clear that node f0 + + // if there is not mem hole enabled, we need to change it's base instead + + hole_sizek = (4*1024*1024) - hole_startk; + + for(ii=NODE_NUMS-1;ii>i;ii--) { + + d = get_dram_base_mask(ii); + + if(!(d.mask & 1)) continue; + + d.base -= (hole_sizek>>9); + d.mask -= (hole_sizek>>9); + set_dram_base_mask(ii, d, sysconf.nodes); + + if(get_DctSelHiEn(ii) & 1) { + sel_m = get_DctSelBaseAddr(ii); + sel_m -= hole_startk>>10; + set_DctSelBaseAddr(ii, sel_m); + } + } + + d = get_dram_base_mask(i); + dev = __f1_dev[i]; + hoist = pci_read_config32(dev, 0xf0); + sel_hi_en = get_DctSelHiEn(i); + + if(sel_hi_en & 1) { + sel_m = get_DctSelBaseAddr(i); + } + + if(hoist & 1) { + pci_write_config32(dev, 0xf0, 0); + d.mask -= (hole_sizek>>9); + set_dram_base_mask(i, d, sysconf.nodes); + if(one_DCT || (sel_m >= (hole_startk>>10))) { + if(sel_hi_en & 1) { + sel_m -= hole_startk>>10; + set_DctSelBaseAddr(i, sel_m); + } + } + if(sel_hi_en & 1) { + set_DctSelBaseOffset(i, 0); + } + } + else { + d.base -= (hole_sizek>>9); + d.mask -= (hole_sizek>>9); + set_dram_base_mask(i, d, sysconf.nodes); + + if(sel_hi_en & 1) { + sel_m -= hole_startk>>10; + set_DctSelBaseAddr(i, sel_m); + } + } + +} +#endif + +#endif + +static void pci_domain_set_resources(device_t dev) +{ +#if CONFIG_PCI_64BIT_PREF_MEM == 1 + struct resource *io, *mem1, *mem2; + struct resource *resource, *last; +#endif + unsigned long mmio_basek; + u32 pci_tolm; + int i, idx; + u32 link; +#if HW_MEM_HOLE_SIZEK != 0 + struct hw_mem_hole_info mem_hole; + u32 reset_memhole = 1; +#endif + +#if CONFIG_PCI_64BIT_PREF_MEM == 1 + + for(link=0; link<dev->links; link++) { + /* Now reallocate the pci resources memory with the + * highest addresses I can manage. + */ + mem1 = find_resource(dev, 1|(link<<2)); + mem2 = find_resource(dev, 2|(link<<2)); + + printk_debug("base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n", + mem1->base, mem1->limit, mem1->size, mem1->align); + printk_debug("base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n", + mem2->base, mem2->limit, mem2->size, mem2->align); + + /* See if both resources have roughly the same limits */ + if (((mem1->limit <= 0xffffffff) && (mem2->limit <= 0xffffffff)) || + ((mem1->limit > 0xffffffff) && (mem2->limit > 0xffffffff))) + { + /* If so place the one with the most stringent alignment first + */ + if (mem2->align > mem1->align) { + struct resource *tmp; + tmp = mem1; + mem1 = mem2; + mem2 = tmp; + } + /* Now place the memory as high up as it will go */ + mem2->base = resource_max(mem2); + mem1->limit = mem2->base - 1; + mem1->base = resource_max(mem1); + } + else { + /* Place the resources as high up as they will go */ + mem2->base = resource_max(mem2); + mem1->base = resource_max(mem1); + } + + printk_debug("base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n", + mem1->base, mem1->limit, mem1->size, mem1->align); + printk_debug("base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n", + mem2->base, mem2->limit, mem2->size, mem2->align); + } + + last = &dev->resource[dev->resources]; + for(resource = &dev->resource[0]; resource < last; resource++) + { + resource->flags |= IORESOURCE_ASSIGNED; + resource->flags &= ~IORESOURCE_STORED; + link = (resource>>2) & 3; + compute_allocate_resource(&dev->link[link], resource, + BRIDGE_IO_MASK, resource->flags & BRIDGE_IO_MASK); + + resource->flags |= IORESOURCE_STORED; + report_resource_stored(dev, resource, ""); + + } +#endif + + pci_tolm = 0xffffffffUL; + for(link=0;link<dev->links; link++) { + pci_tolm = find_pci_tolm(&dev->link[link], pci_tolm); + } + +#warning "FIXME handle interleaved nodes" + mmio_basek = pci_tolm >> 10; + /* Round mmio_basek to something the processor can support */ + mmio_basek &= ~((1 << 6) -1); + +#warning "FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M MMIO hole" + /* Round the mmio hold to 64M */ + mmio_basek &= ~((64*1024) - 1); + +#if HW_MEM_HOLE_SIZEK != 0 +/* if the hw mem hole is already set in raminit stage, here we will compare + * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will + * use hole_basek as mmio_basek and we don't need to reset hole. + * otherwise We reset the hole to the mmio_basek + */ + + mem_hole = get_hw_mem_hole_info(); + + // Use hole_basek as mmio_basek, and we don't need to reset hole anymore + if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk)) { + mmio_basek = mem_hole.hole_startk; + reset_memhole = 0; + } + + #if CONFIG_AMDMCT == 0 + //mmio_basek = 3*1024*1024; // for debug to meet boundary + + if(reset_memhole) { + if(mem_hole.node_id!=-1) { + /* We need to select HW_MEM_HOLE_SIZEK for raminit, it can not + make hole_startk to some basek too! + We need to reset our Mem Hole, because We want more big HOLE + than we already set + Before that We need to disable mem hole at first, becase + memhole could already be set on i+1 instead + */ + disable_hoist_memory(mem_hole.hole_startk, mem_hole.node_id); + } + + #if HW_MEM_HOLE_SIZE_AUTO_INC == 1 + // We need to double check if the mmio_basek is valid for hole + // setting, if it is equal to basek, we need to decrease it some + resource_t basek_pri; + for (i = 0; i < sysconf.nodes; i++) { + struct dram_base_mask_t d; + resource_t basek; + d = get_dram_base_mask(i); + + if(!(d.mask &1)) continue; + + basek = ((resource_t)(d.base & 0x1fffff00)) << 9; + if(mmio_basek == (u32)basek) { + mmio_basek -= (uin32_t)(basek - basek_pri); // increase mem hole size to make sure it is on middle of pri node + break; + } + basek_pri = basek; + } + #endif + } + #endif + + +#endif + + idx = 0x10; + for(i = 0; i < sysconf.nodes; i++) { + struct dram_base_mask_t d; + resource_t basek, limitk, sizek; // 4 1T + d = get_dram_base_mask(i); + + if(!(d.mask & 1)) continue; + basek = ((resource_t)(d.base & 0x1fffff00)) << 9; // could overflow, we may lost 6 bit here + limitk = ((resource_t)((d.mask + 0x00000100) & 0x1fffff00)) << 9 ; + sizek = limitk - basek; + + /* see if we need a hole from 0xa0000 to 0xbffff */ + if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) { + ram_resource(dev, (idx | i), basek, ((8*64)+(8*16)) - basek); + idx += 0x10; + basek = (8*64)+(16*16); + sizek = limitk - ((8*64)+(16*16)); + + } + +// printk_debug("node %d : mmio_basek=%08x, basek=%08x, limitk=%08x\n", i, mmio_basek, basek, limitk); + + /* split the region to accomodate pci memory space */ + if ( (basek < 4*1024*1024 ) && (limitk > mmio_basek) ) { + if (basek <= mmio_basek) { + unsigned pre_sizek; + pre_sizek = mmio_basek - basek; + if(pre_sizek>0) { + ram_resource(dev, (idx | i), basek, pre_sizek); + idx += 0x10; + sizek -= pre_sizek; + } + #if CONFIG_AMDMCT == 0 + #if HW_MEM_HOLE_SIZEK != 0 + if(reset_memhole) { + struct sys_info *sysinfox = (struct sys_info *)((CONFIG_LB_MEM_TOPK<<10) - DCACHE_RAM_GLOBAL_VAR_SIZE); // in RAM + struct mem_info *meminfo; + meminfo = &sysinfox->meminfo[i]; + sizek += hoist_memory(mmio_basek,i, get_one_DCT(meminfo), sysconf.nodes); + } + #endif + #endif + + basek = mmio_basek; + } + if ((basek + sizek) <= 4*1024*1024) { + sizek = 0; + } + else { + basek = 4*1024*1024; + sizek -= (4*1024*1024 - mmio_basek); + } + } + ram_resource(dev, (idx | i), basek, sizek); + idx += 0x10; + } + + for(link = 0; link < dev->links; link++) { + struct bus *bus; + bus = &dev->link[link]; + if (bus->children) { + assign_resources(bus); + } + } +} + +static u32 pci_domain_scan_bus(device_t dev, u32 max) +{ + u32 reg; + int i; + /* Unmap all of the HT chains */ + for(reg = 0xe0; reg <= 0xec; reg += 4) { + f1_write_config32(reg, 0); + } +#if EXT_CONF_SUPPORT == 1 + // all nodes + for(i = 0; i< sysconf.nodes; i++) { + int index; + for(index = 0; index < 64; index++) { + pci_write_config32(__f1_dev[i], 0x110, index | (6<<28)); + pci_write_config32(__f1_dev[i], 0x114, 0); + } + + } +#endif + + + for(i=0;i<dev->links;i++) { + max = pci_scan_bus(&dev->link[i], PCI_DEVFN(CDB, 0), 0xff, max); + } + + /* Tune the hypertransport transaction for best performance. + * Including enabling relaxed ordering if it is safe. + */ + get_fx_devs(); + for(i = 0; i < FX_DEVS; i++) { + device_t f0_dev; + f0_dev = __f0_dev[i]; + if (f0_dev && f0_dev->enabled) { + u32 httc; + httc = pci_read_config32(f0_dev, HT_TRANSACTION_CONTROL); + httc &= ~HTTC_RSP_PASS_PW; + if (!dev->link[0].disable_relaxed_ordering) { + httc |= HTTC_RSP_PASS_PW; + } + printk_spew("%s passpw: %s\n", + dev_path(dev), + (!dev->link[0].disable_relaxed_ordering)? + "enabled":"disabled"); + pci_write_config32(f0_dev, HT_TRANSACTION_CONTROL, httc); + } + } + return max; +} + +static struct device_operations pci_domain_ops = { + .read_resources = pci_domain_read_resources, + .set_resources = pci_domain_set_resources, + .enable_resources = enable_childrens_resources, + .init = 0, + .scan_bus = pci_domain_scan_bus, +#if MMCONF_SUPPORT + .ops_pci_bus = &pci_ops_mmconf, +#else + .ops_pci_bus = &pci_cf8_conf1, +#endif +}; + +static void sysconf_init(device_t dev) // first node +{ + sysconf.sblk = (pci_read_config32(dev, 0x64)>>8) & 7; // don't forget sublink1 + sysconf.segbit = 0; + sysconf.ht_c_num = 0; + + unsigned ht_c_index; + + for(ht_c_index=0; ht_c_index<32; ht_c_index++) { + sysconf.ht_c_conf_bus[ht_c_index] = 0; + } + + sysconf.nodes = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; +#if CONFIG_MAX_PHYSICAL_CPUS > 8 + sysconf.nodes += (((pci_read_config32(dev, 0x160)>>4) & 7)<<3); +#endif + + sysconf.enabled_apic_ext_id = 0; + sysconf.lift_bsp_apicid = 0; + + /* Find the bootstrap processors apicid */ + sysconf.bsp_apicid = lapicid(); + sysconf.apicid_offset = sysconf.bsp_apicid; + +#if (ENABLE_APIC_EXT_ID == 1) + if (pci_read_config32(dev, 0x68) & (HTTC_APIC_EXT_ID|HTTC_APIC_EXT_BRD_CST)) + { + sysconf.enabled_apic_ext_id = 1; + } + #if (APIC_ID_OFFSET>0) + if(sysconf.enabled_apic_ext_id) { + if(sysconf.bsp_apicid == 0) { + /* bsp apic id is not changed */ + sysconf.apicid_offset = APIC_ID_OFFSET; + } else { + sysconf.lift_bsp_apicid = 1; + } + + } + #endif +#endif + +} + +static u32 cpu_bus_scan(device_t dev, u32 max) +{ + struct bus *cpu_bus; + device_t dev_mc; + device_t pci_domain; + int i,j; + int nodes; + unsigned nb_cfg_54; + unsigned siblings; + int cores_found; + int disable_siblings; + unsigned ApicIdCoreIdSize; + + nb_cfg_54 = 0; + ApicIdCoreIdSize = (cpuid_ecx(0x80000008)>>12 & 0xf); + if(ApicIdCoreIdSize) { + siblings = (1<<ApicIdCoreIdSize)-1; + } else { + siblings = 3; //quad core + } + + disable_siblings = !CONFIG_LOGICAL_CPUS; +#if CONFIG_LOGICAL_CPUS == 1 + get_option(&disable_siblings, "quad_core"); +#endif + + // for pre_e0, nb_cfg_54 can not be set, ( even set, when you read it + // still be 0) + // How can I get the nb_cfg_54 of every node' nb_cfg_54 in bsp??? + // and differ d0 and e0 single core + + nb_cfg_54 = read_nb_cfg_54(); + +#if CBB + dev_mc = dev_find_slot(0, PCI_DEVFN(CDB, 0)); //0x00 + if(dev_mc && dev_mc->bus) { + printk_debug("%s found", dev_path(dev_mc)); + pci_domain = dev_mc->bus->dev; + if(pci_domain && (pci_domain->path.type == DEVICE_PATH_PCI_DOMAIN)) { + printk_debug("\n%s move to ",dev_path(dev_mc)); + dev_mc->bus->secondary = CBB; // move to 0xff + printk_debug("%s",dev_path(dev_mc)); + + } else { + printk_debug(" but it is not under pci_domain directly "); + } + printk_debug("\n"); + + } + dev_mc = dev_find_slot(CBB, PCI_DEVFN(CDB, 0)); + if(!dev_mc) { + dev_mc = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + if (dev_mc && dev_mc->bus) { + printk_debug("%s found\n", dev_path(dev_mc)); + pci_domain = dev_mc->bus->dev; + if(pci_domain && (pci_domain->path.type == DEVICE_PATH_PCI_DOMAIN)) { + if((pci_domain->links==1) && (pci_domain->link[0].children == dev_mc)) { + printk_debug("%s move to ",dev_path(dev_mc)); + dev_mc->bus->secondary = CBB; // move to 0xff + printk_debug("%s\n",dev_path(dev_mc)); + while(dev_mc){ + printk_debug("%s move to ",dev_path(dev_mc)); + dev_mc->path.u.pci.devfn -= PCI_DEVFN(0x18,0); + printk_debug("%s\n",dev_path(dev_mc)); + dev_mc = dev_mc->sibling; + } + } + } + } + } + +#endif + + dev_mc = dev_find_slot(CBB, PCI_DEVFN(CDB, 0)); + if (!dev_mc) { + printk_err("%02x:%02x.0 not found", CBB, CDB); + die(""); + } + + sysconf_init(dev_mc); + + nodes = sysconf.nodes; + +#if CBB && (NODE_NUMS > 32) + if(nodes>32) { // need to put node 32 to node 63 to bus 0xfe + if(pci_domain->links==1) { + pci_domain->links++; // from 1 to 2 + pci_domain->link[1].link = 1; + pci_domain->link[1].dev = pci_domain; + pci_domain->link[1].children = 0; + printk_debug("%s links increase to %d\n", dev_path(pci_domain), pci_domain->links); + } + pci_domain->link[1].secondary = CBB - 1; + } +#endif + /* Find which cpus are present */ + cpu_bus = &dev->link[0]; + for(i = 0; i < nodes; i++) { + device_t dev, cpu; + struct device_path cpu_path; + unsigned busn, devn; + struct bus *pbus; + + busn = CBB; + devn = CDB+i; + pbus = dev_mc->bus; +#if CBB && (NODE_NUMS > 32) + if(i>=32) { + busn--; + devn-=32; + pbus = &(pci_domain->link[1]); + } +#endif + + /* Find the cpu's pci device */ + dev = dev_find_slot(busn, PCI_DEVFN(devn, 0)); + if (!dev) { + /* If I am probing things in a weird order + * ensure all of the cpu's pci devices are found. + */ + int j; + for(j = 0; j <= 5; j++) { //FBDIMM? + dev = pci_probe_dev(NULL, pbus, + PCI_DEVFN(devn, j)); + } + dev = dev_find_slot(busn, PCI_DEVFN(devn,0)); + } + if(dev) { + /* Ok, We need to set the links for that device. + * otherwise the device under it will not be scanned + */ + int j; + int linknum; +#if HT3_SUPPORT==1 + linknum = 8; +#else + linknum = 4; +#endif + if(dev->links < linknum) { + for(j=dev->links; j<linknum; j++) { + dev->link[j].link = j; + dev->link[j].dev = dev; + } + dev->links = linknum; + printk_debug("%s links increase to %d\n", dev_path(dev), dev->links); + } + } + + cores_found = 0; // one core + dev = dev_find_slot(busn, PCI_DEVFN(devn, 3)); + if (dev && dev->enabled) { + j = pci_read_config32(dev, 0xe8); + cores_found = (j >> 12) & 3; // dev is func 3 + printk_debug(" %s siblings=%d\n", dev_path(dev), cores_found); + } + + u32 jj; + if(disable_siblings) { + jj = 0; + } else + { + jj = cores_found; + } + + for (j = 0; j <=jj; j++ ) { + + /* Build the cpu device path */ + cpu_path.type = DEVICE_PATH_APIC; + cpu_path.u.apic.apic_id = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:64); // ? + + /* See if I can find the cpu */ + cpu = find_dev_path(cpu_bus, &cpu_path); + + /* Enable the cpu if I have the processor */ + if (dev && dev->enabled) { + if (!cpu) { + cpu = alloc_dev(cpu_bus, &cpu_path); + } + if (cpu) { + cpu->enabled = 1; + } + } + + /* Disable the cpu if I don't have the processor */ + if (cpu && (!dev || !dev->enabled)) { + cpu->enabled = 0; + } + + /* Report what I have done */ + if (cpu) { + cpu->path.u.apic.node_id = i; + cpu->path.u.apic.core_id = j; + #if (ENABLE_APIC_EXT_ID == 1) && (APIC_ID_OFFSET>0) + if(sysconf.enabled_apic_ext_id) { + if(sysconf.lift_bsp_apicid) { + cpu->path.u.apic.apic_id += sysconf.apicid_offset; + } else + { + if (cpu->path.u.apic.apic_id != 0) + cpu->path.u.apic.apic_id += sysconf.apicid_offset; + } + } + #endif + printk_debug("CPU: %s %s\n", + dev_path(cpu), cpu->enabled?"enabled":"disabled"); + } + + } //j + } + return max; +} + + +static void cpu_bus_init(device_t dev) +{ + initialize_cpus(&dev->link[0]); +} + + +static void cpu_bus_noop(device_t dev) +{ +} + + +static struct device_operations cpu_bus_ops = { + .read_resources = cpu_bus_noop, + .set_resources = cpu_bus_noop, + .enable_resources = cpu_bus_noop, + .init = cpu_bus_init, + .scan_bus = cpu_bus_scan, +}; + + +static void root_complex_enable_dev(struct device *dev) +{ + /* Set the operations if it is a special bus type */ + if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) { + dev->ops = &pci_domain_ops; + } + else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) { + dev->ops = &cpu_bus_ops; + } +} + +struct chip_operations northbridge_amd_amdfam10_root_complex_ops = { + CHIP_NAME("AMD FAM10 Root Complex") + .enable_dev = root_complex_enable_dev, +}; diff --git a/src/northbridge/amd/amdfam10/northbridge.h b/src/northbridge/amd/amdfam10/northbridge.h new file mode 100644 index 0000000000..b385e3df82 --- /dev/null +++ b/src/northbridge/amd/amdfam10/northbridge.h @@ -0,0 +1,25 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef NORTHBRIDGE_AMD_AMDFAM10_H +#define NORTHBRIDGE_AMD_AMDFAM10_H + +extern u32 amdfam10_scan_root_bus(device_t root, u32 max); + +#endif /* NORTHBRIDGE_AMD_AMDFAM10_H */ diff --git a/src/northbridge/amd/amdfam10/raminit.h b/src/northbridge/amd/amdfam10/raminit.h new file mode 100644 index 0000000000..36ccf77cd8 --- /dev/null +++ b/src/northbridge/amd/amdfam10/raminit.h @@ -0,0 +1,73 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RAMINIT_H +#define RAMINIT_H + +#if 0 +#if DIMM_SUPPORT==0x0110 +//FBDIMM REG +/* each channel can have 8 fbdimm */ +#define DIMM_SOCKETS 8 +struct mem_controller { + u32 node_id; + device_t f0, f1, f2, f3, f4, f5; + /* channelA, channelB belong to DCT0, + * channelC, channelD belong to DCT1 + * Each DCT may support one ganged logical FBDIMM ---> 128 bit + * or a single unganged channel --->64 bit + * a DCT can not support 2 unganged channels + * two DCTs can not be ganged + */ + u8 spd_switch_addr; + u8 spd_addr[DIMM_SOCKETS*4]; +}; + +#endif +#endif + +//#if (DIMM_SUPPORT & 0x00ff)==0x0004 +//DDR2 REG and unbuffered : Socket F 1027 and AM3 +/* every channel have 4 DDR2 DIMM for socket F + * 2 for socket M2/M3 + * 1 for socket s1g1 + */ +#define DIMM_SOCKETS 4 +struct mem_controller { + u32 node_id; + device_t f0, f1, f2, f3, f4, f5; + /* channel0 is DCT0 --- channelA + * channel1 is DCT1 --- channelB + * can be ganged, a single dual-channel DCT ---> 128 bit + * or unganged a two single-channel DCTs ---> 64bit + * When the DCTs are ganged, the writes to DCT1 set of registers + * (F2x1XX) are ignored and reads return all 0's + * The exception is the DCT phy registers, F2x[1,0]98, F2x[1,0]9C, + * and all the associated indexed registers, are still + * independently accessiable + */ + /* FIXME: I will only support ganged mode for easy support */ + u8 spd_switch_addr; + u8 spd_addr[DIMM_SOCKETS*2]; +}; + +//#endif + + +#endif diff --git a/src/northbridge/amd/amdfam10/raminit_amdmct.c b/src/northbridge/amd/amdfam10/raminit_amdmct.c new file mode 100644 index 0000000000..05446331e7 --- /dev/null +++ b/src/northbridge/amd/amdfam10/raminit_amdmct.c @@ -0,0 +1,155 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +static void print_raminit(const char *strval, u32 val) +{ + printk_debug("%s%08x\n", strval, val); +} + + +#define RAMINIT_DEBUG 1 + + +static void print_tx(const char *strval, u32 val) +{ +#if RAMINIT_DEBUG == 1 + print_raminit(strval, val); +#endif +} + + +static void print_t(const char *strval) +{ +#if RAMINIT_DEBUG == 1 + print_debug(strval); +#endif +} +#include "amdfam10.h" +#include "../amdmct/wrappers/mcti.h" +#include "../amdmct/amddefs.h" +#include "../amdmct/mct/mct_d.h" +#include "../amdmct/mct/mct_d_gcc.h" + +#include "../amdmct/wrappers/mcti_d.c" +#include "../amdmct/mct/mct_d.c" + + +#include "../amdmct/mct/mctmtr_d.c" +#include "../amdmct/mct/mctcsi_d.c" +#include "../amdmct/mct/mctecc_d.c" +#include "../amdmct/mct/mctpro_d.c" +#include "../amdmct/mct/mctdqs_d.c" +#include "../amdmct/mct/mctsrc.c" +#include "../amdmct/mct/mctsrc1p.c" +#include "../amdmct/mct/mcttmrl.c" +#include "../amdmct/mct/mcthdi.c" +#include "../amdmct/mct/mctndi_d.c" +#include "../amdmct/mct/mctchi_d.c" + +#if SYSTEM_TYPE == SERVER +//L1 +#include "../amdmct/mct/mctardk3.c" +#elif SYSTEM_TYPE == DESKTOP +//AM2 +#include "../amdmct/mct/mctardk4.c" +//#elif SYSTEM_TYPE == MOBILE +//s1g1 +//#include "../amdmct/mct/mctardk5.c" +#endif + +#include "../amdmct/mct/mct_fd.c" + +int mctRead_SPD(u32 smaddr, u32 reg) +{ + return spd_read_byte(smaddr, reg); +} + + +void mctSMBhub_Init(u32 node) +{ + struct sys_info *sysinfo = (struct sys_info *)(DCACHE_RAM_BASE + DCACHE_RAM_SIZE - DCACHE_RAM_GLOBAL_VAR_SIZE); + struct mem_controller *ctrl = &( sysinfo->ctrl[node] ); + activate_spd_rom(ctrl); +} + + +void mctGet_DIMMAddr(struct DCTStatStruc *pDCTstat, u32 node) +{ + int j; + struct sys_info *sysinfo = (struct sys_info *)(DCACHE_RAM_BASE + DCACHE_RAM_SIZE - DCACHE_RAM_GLOBAL_VAR_SIZE); + struct mem_controller *ctrl = &( sysinfo->ctrl[node] ); + + for(j=0;j<DIMM_SOCKETS;j++) { + pDCTstat->DIMMAddr[j*2] = ctrl->spd_addr[j] & 0xff; + pDCTstat->DIMMAddr[j*2+1] = ctrl->spd_addr[DIMM_SOCKETS + j] & 0xff; + } + +} + + +u32 mctGetLogicalCPUID(u32 Node) +{ + u32 dev; + u32 val, valx; + u32 family, model, stepping; + u32 ret; + dev = PA_NBMISC(Node); + val = Get_NB32(dev, 0xfc); + print_debug("Family_Model:"); print_debug_hex32(val); print_debug("\n"); + + family = ((val >> 8) & 0x0f) + ((val>>20) & 0xff); + model = ((val>>4) & 0x0f) | ((val>>(16-4)) & 0xf0); + stepping = val & 0xff; + print_debug("Family:"); print_debug_hex8(family); print_debug("\t"); + print_debug("Model:"); print_debug_hex8(model); print_debug("\t"); + print_debug("Stepping:"); print_debug_hex8(stepping); print_debug("\n"); + + valx = (family<<12) | (model<<4) | (stepping); + print_debug("converted:"); print_debug_hex32(valx); print_debug("\n"); + + switch (valx) { + case 0x10000: + ret = AMD_DR_A0A; + break; + case 0x10001: + ret = AMD_DR_A1B; + break; + case 0x10002: + ret = AMD_DR_A2; + break; + default: + ret = 0; + } + + return ret; +} + + +void raminit_amdmct(struct sys_info *sysinfo) +{ + struct MCTStatStruc *pMCTstat = &(sysinfo->MCTstat); + struct DCTStatStruc *pDCTstatA = sysinfo->DCTstatA; + + print_debug("raminit_amdmct begin:\n"); + + mctAutoInitMCT_D(pMCTstat, pDCTstatA); + + print_debug("raminit_amdmct end:\n"); +} diff --git a/src/northbridge/amd/amdfam10/raminit_sysinfo_in_ram.c b/src/northbridge/amd/amdfam10/raminit_sysinfo_in_ram.c new file mode 100644 index 0000000000..643c32c927 --- /dev/null +++ b/src/northbridge/amd/amdfam10/raminit_sysinfo_in_ram.c @@ -0,0 +1,81 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +static void set_htic_bit(u8 i, u32 val, u8 bit) +{ + u32 dword; + dword = pci_read_config32(NODE_PCI(i, 0), HT_INIT_CONTROL); + dword &= ~(1<<bit); + dword |= ((val & 1) <<bit); + pci_write_config32(NODE_PCI(i, 0), HT_INIT_CONTROL, dword); +} + + +static u32 get_htic_bit(u8 i, u8 bit) +{ + u32 dword; + dword = pci_read_config32(NODE_PCI(i, 0), HT_INIT_CONTROL); + dword &= (1<<bit); + return dword; +} + +static void wait_till_sysinfo_in_ram(void) +{ + while(1) { + /* give the NB a break, many CPUs spinning on one bit makes a + * lot of traffic and time is not too important to APs. + */ + udelay_tsc(1000); + if(get_htic_bit(0, 9)) return; + } +} + +static void set_sysinfo_in_ram(u32 val) +{ + set_htic_bit(0, val, 9); +} + +static void fill_mem_ctrl(u32 controllers, struct mem_controller *ctrl_a, const u8 *spd_addr) +{ + int i; + int j; + int index = 0; + struct mem_controller *ctrl; + for(i=0;i<controllers; i++) { + ctrl = &ctrl_a[i]; + ctrl->node_id = i; + ctrl->f0 = NODE_PCI(i, 0); + ctrl->f1 = NODE_PCI(i, 1); + ctrl->f2 = NODE_PCI(i, 2); + ctrl->f3 = NODE_PCI(i, 3); + ctrl->f4 = NODE_PCI(i, 4); + ctrl->f5 = NODE_PCI(i, 5); + + if(spd_addr == (void *)0) continue; + + ctrl->spd_switch_addr = spd_addr[index++]; + + for(j=0; j < 8; j++) { + ctrl->spd_addr[j] = spd_addr[index++]; + + } + } +} + diff --git a/src/northbridge/amd/amdfam10/reset_test.c b/src/northbridge/amd/amdfam10/reset_test.c new file mode 100644 index 0000000000..4298d6549f --- /dev/null +++ b/src/northbridge/amd/amdfam10/reset_test.c @@ -0,0 +1,169 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdint.h> +#include <cpu/x86/lapic.h> + +#define NODE_ID 0x60 +#define HT_INIT_CONTROL 0x6c +#define HTIC_ColdR_Detect (1<<4) +#define HTIC_BIOSR_Detect (1<<5) +#define HTIC_INIT_Detect (1<<6) + +/* mmconf is not ready */ +/* io_ext is not ready */ +static u32 cpu_init_detected(u8 nodeid) +{ + u32 htic; + device_t dev; + + dev = NODE_PCI(nodeid, 0); + htic = pci_io_read_config32(dev, HT_INIT_CONTROL); + + return !!(htic & HTIC_INIT_Detect); +} + +static u32 bios_reset_detected(void) +{ + u32 htic; + htic = pci_io_read_config32(PCI_DEV(CBB, CDB, 0), HT_INIT_CONTROL); + + return (htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect); +} + +static u32 cold_reset_detected(void) +{ + u32 htic; + htic = pci_io_read_config32(PCI_DEV(CBB, CDB, 0), HT_INIT_CONTROL); + + return !(htic & HTIC_ColdR_Detect); +} + +static u32 other_reset_detected(void) // other warm reset not started by BIOS +{ + u32 htic; + htic = pci_io_read_config32(PCI_DEV(CBB, CDB, 0), HT_INIT_CONTROL); + + return (htic & HTIC_ColdR_Detect) && (htic & HTIC_BIOSR_Detect); +} + +static void distinguish_cpu_resets(u8 nodeid) +{ + u32 htic; + device_t device; + device = NODE_PCI(nodeid, 0); + htic = pci_io_read_config32(device, HT_INIT_CONTROL); + htic |= HTIC_ColdR_Detect | HTIC_BIOSR_Detect | HTIC_INIT_Detect; + pci_io_write_config32(device, HT_INIT_CONTROL, htic); +} + +static u32 warm_reset_detect(u8 nodeid) +{ + u32 htic; + device_t device; + device = NODE_PCI(nodeid, 0); + htic = pci_io_read_config32(device, HT_INIT_CONTROL); + return (htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect); +} + +static void set_bios_reset(void) +{ + + u32 nodes; + u32 htic; + device_t dev; + int i; + + nodes = ((pci_read_config32(PCI_DEV(CBB, CDB, 0), 0x60) >> 4) & 7) + 1; + + for(i = 0; i < nodes; i++) { + dev = NODE_PCI(i,0); + htic = pci_read_config32(dev, HT_INIT_CONTROL); + htic &= ~HTIC_BIOSR_Detect; + pci_write_config32(dev, HT_INIT_CONTROL, htic); + } +} + + +/* Look up a which bus a given node/link combination is on. + * return 0 when we can't find the answer. + */ +static u8 node_link_to_bus(u8 node, u8 link) // node are 6 bit, and link three bit +{ + u32 reg; + u32 val; + + // put node and link in correct bit + val = ((node & 0x0f)<<4) | ((node & 0x30)<< (12-4)) | ((link & 0x07)<<8) ; + + for(reg = 0xE0; reg < 0xF0; reg += 0x04) { + u32 config_map; + config_map = pci_io_read_config32(PCI_DEV(CBB, CDB, 1), reg); + if ((config_map & 3) != 3) { + continue; + } + if ((config_map & (((63 & 0x0f)<<4) | ((63 & 0x30)<< (12-4)) | ((7 & 0x07)<<8) ) + ) == val ) + { + return (config_map >> 16) & 0xff; + } + } + +#if EXT_CONF_SUPPORT == 1 + // let's check that in extend space + // use the nodeid extend space to find out the bus for the linkn + u32 tempreg; + int i; + int j; + u32 cfg_map_dest; + device_t dev; + + cfg_map_dest = (1<<7)|(1<<6)|link; + + // three case: index_min==index_max, index_min+1=index_max; index_min+1<index_max + dev = NODE_PCI(node, 1); + for(j=0; j<64; j++) { + pci_io_write_config32(dev, 0x110, j | (6<<28)); + tempreg = pci_io_read_config32(dev, 0x114); + for(i=0; i<=3; i++) { + tempreg >>= (i*8); + if((tempreg & ((1<<7)|(1<<6)|0x3f)) == cfg_map_dest) { + return (i+(j<<2)); //busn_min + } + } + } +#endif + + return 0; +} + +static u32 get_sblk(void) +{ + u32 reg; + /* read PCI_DEV(CBB,CDB,0) 0x64 bit [8:9] to find out SbLink m */ + reg = pci_io_read_config32(PCI_DEV(CBB, CDB, 0), 0x64); + return ((reg>>8) & 3) ; +} + + +static u8 get_sbbusn(u8 sblk) +{ + return node_link_to_bus(0, sblk); +} + diff --git a/src/northbridge/amd/amdfam10/resourcemap.c b/src/northbridge/amd/amdfam10/resourcemap.c new file mode 100644 index 0000000000..a4f0e92d3b --- /dev/null +++ b/src/northbridge/amd/amdfam10/resourcemap.c @@ -0,0 +1,287 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static void setup_default_resource_map(void) +{ + static const u32 register_values[] = { + /* Careful set limit registers before base registers which contain + the enables */ + /* DRAM Limit i Registers + * F1:0x44 i = 0 + * F1:0x4C i = 1 + * F1:0x54 i = 2 + * F1:0x5C i = 3 + * F1:0x64 i = 4 + * F1:0x6C i = 5 + * F1:0x74 i = 6 + * F1:0x7C i = 7 + * [ 2: 0] Destination Node ID + * 000 = Node 0 + * 001 = Node 1 + * 010 = Node 2 + * 011 = Node 3 + * 100 = Node 4 + * 101 = Node 5 + * 110 = Node 6 + * 111 = Node 7 + * [ 7: 3] Reserved + * [10: 8] Interleave select + * specifies the values of A[14:12] to use with + * interleave enable. + * [15:11] Reserved + * [31:16] DRAM Limit Address i Bits 39-24 + * This field defines the upper address bits of a 40 bit + * address that define the end of the DRAM region. + */ + PCI_ADDR(CBB, CDB, 1, 0x44), 0x0000f8f8, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x4C), 0x0000f8f8, 0x00000001, + PCI_ADDR(CBB, CDB, 1, 0x54), 0x0000f8f8, 0x00000002, + PCI_ADDR(CBB, CDB, 1, 0x5C), 0x0000f8f8, 0x00000003, + PCI_ADDR(CBB, CDB, 1, 0x64), 0x0000f8f8, 0x00000004, + PCI_ADDR(CBB, CDB, 1, 0x6C), 0x0000f8f8, 0x00000005, + PCI_ADDR(CBB, CDB, 1, 0x74), 0x0000f8f8, 0x00000006, + PCI_ADDR(CBB, CDB, 1, 0x7C), 0x0000f8f8, 0x00000007, + /* DRAM Base i Registers + * F1:0x40 i = 0 + * F1:0x48 i = 1 + * F1:0x50 i = 2 + * F1:0x58 i = 3 + * F1:0x60 i = 4 + * F1:0x68 i = 5 + * F1:0x70 i = 6 + * F1:0x78 i = 7 + * [ 0: 0] Read Enable + * 0 = Reads Disabled + * 1 = Reads Enabled + * [ 1: 1] Write Enable + * 0 = Writes Disabled + * 1 = Writes Enabled + * [ 7: 2] Reserved + * [10: 8] Interleave Enable + * 000 = No interleave + * 001 = Interleave on A[12] (2 nodes) + * 010 = reserved + * 011 = Interleave on A[12] and A[14] (4 nodes) + * 100 = reserved + * 101 = reserved + * 110 = reserved + * 111 = Interleve on A[12] and A[13] and A[14] (8 nodes) + * [15:11] Reserved + * [13:16] DRAM Base Address i Bits 39-24 + * This field defines the upper address bits of a 40-bit + * address that define the start of the DRAM region. + */ + PCI_ADDR(CBB, CDB, 1, 0x40), 0x0000f8fc, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x48), 0x0000f8fc, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x50), 0x0000f8fc, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x58), 0x0000f8fc, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x60), 0x0000f8fc, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x68), 0x0000f8fc, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x70), 0x0000f8fc, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x78), 0x0000f8fc, 0x00000000, + + /* Memory-Mapped I/O Limit i Registers + * F1:0x84 i = 0 + * F1:0x8C i = 1 + * F1:0x94 i = 2 + * F1:0x9C i = 3 + * F1:0xA4 i = 4 + * F1:0xAC i = 5 + * F1:0xB4 i = 6 + * F1:0xBC i = 7 + * [ 2: 0] Destination Node ID + * 000 = Node 0 + * 001 = Node 1 + * 010 = Node 2 + * 011 = Node 3 + * 100 = Node 4 + * 101 = Node 5 + * 110 = Node 6 + * 111 = Node 7 + * [ 3: 3] Reserved + * [ 5: 4] Destination Link ID + * 00 = Link 0 + * 01 = Link 1 + * 10 = Link 2 + * 11 = Reserved + * [ 6: 6] Reserved + * [ 7: 7] Non-Posted + * 0 = CPU writes may be posted + * 1 = CPU writes must be non-posted + * [31: 8] Memory-Mapped I/O Limit Address i (39-16) + * This field defines the upp adddress bits of a 40-bit + * address that defines the end of a memory-mapped + * I/O region n + */ + PCI_ADDR(CBB, CDB, 1, 0x84), 0x00000048, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x8C), 0x00000048, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x94), 0x00000048, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x9C), 0x00000048, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xA4), 0x00000048, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xAC), 0x00000048, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xB4), 0x00000048, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xBC), 0x00000048, 0x00ffff00, + + /* Memory-Mapped I/O Base i Registers + * F1:0x80 i = 0 + * F1:0x88 i = 1 + * F1:0x90 i = 2 + * F1:0x98 i = 3 + * F1:0xA0 i = 4 + * F1:0xA8 i = 5 + * F1:0xB0 i = 6 + * F1:0xB8 i = 7 + * [ 0: 0] Read Enable + * 0 = Reads disabled + * 1 = Reads Enabled + * [ 1: 1] Write Enable + * 0 = Writes disabled + * 1 = Writes Enabled + * [ 2: 2] Cpu Disable + * 0 = Cpu can use this I/O range + * 1 = Cpu requests do not use this I/O range + * [ 3: 3] Lock + * 0 = base/limit registers i are read/write + * 1 = base/limit registers i are read-only + * [ 7: 4] Reserved + * [31: 8] Memory-Mapped I/O Base Address i (39-16) + * This field defines the upper address bits of a 40bit + * address that defines the start of memory-mapped + * I/O region i + */ + PCI_ADDR(CBB, CDB, 1, 0x80), 0x000000f0, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x88), 0x000000f0, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x90), 0x000000f0, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0x98), 0x000000f0, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xA0), 0x000000f0, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xA8), 0x000000f0, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xB0), 0x000000f0, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xB8), 0x000000f0, 0x00fc0003, + + /* PCI I/O Limit i Registers + * F1:0xC4 i = 0 + * F1:0xCC i = 1 + * F1:0xD4 i = 2 + * F1:0xDC i = 3 + * [ 2: 0] Destination Node ID + * 000 = Node 0 + * 001 = Node 1 + * 010 = Node 2 + * 011 = Node 3 + * 100 = Node 4 + * 101 = Node 5 + * 110 = Node 6 + * 111 = Node 7 + * [ 3: 3] Reserved + * [ 5: 4] Destination Link ID + * 00 = Link 0 + * 01 = Link 1 + * 10 = Link 2 + * 11 = reserved + * [11: 6] Reserved + * [24:12] PCI I/O Limit Address i + * This field defines the end of PCI I/O region n + * [31:25] Reserved + */ + PCI_ADDR(CBB, CDB, 1, 0xC4), 0xFE000FC8, 0x01fff000, + PCI_ADDR(CBB, CDB, 1, 0xCC), 0xFE000FC8, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xD4), 0xFE000FC8, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xDC), 0xFE000FC8, 0x00000000, + + /* PCI I/O Base i Registers + * F1:0xC0 i = 0 + * F1:0xC8 i = 1 + * F1:0xD0 i = 2 + * F1:0xD8 i = 3 + * [ 0: 0] Read Enable + * 0 = Reads Disabled + * 1 = Reads Enabled + * [ 1: 1] Write Enable + * 0 = Writes Disabled + * 1 = Writes Enabled + * [ 3: 2] Reserved + * [ 4: 4] VGA Enable + * 0 = VGA matches Disabled + * 1 = matches all address < 64K and where A[9:0] is in + * the range 3B0-3BB or 3C0-3DF independent of the + * base & limit registers + * [ 5: 5] ISA Enable + * 0 = ISA matches Disabled + * 1 = Blocks address < 64K and in the last 768 bytes of + * eack 1K block from matching agains this base/limit + * pair + * [11: 6] Reserved + * [24:12] PCI I/O Base i + * This field defines the start of PCI I/O region n + * [31:25] Reserved + */ + PCI_ADDR(CBB, CDB, 1, 0xC0), 0xFE000FCC, 0x00000003, + PCI_ADDR(CBB, CDB, 1, 0xC8), 0xFE000FCC, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xD0), 0xFE000FCC, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xD8), 0xFE000FCC, 0x00000000, + + /* Config Base and Limit i Registers + * F1:0xE0 i = 0 + * F1:0xE4 i = 1 + * F1:0xE8 i = 2 + * F1:0xEC i = 3 + * [ 0: 0] Read Enable + * 0 = Reads Disabled + * 1 = Reads Enabled + * [ 1: 1] Write Enable + * 0 = Writes Disabled + * 1 = Writes Enabled + * [ 2: 2] Device Number Compare Enable + * 0 = The ranges are based on bus number + * 1 = The ranges are ranges of devices on bus 0 + * [ 3: 3] Reserved + * [ 6: 4] Destination Node + * 000 = Node 0 + * 001 = Node 1 + * 010 = Node 2 + * 011 = Node 3 + * 100 = Node 4 + * 101 = Node 5 + * 110 = Node 6 + * 111 = Node 7 + * [ 7: 7] Reserved + * [ 9: 8] Destination Link + * 00 = Link 0 + * 01 = Link 1 + * 10 = Link 2 + * 11 - Reserved + * [15:10] Reserved + * [23:16] Bus Number Base i + * This field defines the lowest bus number in + * configuration region i + * [31:24] Bus Number Limit i + * This field defines the highest bus number in + * configuration regin i + */ + PCI_ADDR(CBB, CDB, 1, 0xE0), 0x0000FC88, 0xff000003, + PCI_ADDR(CBB, CDB, 1, 0xE4), 0x0000FC88, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xE8), 0x0000FC88, 0x00000000, + PCI_ADDR(CBB, CDB, 1, 0xEC), 0x0000FC88, 0x00000000, + }; + + u32 max; + max = sizeof(register_values)/sizeof(register_values[0]); + setup_resource_map(register_values, max); +} + diff --git a/src/northbridge/amd/amdfam10/root_complex/Config.lb b/src/northbridge/amd/amdfam10/root_complex/Config.lb new file mode 100644 index 0000000000..610e929159 --- /dev/null +++ b/src/northbridge/amd/amdfam10/root_complex/Config.lb @@ -0,0 +1 @@ +config chip.h diff --git a/src/northbridge/amd/amdfam10/root_complex/chip.h b/src/northbridge/amd/amdfam10/root_complex/chip.h new file mode 100644 index 0000000000..666147f949 --- /dev/null +++ b/src/northbridge/amd/amdfam10/root_complex/chip.h @@ -0,0 +1,24 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +struct northbridge_amd_amdfam10_root_complex_config +{ +}; + +extern struct chip_operations northbridge_amd_amdfam10_root_complex_ops; diff --git a/src/northbridge/amd/amdfam10/setup_resource_map.c b/src/northbridge/amd/amdfam10/setup_resource_map.c new file mode 100644 index 0000000000..f463a58a16 --- /dev/null +++ b/src/northbridge/amd/amdfam10/setup_resource_map.c @@ -0,0 +1,231 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#define RES_DEBUG 0 + +static void setup_resource_map(const u32 *register_values, u32 max) +{ + u32 i; +// print_debug("setting up resource map...."); + + for(i = 0; i < max; i += 3) { + device_t dev; + u32 where; + u32 reg; + + dev = register_values[i] & ~0xff; + where = register_values[i] & 0xff; + reg = pci_read_config32(dev, where); + reg &= register_values[i+1]; + reg |= register_values[i+2]; + pci_write_config32(dev, where, reg); + } +// print_debug("done.\n"); +} + + +static void setup_resource_map_offset(const u32 *register_values, + u32 max, u32 offset_pci_dev, + u32 offset_io_base) +{ + u32 i; +// print_debug("setting up resource map offset...."); + for(i = 0; i < max; i += 3) { + device_t dev; + u32 where; + unsigned long reg; + dev = (register_values[i] & ~0xfff) + offset_pci_dev; + where = register_values[i] & 0xfff; + reg = pci_read_config32(dev, where); + reg &= register_values[i+1]; + reg |= register_values[i+2] + offset_io_base; + pci_write_config32(dev, where, reg); + } +// print_debug("done.\n"); +} + +#define RES_PCI_IO 0x10 +#define RES_PORT_IO_8 0x22 +#define RES_PORT_IO_32 0x20 +#define RES_MEM_IO 0x40 + +static void setup_resource_map_x_offset(const u32 *register_values, u32 max, + u32 offset_pci_dev, u32 offset_io_base) +{ + u32 i; + +#if RES_DEBUG + print_debug("setting up resource map ex offset...."); + +#endif + +#if RES_DEBUG + print_debug("\n"); +#endif + for(i = 0; i < max; i += 4) { +#if RES_DEBUG + printk_debug("%04x: %02x %08x <- & %08x | %08x\n", + i/4, register_values[i], + register_values[i+1] + ( (register_values[i]==RES_PCI_IO) ? offset_pci_dev : 0), + register_values[i+2], + register_values[i+3] + ( ( (register_values[i] & RES_PORT_IO_32) == RES_PORT_IO_32) ? offset_io_base : 0) + ); +#endif + switch (register_values[i]) { + case RES_PCI_IO: //PCI + { + device_t dev; + u32 where; + u32 reg; + dev = (register_values[i+1] & ~0xfff) + offset_pci_dev; + where = register_values[i+1] & 0xfff; + reg = pci_read_config32(dev, where); + reg &= register_values[i+2]; + reg |= register_values[i+3]; + pci_write_config32(dev, where, reg); + } + break; + case RES_PORT_IO_8: // io 8 + { + u32 where; + u32 reg; + where = register_values[i+1] + offset_io_base; + reg = inb(where); + reg &= register_values[i+2]; + reg |= register_values[i+3]; + outb(reg, where); + } + break; + case RES_PORT_IO_32: //io32 + { + u32 where; + u32 reg; + where = register_values[i+1] + offset_io_base; + reg = inl(where); + reg &= register_values[i+2]; + reg |= register_values[i+3]; + outl(reg, where); + } + break; + } // switch + + + } + +#if RES_DEBUG + print_debug("done.\n"); +#endif +} +static void setup_resource_map_x(const u32 *register_values, u32 max) +{ + u32 i; + +#if RES_DEBUG + print_debug("setting up resource map ex offset...."); +#endif + +#if RES_DEBUG + print_debug("\n"); +#endif + for(i = 0; i < max; i += 4) { +#if RES_DEBUG + printk_debug("%04x: %02x %08x <- & %08x | %08x\n", + i/4, register_values[i],register_values[i+1], register_values[i+2], register_values[i+3]); +#endif + switch (register_values[i]) { + case RES_PCI_IO: //PCI + { + device_t dev; + u32 where; + u32 reg; + dev = register_values[i+1] & ~0xff; + where = register_values[i+1] & 0xff; + reg = pci_read_config32(dev, where); + reg &= register_values[i+2]; + reg |= register_values[i+3]; + pci_write_config32(dev, where, reg); + } + break; + case RES_PORT_IO_8: // io 8 + { + u32 where; + u32 reg; + where = register_values[i+1]; + reg = inb(where); + reg &= register_values[i+2]; + reg |= register_values[i+3]; + outb(reg, where); + } + break; + case RES_PORT_IO_32: //io32 + { + u32 where; + u32 reg; + where = register_values[i+1]; + reg = inl(where); + reg &= register_values[i+2]; + reg |= register_values[i+3]; + outl(reg, where); + } + break; + } // switch + + + } + +#if RES_DEBUG + print_debug("done.\n"); +#endif +} + +static void setup_iob_resource_map(const u32 *register_values, u32 max) +{ + u32 i; + + for(i = 0; i < max; i += 3) { + u32 where; + u32 reg; + + where = register_values[i]; + reg = inb(where); + reg &= register_values[i+1]; + reg |= register_values[i+2]; + outb(reg, where); + } +} + +static void setup_io_resource_map(const u32 *register_values, u32 max) +{ + u32 i; + + for(i = 0; i < max; i += 3) { + u32 where; + u32 reg; + + where = register_values[i]; + reg = inl(where); + reg &= register_values[i+1]; + reg |= register_values[i+2]; + + outl(reg, where); + } +} + + diff --git a/src/northbridge/amd/amdfam10/spd_ddr2.h b/src/northbridge/amd/amdfam10/spd_ddr2.h new file mode 100644 index 0000000000..176f76adee --- /dev/null +++ b/src/northbridge/amd/amdfam10/spd_ddr2.h @@ -0,0 +1,88 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* SPDs for DDR2 SDRAM */ +#define SPD_MEM_TYPE 2 + #define SPD_MEM_TYPE_SDRAM_DDR 0x07 + #define SPD_MEM_TYPE_SDRAM_DDR2 0x08 + +#define SPD_DIMM_TYPE 20 /* x bit0 or bit4 =1 mean registered*/ + #define SPD_DIMM_TYPE_RDIMM (1<<0) + #define SPD_DIMM_TYPE_UDIMM (1<<1) + #define SPD_DIMM_TYPE_SODIMM (1<<2) + #define SPD_DIMM_TYPE_uDIMM (1<<3) + #define SPD_DIMM_TYPE_mRDIMM (1<<4) + #define SPD_DIMM_TYPE_mUDIMM (1<<5) +#define SPD_MOD_ATTRIB 21 + #define SPD_MOD_ATTRIB_DIFCK 0x20 + #define SPD_MOD_ATTRIB_REGADC 0x11 /* x */ + #define SPD_MOD_ATTRIB_PROBE 0x40 + +#define SPD_DEV_ATTRIB 22 /* Device attributes --- general */ +#define SPD_DIMM_CONF_TYPE 11 + #define SPD_DIMM_CONF_TYPE_ECC 0x02 + #define SPD_DIMM_CONF_TYPE_ADDR_PARITY 0x04 /* ? */ + +#define SPD_ROW_NUM 3 /* Number of Row addresses */ +#define SPD_COL_NUM 4 /* Number of Column addresses */ +#define SPD_BANK_NUM 17 /* SDRAM Device attributes - Number of Banks on + SDRAM device, it could be 0x4, 0x8, so address + lines for that would be 2, and 3 */ + +/* Number of Ranks bit [2:0], Package (bit4, 1=stack, 0=planr), Height bit[7:5] */ +#define SPD_MOD_ATTRIB_RANK 5 + #define SPD_MOD_ATTRIB_RANK_NUM_SHIFT 0 + #define SPD_MOD_ATTRIB_RANK_NUM_MASK 0x07 + #define SPD_MOD_ATTRIB_RANK_NUM_BASE 1 + #define SPD_MOD_ATTRIB_RANK_NUM_MIN 1 + #define SPD_MOD_ATTRIB_RANK_NUM_MAX 8 + +#define SPD_RANK_SIZE 31 /* Only one bit is set */ + #define SPD_RANK_SIZE_1GB (1<<0) + #define SPD_RANK_SIZE_2GB (1<<1) + #define SPD_RANK_SIZE_4GB (1<<2) + #define SPD_RANK_SIZE_8GB (1<<3) + #define SPD_RANK_SIZE_16GB (1<<4) + #define SPD_RANK_SIZE_128MB (1<<5) + #define SPD_RANK_SIZE_256MB (1<<6) + #define SPD_RANK_SIZE_512MB (1<<7) + +#define SPD_DATA_WIDTH 6 /* valid value 0, 32, 33, 36, 64, 72, 80, 128, 144, 254, 255 */ +#define SPD_PRI_WIDTH 13 /* Primary SDRAM Width, it could be 0x08 or 0x10 */ +#define SPD_ERR_WIDTH 14 /* Error Checking SDRAM Width, it could be 0x08 or 0x10 */ + +#define SPD_CAS_LAT 18 /* SDRAM Device Attributes -- CAS Latency */ + #define SPD_CAS_LAT_2 (1<<2) + #define SPD_CAS_LAT_3 (1<<3) + #define SPD_CAS_LAT_4 (1<<4) + #define SPD_CAS_LAT_5 (1<<5) + #define SPD_CAS_LAT_6 (1<<6) + +#define SPD_TRP 27 /* bit [7:2] = 1-63 ns, bit [1:0] 0.25ns+, final value ((val>>2) + (val & 3) * 0.25)ns */ +#define SPD_TRRD 28 +#define SPD_TRCD 29 +#define SPD_TRAS 30 +#define SPD_TWR 36 /* x */ +#define SPD_TWTR 37 /* x */ +#define SPD_TRTP 38 /* x */ + +#define SPD_TRC 41 /* add byte 0x40 bit [3:1] , so final val41+ table[((val40>>1) & 0x7)] ... table[]={0, 0.25, 0.33, 0.5, 0.75, 0, 0}*/ +#define SPD_TRFC 42 /* add byte 0x40 bit [6:4] , so final val42+ table[((val40>>4) & 0x7)] + (val40 & 1)*256*/ + +#define SPD_TREF 12 diff --git a/src/northbridge/amd/amdfam10/ssdt.dsl b/src/northbridge/amd/amdfam10/ssdt.dsl new file mode 100644 index 0000000000..dae5bb87cd --- /dev/null +++ b/src/northbridge/amd/amdfam10/ssdt.dsl @@ -0,0 +1,346 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Make sure HC_NUMS and HC_POSSIBLE_NUM setting is consistent to this file + */ + +DefinitionBlock ("SSDT.aml", "SSDT", 1, "AMD-FAM10", "AMD-ACPI", 100925440) +{ + /* + * These objects were referenced but not defined in this table + */ + External (\_SB_.PCI0, DeviceObj) + + Scope (\_SB.PCI0) + { + Name (BUSN, Package (0x20) /* HC_NUMS */ + { + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0x10101010, + 0x11111111, + 0x12121212, + 0x13131313, + 0x14141414, + 0x15151515, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc + }) + Name (MMIO, Package (0x80) /* HC_NUMS * 4 */ + { + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0x11111111, + 0x22222222, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0x11111111, + 0x22222222, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0x11111111, + 0x22222222, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0x11111111, + 0x22222222, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0x11111111, + 0x22222222, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888 + }) + Name (PCIO, Package (0x40) /* HC_NUMS * 2 */ + { + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0xaaaaaaaa, + 0xbbbbbbbb, + 0xcccccccc, + 0xdddddddd, + 0xeeeeeeee, + 0x77777777, + 0x88888888, + 0x99999999, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x99999999, + 0xaaaaaaaa, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444 + }) + Name (SBLK, 0x11) + Name (TOM1, 0xaaaaaaaa) + Name (SBDN, 0xbbbbbbbb) + Name (HCLK, Package (0x20) /* HC_POSSIBLE_NUM */ + { + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888 + }) + Name (HCDN, Package (0x20) /* HC_POSSIBLE_NUM */ + { + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888, + 0x11111111, + 0x22222222, + 0x33333333, + 0x44444444, + 0x55555555, + 0x66666666, + 0x77777777, + 0x88888888 + }) + Name (CBB, 0x99) + Name (CBST, 0x88) + Name (CBB2, 0x77) + Name (CBS2, 0x66) + + } +} + diff --git a/src/northbridge/amd/amdfam10/sspr1.dsl b/src/northbridge/amd/amdfam10/sspr1.dsl new file mode 100644 index 0000000000..b0bc3cb252 --- /dev/null +++ b/src/northbridge/amd/amdfam10/sspr1.dsl @@ -0,0 +1,39 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +DefinitionBlock ("SSPR.aml", "SSDT", 1, "AMD-FAM10", "AMD-ACPI", 100925441) +{ + Scope (\_SB) + { + Processor (\_SB.CPAA, 0xbb, 0x120, 6) // CPU0 and 0x01 need to be updated + { + Name(_PCT, Package () + { + ResourceTemplate() {Register (FFixedHW, 0, 0, 0)}, //PERF_CTRL + ResourceTemplate() {Register (FFixedHW, 0, 0, 0)}, //PERF_STATUS + }) + + Name(_PSS, Package() + { + Package(0x06) {0x1111, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + }) + } + + } +} diff --git a/src/northbridge/amd/amdfam10/sspr2.dsl b/src/northbridge/amd/amdfam10/sspr2.dsl new file mode 100644 index 0000000000..d66a107afa --- /dev/null +++ b/src/northbridge/amd/amdfam10/sspr2.dsl @@ -0,0 +1,40 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +DefinitionBlock ("SSPR.aml", "SSDT", 1, "AMD-FAM10", "AMD-ACPI", 100925441) +{ + Scope (\_SB) + { + Processor (\_SB.CPAA, 0xbb, 0x120, 6) // CPU0 and 0x01 need to be updated + { + Name(_PCT, Package () + { + ResourceTemplate() {Register (FFixedHW, 0, 0, 0)}, //PERF_CTRL + ResourceTemplate() {Register (FFixedHW, 0, 0, 0)}, //PERF_STATUS + }) + + Name(_PSS, Package() + { + Package(0x06) {0x1111, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + Package(0x06) {0x7777, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + }) + } + + } +} diff --git a/src/northbridge/amd/amdfam10/sspr3.dsl b/src/northbridge/amd/amdfam10/sspr3.dsl new file mode 100644 index 0000000000..62709824b4 --- /dev/null +++ b/src/northbridge/amd/amdfam10/sspr3.dsl @@ -0,0 +1,41 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +DefinitionBlock ("SSPR.aml", "SSDT", 1, "AMD-FAM10", "AMD-ACPI", 100925441) +{ + Scope (\_SB) + { + Processor (\_SB.CPAA, 0xbb, 0x120, 6) // CPU0 and 0x01 need to be updated + { + Name(_PCT, Package () + { + ResourceTemplate() {Register (FFixedHW, 0, 0, 0)}, //PERF_CTRL + ResourceTemplate() {Register (FFixedHW, 0, 0, 0)}, //PERF_STATUS + }) + + Name(_PSS, Package() + { + Package(0x06) {0x1111, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + Package(0x06) {0x7777, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + Package(0x06) {0x8888, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + }) + } + + } +} diff --git a/src/northbridge/amd/amdfam10/sspr4.dsl b/src/northbridge/amd/amdfam10/sspr4.dsl new file mode 100644 index 0000000000..5634d0fd8e --- /dev/null +++ b/src/northbridge/amd/amdfam10/sspr4.dsl @@ -0,0 +1,42 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +DefinitionBlock ("SSPR.aml", "SSDT", 1, "AMD-FAM10", "AMD-ACPI", 100925441) +{ + Scope (\_SB) + { + Processor (\_SB.CPAA, 0xbb, 0x120, 6) // CPU0 and 0x01 need to be updated + { + Name(_PCT, Package () + { + ResourceTemplate() {Register (FFixedHW, 0, 0, 0)}, //PERF_CTRL + ResourceTemplate() {Register (FFixedHW, 0, 0, 0)}, //PERF_STATUS + }) + + Name(_PSS, Package() + { + Package(0x06) {0x1111, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + Package(0x06) {0x7777, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + Package(0x06) {0x8888, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + Package(0x06) {0x9999, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + }) + } + + } +} diff --git a/src/northbridge/amd/amdfam10/sspr5.dsl b/src/northbridge/amd/amdfam10/sspr5.dsl new file mode 100644 index 0000000000..d63adff512 --- /dev/null +++ b/src/northbridge/amd/amdfam10/sspr5.dsl @@ -0,0 +1,43 @@ +/* + * This file is part of the LinuxBIOS 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +DefinitionBlock ("SSPR.aml", "SSDT", 1, "AMD-FAM10", "AMD-ACPI", 100925441) +{ + Scope (\_SB) + { + Processor (\_SB.CPAA, 0xbb, 0x120, 6) // CPU0 and 0x01 need to be updated + { + Name(_PCT, Package () + { + ResourceTemplate() {Register (FFixedHW, 0, 0, 0)}, //PERF_CTRL + ResourceTemplate() {Register (FFixedHW, 0, 0, 0)}, //PERF_STATUS + }) + + Name(_PSS, Package() + { + Package(0x06) {0x1111, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + Package(0x06) {0x7777, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + Package(0x06) {0x8888, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + Package(0x06) {0x9999, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + Package(0x06) {0xaaaa, 0x222222, 0x3333, 0x4444, 0x55, 0x66 }, + }) + } + + } +} |