summaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdfam10
diff options
context:
space:
mode:
authorMarc Jones <marc.jones@amd.com>2007-12-19 01:32:08 +0000
committerMarc Jones <marc.jones@amd.com>2007-12-19 01:32:08 +0000
commit8ae8c8822068ef1722c08073ffa4ecc25633cbee (patch)
tree8c7bbf2f7b791081e486439a9b7ffb2fd6e649ac /src/northbridge/amd/amdfam10
parent2006b38fed2f5f3680de1736f7fc878823f2f93b (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')
-rw-r--r--src/northbridge/amd/amdfam10/Config.lb79
-rw-r--r--src/northbridge/amd/amdfam10/amdfam10.h1164
-rw-r--r--src/northbridge/amd/amdfam10/amdfam10_acpi.c382
-rw-r--r--src/northbridge/amd/amdfam10/amdfam10_conf.c874
-rw-r--r--src/northbridge/amd/amdfam10/amdfam10_nums.h41
-rw-r--r--src/northbridge/amd/amdfam10/amdfam10_pci.c73
-rw-r--r--src/northbridge/amd/amdfam10/chip.h24
-rw-r--r--src/northbridge/amd/amdfam10/debug.c331
-rw-r--r--src/northbridge/amd/amdfam10/early_ht.c175
-rw-r--r--src/northbridge/amd/amdfam10/get_pci1234.c118
-rw-r--r--src/northbridge/amd/amdfam10/misc_control.c155
-rw-r--r--src/northbridge/amd/amdfam10/northbridge.c1477
-rw-r--r--src/northbridge/amd/amdfam10/northbridge.h25
-rw-r--r--src/northbridge/amd/amdfam10/raminit.h73
-rw-r--r--src/northbridge/amd/amdfam10/raminit_amdmct.c155
-rw-r--r--src/northbridge/amd/amdfam10/raminit_sysinfo_in_ram.c81
-rw-r--r--src/northbridge/amd/amdfam10/reset_test.c169
-rw-r--r--src/northbridge/amd/amdfam10/resourcemap.c287
-rw-r--r--src/northbridge/amd/amdfam10/root_complex/Config.lb1
-rw-r--r--src/northbridge/amd/amdfam10/root_complex/chip.h24
-rw-r--r--src/northbridge/amd/amdfam10/setup_resource_map.c231
-rw-r--r--src/northbridge/amd/amdfam10/spd_ddr2.h88
-rw-r--r--src/northbridge/amd/amdfam10/ssdt.dsl346
-rw-r--r--src/northbridge/amd/amdfam10/sspr1.dsl39
-rw-r--r--src/northbridge/amd/amdfam10/sspr2.dsl40
-rw-r--r--src/northbridge/amd/amdfam10/sspr3.dsl41
-rw-r--r--src/northbridge/amd/amdfam10/sspr4.dsl42
-rw-r--r--src/northbridge/amd/amdfam10/sspr5.dsl43
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 },
+ })
+ }
+
+ }
+}