summaryrefslogtreecommitdiff
path: root/src/southbridge
diff options
context:
space:
mode:
Diffstat (limited to 'src/southbridge')
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sb700/Makefile.inc5
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sb700/early_setup.c44
-rwxr-xr-xsrc/southbridge/amd/sb700/pmio.c55
-rwxr-xr-xsrc/southbridge/amd/sb700/pmio.h34
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sb700/reset.c46
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sb700/sata.c2
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sb700/sb700.h10
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sb700/sm.c28
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sb700/smbus.c89
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sb700/smbus.h10
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sb700/usb.c1
-rw-r--r--src/southbridge/amd/sr5650/Makefile.inc2
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sr5650/cmn.h10
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sr5650/early_setup.c196
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sr5650/pcie.c86
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sr5650/sr5650.c25
-rwxr-xr-x[-rw-r--r--]src/southbridge/amd/sr5650/sr5650.h7
17 files changed, 434 insertions, 216 deletions
diff --git a/src/southbridge/amd/sb700/Makefile.inc b/src/southbridge/amd/sb700/Makefile.inc
index 8e8e0297db..e174e8b347 100644..100755
--- a/src/southbridge/amd/sb700/Makefile.inc
+++ b/src/southbridge/amd/sb700/Makefile.inc
@@ -1,11 +1,16 @@
driver-y += sb700.c
driver-y += usb.c
driver-y += lpc.c
+driver-y += smbus.c
driver-y += sm.c
driver-y += ide.c
driver-y += sata.c
driver-y += hda.c
driver-y += pci.c
ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += fadt.c
+romstage-y += reset.c
ramstage-y += reset.c
romstage-y += enable_usbdebug.c
+
+romstage-y += early_setup.c
+romstage-y += smbus.c
diff --git a/src/southbridge/amd/sb700/early_setup.c b/src/southbridge/amd/sb700/early_setup.c
index a5e76c7a05..1f46da2228 100644..100755
--- a/src/southbridge/amd/sb700/early_setup.c
+++ b/src/southbridge/amd/sb700/early_setup.c
@@ -20,14 +20,19 @@
#ifndef _SB700_EARLY_SETUP_C_
#define _SB700_EARLY_SETUP_C_
+#include <stdint.h>
+#include <arch/cpu.h>
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+
#include <reset.h>
#include <arch/cpu.h>
#include <cbmem.h>
#include "sb700.h"
-#include "smbus.c"
+#include "smbus.h"
-#define SMBUS_IO_BASE 0x6000 /* Is it a temporary SMBus I/O base address? */
- /*SIZE 0x40 */
static void pmio_write(u8 reg, u8 value)
{
@@ -129,7 +134,7 @@ static u8 set_sb700_revision(void)
* Console output through any port besides 0x3f8 is unsupported.
* If you use FWH ROMs, you have to setup IDSEL.
***************************************/
-static void sb7xx_51xx_lpc_init(void)
+void sb7xx_51xx_lpc_init(void)
{
u8 reg8;
u32 reg32;
@@ -216,7 +221,7 @@ void sb7xx_51xx_disable_wideio(u8 wio_index)
}
/* what is its usage? */
-static u32 get_sbdn(u32 bus)
+u32 __attribute__ ((weak)) get_sbdn(u32 bus)
{
device_t dev;
@@ -233,7 +238,7 @@ static u8 dual_core(void)
/*
* RPR 2.4 C-state and VID/FID change for the K8 platform.
*/
-static void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn)
+void __attribute__((weak)) enable_fid_change_on_sb(u32 sbbusn, u32 sbdn)
{
u8 byte;
byte = pmio_read(0x9a);
@@ -284,22 +289,6 @@ static void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn)
pmio_write(0x67, 0x6);
}
-void hard_reset(void)
-{
- set_bios_reset();
-
- /* full reset */
- outb(0x0a, 0x0cf9);
- outb(0x0e, 0x0cf9);
-}
-
-void soft_reset(void)
-{
- set_bios_reset();
- /* link reset */
- outb(0x06, 0x0cf9);
-}
-
void sb7xx_51xx_pci_port80(void)
{
u8 byte;
@@ -681,7 +670,7 @@ static void sb700_por_init(void)
/*
* It should be called during early POST after memory detection and BIOS shadowing but before PCI bus enumeration.
*/
-static void sb7xx_51xx_before_pci_init(void)
+void sb7xx_51xx_before_pci_init(void)
{
sb700_pci_cfg();
}
@@ -689,18 +678,13 @@ static void sb7xx_51xx_before_pci_init(void)
/*
* This function should be called after enable_sb700_smbus().
*/
-static void sb7xx_51xx_early_setup(void)
+void sb7xx_51xx_early_setup(void)
{
printk(BIOS_INFO, "sb700_early_setup()\n");
sb700_por_init();
sb700_acpi_init();
}
-static int smbus_read_byte(u32 device, u32 address)
-{
- return do_smbus_read_byte(SMBUS_IO_BASE, device, address);
-}
-
int s3_save_nvram_early(u32 dword, int size, int nvram_pos)
{
int i;
@@ -732,7 +716,7 @@ int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos)
}
#if CONFIG_HAVE_ACPI_RESUME == 1
-static int acpi_is_wakeup_early(void)
+int acpi_is_wakeup_early(void)
{
u16 tmp;
tmp = inw(ACPI_PM1_CNT_BLK);
diff --git a/src/southbridge/amd/sb700/pmio.c b/src/southbridge/amd/sb700/pmio.c
new file mode 100755
index 0000000000..baded54ba6
--- /dev/null
+++ b/src/southbridge/amd/sb700/pmio.c
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 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 <arch/io.h> /*inb, outb*/
+#include "pmio.h"
+
+static void pmio_write_index(u16 port_base, u8 reg, u8 value)
+{
+ outb(reg, port_base);
+ outb(value, port_base + 1);
+}
+
+static u8 pmio_read_index(u16 port_base, u8 reg)
+{
+ outb(reg, port_base);
+ return inb(port_base + 1);
+}
+
+void pm_iowrite(u8 reg, u8 value)
+{
+ pmio_write_index(PM_INDEX, reg, value);
+}
+
+u8 pm_ioread(u8 reg)
+{
+ return pmio_read_index(PM_INDEX, reg);
+}
+
+void pm2_iowrite(u8 reg, u8 value)
+{
+ pmio_write_index(PM2_INDEX, reg, value);
+}
+
+u8 pm2_ioread(u8 reg)
+{
+ return pmio_read_index(PM2_INDEX, reg);
+}
+
diff --git a/src/southbridge/amd/sb700/pmio.h b/src/southbridge/amd/sb700/pmio.h
new file mode 100755
index 0000000000..207fdc24ab
--- /dev/null
+++ b/src/southbridge/amd/sb700/pmio.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 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 _PMIO_H_
+#define _PMIO_H_
+
+#define PM_INDEX 0xCD6
+#define PM_DATA 0xCD7
+#define PM2_INDEX 0xCD0
+#define PM2_DATA 0xCD1
+
+void pm_iowrite(u8 reg, u8 value);
+u8 pm_ioread(u8 reg);
+void pm2_iowrite(u8 reg, u8 value);
+u8 pm2_ioread(u8 reg);
+
+#endif
diff --git a/src/southbridge/amd/sb700/reset.c b/src/southbridge/amd/sb700/reset.c
index 32ee66b4b5..27ca32eb5e 100644..100755
--- a/src/southbridge/amd/sb700/reset.c
+++ b/src/southbridge/amd/sb700/reset.c
@@ -1,7 +1,7 @@
/*
* This file is part of the coreboot project.
*
- * Copyright (C) 2010 Advanced Micro Devices, Inc.
+ * Copyright (C) 2010 - 2011 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
@@ -17,17 +17,51 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <reset.h>
-#include <arch/io.h>
-#include <arch/romcc_io.h>
+#include <reset.h> /* hard_reset, soft_rest*/
+#include <arch/io.h> /* inb, outb */
+#include <arch/romcc_io.h> /* pci_read_config32, device_t, PCI_DEV */
-#include "../../../northbridge/amd/amdk8/reset_test.c"
+#define HT_INIT_CONTROL 0x6C
+#define HTIC_BIOSR_Detect (1<<5)
+
+#if CONFIG_MAX_PHYSICAL_CPUS > 32
+#define NODE_PCI(x, fn) ((x<32)?(PCI_DEV(CONFIG_CBB,(CONFIG_CDB+x),fn)):(PCI_DEV((CONFIG_CBB-1),(CONFIG_CDB+x-32),fn)))
+#else
+#define NODE_PCI(x, fn) PCI_DEV(CONFIG_CBB,(CONFIG_CDB+x),fn)
+#endif
+
+static void set_bios_reset(void)
+{
+ u32 nodes;
+ u32 htic;
+ device_t dev;
+ int i;
+
+ nodes = ((pci_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_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);
+ }
+}
void hard_reset(void)
{
set_bios_reset();
+
/* Try rebooting through port 0xcf9 */
- /* Actually it is not a real hard_reset --- it only reset coherent link table, but not reset link freq and width */
+ /* Actually it is not a real hard_reset
+ * --- it only reset coherent link table, but not reset link freq and width
+ */
outb((0 << 3) | (0 << 2) | (1 << 1), 0xcf9);
outb((0 << 3) | (1 << 2) | (1 << 1), 0xcf9);
}
+
+void soft_reset(void)
+{
+ set_bios_reset();
+ /* link reset */
+ outb(0x06, 0x0cf9);
+}
+
diff --git a/src/southbridge/amd/sb700/sata.c b/src/southbridge/amd/sb700/sata.c
index 89eba4b168..411baf571f 100644..100755
--- a/src/southbridge/amd/sb700/sata.c
+++ b/src/southbridge/amd/sb700/sata.c
@@ -280,7 +280,7 @@ static void sata_init(struct device *dev)
}
static struct pci_operations lops_pci = {
- /* .set_subsystem = pci_dev_set_subsystem, */
+ .set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations sata_ops = {
diff --git a/src/southbridge/amd/sb700/sb700.h b/src/southbridge/amd/sb700/sb700.h
index 60eea47ee7..794dd96a81 100644..100755
--- a/src/southbridge/amd/sb700/sb700.h
+++ b/src/southbridge/amd/sb700/sb700.h
@@ -63,8 +63,11 @@ void sb7xx_51xx_enable(device_t dev);
#ifdef __PRE_RAM__
void sb7xx_51xx_lpc_port80(void);
void sb7xx_51xx_pci_port80(void);
+void sb7xx_51xx_lpc_init(void);
void sb7xx_51xx_enable_wideio(u8 wio_index, u16 base);
void sb7xx_51xx_disable_wideio(u8 wio_index);
+void sb7xx_51xx_early_setup(void);
+void sb7xx_51xx_before_pci_init(void);
#else
#include <device/pci.h>
/* allow override in mainboard.c */
@@ -72,8 +75,15 @@ void sb7xx_51xx_setup_sata_phys(struct device *dev);
#endif
+#if CONFIG_HAVE_ACPI_RESUME == 1
+int acpi_is_wakeup_early(void);
+#endif
+
int s3_save_nvram_early(u32 dword, int size, int nvram_pos);
int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos);
void enable_usbdebug(unsigned int port);
+
+u32 __attribute__ ((weak)) get_sbdn(u32 bus);
+void __attribute__((weak)) enable_fid_change_on_sb(u32 sbbusn, u32 sbdn);
#endif /* SB700_H */
diff --git a/src/southbridge/amd/sb700/sm.c b/src/southbridge/amd/sb700/sm.c
index 7d341df327..05065b6dbe 100644..100755
--- a/src/southbridge/amd/sb700/sm.c
+++ b/src/southbridge/amd/sb700/sm.c
@@ -30,7 +30,7 @@
#include <arch/ioapic.h>
#include <stdlib.h>
#include "sb700.h"
-#include "smbus.c"
+#include "smbus.h"
#define NMI_OFF 0
@@ -95,6 +95,20 @@ static void sm_init(device_t dev)
byte |= 4 << 2; /* set NumSerIrqBits=4 */
pci_write_config8(dev, 0x69, byte);
+ /* Sx State Settings
+ * Note: These 2 registers need to be set correctly for the S-state
+ * to work properly. Otherwise the system may hang during resume
+ * from the S-state.
+ */
+ /*Use 8us clock for delays in the S-state resume timing sequence.*/
+ byte = pm_ioread(0x65);
+ byte &= ~(1 << 7);
+ pm_iowrite(0x65, byte);
+ /* Delay the APIC interrupt to the CPU until the system has fully resumed from the S-state. */
+ byte = pm_ioread(0x68);
+ byte |= 1 << 2;
+ pm_iowrite(0x68, byte);
+
/* IRQ0From8254 */
byte = pci_read_config8(dev, 0x41);
byte &= ~(1 << 7);
@@ -219,10 +233,10 @@ static void sm_init(device_t dev)
* Transactions for the K8 Platform (for All Revisions) */
abcfg_reg(0x10090, 1 << 8, 1 << 8);
- /* ACPI_SOFT_CLOCK_THROTTLE_PERIOD */
+ /* Set ACPI Software clock Throttling Period to 244 us*/
byte = pm_ioread(0x68);
byte &= ~(3 << 6);
- byte |= (2 << 6); /* 224us */
+ byte |= (2 << 6); /* 244us */
pm_iowrite(0x68, byte);
if (REV_SB700_A15 == rev) {
@@ -367,16 +381,16 @@ static void sb700_sm_read_resources(device_t dev)
res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */
res->align = 8;
res->gran = 8;
- res->flags = IORESOURCE_MEM | IORESOURCE_FIXED;
+ res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_RESERVE | IORESOURCE_ASSIGNED;
- /* Linux ACPI crashes when it is 1. For late debugging. */
+ /* HPET */
res = new_resource(dev, 0xB4); /* TODO: test hpet */
res->base = 0xfed00000; /* reset hpet to widely accepted address */
res->size = 0x400;
res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */
res->align = 8;
res->gran = 8;
- res->flags = IORESOURCE_MEM | IORESOURCE_FIXED;
+ res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_RESERVE | IORESOURCE_ASSIGNED;
/* dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; */
@@ -387,7 +401,7 @@ static void sb700_sm_read_resources(device_t dev)
res->limit = 0xFFFFUL; /* res->base + res->size -1; */
res->align = 8;
res->gran = 8;
- res->flags = IORESOURCE_IO | IORESOURCE_FIXED;
+ res->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_RESERVE | IORESOURCE_ASSIGNED;
compact_resources(dev);
}
diff --git a/src/southbridge/amd/sb700/smbus.c b/src/southbridge/amd/sb700/smbus.c
index e47bceed47..6edc3de80c 100644..100755
--- a/src/southbridge/amd/sb700/smbus.c
+++ b/src/southbridge/amd/sb700/smbus.c
@@ -22,6 +22,51 @@
#include "smbus.h"
+void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val)
+{
+ u32 tmp;
+
+ outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX);
+ tmp = inl(AB_DATA);
+ /* rpr 4.2
+ * For certain revisions of the chip, the ABCFG registers,
+ * with an address of 0x100NN (where 'N' is any hexadecimal
+ * number), require an extra programming step.*/
+ reg_addr & 0x10000 ? outl(0, AB_INDX) : NULL;
+
+ tmp &= ~mask;
+ tmp |= val;
+
+ /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<30 | reg_addr); */
+ outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX); /* probably we dont have to do it again. */
+ outl(tmp, AB_DATA);
+ reg_addr & 0x10000 ? outl(0, AB_INDX) : NULL;
+}
+
+/* space = 0: AX_INDXC, AX_DATAC
+ * space = 1: AX_INDXP, AX_DATAP
+ */
+void alink_ax_indx(u32 space, u32 axindc, u32 mask, u32 val)
+{
+ u32 tmp;
+
+ /* read axindc to tmp */
+ outl(space << 30 | space << 3 | 0x30, AB_INDX);
+ outl(axindc, AB_DATA);
+ outl(space << 30 | space << 3 | 0x34, AB_INDX);
+ tmp = inl(AB_DATA);
+
+ tmp &= ~mask;
+ tmp |= val;
+
+ /* write tmp */
+ outl(space << 30 | space << 3 | 0x30, AB_INDX);
+ outl(axindc, AB_DATA);
+ outl(space << 30 | space << 3 | 0x34, AB_INDX);
+ outl(tmp, AB_DATA);
+}
+
+
static inline void smbus_delay(void)
{
outb(inb(0x80), 0x80);
@@ -177,48 +222,4 @@ int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address, u8 val)
return 0;
}
-static void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val)
-{
- u32 tmp;
-
- outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX);
- tmp = inl(AB_DATA);
- /* rpr 4.2
- * For certain revisions of the chip, the ABCFG registers,
- * with an address of 0x100NN (where 'N' is any hexadecimal
- * number), require an extra programming step.*/
- reg_addr & 0x10000 ? outl(0, AB_INDX) : NULL;
-
- tmp &= ~mask;
- tmp |= val;
-
- /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<30 | reg_addr); */
- outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX); /* probably we dont have to do it again. */
- outl(tmp, AB_DATA);
- reg_addr & 0x10000 ? outl(0, AB_INDX) : NULL;
-}
-
-/* space = 0: AX_INDXC, AX_DATAC
- * space = 1: AX_INDXP, AX_DATAP
- */
-static inline void alink_ax_indx(u32 space /*c or p? */ , u32 axindc,
- u32 mask, u32 val)
-{
- u32 tmp;
-
- /* read axindc to tmp */
- outl(space << 30 | space << 3 | 0x30, AB_INDX);
- outl(axindc, AB_DATA);
- outl(space << 30 | space << 3 | 0x34, AB_INDX);
- tmp = inl(AB_DATA);
-
- tmp &= ~mask;
- tmp |= val;
-
- /* write tmp */
- outl(space << 30 | space << 3 | 0x30, AB_INDX);
- outl(axindc, AB_DATA);
- outl(space << 30 | space << 3 | 0x34, AB_INDX);
- outl(tmp, AB_DATA);
-}
#endif
diff --git a/src/southbridge/amd/sb700/smbus.h b/src/southbridge/amd/sb700/smbus.h
index c21a1dc0a2..9ddfc35303 100644..100755
--- a/src/southbridge/amd/sb700/smbus.h
+++ b/src/southbridge/amd/sb700/smbus.h
@@ -20,6 +20,13 @@
#ifndef SB700_SMBUS_H
#define SB700_SMBUS_H
+#include <stdint.h>
+#include "stddef.h"
+#include <arch/io.h>
+
+#define SMBUS_IO_BASE 0x6000 /* Is it a temporary SMBus I/O base address? */
+ /*SIZE 0x40 */
+
#define SMBHSTSTAT 0x0
#define SMBSLVSTAT 0x1
#define SMBHSTCTRL 0x2
@@ -56,10 +63,11 @@
#define axindxp_reg(reg, mask, val) \
alink_ax_indx(1, (reg), (mask), (val))
+void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val);
+void alink_ax_indx(u32 space, u32 axindc, u32 mask, u32 val);
int do_smbus_recv_byte(u32 smbus_io_base, u32 device);
int do_smbus_send_byte(u32 smbus_io_base, u32 device, u8 val);
int do_smbus_read_byte(u32 smbus_io_base, u32 device, u32 address);
int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address, u8 val);
-
#endif
diff --git a/src/southbridge/amd/sb700/usb.c b/src/southbridge/amd/sb700/usb.c
index 2957dc5aca..793240187f 100644..100755
--- a/src/southbridge/amd/sb700/usb.c
+++ b/src/southbridge/amd/sb700/usb.c
@@ -178,6 +178,7 @@ static void usb_init2(struct device *dev)
dword |= 1 << 8;
dword &= ~(1 << 27); /* 6.23 */
}
+ pci_write_config32(dev, 0x50, dword);
printk(BIOS_DEBUG, "rpr 6.23, final dword=%x\n", dword);
}
diff --git a/src/southbridge/amd/sr5650/Makefile.inc b/src/southbridge/amd/sr5650/Makefile.inc
index a2d10d7145..0a4ce39da9 100644
--- a/src/southbridge/amd/sr5650/Makefile.inc
+++ b/src/southbridge/amd/sr5650/Makefile.inc
@@ -1,3 +1,5 @@
driver-y += sr5650.c
driver-y += pcie.c
driver-y += ht.c
+
+romstage-y += early_setup.c
diff --git a/src/southbridge/amd/sr5650/cmn.h b/src/southbridge/amd/sr5650/cmn.h
index e94fcddc86..6692b86d1f 100644..100755
--- a/src/southbridge/amd/sr5650/cmn.h
+++ b/src/southbridge/amd/sr5650/cmn.h
@@ -20,13 +20,21 @@
#ifndef __SR5650_CMN_H__
#define __SR5650_CMN_H__
+#include <arch/io.h>
+
#define NBMISC_INDEX 0x60
#define NBHTIU_INDEX 0x94 /* Note: It is different with RS690, whose HTIU index is 0xA8 */
#define NBMC_INDEX 0xE8
#define NBPCIE_INDEX 0xE0
-#define EXT_CONF_BASE_ADDRESS 0xE0000000
+#define EXT_CONF_BASE_ADDRESS CONFIG_MMCONF_BASE_ADDRESS
#define TEMP_MMIO_BASE_ADDRESS 0xC0000000
+#define axindxc_reg(reg, mask, val) \
+ alink_ax_indx(0, (reg), (mask), (val))
+
+#define AB_INDX 0xCD8
+#define AB_DATA (AB_INDX+4)
+
static inline u32 nb_read_index(device_t dev, u32 index_reg, u32 index)
{
pci_write_config32(dev, index_reg, index);
diff --git a/src/southbridge/amd/sr5650/early_setup.c b/src/southbridge/amd/sr5650/early_setup.c
index 5f7438ce85..50f836e77c 100644..100755
--- a/src/southbridge/amd/sr5650/early_setup.c
+++ b/src/southbridge/amd/sr5650/early_setup.c
@@ -17,20 +17,50 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <stdint.h>
+#include <arch/cpu.h>
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
#include "sr5650.h"
#include "cmn.h"
+/* space = 0: AX_INDXC, AX_DATAC
+ * space = 1: AX_INDXP, AX_DATAP
+ */
+static void alink_ax_indx(u32 space, u32 axindc, u32 mask, u32 val)
+{
+ u32 tmp;
+
+ /* read axindc to tmp */
+ outl(space << 30 | space << 3 | 0x30, AB_INDX);
+ outl(axindc, AB_DATA);
+ outl(space << 30 | space << 3 | 0x34, AB_INDX);
+ tmp = inl(AB_DATA);
+
+ tmp &= ~mask;
+ tmp |= val;
+
+ /* write tmp */
+ outl(space << 30 | space << 3 | 0x30, AB_INDX);
+ outl(axindc, AB_DATA);
+ outl(space << 30 | space << 3 | 0x34, AB_INDX);
+ outl(tmp, AB_DATA);
+}
+
+
/* family 10 only, for reg > 0xFF */
-#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1
+#if (CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1) || (CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY10 == 1)
static void set_fam10_ext_cfg_enable_bits(device_t fam10_dev, u32 reg_pos, u32 mask,
u32 val)
{
u32 reg_old, reg;
- reg = reg_old = Get_NB32(fam10_dev, reg_pos);
+ reg = reg_old = pci_read_config32(fam10_dev, reg_pos);
reg &= ~mask;
reg |= val;
if (reg != reg_old) {
- Set_NB32(fam10_dev, reg_pos, reg);
+ pci_write_config32(fam10_dev, reg_pos, reg);
}
}
#else
@@ -113,17 +143,19 @@ static const u8 sr5650_ibias[] = {
[0xe] = 0xC6, /* 2.6Ghz HyperTransport 3 only */
};
-static void sr5650_htinit(void)
+void sr5650_htinit(void)
{
/*
* About HT, it has been done in enumerate_ht_chain().
*/
- device_t cpu_f0, sr5650_f0, clk_f1, cpu1_f0;
+ device_t cpu_f0, sr5650_f0, clk_f1;
u32 reg;
- u8 cpu_ht_freq, ibias;
+ u8 cpu_ht_freq, cpu_htfreq_max, ibias;
+ u8 sbnode;
+ u8 sblink;
+ u16 linkfreq_reg;
+ u16 linkfreqext_reg;
- cpu_f0 = PCI_DEV(0, 0x18, 0);
- cpu1_f0 = PCI_DEV(0, 0x19, 0);
/************************
* get cpu's ht freq, in cpu's function 0, offset 0x88
* bit11-8, specifics the maximum operation frequency of the link's transmitter clock.
@@ -133,16 +165,36 @@ static void sr5650_htinit(void)
* please see the table sr5650_ibias about the value and its corresponding frequency.
************************/
/* Link0, Link1 are for connection between P0 and P1.
- * Link2 should be 0xC8?
* TODO: Check the topology of the MP and NB. Or we just read the nbconfig? */
/* NOTE: In most cases, we only have one CPU. In that case, we should read 0x88. */
- reg = pci_read_config32(cpu1_f0, 0x0);
- reg = pci_read_config32(cpu_f0,
- reg == 0 || reg == -1 ? 0x88 : 0xC8
- );
+ /* Find out the node ID and the Link ID that
+ * connects to the Southbridge (system IO hub).
+ */
+ sbnode = (pci_read_config32(PCI_DEV(0, 0x18, 0), 0x60) >> 8) & 7;
+ sblink = (pci_read_config32(PCI_DEV(0, 0x18, 0), 0x64) >> 8) & 3; /* bit[10] sublink, bit[9,8] link. */
+ cpu_f0 = PCI_DEV(0, (0x18 + sbnode), 0);
+
+ /*
+ * link freq reg of Link0, 1, 2, 3 is 0x88, 0xA8, 0xC8, 0xE8 respectively
+ * link freq ext reg of Link0, 1, 2, 3 is 0x9C, 0xBC, 0xDC, 0xFC respectively
+ */
+ linkfreq_reg = 0x88 + (sblink << 5);
+ linkfreqext_reg = 0x9C + (sblink << 5);
+ reg = pci_read_config32(cpu_f0, linkfreq_reg);
+
cpu_ht_freq = (reg & 0xf00) >> 8;
- printk(BIOS_INFO, "sr5650_htinit cpu_ht_freq=%x.\n", cpu_ht_freq);
+
+ /* Freq[4] is only valid for revision D and later processors */
+ if (cpuid_eax(1) >= 0x100F80) {
+ cpu_htfreq_max = 0x14;
+ cpu_ht_freq |= ((pci_read_config32(cpu_f0, linkfreqext_reg) & 0x01) << 4);
+ } else {
+ cpu_htfreq_max = 0x0F;
+ }
+
+ printk(BIOS_INFO, "sr5650_htinit: Node %x Link %x, HT freq=%x.\n",
+ sbnode, sblink, cpu_ht_freq);
sr5650_f0 = PCI_DEV(0, 0, 0);
clk_f1 = PCI_DEV(0, 0, 1); /* We need to make sure the F1 is accessible. */
@@ -162,13 +214,13 @@ static void sr5650_htinit(void)
set_nbcfg_enable_bits(clk_f1, 0xD8, 0x3FF, ibias);
/* Optimizes chipset HT transmitter drive strength */
set_htiu_enable_bits(sr5650_f0, 0x2A, 0x3, 0x3);
- } else if ((cpu_ht_freq > 0x6) && (cpu_ht_freq < 0xf)) {
+ } else if ((cpu_ht_freq > 0x6) && (cpu_ht_freq < cpu_htfreq_max)) {
printk(BIOS_INFO, "sr5650_htinit: HT3 mode\n");
/* Enable Protocol checker */
set_htiu_enable_bits(sr5650_f0, 0x1E, 0xFFFFFFFF, 0x7FFFFFFC);
- #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */
+#if (CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1) || (CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY10 == 1) /* save some spaces */
/* HT3 mode, RPR 5.4.3 */
set_nbcfg_enable_bits(sr5650_f0, 0x9c, 0x3 << 16, 0);
@@ -189,83 +241,36 @@ static void sr5650_htinit(void)
/* Enables strict TM4 detection */
set_htiu_enable_bits(sr5650_f0, 0x15, 0x1 << 22, 0x1 << 22);
+ /* Optimizes chipset HT transmitter drive strength */
+ set_htiu_enable_bits(sr5650_f0, 0x2A, 0x3 << 0, 0x1 << 0);
+
/* HyperTransport 3 Processor register settings to be done in northbridge */
+
/* Enables error-retry mode */
- set_fam10_ext_cfg_enable_bits(cpu_f0, 0x130, 1 << 0, 1 << 0);
- set_fam10_ext_cfg_enable_bits(cpu_f0, 0x134, 1 << 0, 1 << 0); /* TODO: Check if it is needed to set other node. */
- set_fam10_ext_cfg_enable_bits(cpu_f0, 0x138, 1 << 0, 1 << 0);
+ set_fam10_ext_cfg_enable_bits(cpu_f0, 0x130 + (sblink << 2), 1 << 0, 1 << 0);
+
/* Enables scrambling */
- set_fam10_ext_cfg_enable_bits(cpu_f0, 0x170, 1 << 3, 1 << 3);
- set_fam10_ext_cfg_enable_bits(cpu_f0, 0x174, 1 << 3, 1 << 3); /* TODO: Check if it is needed to set other node. */
- set_fam10_ext_cfg_enable_bits(cpu_f0, 0x178, 1 << 3, 1 << 3);
+ set_fam10_ext_cfg_enable_bits(cpu_f0, 0x170 + (sblink << 2), 1 << 3, 1 << 3);
+
/* Enables transmitter de-emphasis
- * This depends on the PCB design and the trace */
+ * This depends on the PCB design and the trace
+ */
/* Disables command throttling */
set_fam10_ext_cfg_enable_bits(cpu_f0, 0x168, 1 << 10, 1 << 10);
+
/* Sets Training 0 Time. See T0Time table for encodings */
- set_fam10_ext_cfg_enable_bits(cpu_f0, 0x16C, 0x3F, 0x20);
+ /* AGESA have set it to recommanded value already
+ * The recommended values are 14h(2us) if F0x[18C:170][LS2En]=0
+ * and 26h(12us) if F0x[18C:170][LS2En]=1
+ */
+ //set_fam10_ext_cfg_enable_bits(cpu_f0, 0x16C, 0x3F, 0x26);
+
/* HT Buffer Allocation for Ganged Links!!! */
- #endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 */
+#endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 */
}
}
-#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 != 1 /* save some spaces */
-/*******************************************************
-* Optimize k8 with UMA.
-* See BKDG_NPT_0F guide for details.
-* The processor node is addressed by its Node ID on the HT link and can be
-* accessed with a device number in the PCI configuration space on Bus0.
-* The Node ID 0 is mapped to Device 24 (0x18), the Node ID 1 is mapped
-* to Device 25, and so on.
-* The processor implements configuration registers in PCI configuration
-* space using the following four headers
-* Function0: HT technology configuration
-* Function1: Address map configuration
-* Function2: DRAM and HT technology Trace mode configuration
-* Function3: Miscellaneous configuration
-*******************************************************/
-static void k8_optimization(void)
-{
- device_t k8_f0, k8_f2, k8_f3;
- msr_t msr;
-
- printk(BIOS_INFO, "k8_optimization()\n");
- k8_f0 = PCI_DEV(0, 0x18, 0);
- k8_f2 = PCI_DEV(0, 0x18, 2);
- k8_f3 = PCI_DEV(0, 0x18, 3);
-
- pci_write_config32(k8_f0, 0x90, 0x01700169); /* CIM NPT_Optimization */
- set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 28, 0 << 28);
- set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 26 | 1 << 27,
- 1 << 26 | 1 << 27);
- set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 11, 1 << 11);
- /* set_nbcfg_enable_bits(k8_f0, 0x84, 1 << 11 | 1 << 13 | 1 << 15, 1 << 11 | 1 << 13 | 1 << 15); */ /* TODO */
-
- pci_write_config32(k8_f3, 0x70, 0x51220111); /* CIM NPT_Optimization */
- pci_write_config32(k8_f3, 0x74, 0x50404021);
- pci_write_config32(k8_f3, 0x78, 0x08002A00);
- if (pci_read_config32(k8_f3, 0xE8) & 0x3<<12)
- pci_write_config32(k8_f3, 0x7C, 0x0000211A); /* dual core */
- else
- pci_write_config32(k8_f3, 0x7C, 0x0000212B); /* single core */
- set_nbcfg_enable_bits_8(k8_f3, 0xDC, 0xFF, 0x25);
-
- set_nbcfg_enable_bits(k8_f2, 0xA0, 1 << 5, 1 << 5);
- set_nbcfg_enable_bits(k8_f2, 0x94, 0xF << 24, 7 << 24);
- set_nbcfg_enable_bits(k8_f2, 0x90, 1 << 10, 0 << 10);
- set_nbcfg_enable_bits(k8_f2, 0xA0, 3 << 2, 3 << 2);
- set_nbcfg_enable_bits(k8_f2, 0xA0, 1 << 5, 1 << 5);
-
- msr = rdmsr(0xC001001F);
- msr.lo &= ~(1 << 9);
- msr.hi &= ~(1 << 4);
- wrmsr(0xC001001F, msr);
-}
-#else
-#define k8_optimization() do{}while(0)
-#endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 != 1 */
-
-#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */
+#if (CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1) || (CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY10 == 1) /* save some spaces */
void fam10_optimization(void)
{
device_t cpu_f0, cpu_f2, cpu_f3;
@@ -340,13 +345,12 @@ static void sr5650_por_misc_index_init(device_t nb_dev)
set_nbmisc_enable_bits(nb_dev, 0x2B, 1 << 15 | 1 << 27, 1 << 15 | 1 << 27);
set_nbmisc_enable_bits(nb_dev, 0x2C, 1 << 0 | 1 << 1 | 1 << 5 | 1 << 4 | 1 << 10, 1 << 0 | 1 << 1 | 1 << 5);
set_nbmisc_enable_bits(nb_dev, 0x32, 0x3F << 20, 0x2A << 20);
- set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31, 0); /* bit31 BTS fail */
+ set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 7 | 1 << 15 | 1 << 23, 0);
set_nbmisc_enable_bits(nb_dev, 0x35, 0x3F << 26, 0x2A << 26);
set_nbmisc_enable_bits(nb_dev, 0x37, 0xfff << 20, 0xddd << 20);
set_nbmisc_enable_bits(nb_dev, 0x37, 7 << 11, 0);
/* PCIE CDR setting */
set_nbmisc_enable_bits(nb_dev, 0x38, 0xFFFFFFFF, 0xC0C0C0);
- set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 31, 0); /* bit31 BTS fail */
set_nbmisc_enable_bits(nb_dev, 0x22, 0xFFFFFFFF, (1 << 27) | (0x8 << 12) | (0x8 << 16) | (0x8 << 20));
set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 1 | 1 << 2 | 1 << 6 | 1 << 7, 1 << 1 | 1 << 2 | 1 << 6 | 1 << 7);
@@ -381,7 +385,7 @@ static void sr5650_por_misc_index_init(device_t nb_dev)
set_nbmisc_enable_bits(nb_dev, 0x47, 0xFFFFFFFF, 0x0000000B);
set_nbmisc_enable_bits(nb_dev, 0x12, 0xFFFFFFFF, 0x00FB5555);
- set_nbmisc_enable_bits(nb_dev, 0x0C, 0xFFFFFFFF, 0x001f37EC);
+ set_nbmisc_enable_bits(nb_dev, 0x0C, 0xFFFFFFFF, 0x001F37FC);
set_nbmisc_enable_bits(nb_dev, 0x15, 0xFFFFFFFF, 0x0);
/* NB_PROG_DEVICE_REMAP */
@@ -478,7 +482,7 @@ static void sr5650_por_init(device_t nb_dev)
}
/* enable CFG access to Dev8, which is the SB P2P Bridge */
-static void enable_sr5650_dev8(void)
+void enable_sr5650_dev8(void)
{
set_nbmisc_enable_bits(PCI_DEV(0, 0, 0), 0x00, 1 << 6, 1 << 6);
}
@@ -486,14 +490,14 @@ static void enable_sr5650_dev8(void)
/*
* Compliant with CIM_33's AtiNBInitEarlyPost (AtiInitNBBeforePCIInit).
*/
-static void sr5650_before_pci_init(void)
+void sr5650_before_pci_init(void)
{
}
/*
* The calling sequence is same as CIM.
*/
-static void sr5650_early_setup(void)
+void sr5650_early_setup(void)
{
device_t nb_dev = PCI_DEV(0, 0, 0);
printk(BIOS_INFO, "sr5650_early_setup()\n");
@@ -513,28 +517,24 @@ static void sr5650_early_setup(void)
break;
}
-#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1
-
fam10_optimization();
-#else
- k8_optimization();
-#endif
-
sr5650_por_init(nb_dev);
}
/**
- * @brief disable GPP1 Port0,1, GPP3a Port0,1,2,3,4,5
+ * @brief disable GPP1 Port0,1, GPP2, GPP3a Port0,1,2,3,4,5, GPP3b
*
*/
-void disable_pcie_bridge(void)
+void sr5650_disable_pcie_bridge(void)
{
u32 mask;
u32 reg;
device_t nb_dev = PCI_DEV(0, 0, 0);
- mask = (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) |
- (1 << 16) | (1 << 17);
+ mask = (1 << 2) | (1 << 3); /*GPP1*/
+ mask |= (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 16) | (1 << 17); /*GPP3a*/
+ mask |= (1 << 18) | (1 << 19); /*GPP2*/
+ mask |= (1 << 20); /*GPP3b*/
reg = mask;
set_nbmisc_enable_bits(nb_dev, 0x0c, mask, reg);
}
diff --git a/src/southbridge/amd/sr5650/pcie.c b/src/southbridge/amd/sr5650/pcie.c
index 3ad5a7d3c3..37743cacae 100644..100755
--- a/src/southbridge/amd/sr5650/pcie.c
+++ b/src/southbridge/amd/sr5650/pcie.c
@@ -267,23 +267,25 @@ void disable_pcie_bar3(device_t nb_dev)
}
/*
-*/
+ * GEN2 Software Compliance
+ */
void init_gen2(device_t nb_dev, device_t dev, u8 port)
{
u32 reg, val;
+
/* for A11 (0x89 == 0) */
reg = 0x34;
- if (port <= 3){
+ if (port <= 3) {
val = 1<<5;
- }else{
+ } else {
val = 1<<31;
- if (port >= 9 )
+ if (port >= 9)
reg = 0x39;
}
- /* todo: check for rev > a11
+ /* TODO: check for rev > a11 */
switch (port) {
- case 2;
+ case 2:
reg = 0x34;
val = 1<<5;
break;
@@ -300,7 +302,9 @@ void init_gen2(device_t nb_dev, device_t dev, u8 port)
reg = 0x39;
val = 1<<31;
break;
- case 7..9:
+ case 7:
+ case 8:
+ case 9:
reg = 0x37;
val = 1<<port;
break;
@@ -312,9 +316,11 @@ void init_gen2(device_t nb_dev, device_t dev, u8 port)
reg = 0;
break;
}
- */
+
+ /* Enables GEN2 capability of the device */
set_pcie_enable_bits(dev, 0xA4, 0x1, 0x1);
- pci_ext_write_config32(nb_dev, dev, 0x88, 0xF0, 1<<2); /* LINK_CRTL2*/
+ /* Advertise the link speed to be Gen2 */
+ pci_ext_write_config32(nb_dev, dev, 0x88, 0xF0, 1<<2); /* LINK_CRTL2 */
set_nbmisc_enable_bits(nb_dev, reg, val, val);
}
@@ -409,7 +415,7 @@ static void gpp12_cpl_buf_alloc(device_t nb_dev, device_t dev)
}
}
-#if 0 /* BTS report error without this function. But some board
+#if 1 /* BTS report error without this function. But some board
* fail to boot. Leave it here for future debug. */
/*
@@ -424,6 +430,7 @@ static void EnableLclkGating(device_t dev)
device_t nb_dev = dev_find_slot(0, 0);
device_t clk_f1= dev_find_slot(0, 1);
+ reg = 0xE8;
port = dev->path.pci.devfn >> 3;
switch (port) {
//PCIE_CORE_INDEX_GPP1
@@ -436,7 +443,6 @@ static void EnableLclkGating(device_t dev)
//PCIE_CORE_INDEX_GPP2
case 11:
case 12:
- reg = 0xE8;
value = 1 << 28;
break;
@@ -444,13 +450,11 @@ static void EnableLclkGating(device_t dev)
case 4 ... 7:
case 9:
case 10:
- reg = 0xE8;
value = 1 << 31;
break;
//PCIE_CORE_INDEX_GPP3b;
case 13:
- reg = 0xE8;
value = 1 << 25;
break;
@@ -541,6 +545,14 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port)
/* 4.4.2.step13.6. Set REGS_LC_ALLOW_TX_L1_CONTROL to allow TX to
prevent LC from going to L1 when there are outstanding completions.*/
set_pcie_enable_bits(dev, 0x02, 1 << 15, 1 << 15);
+
+ /* Enables the PLL power down when all lanes are inactive.
+ * It should be on in GPP.
+ */
+ if (gpp_sb_sel == PCIE_CORE_INDEX_GPP3a || gpp_sb_sel == PCIE_CORE_INDEX_GPP3b || gpp_sb_sel == PCIE_CORE_INDEX_SB) {
+ set_pcie_enable_bits(nb_dev, 0x02 | gpp_sb_sel, 1 << 3, 1 << 3);
+ }
+
/* 4.4.2.step13.7. Set REGS_LC_DONT_GO_TO_L0S_IF_L1_ARMED to prevent
lc to go to from L0 to Rcv_L0s if L1 is armed. */
set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11);
@@ -594,8 +606,11 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port)
* RPR typo- it says enable but the bit setting says disable.
* Disable it here and we enable it later. */
set_pcie_enable_bits(dev, 0xA4, 1 << 0, 1 << 0);
- /* 4.4.2.step13.21. */
- /* 4.4.2.step13.22 */
+
+ /* 4.4.2.step13.21. Legacy Hot Plug -CMOS Option */
+ /* NOTE: This feature can be enabled only for Hot-Plug slots implemented on SR5690 platform. */
+
+ /* 4.4.2.step13.22. Native PCIe Mode -CMOS Option */
/* Enable native PME. */
set_pcie_enable_bits(dev, 0x10, 1 << 3, 1 < 3);
/* This bit when set indicates that the PCIe Link associated with this port
@@ -607,7 +622,7 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port)
/* Enables flushing of TLPs when Data Link is down. */
set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19);
- /* 4.4.2.step14. Server Class Hot Plug Feature */
+ /* 4.4.2.step14. Server Class Hot Plug Feature. NOTE: This feature is not supported on SR5670 and SR5650 */
/* 4.4.2 step14.1: Advertising Hot Plug Capabilities */
/* 4.4.2.step14.2: Firmware Upload */
/* 4.4.2.Step14.3: SBIOS Acknowledgment to Firmware of Successful Firmware Upload */
@@ -630,11 +645,13 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port)
if ( port == 8 )
set_pcie_enable_bits(dev, 0xA0, 0, 1 << 23);
+#if 0 //SR56x0 pcie Gen2 code is not tested yet, we should enable it again when test finished.
/* set automatic Gen2 support, needs mainboard config option as Gen2 can cause issues on some platforms. */
init_gen2(nb_dev, dev, port);
set_pcie_enable_bits(dev, 0xA4, 1 << 29, 1 << 29);
set_pcie_enable_bits(dev, 0xC0, 1 << 15, 0);
set_pcie_enable_bits(dev, 0xA2, 1 << 13, 0);
+#endif
/* Hotplug Support - bit5 + bit6 capable and surprise */
pci_ext_write_config32(nb_dev, dev, 0x6c, 0x60, 0x60);
@@ -715,12 +732,13 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port)
/* 4.4..7.1 TXCLK Gating in L1, Enables powering down TXCLK clock pads on the receive side. */
set_pcie_enable_bits(nb_dev, 0x40 | gpp_sb_sel, 1 << 6, 1 << 6);
- /* Step 21: Register Locking PCIE Misc. Late Core sttting - Must move somewhere do PciInitLate FIXME */
- /* Lock HWInit Register */
- //set_pcie_enable_bits(nb_dev, 0x10 | gpp_sb_sel, 1 << 0, 1 << 0);
+ /* Step 20: Disables immediate RCB timeout on link down */
+ if (!((pci_read_config32(dev, 0x6C ) >> 6) & 0x01)) {
+ set_pcie_enable_bits(dev, 0x70, 1 << 19, 0 << 19);
+ }
/* Step 27: LCLK Gating */
- //EnableLclkGating(dev);
+ EnableLclkGating(dev);
/* Set Common Clock */
/* If dev present, set PcieCapPtr+0x10, BIT6);
@@ -734,6 +752,34 @@ void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port)
}
}
+/**
+ * Step 21: Register Locking
+ * Lock HWInit Register of each pcie core
+ */
+static void lock_hwinitreg(device_t nb_dev)
+{
+ /* Step 21: Register Locking, Lock HWInit Register */
+ set_pcie_enable_bits(nb_dev, 0x10 | PCIE_CORE_INDEX_GPP1, 1 << 0, 1 << 0);
+ set_pcie_enable_bits(nb_dev, 0x10 | PCIE_CORE_INDEX_SB, 1 << 0, 1 << 0);
+ set_pcie_enable_bits(nb_dev, 0x10 | PCIE_CORE_INDEX_GPP2, 1 << 0, 1 << 0);
+ set_pcie_enable_bits(nb_dev, 0x10 | PCIE_CORE_INDEX_GPP3a, 1 << 0, 1 << 0);
+ set_pcie_enable_bits(nb_dev, 0x10 | PCIE_CORE_INDEX_GPP3b, 1 << 0, 1 << 0);
+}
+
+/**
+ * Lock HWInit Register
+ */
+void sr56x0_lock_hwinitreg(void)
+{
+ device_t nb_dev = dev_find_slot(0, PCI_DEVFN(0, 0));
+
+ /* Lock HWInit Register */
+ lock_hwinitreg(nb_dev);
+
+ /* Lock HWInit Register NBMISCIND:0x0 NBCNTL[7] HWINIT_WR_LOCK */
+ set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 7, 1 << 7);
+}
+
/*****************************************
* Compliant with CIM_33's PCIEConfigureGPPCore
*****************************************/
diff --git a/src/southbridge/amd/sr5650/sr5650.c b/src/southbridge/amd/sr5650/sr5650.c
index 616ca44ee6..14b919de72 100644..100755
--- a/src/southbridge/amd/sr5650/sr5650.c
+++ b/src/southbridge/amd/sr5650/sr5650.c
@@ -266,15 +266,21 @@ u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port)
}
/*
-* Compliant with CIM_33's ATINB_SetToms.
-* Set Top Of Memory below and above 4G.
-*/
+ * Set Top Of Memory below and above 4G.
+ */
void sr5650_set_tom(device_t nb_dev)
{
- extern u64 uma_memory_base;
+ msr_t sysmem;
+
+ /* The system top memory in SR56X0. */
+ sysmem = rdmsr(0xc001001A);
+ printk(BIOS_DEBUG, "Sysmem TOM = %x_%x\n", sysmem.hi, sysmem.lo);
+ pci_write_config32(nb_dev, 0x90, sysmem.lo);
- /* set TOM */
- pci_write_config32(nb_dev, 0x90, uma_memory_base);
+ sysmem = rdmsr(0xc001001D);
+ printk(BIOS_DEBUG, "Sysmem TOM2 = %x_%x\n", sysmem.hi, sysmem.lo);
+ htiu_write_index(nb_dev, 0x31, sysmem.hi);
+ htiu_write_index(nb_dev, 0x30, sysmem.lo | 1);
}
u32 get_vid_did(device_t dev)
@@ -308,7 +314,7 @@ void sr5650_nb_pci_table(device_t nb_dev)
temp8 &= ~(1<<1);
pci_write_config8(nb_dev, 0x8d, temp8);
- /* set temporary NB TOM to 0x40000000. */
+ /* The system top memory in SR56X0. */
sr5650_set_tom(nb_dev);
/* Program NB HTIU table. */
@@ -424,6 +430,11 @@ void sr5650_enable(device_t dev)
default:
printk(BIOS_DEBUG, "unknown dev: %s\n", dev_path(dev));
}
+
+ /* Lock HWInit Register after the last device was done */
+ if (dev_ind == 13) {
+ sr56x0_lock_hwinitreg();
+ }
}
struct chip_operations southbridge_amd_sr5650_ops = {
diff --git a/src/southbridge/amd/sr5650/sr5650.h b/src/southbridge/amd/sr5650/sr5650.h
index 5da354493b..1b5112b7c2 100644..100755
--- a/src/southbridge/amd/sr5650/sr5650.h
+++ b/src/southbridge/amd/sr5650/sr5650.h
@@ -103,6 +103,10 @@ void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add);
void enable_pcie_bar3(device_t nb_dev);
void disable_pcie_bar3(device_t nb_dev);
+void enable_sr5650_dev8(void);
+void sr5650_htinit(void);
+void sr5650_early_setup(void);
+void sr5650_before_pci_init(void);
void sr5650_enable(device_t dev);
void sr5650_gpp_sb_init(device_t nb_dev, device_t dev, u32 port);
void sr5650_gfx_init(device_t nb_dev, device_t dev, u32 port);
@@ -112,8 +116,9 @@ void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port);
u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port);
void pcie_config_misc_clk(device_t nb_dev);
void fam10_optimization(void);
-void disable_pcie_bridge(void);
+void sr5650_disable_pcie_bridge(void);
u32 get_vid_did(device_t dev);
void sr5650_nb_pci_table(device_t nb_dev);
void init_gen2(device_t nb_dev, device_t dev, u8 port);
+void sr56x0_lock_hwinitreg(void);
#endif /* SR5650_H */