From 836ae29ee325b1e3d28ff59468cc50913b1e24ce Mon Sep 17 00:00:00 2001 From: stepan Date: Wed, 8 Dec 2010 05:42:47 +0000 Subject: first round name simplification. drop the _ prefix. the prefix was introduced in the early v2 tree many years ago because our old build system "newconfig" could not handle two files with the same name in different paths like /path/to/usb.c and /another/path/to/usb.c correctly. Only one of the files would end up being compiled into the final image. Since Kconfig (actually since shortly before we switched to Kconfig) we don't suffer from that problem anymore. So we could drop the sb700_ prefix from all those filenames (or, the _ prefix in general) - makes it easier to fork off a new chipset - makes it easier to diff against other chipsets - storing redundant information in filenames seems wrong Signed-off-by: Acked-by: Patrick Georgi Acked-by: Peter Stuge git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6149 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/southbridge/amd/rs780/Makefile.inc | 8 +- src/southbridge/amd/rs780/cmn.c | 403 ++++++++ src/southbridge/amd/rs780/early_setup.c | 675 +++++++++++++ src/southbridge/amd/rs780/gfx.c | 1340 +++++++++++++++++++++++++ src/southbridge/amd/rs780/ht.c | 90 ++ src/southbridge/amd/rs780/pcie.c | 392 ++++++++ src/southbridge/amd/rs780/rev.h | 27 + src/southbridge/amd/rs780/rs780.h | 2 +- src/southbridge/amd/rs780/rs780_cmn.c | 403 -------- src/southbridge/amd/rs780/rs780_early_setup.c | 675 ------------- src/southbridge/amd/rs780/rs780_gfx.c | 1340 ------------------------- src/southbridge/amd/rs780/rs780_ht.c | 90 -- src/southbridge/amd/rs780/rs780_pcie.c | 392 -------- src/southbridge/amd/rs780/rs780_rev.h | 27 - 14 files changed, 2932 insertions(+), 2932 deletions(-) create mode 100644 src/southbridge/amd/rs780/cmn.c create mode 100644 src/southbridge/amd/rs780/early_setup.c create mode 100644 src/southbridge/amd/rs780/gfx.c create mode 100644 src/southbridge/amd/rs780/ht.c create mode 100644 src/southbridge/amd/rs780/pcie.c create mode 100644 src/southbridge/amd/rs780/rev.h delete mode 100644 src/southbridge/amd/rs780/rs780_cmn.c delete mode 100644 src/southbridge/amd/rs780/rs780_early_setup.c delete mode 100644 src/southbridge/amd/rs780/rs780_gfx.c delete mode 100644 src/southbridge/amd/rs780/rs780_ht.c delete mode 100644 src/southbridge/amd/rs780/rs780_pcie.c delete mode 100644 src/southbridge/amd/rs780/rs780_rev.h (limited to 'src/southbridge/amd/rs780') diff --git a/src/southbridge/amd/rs780/Makefile.inc b/src/southbridge/amd/rs780/Makefile.inc index f76e517c82..db425702d6 100644 --- a/src/southbridge/amd/rs780/Makefile.inc +++ b/src/southbridge/amd/rs780/Makefile.inc @@ -1,5 +1,5 @@ driver-y += rs780.c -driver-y += rs780_cmn.c -driver-y += rs780_pcie.c -driver-y += rs780_ht.c -driver-y += rs780_gfx.c +driver-y += cmn.c +driver-y += pcie.c +driver-y += ht.c +driver-y += gfx.c diff --git a/src/southbridge/amd/rs780/cmn.c b/src/southbridge/amd/rs780/cmn.c new file mode 100644 index 0000000000..4bd870bbf2 --- /dev/null +++ b/src/southbridge/amd/rs780/cmn.c @@ -0,0 +1,403 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rs780.h" + +static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) +{ + pci_write_config32(dev, index_reg, index); + return pci_read_config32(dev, index_reg + 0x4); +} + +static void nb_write_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); +} + +/* extension registers */ +u32 pci_ext_read_config32(device_t nb_dev, device_t dev, u32 reg) +{ + /*get BAR3 base address for nbcfg0x1c */ + u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; + printk(BIOS_DEBUG, "addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, + dev->path.pci.devfn); + addr |= dev->bus->secondary << 20 | /* bus num */ + dev->path.pci.devfn << 12 | reg; + return *((u32 *) addr); +} + +void pci_ext_write_config32(device_t nb_dev, device_t dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + + /*get BAR3 base address for nbcfg0x1c */ + u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; + /*printk(BIOS_DEBUG, "write: addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, + dev->path.pci.devfn);*/ + addr |= dev->bus->secondary << 20 | /* bus num */ + dev->path.pci.devfn << 12 | reg_pos; + + reg = reg_old = *((u32 *) addr); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + *((u32 *) addr) = reg; + } +} + +u32 nbmisc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMISC_INDEX, (index)); +} + +void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); +} + +u32 nbpcie_p_read_index(device_t dev, u32 index) +{ + return nb_read_index((dev), NBPCIE_INDEX, (index)); +} + +void nbpcie_p_write_index(device_t dev, u32 index, u32 data) +{ + nb_write_index((dev), NBPCIE_INDEX, (index), (data)); +} + +u32 nbpcie_ind_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBPCIE_INDEX, (index)); +} + +void nbpcie_ind_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBPCIE_INDEX, (index), (data)); +} + +u32 htiu_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); +} + +void htiu_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); +} + +u32 nbmc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMC_INDEX, (index)); +} + +void nbmc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); +} + +void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = pci_read_config32(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config32(nb_dev, reg_pos, reg); + } +} + +void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, u8 val) +{ + u8 reg_old, reg; + reg = reg_old = pci_read_config8(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config8(nb_dev, reg_pos, reg); + } +} + +void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmc_write_index(nb_dev, reg_pos, reg); + } +} + +void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = htiu_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + htiu_write_index(nb_dev, reg_pos, reg); + } +} + +void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmisc_write_index(nb_dev, reg_pos, reg); + } +} + +void set_pcie_enable_bits(device_t dev, u32 reg_pos, u32 mask, u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nb_read_index(dev, NBPCIE_INDEX, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nb_write_index(dev, NBPCIE_INDEX, reg_pos, reg); + } +} + +/*********************************************************** +* To access bar3 we need to program PCI MMIO 7 in K8. +* in_out: +* 1: enable/enter k8 temp mmio base +* 0: disable/restore +***********************************************************/ +void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add) +{ + /* K8 Function1 is address map */ + device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); + device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + + if (in_out) { + u32 dword, sblk; + + /* Get SBLink value (HyperTransport I/O Hub Link ID). */ + dword = pci_read_config32(k8_f0, 0x64); + sblk = (dword >> 8) & 0x3; + + /* Fill MMIO limit/base pair. */ + pci_write_config32(k8_f1, 0xbc, + (((pcie_base_add + 0x10000000 - + 1) >> 8) & 0xffffff00) | 0x80 | (sblk << 4)); + pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3); + pci_write_config32(k8_f1, 0xb4, + (((mmio_base_add + 0x10000000 - + 1) >> 8) & 0xffffff00) | (sblk << 4)); + pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3); + } else { + pci_write_config32(k8_f1, 0xb8, 0); + pci_write_config32(k8_f1, 0xbc, 0); + pci_write_config32(k8_f1, 0xb0, 0); + pci_write_config32(k8_f1, 0xb4, 0); + } +} + +void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port) +{ + switch (port) { + case 2: /* GFX, bit4-5 */ + case 3: + set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, + 1 << (port + 2), 0 << (port + 2)); + break; + case 4: /* GPPSB, bit20-24 */ + case 5: + case 6: + case 7: + set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, + 1 << (port + 17), 0 << (port + 17)); + break; + case 9: /* GPP, bit 4,5 of miscind 0x2D */ + case 10: + set_nbmisc_enable_bits(nb_dev, 0x2D, + 1 << (port - 5), 0 << (port - 5)); + break; + } +} + +/******************************************************************************************************** +* Output: +* 0: no device is present. +* 1: device is present and is trained. +********************************************************************************************************/ +u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port) +{ + u16 count = 5000; + u32 lc_state, reg, current_link_width, lane_mask; + int8_t current, res = 0; + u32 gfx_gpp_sb_sel; + void set_pcie_dereset(void); + void set_pcie_reset(void); + + switch (port) { + case 2 ... 3: + gfx_gpp_sb_sel = PCIE_CORE_INDEX_GFX; + break; + case 4 ... 7: + gfx_gpp_sb_sel = PCIE_CORE_INDEX_GPPSB; + break; + case 9 ... 10: + gfx_gpp_sb_sel = PCIE_CORE_INDEX_GPP; + break; + default: + gfx_gpp_sb_sel = -1; + return 0; + } + + while (count--) { + mdelay(40); + udelay(200); + lc_state = nbpcie_p_read_index(dev, 0xa5); /* lc_state */ + printk(BIOS_DEBUG, "PcieLinkTraining port=%x:lc current state=%x\n", + port, lc_state); + current = lc_state & 0x3f; /* get LC_CURRENT_STATE, bit0-5 */ + + switch (current) { + case 0x00: /* 0x00-0x04 means no device is present */ + case 0x01: + case 0x02: + case 0x03: + case 0x04: + res = 0; + count = 0; + break; + case 0x06: + /* read back current link width [6:4]. */ + current_link_width = (nbpcie_p_read_index(dev, 0xA2) >> 4) & 0x7; + /* 4 means 7:4 and 15:12 + * 3 means 7:2 and 15:10 + * 2 means 7:1 and 15:9 + * egnoring the reversal case + */ + lane_mask = (0xFF << (current_link_width - 2) * 2) & 0xFF; + reg = nbpcie_ind_read_index(nb_dev, 0x65 | gfx_gpp_sb_sel); + reg |= lane_mask << 8 | lane_mask; + reg = 0xE0E0; /* TODO: See the comments in rs780_pcie.c, at about line 145. */ + nbpcie_ind_write_index(nb_dev, 0x65 | gfx_gpp_sb_sel, reg); + printk(BIOS_DEBUG, "link_width=%x, lane_mask=%x", + current_link_width, lane_mask); + set_pcie_reset(); + mdelay(1); + set_pcie_dereset(); + break; + case 0x07: /* device is in compliance state (training sequence is done). Move to train the next device */ + res = 0; + count = 0; + break; + case 0x10: + reg = + pci_ext_read_config32(nb_dev, dev, + PCIE_VC0_RESOURCE_STATUS); + printk(BIOS_DEBUG, "PcieTrainPort reg=0x%x\n", reg); + /* check bit1 */ + if (reg & VC_NEGOTIATION_PENDING) { /* bit1=1 means the link needs to be re-trained. */ + /* set bit8=1, bit0-2=bit4-6 */ + u32 tmp; + reg = + nbpcie_p_read_index(dev, + PCIE_LC_LINK_WIDTH); + tmp = (reg >> 4) && 0x3; /* get bit4-6 */ + reg &= 0xfff8; /* clear bit0-2 */ + reg += tmp; /* merge */ + reg |= 1 << 8; + count++; /* CIM said "keep in loop"? */ + } else { + res = 1; + count = 0; + } + break; + default: /* reset pcie */ + res = 0; + count = 0; /* break loop */ + break; + } + } + return res; +} + +/* +* Compliant with CIM_33's ATINB_SetToms. +* Set Top Of Memory below and above 4G. +*/ +void rs780_set_tom(device_t nb_dev) +{ + extern uint64_t uma_memory_base; + + /* set TOM */ + pci_write_config32(nb_dev, 0x90, uma_memory_base); + //nbmc_write_index(nb_dev, 0x1e, uma_memory_base); +} + +// extract single bit +u32 extractbit(u32 data, int bit_number) +{ + return (data >> bit_number) & 1; +} + +// extract bit field +u32 extractbits(u32 source, int lsb, int msb) +{ + int field_width = msb - lsb + 1; + u32 mask = 0xFFFFFFFF >> (32 - field_width); + return (source >> lsb) & mask; +} + +// return AMD cpuid family +int cpuidFamily(void) +{ + u32 baseFamily, extendedFamily, fms; + + fms = cpuid_eax (1); + baseFamily = extractbits (fms, 8, 11); + extendedFamily = extractbits (fms, 20, 27); + return baseFamily + extendedFamily; +} + + +// return non-zero for AMD family 0Fh processor found +int is_family0Fh(void) +{ + return cpuidFamily() == 0x0F; +} + + +// return non-zero for AMD family 10h processor found +int is_family10h(void) +{ + return cpuidFamily() == 0x10; +} diff --git a/src/southbridge/amd/rs780/early_setup.c b/src/southbridge/amd/rs780/early_setup.c new file mode 100644 index 0000000000..a93ba83172 --- /dev/null +++ b/src/southbridge/amd/rs780/early_setup.c @@ -0,0 +1,675 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 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 CONFIG_NORTHBRIDGE_AMD_AMDFAM10 +#define CONFIG_NORTHBRIDGE_AMD_AMDFAM10 0 +#endif + +#include "rev.h" + +#define NBHTIU_INDEX 0x94 /* Note: It is different with RS690, whose HTIU index is 0xA8 */ +#define NBMISC_INDEX 0x60 +#define NBMC_INDEX 0xE8 + +static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) +{ + pci_write_config32(dev, index_reg, index); + return pci_read_config32(dev, index_reg + 0x4); +} + +static void nb_write_index(device_t dev, u32 index_reg, u32 index, u32 data) +{ + pci_write_config32(dev, index_reg, index /* | 0x80 */ ); + pci_write_config32(dev, index_reg + 0x4, data); +} + +static u32 nbmisc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMISC_INDEX, (index)); +} + +static void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); +} + +static u32 htiu_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); +} + +static void htiu_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); +} + +static u32 nbmc_read_index(device_t nb_dev, u32 index) +{ + return nb_read_index((nb_dev), NBMC_INDEX, (index)); +} + +static void nbmc_write_index(device_t nb_dev, u32 index, u32 data) +{ + nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); +} + +static void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = htiu_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + htiu_write_index(nb_dev, reg_pos, reg); + } +} + +static void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmisc_write_index(nb_dev, reg_pos, reg); + } +} + +static void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = pci_read_config32(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config32(nb_dev, reg_pos, reg); + } +} +/* family 10 only, for reg > 0xFF */ +#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 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 &= ~mask; + reg |= val; + if (reg != reg_old) { + Set_NB32(fam10_dev, reg_pos, reg); + } +} +#else +#define set_fam10_ext_cfg_enable_bits(a, b, c, d) do {} while (0) +#endif + + +static void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, + u8 val) +{ + u8 reg_old, reg; + reg = reg_old = pci_read_config8(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + pci_write_config8(nb_dev, reg_pos, reg); + } +} + +static void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, + u32 val) +{ + u32 reg_old, reg; + reg = reg_old = nbmc_read_index(nb_dev, reg_pos); + reg &= ~mask; + reg |= val; + if (reg != reg_old) { + nbmc_write_index(nb_dev, reg_pos, reg); + } +} + +static void get_cpu_rev(void) +{ + u32 eax; + + eax = cpuid_eax(1); + printk(BIOS_INFO, "get_cpu_rev EAX=0x%x.\n", eax); + if (eax <= 0xfff) + printk(BIOS_INFO, "CPU Rev is K8_Cx.\n"); + else if (eax <= 0x10fff) + printk(BIOS_INFO, "CPU Rev is K8_Dx.\n"); + else if (eax <= 0x20fff) + printk(BIOS_INFO, "CPU Rev is K8_Ex.\n"); + else if (eax <= 0x40fff) + printk(BIOS_INFO, "CPU Rev is K8_Fx.\n"); + else if (eax == 0x60fb1 || eax == 0x60f81) /*These two IDS are exception, they are G1. */ + printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); + else if (eax <= 0X60FF0) + printk(BIOS_INFO, "CPU Rev is K8_G0.\n"); + else if (eax <= 0x100000) + printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); + else if (eax <= 0x100f00) + printk(BIOS_INFO, "CPU Rev is Fam 10.\n"); + else + printk(BIOS_INFO, "CPU Rev is K8_10.\n"); +} + +static u8 is_famly10(void) +{ + return (cpuid_eax(1) & 0xff00000) != 0; +} + +#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */ +static u8 l3_cache(void) +{ + return (cpuid_edx(0x80000006) & (0x3FFF << 18)) != 0; +} + +static u8 cpu_core_number(void) +{ + return (cpuid_ecx(0x80000008) & 0xFF) + 1; +} +#endif + +static u8 get_nb_rev(device_t nb_dev) +{ + u8 reg; + reg = pci_read_config8(nb_dev, 0x89); /* copy from CIM, can't find in doc */ + switch(reg & 3) + { + case 0x01: + reg = REV_RS780_A12; + break; + case 0x02: + reg = REV_RS780_A13; + break; + default: + reg = REV_RS780_A11; + break; + } + return reg; +} + +/***************************************** + * Init HT link speed/width for rs780 -- k8 link + * 1: Check CPU Family, Family10? + * 2: Get CPU's HT speed and width + * 3: Decide HT mode 1 or 3 by HT Speed. >1GHz: HT3, else HT1 + *****************************************/ +static const u8 rs780_ibias[] = { + /* 1, 3 are reserved. */ + [0x0] = 0x4C, /* 200Mhz HyperTransport 1 only */ + [0x2] = 0x4C, /* 400Mhz HyperTransport 1 only */ + [0x4] = 0xB6, /* 600Mhz HyperTransport 1 only */ + [0x5] = 0x4C, /* 800Mhz HyperTransport 1 only */ + [0x6] = 0x9D, /* 1Ghz HyperTransport 1 only */ + /* HT3 for Family 10 */ + [0x7] = 0xB6, /* 1.2Ghz HyperTransport 3 only */ + [0x8] = 0x2B, /* 1.4Ghz HyperTransport 3 only */ + [0x9] = 0x4C, /* 1.6Ghz HyperTransport 3 only */ + [0xa] = 0x6C, /* 1.8Ghz HyperTransport 3 only */ + [0xb] = 0x9D, /* 2.0Ghz HyperTransport 3 only */ + [0xc] = 0xAD, /* 2.2Ghz HyperTransport 3 only */ + [0xd] = 0xB6, /* 2.4Ghz HyperTransport 3 only */ + [0xe] = 0xC6, /* 2.6Ghz HyperTransport 3 only */ +}; + +static void rs780_htinit(void) +{ + /* + * About HT, it has been done in enumerate_ht_chain(). + */ + device_t cpu_f0, rs780_f0, clk_f1; + u32 reg; + u8 cpu_ht_freq, ibias; + + cpu_f0 = PCI_DEV(0, 0x18, 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. + * The link frequency field (Frq) is cleared by cold reset. SW can write a nonzero + * value to this reg, and that value takes effect on the next warm reset or + * LDTSTOP_L disconnect sequence. + * please see the table rs780_ibias about the value and its corresponding frequency. + ************************/ + reg = pci_read_config32(cpu_f0, 0x88); + cpu_ht_freq = (reg & 0xf00) >> 8; + printk(BIOS_INFO, "rs780_htinit cpu_ht_freq=%x.\n", cpu_ht_freq); + rs780_f0 = PCI_DEV(0, 0, 0); + //set_nbcfg_enable_bits(rs780_f0, 0xC8, 0x7<<24 | 0x7<<28, 1<<24 | 1<<28); + + clk_f1 = PCI_DEV(0, 0, 1); /* We need to make sure the F1 is accessible. */ + + ibias = rs780_ibias[cpu_ht_freq]; + + /* If HT freq>1GHz, we assume the CPU is fam10, else it is K8. + * Is it appropriate? + * Frequency is 1GHz, i.e. cpu_ht_freq is 6, in most cases. + * So we check 6 only, it would be faster. */ + if ((cpu_ht_freq == 0x6) || (cpu_ht_freq == 0x5) || (cpu_ht_freq == 0x4) || + (cpu_ht_freq == 0x2) || (cpu_ht_freq == 0x0)) { + printk(BIOS_INFO, "rs780_htinit: HT1 mode\n"); + + /* HT1 mode, RPR 8.4.2 */ + /* set IBIAS code */ + set_nbcfg_enable_bits(clk_f1, 0xD8, 0x3FF, ibias); + /* Optimizes chipset HT transmitter drive strength */ + set_htiu_enable_bits(rs780_f0, 0x2A, 0x3, 0x1); + } else if ((cpu_ht_freq > 0x6) && (cpu_ht_freq < 0xf)) { + printk(BIOS_INFO, "rs780_htinit: HT3 mode\n"); + + #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */ + /* HT3 mode, RPR 8.4.3 */ + set_nbcfg_enable_bits(rs780_f0, 0x9c, 0x3 << 16, 0); + + /* set IBIAS code */ + set_nbcfg_enable_bits(clk_f1, 0xD8, 0x3FF, ibias); + /* Optimizes chipset HT transmitter drive strength */ + set_htiu_enable_bits(rs780_f0, 0x2A, 0x3, 0x1); + /* Enables error-retry mode */ + set_nbcfg_enable_bits(rs780_f0, 0x44, 0x1, 0x1); + /* Enables scrambling and Disalbes command throttling */ + set_nbcfg_enable_bits(rs780_f0, 0xac, (1 << 3) | (1 << 14), (1 << 3) | (1 << 14)); + /* Enables transmitter de-emphasis */ + set_nbcfg_enable_bits(rs780_f0, 0xa4, 1 << 31, 1 << 31); + /* Enabels transmitter de-emphasis level */ + /* Sets training 0 time */ + set_nbcfg_enable_bits(rs780_f0, 0xa0, 0x3F, 0x14); + + /* Enables strict TM4 detection */ + set_htiu_enable_bits(rs780_f0, 0x15, 0x1 << 22, 0x1 << 22); + /* Enables proprer DLL reset sequence */ + set_htiu_enable_bits(rs780_f0, 0x16, 0x1 << 10, 0x1 << 10); + + /* 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); + /* Enables scrambling */ + set_fam10_ext_cfg_enable_bits(cpu_f0, 0x170, 1 << 3, 1 << 3); + /* Enables transmitter de-emphasis + * This depends on the PCB design and the trace */ + /* TODO: */ + /* 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); + /* TODO: */ + #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); + + /* 8.6.6 K8 Buffer Allocation Settings */ + 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, 3 << 26, 3 << 26); + 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); + 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 */ +static void fam10_optimization(void) +{ + device_t cpu_f0, cpu_f2, cpu_f3; + u32 val; + + printk(BIOS_INFO, "fam10_optimization()\n"); + + cpu_f0 = PCI_DEV(0, 0x18, 0); + cpu_f2 = PCI_DEV(0, 0x18, 2); + cpu_f3 = PCI_DEV(0, 0x18, 3); + + /* 8.6.4.1 */ + /* Table 8-13 */ + pci_write_config32(cpu_f0, 0x90, 0x808502D0); + /* Table 8-14 */ + pci_write_config32(cpu_f0, 0x94, 0x00000000); + + /* Table 8-15 */ + val = pci_read_config32(cpu_f0, 0x68); + val |= 1 << 24; + pci_write_config32(cpu_f0, 0x68, val); + + /* Table 8-16 */ + val = pci_read_config32(cpu_f0, 0x84); + val &= ~(1 << 12); + pci_write_config32(cpu_f0, 0x84, val); + + /* Table 8-17 */ + val = pci_read_config32(cpu_f2, 0x90); + val &= ~(1 << 10); + pci_write_config32(cpu_f2, 0x90, val); + + /* Table 8-18 */ + pci_write_config32(cpu_f3, 0x6C, 0x60018051); + /* Table 8-19 */ + pci_write_config32(cpu_f3, 0x70, 0x60321151); + /* Table 8-20 */ + pci_write_config32(cpu_f3, 0x74, 0x00980101); + /* Table 8-21 */ + pci_write_config32(cpu_f3, 0x78, 0x00200C14); + /* Table 8-22 */ + pci_write_config32(cpu_f3, 0x7C, 0x00070811); /* TODO: Check if L3 Cache is enabled. */ + + /* Table 8-23 */ + Set_NB32(cpu_f3, 0x140, 0x00D33656); + /* Table 8-24 */ + Set_NB32(cpu_f3, 0x144, 0x00000036); + /* Table 8-25 */ + Set_NB32(cpu_f3, 0x148, 0x8000832A); + /* Table 8-26 */ + Set_NB32(cpu_f3, 0x158, 0); + /* L3 Disabled: L3 Enabled: */ + /* cores: 2 3 4 2 3 4 */ + /* bit8:4 28 26 24 24 20 16 */ + if (!l3_cache()) { + Set_NB32(cpu_f3, 0x1A0, 4 << 12 | (24 + 2*(4-cpu_core_number())) << 4 | 2); + } else { + Set_NB32(cpu_f3, 0x1A0, 4 << 12 | (16 + 4*(4-cpu_core_number())) << 4 | 4); + } +} +#else +#define fam10_optimization() do{}while(0) +#endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 */ + +/***************************************** +* rs780_por_pcicfg_init() +*****************************************/ +static void rs780_por_pcicfg_init(device_t nb_dev) +{ + /* enable PCI Memory Access */ + set_nbcfg_enable_bits_8(nb_dev, 0x04, (u8)(~0xFD), 0x02); + /* Set RCRB Enable */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x1); + /* allow decode of 640k-1MB */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xEF), 0x10); + /* Enable PM2_CNTL(BAR2) IO mapped cfg write access to be broadcast to both NB and SB */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x4); + /* Power Management Register Enable */ + set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x80); + + /* Reg4Ch[1]=1 (APIC_ENABLE) force cpu request with address 0xFECx_xxxx to south-bridge + * Reg4Ch[6]=1 (BMMsgEn) enable BM_Set message generation + * BMMsgEn */ + set_nbcfg_enable_bits_8(nb_dev, 0x4C, (u8)(~0x00), 0x42 | 1); + + /* Reg4Ch[16]=1 (WakeC2En) enable Wake_from_C2 message generation. + * Reg4Ch[18]=1 (P4IntEnable) Enable north-bridge to accept MSI with address 0xFEEx_xxxx from south-bridge */ + set_nbcfg_enable_bits_8(nb_dev, 0x4E, (u8)(~0xFF), 0x05); + /* Reg94h[4:0] = 0x0 P drive strength offset 0 + * Reg94h[6:5] = 0x2 P drive strength additive adjust */ + set_nbcfg_enable_bits_8(nb_dev, 0x94, (u8)(~0x80), 0x40); + + /* Reg94h[20:16] = 0x0 N drive strength offset 0 + * Reg94h[22:21] = 0x2 N drive strength additive adjust */ + set_nbcfg_enable_bits_8(nb_dev, 0x96, (u8)(~0x80), 0x40); + + /* Reg80h[4:0] = 0x0 Termination offset + * Reg80h[6:5] = 0x2 Termination additive adjust */ + set_nbcfg_enable_bits_8(nb_dev, 0x80, (u8)(~0x80), 0x40); + + /* Reg80h[14] = 0x1 Enable receiver termination control */ + set_nbcfg_enable_bits_8(nb_dev, 0x81, (u8)(~0xFF), 0x40); + + /* Reg94h[15] = 0x1 Enables HT transmitter advanced features to be turned on + * Reg94h[14] = 0x1 Enable drive strength control */ + set_nbcfg_enable_bits_8(nb_dev, 0x95, (u8)(~0x3F), 0xC4); + + /* Reg94h[31:29] = 0x7 Enables HT transmitter de-emphasis */ + set_nbcfg_enable_bits_8(nb_dev, 0x97, (u8)(~0x1F), 0xE0); + + /* Reg8Ch[9] enables Gfx Debug BAR programming + * Reg8Ch[10] enables Gfx Debug BAR operation + * Enable programming of the debug bar now, but enable + * operation only after it has been programmed */ + set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x02); +} + +static void rs780_por_mc_index_init(device_t nb_dev) +{ + set_nbmc_enable_bits(nb_dev, 0x7A, ~0xFFFFFF80, 0x0000005F); + set_nbmc_enable_bits(nb_dev, 0xD8, ~0x00000000, 0x00600060); + set_nbmc_enable_bits(nb_dev, 0xD9, ~0x00000000, 0x00600060); + set_nbmc_enable_bits(nb_dev, 0xE0, ~0x00000000, 0x00000000); + set_nbmc_enable_bits(nb_dev, 0xE1, ~0x00000000, 0x00000000); + set_nbmc_enable_bits(nb_dev, 0xE8, ~0x00000000, 0x003E003E); + set_nbmc_enable_bits(nb_dev, 0xE9, ~0x00000000, 0x003E003E); +} + +static void rs780_por_misc_index_init(device_t nb_dev) +{ + /* NB_MISC_IND_WR_EN + IOC_PCIE_CNTL + * Block non-snoop DMA request if PMArbDis is set. + * Set BMSetDis */ + set_nbmisc_enable_bits(nb_dev, 0x0B, ~0xFFFF0000, 0x00000180); + set_nbmisc_enable_bits(nb_dev, 0x01, ~0xFFFFFFFF, 0x00000040); + + /* NBCFG (NBMISCIND 0x0): NB_CNTL - + * HIDE_NB_AGP_CAP ([0], default=1)HIDE + * HIDE_P2P_AGP_CAP ([1], default=1)HIDE + * HIDE_NB_GART_BAR ([2], default=1)HIDE + * AGPMODE30 ([4], default=0)DISABLE + * AGP30ENCHANCED ([5], default=0)DISABLE + * HIDE_AGP_CAP ([8], default=1)ENABLE */ + set_nbmisc_enable_bits(nb_dev, 0x00, ~0xFFFF0000, 0x00000506); /* set bit 10 for MSI */ + + /* NBMISCIND:0x6A[16]= 1 SB link can get a full swing + * set_nbmisc_enable_bits(nb_dev, 0x6A, 0ffffffffh, 000010000); + * NBMISCIND:0x6A[17]=1 Set CMGOOD_OVERRIDE. */ + set_nbmisc_enable_bits(nb_dev, 0x6A, ~0xffffffff, 0x00020000); + + /* NBMISIND:0x40 Bit[8]=1 and Bit[10]=1 following bits are required to set in order to allow LVDS or PWM features to work. */ + set_nbmisc_enable_bits(nb_dev, 0x40, ~0xffffffff, 0x00000500); + + /* NBMISIND:0xC Bit[13]=1 Enable GSM mode for C1e or C3 with pop-up. */ + set_nbmisc_enable_bits(nb_dev, 0x0C, ~0xffffffff, 0x00002000); + + /* Set NBMISIND:0x1F[3] to map NB F2 interrupt pin to INTB# */ + set_nbmisc_enable_bits(nb_dev, 0x1F, ~0xffffffff, 0x00000008); + + /* + * Enable access to DEV8 + * Enable setPower message for all ports + */ + set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 6, 1 << 6); + set_nbmisc_enable_bits(nb_dev, 0x0b, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x51, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x53, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x55, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x57, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x59, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x5B, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x5D, 1 << 20, 1 << 20); + set_nbmisc_enable_bits(nb_dev, 0x5F, 1 << 20, 1 << 20); + + set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 7, 1 << 7); + set_nbmisc_enable_bits(nb_dev, 0x07, 0x000000f0, 0x30); + + set_nbmisc_enable_bits(nb_dev, 0x01, 0xFFFFFFFF, 0x48); + /* Disable bus-master trigger event from SB and Enable set_slot_power message to SB */ + set_nbmisc_enable_bits(nb_dev, 0x0B, 0xffffffff, 0x500180); +} + +/***************************************** +* Some setting is from rpr. Some is from CIMx. +*****************************************/ +static void rs780_por_htiu_index_init(device_t nb_dev) +{ +#if 0 /* get from rpr. */ + set_htiu_enable_bits(nb_dev, 0x1C, 0x1<<17, 0x1<<17); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<0, 0x0<<0); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<1, 0x1<<1); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<9, 0x1<<9); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<13, 0x1<<13); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<17, 0x1<<17); + set_htiu_enable_bits(nb_dev, 0x06, 0x3<<15, 0x3<<15); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<25, 0x1<<25); + set_htiu_enable_bits(nb_dev, 0x06, 0x1<<30, 0x1<<30); + + set_htiu_enable_bits(nb_dev, 0x07, 0x1<<0, 0x1<<0); + set_htiu_enable_bits(nb_dev, 0x07, 0x1<<1, 0x0<<1); + set_htiu_enable_bits(nb_dev, 0x07, 0x1<<2, 0x0<<2); + set_htiu_enable_bits(nb_dev, 0x07, 0x1<<15, 0x1<<15); + + set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<0, 0x1<<0); + set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<2, 0x2<<2); + set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<4, 0x0<<4); + + /* A12 only */ + set_htiu_enable_bits(nb_dev, 0x2D, 0x1<<4, 0x1<<4); + set_htiu_enable_bits(nb_dev, 0x2D, 0x1<<6, 0x1<<6); + set_htiu_enable_bits(nb_dev, 0x05, 0x1<<2, 0x1<<2); + + set_htiu_enable_bits(nb_dev, 0x1E, 0xFFFFFFFF, 0xFFFFFFFF); +#else /* get from CIM. It is more reliable than above. */ + set_htiu_enable_bits(nb_dev, 0x05, (1<<10|1<<9), 1<<10 | 1<<9); + set_htiu_enable_bits(nb_dev, 0x06, ~0xFFFFFFFE, 0x04203A202); + + set_htiu_enable_bits(nb_dev, 0x07, ~0xFFFFFFF9, 0x8001/* | 7 << 8 */); /* fam 10 */ + + set_htiu_enable_bits(nb_dev, 0x15, ~0xFFFFFFFF, 1<<31| 1<<30 | 1<<27); + set_htiu_enable_bits(nb_dev, 0x1C, ~0xFFFFFFFF, 0xFFFE0000); + + set_htiu_enable_bits(nb_dev, 0x4B, (1<<11), 1<<11); + + set_htiu_enable_bits(nb_dev, 0x0C, ~0xFFFFFFC0, 1<<0|1<<3); + + set_htiu_enable_bits(nb_dev, 0x17, (1<<27|1<<1), 0x1<<1); + set_htiu_enable_bits(nb_dev, 0x17, 0x1 << 30, 0x1<<30); + + set_htiu_enable_bits(nb_dev, 0x19, (0xFFFFF+(1<<31)), 0x186A0+(1<<31)); + + set_htiu_enable_bits(nb_dev, 0x16, (0x3F<<10), 0x7<<10); + + set_htiu_enable_bits(nb_dev, 0x23, 0xFFFFFFF, 1<<28); + + set_htiu_enable_bits(nb_dev, 0x1E, 0xFFFFFFFF, 0xFFFFFFFF); +#endif +} + +/***************************************** +* Configure RS780 registers to power-on default RPR. +* POR: Power On Reset +* RPR: Register Programming Requirements +*****************************************/ +static void rs780_por_init(device_t nb_dev) +{ + printk(BIOS_INFO, "rs780_por_init\n"); + /* ATINB_PCICFG_POR_TABLE, initialize the values for rs780 PCI Config registers */ + rs780_por_pcicfg_init(nb_dev); + + /* ATINB_MCIND_POR_TABLE */ + rs780_por_mc_index_init(nb_dev); + + /* ATINB_MISCIND_POR_TABLE */ + rs780_por_misc_index_init(nb_dev); + + /* ATINB_HTIUNBIND_POR_TABLE */ + rs780_por_htiu_index_init(nb_dev); + + /* ATINB_CLKCFG_PORT_TABLE */ + /* rs780 A11 SB Link full swing? */ +} + +/* enable CFG access to Dev8, which is the SB P2P Bridge */ +static void enable_rs780_dev8(void) +{ + set_nbmisc_enable_bits(PCI_DEV(0, 0, 0), 0x00, 1 << 6, 1 << 6); +} + +static void rs780_before_pci_init(void) +{ +} + +static void rs780_early_setup(void) +{ + device_t nb_dev = PCI_DEV(0, 0, 0); + printk(BIOS_INFO, "rs780_early_setup()\n"); + + get_cpu_rev(); + + /* The printk(BIOS_INFO, s) below cause the system unstable. */ + switch (get_nb_rev(nb_dev)) { + case REV_RS780_A11: + /* printk(BIOS_INFO, "NB Revision is A11.\n"); */ + break; + case REV_RS780_A12: + /* printk(BIOS_INFO, "NB Revision is A12.\n"); */ + break; + case REV_RS780_A13: + /* printk(BIOS_INFO, "NB Revision is A13.\n"); */ + break; + } + + if (is_famly10()) + fam10_optimization(); + else + k8_optimization(); + + rs780_por_init(nb_dev); +} diff --git a/src/southbridge/amd/rs780/gfx.c b/src/southbridge/amd/rs780/gfx.c new file mode 100644 index 0000000000..1763c36047 --- /dev/null +++ b/src/southbridge/amd/rs780/gfx.c @@ -0,0 +1,1340 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 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 rs780 internal graphics device + * device id of internal grphics: + * RS780: 0x9610 + * RS780C: 0x9611 + * RS780M: 0x9612 + * RS780MC:0x9613 + * RS780E: 0x9615 + * RS785G: 0x9710 - just works, not much tested + */ +#include +#include +#include +#include +#include +#include +#include +#include "rs780.h" +extern int is_dev3_present(void); +void set_pcie_reset(void); +void set_pcie_dereset(void); + +extern uint64_t uma_memory_base, uma_memory_size; + +/* Trust the original resource allocation. Don't do it again. */ +#undef DONT_TRUST_RESOURCE_ALLOCATION +//#define DONT_TRUST_RESOURCE_ALLOCATION + +#define CLK_CNTL_INDEX 0x8 +#define CLK_CNTL_DATA 0xC + +/* The Integrated Info Table. */ +ATOM_INTEGRATED_SYSTEM_INFO_V2 vgainfo; + +#ifdef UNUSED_CODE +static u32 clkind_read(device_t dev, u32 index) +{ + u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; + + *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index & 0x7F; + return *(u32*)(gfx_bar2+CLK_CNTL_DATA); +} +#endif + +static void clkind_write(device_t dev, u32 index, u32 data) +{ + u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; + /* printk(BIOS_DEBUG, "gfx bar 2 %02x\n", gfx_bar2); */ + + *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index | 1<<7; + *(u32*)(gfx_bar2+CLK_CNTL_DATA) = data; +} + +/* +* pci_dev_read_resources thinks it is a IO type. +* We have to force it to mem type. +*/ +static void rs780_gfx_read_resources(device_t dev) +{ + printk(BIOS_DEBUG, "rs780_gfx_read_resources.\n"); + + /* The initial value of 0x24 is 0xFFFFFFFF, which is confusing. + Even if we write 0xFFFFFFFF into it, it will be 0xFFF00000, + which tells us it is a memory address base. + */ + pci_write_config32(dev, 0x24, 0x00000000); + + /* Get the normal pci resources of this device */ + pci_dev_read_resources(dev); + compact_resources(dev); +} + +typedef struct _MMIORANGE +{ + u32 Base; + u32 Limit; + u8 Attribute; +} MMIORANGE; + +MMIORANGE MMIO[8], CreativeMMIO[8]; + +#define CIM_STATUS u32 +#define CIM_SUCCESS 0x00000000 +#define CIM_ERROR 0x80000000 +#define CIM_UNSUPPORTED 0x80000001 +#define CIM_DISABLEPORT 0x80000002 + +#define MMIO_ATTRIB_NP_ONLY 1 +#define MMIO_ATTRIB_BOTTOM_TO_TOP 1<<1 +#define MMIO_ATTRIB_SKIP_ZERO 1<<2 + +#ifdef DONT_TRUST_RESOURCE_ALLOCATION +static MMIORANGE* AllocMMIO(MMIORANGE* pMMIO) +{ + int i; + for (i=0; i<8; i++) { + if (pMMIO[i].Limit == 0) + return &pMMIO[i]; + } + return 0; +} + +static void FreeMMIO(MMIORANGE* pMMIO) +{ + pMMIO->Base = 0; + pMMIO->Limit = 0; +} + +static u32 SetMMIO(u32 Base, u32 Limit, u8 Attribute, MMIORANGE *pMMIO) +{ + int i; + MMIORANGE * TempRange; + for(i=0; i<8; i++) + { + if(pMMIO[i].Attribute != Attribute && Base >= pMMIO[i].Base && Limit <= pMMIO[i].Limit) + { + TempRange = AllocMMIO(pMMIO); + if(TempRange == 0) return 0x80000000; + TempRange->Base = Limit; + TempRange->Limit = pMMIO[i].Limit; + TempRange->Attribute = pMMIO[i].Attribute; + pMMIO[i].Limit = Base; + } + } + TempRange = AllocMMIO(pMMIO); + if(TempRange == 0) return 0x80000000; + TempRange->Base = Base; + TempRange->Limit = Limit; + TempRange->Attribute = Attribute; + return 0; +} + +static u8 FinalizeMMIO(MMIORANGE *pMMIO) +{ + int i, j, n = 0; + for(i=0; i<8; i++) + { + if (pMMIO[i].Base == pMMIO[i].Limit) + { + FreeMMIO(&pMMIO[i]); + continue; + } + for(j=0; j> 8) & 0xFF; + BusEnd = (Value >> 16) & 0xFF; + for(Bus = BusStart; Bus <= BusEnd; Bus++) + { + for(Dev = 0; Dev <= 0x1f; Dev++) + { + tempdev = dev_find_slot(Bus, Dev << 3); + Value = pci_read_config32(tempdev, 0); + printk(BIOS_DEBUG, "Dev ID %x \n", Value); + if((Value & 0xffff) == 0x1102) + {//Creative + //Found Creative SB + u32 MMIOStart = 0xffffffff; + u32 MMIOLimit = 0; + for(Reg = 0x10; Reg < 0x20; Reg+=4) + { + u32 BaseA, LimitA; + BaseA = pci_read_config32(tempdev, Reg); + Value = BaseA; + if(!(Value & 0x01)) + { + Value = Value & 0xffffff00; + if(Value != 0) + { + if(MMIOStart > Value) + MMIOStart = Value; + LimitA = 0xffffffff; + //WritePCI(PciAddress,AccWidthUint32,&LimitA); + pci_write_config32(tempdev, Reg, LimitA); + //ReadPCI(PciAddress,AccWidthUint32,&LimitA); + LimitA = pci_read_config32(tempdev, Reg); + LimitA = Value + (~LimitA + 1); + //WritePCI(PciAddress,AccWidthUint32,&BaseA); + pci_write_config32(tempdev, Reg, BaseA); + if (LimitA > MMIOLimit) + MMIOLimit = LimitA; + } + } + } + printk(BIOS_DEBUG, " MMIOStart %x MMIOLimit %x \n", MMIOStart, MMIOLimit); + if (MMIOStart < MMIOLimit) + { + Status = SetMMIO(MMIOStart>>8, MMIOLimit>>8, 0x80, pMMIO); + if(Status == CIM_ERROR) return Status; + } + } + } + } + if(Status == CIM_SUCCESS) + { + //Lets optimize MMIO + if(FinalizeMMIO(pMMIO) > 4) + { + Status = CIM_ERROR; + } + } + + return Status; +} + +static void ProgramMMIO(MMIORANGE *pMMIO, u8 LinkID, u8 Attribute) +{ + int i, j, n = 7; + device_t k8_f1; + + k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); + + for(i = 0; i < 8; i++) + { + int k = 0, MmioReg; + u32 Base = 0; + u32 Limit = 0; + for(j = 0; j < 8; j++) + { + if (Base < pMMIO[j].Base) + { + Base = pMMIO[j].Base; + k = j; + } + } + if(pMMIO[k].Limit != 0) + { + if(Attribute & MMIO_ATTRIB_NP_ONLY && pMMIO[k].Attribute == 0 ) + { + Base = 0; + } + else + { + Base = pMMIO[k].Base | 0x3; + Limit= ((pMMIO[k].Limit - 1) & 0xffffff00) | pMMIO[k].Attribute | (LinkID << 4); + } + FreeMMIO(&pMMIO[k]); + } + if (Attribute & MMIO_ATTRIB_SKIP_ZERO && Base == 0 && Limit == 0) continue; + MmioReg = (Attribute & MMIO_ATTRIB_BOTTOM_TO_TOP)?n:(7-n); + n--; + //RWPCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x80+MmioReg*8),AccWidthUint32 |S3_SAVE,0x0,0x0); + pci_write_config32(k8_f1, 0x80+MmioReg*8, 0); + + //WritePCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x84+MmioReg*8),AccWidthUint32 |S3_SAVE,&Limit); + pci_write_config32(k8_f1, 0x84+MmioReg*8, Limit); + + //WritePCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x80+MmioReg*8),AccWidthUint32 |S3_SAVE,&Base); + pci_write_config32(k8_f1, 0x80+MmioReg*8, Base); + } +} +#endif + +static void internal_gfx_pci_dev_init(struct device *dev) +{ + unsigned char * bpointer; + volatile u32 * GpuF0MMReg; + volatile u32 * pointer; + int i; + u16 command; + u32 value; + u16 deviceid, vendorid; + device_t nb_dev = dev_find_slot(0, 0); + device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); + device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + static const u8 ht_freq_lookup [] = {2, 0, 4, 0, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 0, 0, 28, 30, 32}; + static const u8 ht_width_lookup [] = {8, 16, 0, 0, 2, 4, 0, 0}; + static const u16 memclk_lookup_fam0F [] = {100, 0, 133, 0, 0, 166, 0, 200}; + static const u16 memclk_lookup_fam10 [] = {200, 266, 333, 400, 533, 667, 800, 800}; + + /* We definetely will use this in future. Just leave it here. */ + /*struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)dev->chip_info;*/ + + deviceid = pci_read_config16(dev, PCI_DEVICE_ID); + vendorid = pci_read_config16(dev, PCI_VENDOR_ID); + printk(BIOS_DEBUG, "internal_gfx_pci_dev_init device=%x, vendor=%x.\n", + deviceid, vendorid); + + command = pci_read_config16(dev, 0x04); + command |= 0x7; + pci_write_config16(dev, 0x04, command); + + /* Clear vgainfo. */ + bpointer = (unsigned char *) &vgainfo; + for(i=0; i>8)|((value&0xff000000)>>8); + *(GpuF0MMReg + 0x2c04/4) = ((value&0xff00)<<8); + *(GpuF0MMReg + 0x5428/4) = ((value&0xffff0000)+0x10000)-((value&0xffff)<<16); + *(GpuF0MMReg + 0xF774/4) = 0xffffffff; + *(GpuF0MMReg + 0xF770/4) = 0x00000001; + *(GpuF0MMReg + 0x2000/4) = 0x00000011; + *(GpuF0MMReg + 0x200c/4) = 0x00000020; + *(GpuF0MMReg + 0x2010/4) = 0x10204810; + *(GpuF0MMReg + 0x2010/4) = 0x00204810; + *(GpuF0MMReg + 0x2014/4) = 0x10408810; + *(GpuF0MMReg + 0x2014/4) = 0x00408810; + *(GpuF0MMReg + 0x2414/4) = 0x00000080; + *(GpuF0MMReg + 0x2418/4) = 0x84422415; + *(GpuF0MMReg + 0x2418/4) = 0x04422415; + *(GpuF0MMReg + 0x5490/4) = 0x00000001; + *(GpuF0MMReg + 0x7de4/4) |= (1<<3) | (1<<4); + /* Force allow LDT_STOP Cool'n'Quiet workaround. */ + *(GpuF0MMReg + 0x655c/4) |= 1<<4; + + // disable write combining, needed for stability + // reference bios does this only for RS780 rev A11 + // need to figure out why we need it for all revs + *(GpuF0MMReg + 0x2000/4) = 0x00000010; + *(GpuF0MMReg + 0x2408/4) = 1 << 9; + *(GpuF0MMReg + 0x2000/4) = 0x00000011; + + /* GFX_InitFBAccess finished. */ + +#if (CONFIG_GFXUMA == 1) /* for UMA mode. */ + /* GFX_StartMC. */ + set_nbmc_enable_bits(nb_dev, 0x02, 0x00000000, 0x80000000); + set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000001); + set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000004); + set_nbmc_enable_bits(nb_dev, 0x01, 0x00040000, 0x00000000); + set_nbmc_enable_bits(nb_dev, 0xB1, 0xFFFF0000, 0x00000040); + set_nbmc_enable_bits(nb_dev, 0xC3, 0x00000000, 0x00000001); + set_nbmc_enable_bits(nb_dev, 0x07, 0xFFFFFFFF, 0x00000018); + set_nbmc_enable_bits(nb_dev, 0x06, 0xFFFFFFFF, 0x00000102); + set_nbmc_enable_bits(nb_dev, 0x09, 0xFFFFFFFF, 0x40000008); + set_nbmc_enable_bits(nb_dev, 0x06, 0x00000000, 0x80000000); + /* GFX_StartMC finished. */ +#else + /* for SP mode. */ + set_nbmc_enable_bits(nb_dev, 0xaa, 0xf0, 0x30); + set_nbmc_enable_bits(nb_dev, 0xce, 0xf0, 0x30); + set_nbmc_enable_bits(nb_dev, 0xca, 0xff000000, 0x47000000); + set_nbmc_enable_bits(nb_dev, 0xcb, 0x3f000000, 0x01000000); + set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<0); + set_nbmc_enable_bits(nb_dev, 0x04, 0, 1<<31); + set_nbmc_enable_bits(nb_dev, 0xb4, 0x3f, 0x3f); + set_nbmc_enable_bits(nb_dev, 0xb4, 0, 1<<6); + set_nbmc_enable_bits(nb_dev, 0xc3, 1<<11, 0); + set_nbmc_enable_bits(nb_dev, 0xa0, 1<<29, 0); + nbmc_write_index(nb_dev, 0xa4, 0x3484576f); + nbmc_write_index(nb_dev, 0xa5, 0x222222df); + nbmc_write_index(nb_dev, 0xa6, 0x00000000); + nbmc_write_index(nb_dev, 0xa7, 0x00000000); + set_nbmc_enable_bits(nb_dev, 0xc3, 1<<8, 0); + udelay(10); + set_nbmc_enable_bits(nb_dev, 0xc3, 1<<9, 0); + udelay(10); + set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<2); + udelay(200); + set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<3); + set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<31); + udelay(500); + set_nbmc_enable_bits(nb_dev, 0x02, 0, 1<<31); + set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<30); + set_nbmc_enable_bits(nb_dev, 0xa0, 1<<31, 0); + set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<29); + nbmc_write_index(nb_dev, 0xa4, 0x23484576); + nbmc_write_index(nb_dev, 0xa5, 0x00000000); + nbmc_write_index(nb_dev, 0xa6, 0x00000000); + nbmc_write_index(nb_dev, 0xa7, 0x00000000); + /* GFX_StartMC finished. */ + + /* GFX_SPPowerManagment, don't care for new. */ + /* Post MC Init table programming. */ + set_nbmc_enable_bits(nb_dev, 0xac, ~(0xfffffff0), 0x0b); + + /* Do we need Write and Read Calibration? */ + /* GFX_Init finished. */ +#endif + + /* GFX_InitIntegratedInfo. */ + /* fill the Integrated Info Table. */ + vgainfo.sHeader.usStructureSize = sizeof(ATOM_INTEGRATED_SYSTEM_INFO_V2); + vgainfo.sHeader.ucTableFormatRevision = 1; + vgainfo.sHeader.ucTableContentRevision = 2; + +#if (CONFIG_GFXUMA == 0) /* SP mode. */ + // Side port support is incomplete, do not use it + // These parameters must match the motherboard + vgainfo.ulBootUpSidePortClock = 667*100; + vgainfo.ucMemoryType = 3; // 3=ddr3 sp mem, 2=ddr2 sp mem + vgainfo.ulMinSidePortClock = 333*100; +#endif + + vgainfo.ulBootUpEngineClock = 500 * 100; // setup option on reference BIOS, 500 is default + + // find the DDR memory frequency + if (is_family10h()) { + value = pci_read_config32(k8_f2, 0x94); // read channel 0 DRAM Configuration High Register + if (extractbit(value, 14)) // if channel 0 disabled, channel 1 must have memory + value = pci_read_config32(k8_f2, 0x194);// read channel 1 DRAM Configuration High Register + vgainfo.ulBootUpUMAClock = memclk_lookup_fam10 [extractbits (value, 0, 2)] * 100; + } + if (is_family0Fh()) { + value = pci_read_config32(k8_f2, 0x94); + vgainfo.ulBootUpUMAClock = memclk_lookup_fam0F [extractbits (value, 20, 22)] * 100; + } + + /* UMA Channel Number: 1 or 2. */ + vgainfo.ucUMAChannelNumber = 1; + if (is_family0Fh()) { + value = pci_read_config32(k8_f2, 0x90); + if (extractbit(value, 11)) // 128-bit mode + vgainfo.ucUMAChannelNumber = 2; + } + if (is_family10h()) { + u32 dch0 = pci_read_config32(k8_f2, 0x94); + u32 dch1 = pci_read_config32(k8_f2, 0x194); + if (extractbit(dch0, 14) == 0 && extractbit(dch1, 14) == 0) { // both channels enabled + value = pci_read_config32(k8_f2, 0x110); + if (extractbit(value, 4)) // ganged mode + vgainfo.ucUMAChannelNumber = 2; + } + } + + // processor type + if (is_family0Fh()) + vgainfo.ulCPUCapInfo = 3; + if (is_family10h()) + vgainfo.ulCPUCapInfo = 2; + + /* HT speed */ + value = pci_read_config8(nb_dev, 0xd1); + value = ht_freq_lookup [value] * 100; // HT link frequency in MHz + vgainfo.ulHTLinkFreq = value * 100; // HT frequency in units of 100 MHz + vgainfo.ulHighVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; + vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; + + if (value <= 1800) + vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; + else { + int sblink, cpuLnkFreqCap, nbLnkFreqCap; + value = pci_read_config32(k8_f0, 0x64); + sblink = extractbits(value, 8, 10); + cpuLnkFreqCap = pci_read_config16(k8_f0, 0x8a + sblink * 0x20); + nbLnkFreqCap = pci_read_config16(nb_dev, 0xd2); + if (cpuLnkFreqCap & nbLnkFreqCap & (1 << 10)) // if both 1800 MHz capable + vgainfo.ulLowVoltageHTLinkFreq = 1800*100; + } + + /* HT width. */ + value = pci_read_config8(nb_dev, 0xcb); + vgainfo.usMinDownStreamHTLinkWidth = + vgainfo.usMaxDownStreamHTLinkWidth = + vgainfo.usMinUpStreamHTLinkWidth = + vgainfo.usMaxUpStreamHTLinkWidth = + vgainfo.usMinHTLinkWidth = + vgainfo.usMaxHTLinkWidth = ht_width_lookup [extractbits(value, 0, 2)]; + + if (is_family0Fh()) { + vgainfo.usUMASyncStartDelay = 322; + vgainfo.usUMADataReturnTime = 286; + } + + if (is_family10h()) { + static u16 t0mult_lookup [] = {10, 50, 200, 2000}; + int t0time, t0scale; + value = pci_read_config32(k8_f0, 0x16c); + t0time = extractbits(value, 0, 3); + t0scale = extractbits(value, 4, 5); + vgainfo.usLinkStatusZeroTime = t0mult_lookup [t0scale] * t0time; + vgainfo.usUMASyncStartDelay = 100; + if (vgainfo.ulHTLinkFreq < 1000 * 100) { // less than 1000 MHz + vgainfo.usUMADataReturnTime = 300; + vgainfo.usLinkStatusZeroTime = 6 * 100; // 6us for GH in HT1 mode + } + else { + int lssel; + value = pci_read_config32(nb_dev, 0xac); + lssel = extractbits (value, 7, 8); + vgainfo.usUMADataReturnTime = 1300; + if (lssel == 0) vgainfo.usUMADataReturnTime = 150; + } + } + + /* Transfer the Table to VBIOS. */ + pointer = (u32 *)&vgainfo; + for(i=0; i> 8; + if(Base32 < Limit32) + { + Status = GetCreativeMMIO(&CreativeMMIO[0]); + if(Status != CIM_ERROR) + SetMMIO(Base32, Limit32, 0x0, &MMIO[0]); + } + /* Set MMIO for prefetchable P2P. */ + if(Status != CIM_ERROR) + { + temp = pci_read_config32(dev0x14, 0x24); + + Base32 = (temp & 0x0fff0) <<8; + Limit32 = ((temp & 0x0fff00000) + 0x100000) >> 8; + if(Base32 < Limit32) + SetMMIO(Base32, Limit32, 0x0, &MMIO[0]); + } + + FinalizeMMIO(&MMIO[0]); + + ProgramMMIO(&CreativeMMIO[0], 0, MMIO_ATTRIB_NP_ONLY); + ProgramMMIO(&MMIO[0], 0, MMIO_ATTRIB_NP_ONLY | MMIO_ATTRIB_BOTTOM_TO_TOP | MMIO_ATTRIB_SKIP_ZERO); +#endif + + pci_dev_init(dev); + + /* clk ind */ + clkind_write(dev, 0x08, 0x01); + clkind_write(dev, 0x0C, 0x22); + clkind_write(dev, 0x0F, 0x0); + clkind_write(dev, 0x11, 0x0); + clkind_write(dev, 0x12, 0x0); + clkind_write(dev, 0x14, 0x0); + clkind_write(dev, 0x15, 0x0); + clkind_write(dev, 0x16, 0x0); + clkind_write(dev, 0x17, 0x0); + clkind_write(dev, 0x18, 0x0); + clkind_write(dev, 0x19, 0x0); + clkind_write(dev, 0x1A, 0x0); + clkind_write(dev, 0x1B, 0x0); + clkind_write(dev, 0x1C, 0x0); + clkind_write(dev, 0x1D, 0x0); + clkind_write(dev, 0x1E, 0x0); + clkind_write(dev, 0x26, 0x0); + clkind_write(dev, 0x27, 0x0); + clkind_write(dev, 0x28, 0x0); + clkind_write(dev, 0x5C, 0x0); +} + + +/* +* Set registers in RS780 and CPU to enable the internal GFX. +* Please refer to CIM source code and BKDG. +*/ + +static void rs780_internal_gfx_enable(device_t dev) +{ + u32 l_dword; + int i; + device_t nb_dev = dev_find_slot(0, 0); + msr_t sysmem; + +#if (CONFIG_GFXUMA == 0) + u32 FB_Start, FB_End; +#endif + + printk(BIOS_DEBUG, "rs780_internal_gfx_enable dev = 0x%p, nb_dev = 0x%p.\n", dev, nb_dev); + + sysmem = rdmsr(0xc001001a); + printk(BIOS_DEBUG, "sysmem = %x_%x\n", sysmem.hi, sysmem.lo); + + /* The system top memory in 780. */ + pci_write_config32(nb_dev, 0x90, sysmem.lo); + htiu_write_index(nb_dev, 0x30, 0); + htiu_write_index(nb_dev, 0x31, 0); + + /* Disable external GFX and enable internal GFX. */ + l_dword = pci_read_config32(nb_dev, 0x8c); + l_dword &= ~(1<<0); + l_dword |= 1<<1; + pci_write_config32(nb_dev, 0x8c, l_dword); + + /* NB_SetDefaultIndexes */ + pci_write_config32(nb_dev, 0x94, 0x7f); + pci_write_config32(nb_dev, 0x60, 0x7f); + pci_write_config32(nb_dev, 0xe0, 0); + + /* NB_InitEarlyNB finished. */ + + /* LPC DMA Deadlock workaround? */ + /* GFX_InitCommon*/ + device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + l_dword = pci_read_config32(k8_f0, 0x68); + l_dword &= ~(3 << 21); + l_dword |= (1 << 21); + pci_write_config32(k8_f0, 0x68, l_dword); + + /* GFX_InitCommon. */ + nbmc_write_index(nb_dev, 0x23, 0x00c00010); + set_nbmc_enable_bits(nb_dev, 0x16, 1<<15, 1<<15); + set_nbmc_enable_bits(nb_dev, 0x25, 0xffffffff, 0x111f111f); + set_htiu_enable_bits(nb_dev, 0x37, 1<<24, 1<<24); + +#if (CONFIG_GFXUMA == 1) + /* GFX_InitUMA. */ + /* Copy CPU DDR Controller to NB MC. */ + device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); + device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); + device_t k8_f4 = dev_find_slot(0, PCI_DEVFN(0x18, 4)); + for (i = 0; i < 12; i++) + { + l_dword = pci_read_config32(k8_f2, 0x40 + i * 4); + nbmc_write_index(nb_dev, 0x30 + i, l_dword); + } + + l_dword = pci_read_config32(k8_f2, 0x80); + nbmc_write_index(nb_dev, 0x3c, l_dword); + l_dword = pci_read_config32(k8_f2, 0x94); + set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<22))<<16); + set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<< 8))<<17); + l_dword = pci_read_config32(k8_f2, 0x90); + set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<10))<<18); + if (is_family10h()) + { + for (i = 0; i < 12; i++) + { + l_dword = pci_read_config32(k8_f2, 0x140 + i * 4); + nbmc_write_index(nb_dev, 0x3d + i, l_dword); + } + + l_dword = pci_read_config32(k8_f2, 0x180); + nbmc_write_index(nb_dev, 0x49, l_dword); + l_dword = pci_read_config32(k8_f2, 0x194); + set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<22))<<16); + set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<< 8))<<17); + l_dword = pci_read_config32(k8_f2, 0x190); + set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<10))<<18); + + l_dword = pci_read_config32(k8_f2, 0x110); + nbmc_write_index(nb_dev, 0x4a, l_dword); + l_dword = pci_read_config32(k8_f2, 0x114); + nbmc_write_index(nb_dev, 0x4b, l_dword); + l_dword = pci_read_config32(k8_f4, 0x44); + set_nbmc_enable_bits(nb_dev, 0x4a, 0, !!(l_dword & (1<<22))<<24); + l_dword = pci_read_config32(k8_f1, 0x40); + nbmc_write_index(nb_dev, 0x4c, l_dword); + l_dword = pci_read_config32(k8_f1, 0xf0); + nbmc_write_index(nb_dev, 0x4d, l_dword); + } + + + /* Set UMA in the 780 side. */ + /* UMA start address, size. */ + /* The UMA starts at 0xC0000000 of internal RS780 address space + [31:16] addr of last byte | [31:16] addr of first byte + */ + nbmc_write_index(nb_dev, 0x10, ((uma_memory_size - 1 + 0xC0000000) & (~0xffff)) | 0xc000); + nbmc_write_index(nb_dev, 0x11, uma_memory_base); + nbmc_write_index(nb_dev, 0x12, 0); + nbmc_write_index(nb_dev, 0xf0, uma_memory_size >> 20); + /* GFX_InitUMA finished. */ +#else + /* GFX_InitSP. */ + /* SP memory:Hynix HY5TQ1G631ZNFP. 128MB = 64M * 16. 667MHz. DDR3. */ + + /* Enable Async mode. */ + set_nbmc_enable_bits(nb_dev, 0x06, 7<<8, 1<<8); + set_nbmc_enable_bits(nb_dev, 0x08, 1<<10, 0); + /* The last item in AsynchMclkTaskFileIndex. Why? */ + /* MC_MPLL_CONTROL2. */ + nbmc_write_index(nb_dev, 0x07, 0x40100028); + /* MC_MPLL_DIV_CONTROL. */ + nbmc_write_index(nb_dev, 0x0b, 0x00000028); + /* MC_MPLL_FREQ_CONTROL. */ + set_nbmc_enable_bits(nb_dev, 0x09, 3<<12|15<<16|15<<8, 1<<12|4<<16|0<<8); + /* MC_MPLL_CONTROL3. For PM. */ + set_nbmc_enable_bits(nb_dev, 0x08, 0xff<<13, 1<<13|1<<18); + /* MPLL_CAL_TRIGGER. */ + set_nbmc_enable_bits(nb_dev, 0x06, 0, 1<<0); + udelay(200); /* time is long enough? */ + set_nbmc_enable_bits(nb_dev, 0x06, 0, 1<<1); + set_nbmc_enable_bits(nb_dev, 0x06, 1<<0, 0); + /* MCLK_SRC_USE_MPLL. */ + set_nbmc_enable_bits(nb_dev, 0x02, 0, 1<<20); + + /* Pre Init MC. */ + nbmc_write_index(nb_dev, 0x01, 0x88108280); + set_nbmc_enable_bits(nb_dev, 0x02, ~(1<<20), 0x00030200); + nbmc_write_index(nb_dev, 0x04, 0x08881018); + nbmc_write_index(nb_dev, 0x05, 0x000000bb); + nbmc_write_index(nb_dev, 0x0c, 0x0f00001f); + nbmc_write_index(nb_dev, 0xa1, 0x01f10000); + /* MCA_INIT_DLL_PM. */ + set_nbmc_enable_bits(nb_dev, 0xc9, 1<<24, 1<<24); + nbmc_write_index(nb_dev, 0xa2, 0x74f20000); + nbmc_write_index(nb_dev, 0xa3, 0x8af30000); + nbmc_write_index(nb_dev, 0xaf, 0x47d0a41c); + nbmc_write_index(nb_dev, 0xb0, 0x88800130); + nbmc_write_index(nb_dev, 0xb1, 0x00000040); + nbmc_write_index(nb_dev, 0xb4, 0x41247000); + nbmc_write_index(nb_dev, 0xb5, 0x00066664); + nbmc_write_index(nb_dev, 0xb6, 0x00000022); + nbmc_write_index(nb_dev, 0xb7, 0x00000044); + nbmc_write_index(nb_dev, 0xb8, 0xbbbbbbbb); + nbmc_write_index(nb_dev, 0xb9, 0xbbbbbbbb); + nbmc_write_index(nb_dev, 0xba, 0x55555555); + nbmc_write_index(nb_dev, 0xc1, 0x00000000); + nbmc_write_index(nb_dev, 0xc2, 0x00000000); + nbmc_write_index(nb_dev, 0xc3, 0x80006b00); + nbmc_write_index(nb_dev, 0xc4, 0x00066664); + nbmc_write_index(nb_dev, 0xc5, 0x00000000); + nbmc_write_index(nb_dev, 0xd2, 0x00000022); + nbmc_write_index(nb_dev, 0xd3, 0x00000044); + nbmc_write_index(nb_dev, 0xd6, 0x00050005); + nbmc_write_index(nb_dev, 0xd7, 0x00000000); + nbmc_write_index(nb_dev, 0xd8, 0x00700070); + nbmc_write_index(nb_dev, 0xd9, 0x00700070); + nbmc_write_index(nb_dev, 0xe0, 0x00200020); + nbmc_write_index(nb_dev, 0xe1, 0x00200020); + nbmc_write_index(nb_dev, 0xe8, 0x00200020); + nbmc_write_index(nb_dev, 0xe9, 0x00200020); + nbmc_write_index(nb_dev, 0xe0, 0x00180018); + nbmc_write_index(nb_dev, 0xe1, 0x00180018); + nbmc_write_index(nb_dev, 0xe8, 0x00180018); + nbmc_write_index(nb_dev, 0xe9, 0x00180018); + + /* Misc options. */ + /* Memory Termination. */ + set_nbmc_enable_bits(nb_dev, 0xa1, 0x0ff, 0x044); + set_nbmc_enable_bits(nb_dev, 0xb4, 0xf00, 0xb00); +#if 0 + /* Controller Termation. */ + set_nbmc_enable_bits(nb_dev, 0xb1, 0x77770000, 0x77770000); +#endif + + /* OEM Init MC. 667MHz. */ + nbmc_write_index(nb_dev, 0xa8, 0x7a5aaa78); + nbmc_write_index(nb_dev, 0xa9, 0x514a2319); + nbmc_write_index(nb_dev, 0xaa, 0x54400520); + nbmc_write_index(nb_dev, 0xab, 0x441460ff); + nbmc_write_index(nb_dev, 0xa0, 0x20f00a48); + set_nbmc_enable_bits(nb_dev, 0xa2, ~(0xffffffc7), 0x10); + nbmc_write_index(nb_dev, 0xb2, 0x00000303); + set_nbmc_enable_bits(nb_dev, 0xb1, ~(0xffffff70), 0x45); + /* Do it later. */ + /* set_nbmc_enable_bits(nb_dev, 0xac, ~(0xfffffff0), 0x0b); */ + + /* Init PM timing. */ + for(i=0; i<4; i++) + { + l_dword = nbmc_read_index(nb_dev, 0xa0+i); + nbmc_write_index(nb_dev, 0xc8+i, l_dword); + } + for(i=0; i<4; i++) + { + l_dword = nbmc_read_index(nb_dev, 0xa8+i); + nbmc_write_index(nb_dev, 0xcc+i, l_dword); + } + l_dword = nbmc_read_index(nb_dev, 0xb1); + set_nbmc_enable_bits(nb_dev, 0xc8, 0xff<<24, ((l_dword&0x0f)<<24)|((l_dword&0xf00)<<20)); + + /* Init MC FB. */ + /* FB_Start = ; FB_End = ; iSpSize = 0x0080, 128MB. */ + nbmc_write_index(nb_dev, 0x11, 0x40000000); + FB_Start = 0xc00 + 0x080; + FB_End = 0xc00 + 0x080; + nbmc_write_index(nb_dev, 0x10, (((FB_End&0xfff)<<20)-0x10000)|(((FB_Start&0xfff)-0x080)<<4)); + set_nbmc_enable_bits(nb_dev, 0x0d, ~0x000ffff0, (FB_Start&0xfff)<<20); + nbmc_write_index(nb_dev, 0x0f, 0); + nbmc_write_index(nb_dev, 0x0e, (FB_Start&0xfff)|(0xaaaa<<12)); +#endif + + /* GFX_InitSP finished. */ +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations pcie_ops = { + .read_resources = rs780_gfx_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = internal_gfx_pci_dev_init, /* The option ROM initializes the device. rs780_gfx_init, */ + .scan_bus = 0, + .enable = rs780_internal_gfx_enable, + .ops_pci = &lops_pci, +}; + +/* + * We should list all of them here. + * */ +static const struct pci_driver pcie_driver_780 __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS780_INT_GFX, +}; + +static const struct pci_driver pcie_driver_780c __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS780C_INT_GFX, +}; +static const struct pci_driver pcie_driver_780m __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS780M_INT_GFX, +}; +static const struct pci_driver pcie_driver_780mc __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS780MC_INT_GFX, +}; +static const struct pci_driver pcie_driver_780e __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS780E_INT_GFX, +}; +static const struct pci_driver pcie_driver_785g __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS785G_INT_GFX, +}; + +/* step 12 ~ step 14 from rpr */ +static void single_port_configuration(device_t nb_dev, device_t dev) +{ + u8 result, width; + u32 reg32; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration.\n"); + + /* step 12 training, releases hold training for GFX port 0 (device 2) */ + PcieReleasePortTraining(nb_dev, dev, 2); + result = PcieTrainPort(nb_dev, dev, 2); + printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step12.\n"); + + /* step 13 Power Down Control */ + /* step 13.1 Enables powering down transmitter and receiver pads along with PLL macros. */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); + + /* step 13.a Link Training was NOT successful */ + if (!result) { + set_nbmisc_enable_bits(nb_dev, 0x8, 0, 0x3 << 4); /* prevent from training. */ + set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x3 << 2); /* hide the GFX bridge. */ + if (cfg->gfx_tmds) + nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0); + else { + nbpcie_ind_write_index(nb_dev, 0x65, 0xffffffff); + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 3, 1 << 3); + } + } else { /* step 13.b Link Training was successful */ + set_pcie_enable_bits(dev, 0xA2, 0xFF, 0x1); + reg32 = nbpcie_p_read_index(dev, 0x29); + width = reg32 & 0xFF; + printk(BIOS_DEBUG, "GFX Inactive Lanes = 0x%x.\n", width); + switch (width) { + case 1: + case 2: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x7f7f : 0xccfefe); + break; + case 4: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x3f3f : 0xccfcfc); + break; + case 8: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x0f0f : 0xccf0f0); + break; + } + } + printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step13.\n"); + + /* step 14 Reset Enumeration Timer, disables the shortening of the enumeration timer */ + set_pcie_enable_bits(dev, 0x70, 1 << 19, 1 << 19); + printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step14.\n"); +} + +static void dual_port_configuration(device_t nb_dev, device_t dev) +{ + u8 result, width; + u32 reg32, dev_ind = dev->path.pci.devfn >> 3; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + /* 5.4.1.2 Dual Port Configuration */ + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); + set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); + + /* 5.7. Training for Device 2 */ + /* 5.7.1. Releases hold training for GFX port 0 (device 2) */ + PcieReleasePortTraining(nb_dev, dev, dev_ind); + /* 5.7.2- 5.7.9. PCIE Link Training Sequence */ + result = PcieTrainPort(nb_dev, dev, dev_ind); + + /* Power Down Control for Device 2 */ + /* Link Training was NOT successful */ + if (!result) { + /* Powers down all lanes for port A */ + /* nbpcie_ind_write_index(nb_dev, 0x65, 0x0f0f); */ + /* Note: I have to disable the slot where there isnt a device, + * otherwise the system will hang. I dont know why. */ + set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << dev_ind, 1 << dev_ind); + + } else { /* step 16.b Link Training was successful */ + reg32 = nbpcie_p_read_index(dev, 0xa2); + width = (reg32 >> 4) & 0x7; + printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); + switch (width) { + case 1: + case 2: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x0707 : 0x0e0e); + break; + case 4: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x0303 : 0x0c0c); + break; + } + } +} + +/* For single port GFX configuration Only +* width: +* 000 = x16 +* 001 = x1 +* 010 = x2 +* 011 = x4 +* 100 = x8 +* 101 = x12 (not supported) +* 110 = x16 +*/ +static void dynamic_link_width_control(device_t nb_dev, device_t dev, u8 width) +{ + u32 reg32; + device_t sb_dev; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + /* step 5.9.1.1 */ + reg32 = nbpcie_p_read_index(dev, 0xa2); + + /* step 5.9.1.2 */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); + /* step 5.9.1.3 */ + set_pcie_enable_bits(dev, 0xa2, 3 << 0, width << 0); + /* step 5.9.1.4 */ + set_pcie_enable_bits(dev, 0xa2, 1 << 8, 1 << 8); + /* step 5.9.2.4 */ + if (0 == cfg->gfx_reconfiguration) + set_pcie_enable_bits(dev, 0xa2, 1 << 11, 1 << 11); + + /* step 5.9.1.5 */ + do { + reg32 = nbpcie_p_read_index(dev, 0xa2); + } + while (reg32 & 0x100); + + /* step 5.9.1.6 */ + sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0)); + do { + reg32 = pci_ext_read_config32(nb_dev, sb_dev, + PCIE_VC0_RESOURCE_STATUS); + } while (reg32 & VC_NEGOTIATION_PENDING); + + /* step 5.9.1.7 */ + reg32 = nbpcie_p_read_index(dev, 0xa2); + if (((reg32 & 0x70) >> 4) != 0x6) { + /* the unused lanes should be powered off. */ + } + + /* step 5.9.1.8 */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 0 << 0); +} + +/* +* GFX Core initialization, dev2, dev3 +*/ +void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port) +{ + u32 reg32; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + printk(BIOS_DEBUG, "rs780_gfx_init, nb_dev=0x%p, dev=0x%p, port=0x%x.\n", + nb_dev, dev, port); + + /* GFX Core Initialization */ + //if (port == 2) return; + + /* step 2, TMDS, (only need if CMOS option is enabled) */ + if (cfg->gfx_tmds) { + } + +#if 1 /* external clock mode */ + /* table 5-22, 5.9.1. REFCLK */ + /* 5.9.1.1. Disables the GFX REFCLK transmitter so that the GFX + * REFCLK PAD can be driven by an external source. */ + /* 5.9.1.2. Enables GFX REFCLK receiver to receive the REFCLK from an external source. */ + set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28 | 1 << 26, 1 << 28); + + /* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */ + /* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */ + /* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */ + set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10, + 1 << 6 | 1 << 8 | 1 << 10); + reg32 = nbmisc_read_index(nb_dev, 0x28); + printk(BIOS_DEBUG, "misc 28 = %x\n", reg32); + + /* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */ + set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 1 << 31); +#else /* internal clock mode */ + /* table 5-23, 5.9.1. REFCLK */ + /* 5.9.1.1. Enables the GFX REFCLK transmitter so that the GFX + * REFCLK PAD can be driven by the SB REFCLK. */ + /* 5.9.1.2. Disables GFX REFCLK receiver from receiving the + * REFCLK from an external source.*/ + set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28, 1 << 29 | 0 << 28); + + /* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */ + /* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */ + /* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */ + set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10, + 0); + reg32 = nbmisc_read_index(nb_dev, 0x28); + printk(BIOS_DEBUG, "misc 28 = %x\n", reg32); + + /* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */ + set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 0 << 31); +#endif + + /* step 5.9.3, GFX overclocking, (only need if CMOS option is enabled) */ + /* 5.9.3.1. Increases PLL BW for 6G operation.*/ + /* set_nbmisc_enable_bits(nb_dev, 0x36, 0x3FF << 4, 0xB5 << 4); */ + /* skip */ + + /* step 5.9.4, reset the GFX link */ + /* step 5.9.4.1 asserts both calibration reset and global reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); + + /* step 5.9.4.2 de-asserts calibration reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 14, 0 << 14); + + /* step 5.9.4.3 wait for at least 200us */ + udelay(300); + + /* step 5.9.4.4 de-asserts global reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 15, 0 << 15); + + /* 5.9.5 Reset PCIE_GFX Slot */ + /* It is done in mainboard.c */ + set_pcie_reset(); + mdelay(1); + set_pcie_dereset(); + + /* step 5.9.8 program PCIE memory mapped configuration space */ + /* done by enable_pci_bar3() before */ + + /* step 7 compliance state, (only need if CMOS option is enabled) */ + /* the compliance stete is just for test. refer to 4.2.5.2 of PCIe specification */ + if (cfg->gfx_compliance) { + /* force compliance */ + set_nbmisc_enable_bits(nb_dev, 0x32, 1 << 6, 1 << 6); + /* release hold training for device 2. GFX initialization is done. */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4); + dynamic_link_width_control(nb_dev, dev, cfg->gfx_link_width); + printk(BIOS_DEBUG, "rs780_gfx_init step7.\n"); + return; + } + + /* 5.9.12 Core Initialization. */ + /* 5.9.12.1 sets RCB timeout to be 25ms */ + /* 5.9.12.2. RCB Cpl timeout on link down. */ + set_pcie_enable_bits(dev, 0x70, 7 << 16 | 1 << 19, 4 << 16 | 1 << 19); + printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.1.\n"); + + /* step 5.9.12.3 disables slave ordering logic */ + set_pcie_enable_bits(nb_dev, 0x20, 1 << 8, 1 << 8); + printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.3.\n"); + + /* step 5.9.12.4 sets DMA payload size to 64 bytes */ + set_pcie_enable_bits(nb_dev, 0x10, 7 << 10, 4 << 10); + /* 5.9.12.5. Blocks DMA traffic during C3 state. */ + set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); + + /* 5.9.12.6. Disables RC ordering logic */ + set_pcie_enable_bits(nb_dev, 0x20, 1 << 9, 1 << 9); + + /* Enabels TLP flushing. */ + /* Note: It is got from RS690. The system will hang without this action. */ + set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19); + + /* 5.9.12.7. Ignores DLLPs during L1 so that txclk can be turned off */ + set_pcie_enable_bits(nb_dev, 0x2, 1 << 0, 1 << 0); + + /* 5.9.12.8 Prevents LC to go from L0 to Rcv_L0s if L1 is armed. */ + set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); + + /* 5.9.12.9 CMGOOD_OVERRIDE for end point initiated lane degradation. */ + set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17); + printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.9.\n"); + + /* 5.9.12.10 Sets the timer in Config state from 20us to */ + /* 5.9.12.11 De-asserts RX_EN in L0s. */ + /* 5.9.12.12 Enables de-assertion of PG2RX_CR_EN to lock clock + * recovery parameter when lane is in electrical idle in L0s.*/ + set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 << 23 | 1 << 19 | 1 << 28); + + /* 5.9.12.13. Turns off offset calibration. */ + /* 5.9.12.14. Enables Rx Clock gating in CDR */ + set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 10/* | 1 << 22 */, 1 << 10/* | 1 << 22 */); + + /* 5.9.12.15. Sets number of TX Clocks to drain TX Pipe to 3. */ + set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 3 << 4); + + /* 5.9.12.16. Lets PI use Electrical Idle from PHY when + * turning off PLL in L1 at Gen2 speed instead Inferred Electrical Idle. */ + set_pcie_enable_bits(nb_dev, 0x40, 3 << 14, 2 << 14); + + /* 5.9.12.17. Prevents the Electrical Idle from causing a transition from Rcv_L0 to Rcv_L0s. */ + set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20); + + /* 5.9.12.18. Prevents the LTSSM from going to Rcv_L0s if it has already + * acknowledged a request to go to L1. */ + set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); + + /* 5.9.12.19. LDSK only taking deskew on deskewing error detect */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 28, 0 << 28); + + /* 5.9.12.20. Bypasses lane de-skew logic if in x1 */ + set_pcie_enable_bits(nb_dev, 0xC2, 1 << 14, 1 << 14); + + /* 5.9.12.21. Sets Electrical Idle Threshold. */ + set_nbmisc_enable_bits(nb_dev, 0x35, 3 << 21, 2 << 21); + + /* 5.9.12.22. Advertises -6 dB de-emphasis value in TS1 Data Rate Identifier + * Only if CMOS Option in section. skip */ + + /* 5.9.12.23. Disables GEN2 capability of the device. */ + set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0); + + /* 5.9.12.24.Disables advertising Upconfigure Support. */ + set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13); + + /* 5.9.12.25. No comment in RPR. */ + set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 10, 0 << 10); + + /* 5.9.12.26. This capacity is required since links wider than x1 and/or multiple link + * speed are supported */ + set_pcie_enable_bits(nb_dev, 0xC1, 1 << 0, 1 << 0); + + /* 5.9.12.27. Enables NVG86 ECO. A13 above only. */ + if (get_nb_rev(nb_dev) == REV_RS780_A12) /* A12 */ + set_pcie_enable_bits(dev, 0x02, 1 << 11, 1 << 11); + + /* 5.9.12.28 Hides and disables the completion timeout method. */ + set_pcie_enable_bits(nb_dev, 0xC1, 1 << 2, 0 << 2); + + /* 5.9.12.29. Use the bif_core de-emphasis strength by default. */ + /* set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 28, 1 << 28); */ + + /* 5.9.12.30. Set TX arbitration algorithm to round robin */ + set_pcie_enable_bits(nb_dev, 0x1C, + 1 << 0 | 0x1F << 1 | 0x1F << 6, + 1 << 0 | 0x04 << 1 | 0x04 << 6); + + /* Single-port/Dual-port configureation. */ + switch (cfg->gfx_dual_slot) { + case 0: + /* step 1, lane reversal (only need if build config option is enabled) */ + if (cfg->gfx_lane_reversal) { + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); + } + printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); + + printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); + if((dev->path.pci.devfn >> 3) == 2) { + single_port_configuration(nb_dev, dev); + } else { + set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x2 << 2); /* hide the GFX bridge. */ + printk(BIOS_INFO, "Single port. Do nothing.\n"); // If dev3 + } + + break; + case 1: + /* step 1, lane reversal (only need if build config option is enabled) */ + if (cfg->gfx_lane_reversal) { + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); + } + printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); + /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ + /* AMD calls the configuration CrossFire */ + set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); + printk(BIOS_DEBUG, "rs780_gfx_init step2.\n"); + + printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); + dual_port_configuration(nb_dev, dev); + break; + + case 2: + + if(is_dev3_present()){ + /* step 1, lane reversal (only need if CMOS option is enabled) */ + if (cfg->gfx_lane_reversal) { + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); + } + printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); + /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ + /* AMD calls the configuration CrossFire */ + set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); + printk(BIOS_DEBUG, "rs780_gfx_init step2.\n"); + + + printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); + dual_port_configuration(nb_dev, dev); + + }else{ + if (cfg->gfx_lane_reversal) { + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); + } + printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); + + if((dev->path.pci.devfn >> 3) == 2) + single_port_configuration(nb_dev, dev); + else{ + set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x2 << 2); /* hide the GFX bridge. */ + printk(BIOS_DEBUG, "If dev3.., single port. Do nothing.\n"); + } + } + + default: + printk(BIOS_INFO, "Incorrect configuration of external GFX slot.\n"); + break; + } +} diff --git a/src/southbridge/amd/rs780/ht.c b/src/southbridge/amd/rs780/ht.c new file mode 100644 index 0000000000..03d4f84645 --- /dev/null +++ b/src/southbridge/amd/rs780/ht.c @@ -0,0 +1,90 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 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 +#include +#include +#include +#include +#include "rs780.h" + +/* for UMA internal graphics */ +void avoid_lpc_dma_deadlock(device_t nb_dev, device_t sb_dev) +{ + device_t cpu_f0; + u8 reg; + + cpu_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + set_nbcfg_enable_bits(cpu_f0, 0x68, 3 << 21, 1 << 21); + + reg = nbpcie_p_read_index(sb_dev, 0x10); + reg |= 0x100; /* bit9=1 */ + nbpcie_p_write_index(sb_dev, 0x10, reg); + + reg = nbpcie_p_read_index(nb_dev, 0x10); + reg |= 0x100; /* bit9=1 */ + nbpcie_p_write_index(nb_dev, 0x10, reg); + + /* Enable NP protocol over PCIE for memory-mapped writes targeting LPC + * Set this bit to avoid a deadlock condition. */ + reg = htiu_read_index(nb_dev, 0x6); + reg |= 0x1000000; /* bit26 */ + htiu_write_index(nb_dev, 0x6, reg); +} + +static void pcie_init(struct device *dev) +{ + /* Enable pci error detecting */ + u32 dword; + + printk(BIOS_INFO, "pcie_init in rs780_ht.c\n"); + + /* System error enable */ + dword = pci_read_config32(dev, 0x04); + dword |= (1 << 8); /* System error enable */ + dword |= (1 << 30); /* Clear possible errors */ + pci_write_config32(dev, 0x04, dword); + + /* + * 1 is APIC enable + * 18 is enable nb to accept A4 interrupt request from SB. + */ + dword = pci_read_config32(dev, 0x4C); + dword |= 1 << 1 | 1 << 18; /* Clear possible errors */ + pci_write_config32(dev, 0x4C, dword); +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations ht_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .init = pcie_init, + .scan_bus = 0, + .ops_pci = &lops_pci, +}; + +static const struct pci_driver ht_driver __pci_driver = { + .ops = &ht_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_RS780_HT, +}; diff --git a/src/southbridge/amd/rs780/pcie.c b/src/southbridge/amd/rs780/pcie.c new file mode 100644 index 0000000000..9cbd832661 --- /dev/null +++ b/src/southbridge/amd/rs780/pcie.c @@ -0,0 +1,392 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 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 +#include +#include +#include +#include +#include +#include "rs780.h" + +/*------------------------------------------------ +* Global variable +------------------------------------------------*/ +PCIE_CFG AtiPcieCfg = { + PCIE_ENABLE_STATIC_DEV_REMAP, /* Config */ + 0, /* ResetReleaseDelay */ + 0, /* Gfx0Width */ + 0, /* Gfx1Width */ + 0, /* GfxPayload */ + 0, /* GppPayload */ + 0, /* PortDetect, filled by GppSbInit */ + 0, /* PortHp */ + 0, /* DbgConfig */ + 0, /* DbgConfig2 */ + 0, /* GfxLx */ + 0, /* GppLx */ + 0, /* NBSBLx */ + 0, /* PortSlotInit */ + 0, /* Gfx0Pwr */ + 0, /* Gfx1Pwr */ + 0 /* GppPwr */ +}; + +static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port); +static void ValidatePortEn(device_t nb_dev); + +static void ValidatePortEn(device_t nb_dev) +{ +} + +/***************************************************************** +* Compliant with CIM_33's PCIEPowerOffGppPorts +* Power off unused GPP lines +*****************************************************************/ +static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port) +{ + u32 reg; + u16 state_save; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + u8 state = cfg->port_enable; + + if (!(AtiPcieCfg.Config & PCIE_DISABLE_HIDE_UNUSED_PORTS)) + state &= AtiPcieCfg.PortDetect; + state = ~state; + state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7); + state_save = state << 17; + state &= !(AtiPcieCfg.PortHp); + reg = nbmisc_read_index(nb_dev, 0x0c); + reg |= state; + nbmisc_write_index(nb_dev, 0x0c, reg); + + reg = nbmisc_read_index(nb_dev, 0x08); + reg |= state_save; + nbmisc_write_index(nb_dev, 0x08, reg); + + if ((AtiPcieCfg.Config & PCIE_OFF_UNUSED_GPP_LANES) + && !(AtiPcieCfg. + Config & (PCIE_DISABLE_HIDE_UNUSED_PORTS + + PCIE_GFX_COMPLIANCE))) { + } + /* step 3 Power Down Control for Southbridge */ + reg = nbpcie_p_read_index(dev, 0xa2); + + switch ((reg >> 4) & 0x7) { /* get bit 4-6, LC_LINK_WIDTH_RD */ + case 1: + nbpcie_ind_write_index(nb_dev, 0x65, 0x0e0e); + break; + case 2: + nbpcie_ind_write_index(nb_dev, 0x65, 0x0c0c); + break; + default: + break; + } +} + +/********************************************************************** +**********************************************************************/ +static void switching_gppsb_configurations(device_t nb_dev, device_t sb_dev) +{ + u32 reg; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + /* 5.5.7.1-3 enables GPP reconfiguration */ + reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); + reg |= + (RECONFIG_GPPSB_EN + RECONFIG_GPPSB_LINK_CONFIG + + RECONFIG_GPPSB_ATOMIC_RESET); + nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); + + /* 5.5.7.4a. De-asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ + reg = nbmisc_read_index(nb_dev, 0x66); + reg |= 1 << 31; + nbmisc_write_index(nb_dev, 0x66, reg); + /* 5.5.7.4b. sets desired GPPSB configurations, bit4-7 */ + reg = nbmisc_read_index(nb_dev, 0x67); + reg &= 0xFFFFff0f; /* clean */ + reg |= cfg->gppsb_configuration << 4; + nbmisc_write_index(nb_dev, 0x67, reg); + +#if 1 + /* NOTE: + * In CIMx 4.5.0 and RPR, 4c is done before 5 & 6. But in this way, + * a x4 device in port B (dev 4) of Configuration B can only be detected + * as x1, instead of x4. When the port B is being trained, the + * LC_CURRENT_STATE is 6 and the LC_LINK_WIDTH_RD is 1. We have + * to set the PCIEIND:0x65 as 0xE0E0 and reset the slot. Then the card + * seems to work in x1 mode. + * In the 2nd way below, we do the 5 & 6 before 4c. it conforms the + * CIMx 4.3.0. It conflicts with RPR. But based on the test result I've + * made so far, I haven't found any mistake. + */ + /* 5.5.7.4c. Asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ + reg = nbmisc_read_index(nb_dev, 0x66); + reg &= ~(1 << 31); + nbmisc_write_index(nb_dev, 0x66, reg); + + /* 5.5.7.5-6. read bit14 and write back its inverst value */ + reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); + reg ^= RECONFIG_GPPSB_GPPSB; + nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); +#else + /* 5.5.7.5-6. read bit14 and write back its inverst value */ + reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); + reg ^= RECONFIG_GPPSB_GPPSB; + nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); + + /* 5.5.7.4c. Asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ + reg = nbmisc_read_index(nb_dev, 0x66); + reg &= ~(1 << 31); + nbmisc_write_index(nb_dev, 0x66, reg); +#endif + /* 5.5.7.7. delay 1ms */ + mdelay(1); + + /* 5.5.7.8. waits until SB has trained to L0, poll for bit0-5 = 0x10 */ + do { + reg = nbpcie_p_read_index(sb_dev, PCIE_LC_STATE0); + reg &= 0x3f; /* remain LSB [5:0] bits */ + } while (LC_STATE_RECONFIG_GPPSB != reg); + + /* 5.5.7.9.ensures that virtual channel negotiation is completed. poll for bit1 = 0 */ + do { + reg = + pci_ext_read_config32(nb_dev, sb_dev, + PCIE_VC0_RESOURCE_STATUS); + } while (reg & VC_NEGOTIATION_PENDING); +} + +static void switching_gpp_configurations(device_t nb_dev, device_t sb_dev) +{ + u32 reg; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + /* 5.6.2.1. De-asserts STRAP_BIF_all_valid for PCIE-GPP core */ + reg = nbmisc_read_index(nb_dev, 0x22); + reg |= 1 << 14; + nbmisc_write_index(nb_dev, 0x22, reg); + /* 5.6.2.2. sets desired GPPSB configurations, bit4-7 */ + reg = nbmisc_read_index(nb_dev, 0x2D); + reg &= ~(0xF << 7); /* clean */ + reg |= cfg->gpp_configuration << 7; + nbmisc_write_index(nb_dev, 0x2D, reg); + /* 5.6.2.3. Asserts STRAP_BIF_all_valid for PCIE-GPP core */ + reg = nbmisc_read_index(nb_dev, 0x22); + reg &= ~(1 << 14); + nbmisc_write_index(nb_dev, 0x22, reg); +} + +/***************************************************************** +* The rs780 uses NBCONFIG:0x1c (BAR3) to map the PCIE Extended Configuration +* Space to a 256MB range within the first 4GB of addressable memory. +*****************************************************************/ +void enable_pcie_bar3(device_t nb_dev) +{ + printk(BIOS_DEBUG, "enable_pcie_bar3()\n"); + set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 1 << 30); /* Enables writes to the BAR3 register. */ + set_nbcfg_enable_bits(nb_dev, 0x84, 7 << 16, 0 << 16); + + pci_write_config32(nb_dev, 0x1C, EXT_CONF_BASE_ADDRESS); /* PCIEMiscInit */ + pci_write_config32(nb_dev, 0x20, 0x00000000); + set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 1 << 28); /* PCIEMiscInit */ + ProgK8TempMmioBase(1, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); +} + +/***************************************************************** +* We should disable bar3 when we want to exit rs780_enable, because bar3 will be +* remapped in set_resource later. +*****************************************************************/ +void disable_pcie_bar3(device_t nb_dev) +{ + printk(BIOS_DEBUG, "disable_pcie_bar3()\n"); + pci_write_config32(nb_dev, 0x1C, 0); /* clear BAR3 address */ + set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3. */ + set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 0); /* disable bar3 decode */ + ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); +} + +/***************************************** +* Compliant with CIM_33's PCIEGPPInit +* nb_dev: +* root bridge struct +* dev: +* p2p bridge struct +* port: +* p2p bridge number, 4-10 +*****************************************/ +void rs780_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) +{ + u32 gfx_gpp_sb_sel; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + printk(BIOS_DEBUG, "gpp_sb_init nb_dev=0x%x, dev=0x%x, port=0x%x\n", nb_dev->path.pci.devfn, dev->path.pci.devfn, port); + + gfx_gpp_sb_sel = port >= 4 && port <= 8 ? + PCIE_CORE_INDEX_GPPSB : /* 4,5,6,7,8 */ + PCIE_CORE_INDEX_GPP; /* 9,10 */ + /* init GPP core */ + /* 5.10.8.3. Disable slave ordering logic */ + set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 8, + 1 << 8); + /* 5.10.8.7. PCIE initialization 5.10.2: rpr 2.12*/ + set_pcie_enable_bits(nb_dev, 0x02 | gfx_gpp_sb_sel, 1 << 0, 1 << 0); /* no description in datasheet. */ + + /* init GPPSB port. rpr 5.10.8 */ + /* 5.10.8.1-5.10.8.2. Sets RCB timeout to be 100ms/4=25ms by setting bits[18:16] to 3 h4 + * and shortens the enumeration timer by setting bit[19] to 1 + */ + set_pcie_enable_bits(dev, 0x70, 0xF << 16, 0x4 << 16 | 1 << 19); + /* 5.10.8.4. Sets DMA payload size to 64 bytes. */ + set_pcie_enable_bits(nb_dev, 0x10 | gfx_gpp_sb_sel, 7 << 10, 4 << 10); + /* 5.10.8.6. Disable RC ordering logic */ + set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 9, 1 << 9); + /* 5.10.8.7. Ignores DLLs druing L1 */ + set_pcie_enable_bits(nb_dev, 0x02 | gfx_gpp_sb_sel, 1 << 0, 1 << 0); + /* 5.10.8.8. Prevents LCto go from L0 to Rcv_L0s if L1 is armed. */ + set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); + /* 5.10.8.9. Sets timer in Config state from 20us to 1us. + * 5.10.8.10. De-asserts RX_EN in L0s + * 5.10.8.11. Enables de-assertion of PG2RX_CR_EN to lock clock recovery parameter when .. */ + set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 <<23 | 1 << 19 | 1 << 28); + /* 5.10.8.12. Turns off offset calibration */ + /* 5.10.8.13. Enables Rx Clock gating in CDR */ + if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) + set_nbmisc_enable_bits(nb_dev, 0x67, 1 << 14 | 1 << 26, 1 << 14 | 1 << 26); /* 4,5,6,7 */ + else + set_nbmisc_enable_bits(nb_dev, 0x24, 1 << 29 | 1 << 28, 1 << 29 | 1 << 28); /* 9,10 */ + /* 5.10.8.14. Sets number of TX Clocks to drain TX Pipe to 3 */ + set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 0x3 << 4); + /* 5.10.8.15. empty */ + /* 5.10.8.16. P_ELEC_IDLE_MODE */ + set_pcie_enable_bits(nb_dev, 0x40 | gfx_gpp_sb_sel, 0x3 << 14, 0x2 << 14); + /* 5.10.8.17. LC_BLOCK_EL_IDLE_IN_L0 */ + set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20); + /* 5.10.8.18. LC_DONT_GO_TO_L0S_IFL1_ARMED */ + set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); + /* 5.10.8.19. RXP_REALIGN_ON_EACH_TSX_OR_SKP */ + set_pcie_enable_bits(nb_dev, 0x40 | gfx_gpp_sb_sel, 1 << 28, 0 << 28); + /* 5.10.8.20. Bypass lane de-skew logic if in x1 */ + set_pcie_enable_bits(nb_dev, 0xC2 | gfx_gpp_sb_sel, 1 << 14, 1 << 14); + /* 5.10.8.21. sets electrical idle threshold. */ + if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) + set_nbmisc_enable_bits(nb_dev, 0x6A, 3 << 22, 2 << 22); + else + set_nbmisc_enable_bits(nb_dev, 0x24, 3 << 16, 2 << 16); + + /* 5.10.8.22. Disable GEN2 */ + /* TODO: should be 2 seperated cases. */ + set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 31, 0 << 31); + set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 5, 0 << 5); + set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 31, 0 << 31); + set_nbmisc_enable_bits(nb_dev, 0x37, 7 << 5, 0 << 5); + /* 5.10.8.23. Disables GEN2 capability of the device. RPR says enable? No! */ + set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0); + /* 5.10.8.24. Disable advertising upconfigure support. */ + set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13); + /* 5.10.8.25-26. STRAP_BIF_DSN_EN */ + if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) + set_nbmisc_enable_bits(nb_dev, 0x68, 1 << 19, 0 << 19); + else + set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 3, 0 << 3); + /* 5.10.8.27-28. */ + set_pcie_enable_bits(nb_dev, 0xC1 | gfx_gpp_sb_sel, 1 << 0 | 1 << 2, 1 << 0 | 0 << 2); + /* 5.10.8.29. Uses the bif_core de-emphasis strength by default. */ + if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) { + set_nbmisc_enable_bits(nb_dev, 0x67, 1 << 10, 1 << 10); + set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 29, 1 << 29); + } + else { + set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 30, 1 << 30); + } + /* 5.10.8.30. Set TX arbitration algorithm to round robin. */ + set_pcie_enable_bits(nb_dev, 0x1C | gfx_gpp_sb_sel, + 1 << 0 | 0x1F << 1 | 0x1F << 6, + 1 << 0 | 0x04 << 1 | 0x04 << 6); + + /* check compliance rpr step 2.1*/ + if (AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE) { + u32 tmp; + tmp = nbmisc_read_index(nb_dev, 0x67); + tmp |= 1 << 3; + nbmisc_write_index(nb_dev, 0x67, tmp); + } + + /* step 5: dynamic slave CPL buffer allocation. Disable it, otherwise linux hangs. Why? */ + /* set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 11, 1 << 11); */ + + /* step 5a: Training for GPP devices */ + /* init GPP */ + switch (port) { + case 4: /* GPP */ + case 5: + case 6: + case 7: + case 9: + case 10: + /* 5.10.8.5. Blocks DMA traffic during C3 state */ + set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); + /* Enabels TLP flushing */ + set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19); + + /* check port enable */ + if (cfg->port_enable & (1 << port)) { + PcieReleasePortTraining(nb_dev, dev, port); + if (!(AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE)) { + u8 res = PcieTrainPort(nb_dev, dev, port); + printk(BIOS_DEBUG, "PcieTrainPort port=0x%x result=%d\n", port, res); + if (res) { + AtiPcieCfg.PortDetect |= 1 << port; + } + } + } + break; + case 8: /* SB */ + break; + } + PciePowerOffGppPorts(nb_dev, dev, port); +} + +/***************************************** +* Compliant with CIM_33's PCIEConfigureGPPCore +*****************************************/ +void config_gpp_core(device_t nb_dev, device_t sb_dev) +{ + u32 reg; + struct southbridge_amd_rs780_config *cfg = + (struct southbridge_amd_rs780_config *)nb_dev->chip_info; + + reg = nbmisc_read_index(nb_dev, 0x20); + if (AtiPcieCfg.Config & PCIE_ENABLE_STATIC_DEV_REMAP) + reg &= 0xfffffffd; /* set bit1 = 0 */ + else + reg |= 0x2; /* set bit1 = 1 */ + nbmisc_write_index(nb_dev, 0x20, reg); + + reg = nbmisc_read_index(nb_dev, 0x67); /* get STRAP_BIF_LINK_CONFIG_GPPSB at bit 4-7 */ + if (cfg->gppsb_configuration != ((reg >> 4) & 0xf)) + switching_gppsb_configurations(nb_dev, sb_dev); + reg = nbmisc_read_index(nb_dev, 0x2D); /* get STRAP_BIF_LINK_CONFIG_GPP at bit 7-10 */ + if (cfg->gpp_configuration != ((reg >> 7) & 0xf)) + switching_gpp_configurations(nb_dev, sb_dev); + ValidatePortEn(nb_dev); +} diff --git a/src/southbridge/amd/rs780/rev.h b/src/southbridge/amd/rs780/rev.h new file mode 100644 index 0000000000..94ab752f9f --- /dev/null +++ b/src/southbridge/amd/rs780/rev.h @@ -0,0 +1,27 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 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 __RS780_REV_H__ +#define __RS780_REV_H__ + +#define REV_RS780_A11 0 +#define REV_RS780_A12 1 +#define REV_RS780_A13 2 + +#endif /* __RS780_REV_H__ */ diff --git a/src/southbridge/amd/rs780/rs780.h b/src/southbridge/amd/rs780/rs780.h index c91a4b3022..aba3e6929b 100644 --- a/src/southbridge/amd/rs780/rs780.h +++ b/src/southbridge/amd/rs780/rs780.h @@ -23,7 +23,7 @@ #include #include #include "chip.h" -#include "rs780_rev.h" +#include "rev.h" #define NBMISC_INDEX 0x60 #define NBHTIU_INDEX 0x94 diff --git a/src/southbridge/amd/rs780/rs780_cmn.c b/src/southbridge/amd/rs780/rs780_cmn.c deleted file mode 100644 index 4bd870bbf2..0000000000 --- a/src/southbridge/amd/rs780/rs780_cmn.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 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 - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rs780.h" - -static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) -{ - pci_write_config32(dev, index_reg, index); - return pci_read_config32(dev, index_reg + 0x4); -} - -static void nb_write_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); -} - -/* extension registers */ -u32 pci_ext_read_config32(device_t nb_dev, device_t dev, u32 reg) -{ - /*get BAR3 base address for nbcfg0x1c */ - u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; - printk(BIOS_DEBUG, "addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, - dev->path.pci.devfn); - addr |= dev->bus->secondary << 20 | /* bus num */ - dev->path.pci.devfn << 12 | reg; - return *((u32 *) addr); -} - -void pci_ext_write_config32(device_t nb_dev, device_t dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - - /*get BAR3 base address for nbcfg0x1c */ - u32 addr = pci_read_config32(nb_dev, 0x1c) & ~0xF; - /*printk(BIOS_DEBUG, "write: addr=%x,bus=%x,devfn=%x\n", addr, dev->bus->secondary, - dev->path.pci.devfn);*/ - addr |= dev->bus->secondary << 20 | /* bus num */ - dev->path.pci.devfn << 12 | reg_pos; - - reg = reg_old = *((u32 *) addr); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - *((u32 *) addr) = reg; - } -} - -u32 nbmisc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMISC_INDEX, (index)); -} - -void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); -} - -u32 nbpcie_p_read_index(device_t dev, u32 index) -{ - return nb_read_index((dev), NBPCIE_INDEX, (index)); -} - -void nbpcie_p_write_index(device_t dev, u32 index, u32 data) -{ - nb_write_index((dev), NBPCIE_INDEX, (index), (data)); -} - -u32 nbpcie_ind_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBPCIE_INDEX, (index)); -} - -void nbpcie_ind_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBPCIE_INDEX, (index), (data)); -} - -u32 htiu_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); -} - -void htiu_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); -} - -u32 nbmc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMC_INDEX, (index)); -} - -void nbmc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); -} - -void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = pci_read_config32(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config32(nb_dev, reg_pos, reg); - } -} - -void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, u8 val) -{ - u8 reg_old, reg; - reg = reg_old = pci_read_config8(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config8(nb_dev, reg_pos, reg); - } -} - -void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmc_write_index(nb_dev, reg_pos, reg); - } -} - -void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = htiu_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - htiu_write_index(nb_dev, reg_pos, reg); - } -} - -void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmisc_write_index(nb_dev, reg_pos, reg); - } -} - -void set_pcie_enable_bits(device_t dev, u32 reg_pos, u32 mask, u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nb_read_index(dev, NBPCIE_INDEX, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nb_write_index(dev, NBPCIE_INDEX, reg_pos, reg); - } -} - -/*********************************************************** -* To access bar3 we need to program PCI MMIO 7 in K8. -* in_out: -* 1: enable/enter k8 temp mmio base -* 0: disable/restore -***********************************************************/ -void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add) -{ - /* K8 Function1 is address map */ - device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); - device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - - if (in_out) { - u32 dword, sblk; - - /* Get SBLink value (HyperTransport I/O Hub Link ID). */ - dword = pci_read_config32(k8_f0, 0x64); - sblk = (dword >> 8) & 0x3; - - /* Fill MMIO limit/base pair. */ - pci_write_config32(k8_f1, 0xbc, - (((pcie_base_add + 0x10000000 - - 1) >> 8) & 0xffffff00) | 0x80 | (sblk << 4)); - pci_write_config32(k8_f1, 0xb8, (pcie_base_add >> 8) | 0x3); - pci_write_config32(k8_f1, 0xb4, - (((mmio_base_add + 0x10000000 - - 1) >> 8) & 0xffffff00) | (sblk << 4)); - pci_write_config32(k8_f1, 0xb0, (mmio_base_add >> 8) | 0x3); - } else { - pci_write_config32(k8_f1, 0xb8, 0); - pci_write_config32(k8_f1, 0xbc, 0); - pci_write_config32(k8_f1, 0xb0, 0); - pci_write_config32(k8_f1, 0xb4, 0); - } -} - -void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port) -{ - switch (port) { - case 2: /* GFX, bit4-5 */ - case 3: - set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, - 1 << (port + 2), 0 << (port + 2)); - break; - case 4: /* GPPSB, bit20-24 */ - case 5: - case 6: - case 7: - set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, - 1 << (port + 17), 0 << (port + 17)); - break; - case 9: /* GPP, bit 4,5 of miscind 0x2D */ - case 10: - set_nbmisc_enable_bits(nb_dev, 0x2D, - 1 << (port - 5), 0 << (port - 5)); - break; - } -} - -/******************************************************************************************************** -* Output: -* 0: no device is present. -* 1: device is present and is trained. -********************************************************************************************************/ -u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port) -{ - u16 count = 5000; - u32 lc_state, reg, current_link_width, lane_mask; - int8_t current, res = 0; - u32 gfx_gpp_sb_sel; - void set_pcie_dereset(void); - void set_pcie_reset(void); - - switch (port) { - case 2 ... 3: - gfx_gpp_sb_sel = PCIE_CORE_INDEX_GFX; - break; - case 4 ... 7: - gfx_gpp_sb_sel = PCIE_CORE_INDEX_GPPSB; - break; - case 9 ... 10: - gfx_gpp_sb_sel = PCIE_CORE_INDEX_GPP; - break; - default: - gfx_gpp_sb_sel = -1; - return 0; - } - - while (count--) { - mdelay(40); - udelay(200); - lc_state = nbpcie_p_read_index(dev, 0xa5); /* lc_state */ - printk(BIOS_DEBUG, "PcieLinkTraining port=%x:lc current state=%x\n", - port, lc_state); - current = lc_state & 0x3f; /* get LC_CURRENT_STATE, bit0-5 */ - - switch (current) { - case 0x00: /* 0x00-0x04 means no device is present */ - case 0x01: - case 0x02: - case 0x03: - case 0x04: - res = 0; - count = 0; - break; - case 0x06: - /* read back current link width [6:4]. */ - current_link_width = (nbpcie_p_read_index(dev, 0xA2) >> 4) & 0x7; - /* 4 means 7:4 and 15:12 - * 3 means 7:2 and 15:10 - * 2 means 7:1 and 15:9 - * egnoring the reversal case - */ - lane_mask = (0xFF << (current_link_width - 2) * 2) & 0xFF; - reg = nbpcie_ind_read_index(nb_dev, 0x65 | gfx_gpp_sb_sel); - reg |= lane_mask << 8 | lane_mask; - reg = 0xE0E0; /* TODO: See the comments in rs780_pcie.c, at about line 145. */ - nbpcie_ind_write_index(nb_dev, 0x65 | gfx_gpp_sb_sel, reg); - printk(BIOS_DEBUG, "link_width=%x, lane_mask=%x", - current_link_width, lane_mask); - set_pcie_reset(); - mdelay(1); - set_pcie_dereset(); - break; - case 0x07: /* device is in compliance state (training sequence is done). Move to train the next device */ - res = 0; - count = 0; - break; - case 0x10: - reg = - pci_ext_read_config32(nb_dev, dev, - PCIE_VC0_RESOURCE_STATUS); - printk(BIOS_DEBUG, "PcieTrainPort reg=0x%x\n", reg); - /* check bit1 */ - if (reg & VC_NEGOTIATION_PENDING) { /* bit1=1 means the link needs to be re-trained. */ - /* set bit8=1, bit0-2=bit4-6 */ - u32 tmp; - reg = - nbpcie_p_read_index(dev, - PCIE_LC_LINK_WIDTH); - tmp = (reg >> 4) && 0x3; /* get bit4-6 */ - reg &= 0xfff8; /* clear bit0-2 */ - reg += tmp; /* merge */ - reg |= 1 << 8; - count++; /* CIM said "keep in loop"? */ - } else { - res = 1; - count = 0; - } - break; - default: /* reset pcie */ - res = 0; - count = 0; /* break loop */ - break; - } - } - return res; -} - -/* -* Compliant with CIM_33's ATINB_SetToms. -* Set Top Of Memory below and above 4G. -*/ -void rs780_set_tom(device_t nb_dev) -{ - extern uint64_t uma_memory_base; - - /* set TOM */ - pci_write_config32(nb_dev, 0x90, uma_memory_base); - //nbmc_write_index(nb_dev, 0x1e, uma_memory_base); -} - -// extract single bit -u32 extractbit(u32 data, int bit_number) -{ - return (data >> bit_number) & 1; -} - -// extract bit field -u32 extractbits(u32 source, int lsb, int msb) -{ - int field_width = msb - lsb + 1; - u32 mask = 0xFFFFFFFF >> (32 - field_width); - return (source >> lsb) & mask; -} - -// return AMD cpuid family -int cpuidFamily(void) -{ - u32 baseFamily, extendedFamily, fms; - - fms = cpuid_eax (1); - baseFamily = extractbits (fms, 8, 11); - extendedFamily = extractbits (fms, 20, 27); - return baseFamily + extendedFamily; -} - - -// return non-zero for AMD family 0Fh processor found -int is_family0Fh(void) -{ - return cpuidFamily() == 0x0F; -} - - -// return non-zero for AMD family 10h processor found -int is_family10h(void) -{ - return cpuidFamily() == 0x10; -} diff --git a/src/southbridge/amd/rs780/rs780_early_setup.c b/src/southbridge/amd/rs780/rs780_early_setup.c deleted file mode 100644 index 57a7b62427..0000000000 --- a/src/southbridge/amd/rs780/rs780_early_setup.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 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 CONFIG_NORTHBRIDGE_AMD_AMDFAM10 -#define CONFIG_NORTHBRIDGE_AMD_AMDFAM10 0 -#endif - -#include "rs780_rev.h" - -#define NBHTIU_INDEX 0x94 /* Note: It is different with RS690, whose HTIU index is 0xA8 */ -#define NBMISC_INDEX 0x60 -#define NBMC_INDEX 0xE8 - -static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) -{ - pci_write_config32(dev, index_reg, index); - return pci_read_config32(dev, index_reg + 0x4); -} - -static void nb_write_index(device_t dev, u32 index_reg, u32 index, u32 data) -{ - pci_write_config32(dev, index_reg, index /* | 0x80 */ ); - pci_write_config32(dev, index_reg + 0x4, data); -} - -static u32 nbmisc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMISC_INDEX, (index)); -} - -static void nbmisc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data)); -} - -static u32 htiu_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBHTIU_INDEX, (index)); -} - -static void htiu_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data)); -} - -static u32 nbmc_read_index(device_t nb_dev, u32 index) -{ - return nb_read_index((nb_dev), NBMC_INDEX, (index)); -} - -static void nbmc_write_index(device_t nb_dev, u32 index, u32 data) -{ - nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data)); -} - -static void set_htiu_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = htiu_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - htiu_write_index(nb_dev, reg_pos, reg); - } -} - -static void set_nbmisc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmisc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmisc_write_index(nb_dev, reg_pos, reg); - } -} - -static void set_nbcfg_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = pci_read_config32(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config32(nb_dev, reg_pos, reg); - } -} -/* family 10 only, for reg > 0xFF */ -#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 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 &= ~mask; - reg |= val; - if (reg != reg_old) { - Set_NB32(fam10_dev, reg_pos, reg); - } -} -#else -#define set_fam10_ext_cfg_enable_bits(a, b, c, d) do {} while (0) -#endif - - -static void set_nbcfg_enable_bits_8(device_t nb_dev, u32 reg_pos, u8 mask, - u8 val) -{ - u8 reg_old, reg; - reg = reg_old = pci_read_config8(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - pci_write_config8(nb_dev, reg_pos, reg); - } -} - -static void set_nbmc_enable_bits(device_t nb_dev, u32 reg_pos, u32 mask, - u32 val) -{ - u32 reg_old, reg; - reg = reg_old = nbmc_read_index(nb_dev, reg_pos); - reg &= ~mask; - reg |= val; - if (reg != reg_old) { - nbmc_write_index(nb_dev, reg_pos, reg); - } -} - -static void get_cpu_rev(void) -{ - u32 eax; - - eax = cpuid_eax(1); - printk(BIOS_INFO, "get_cpu_rev EAX=0x%x.\n", eax); - if (eax <= 0xfff) - printk(BIOS_INFO, "CPU Rev is K8_Cx.\n"); - else if (eax <= 0x10fff) - printk(BIOS_INFO, "CPU Rev is K8_Dx.\n"); - else if (eax <= 0x20fff) - printk(BIOS_INFO, "CPU Rev is K8_Ex.\n"); - else if (eax <= 0x40fff) - printk(BIOS_INFO, "CPU Rev is K8_Fx.\n"); - else if (eax == 0x60fb1 || eax == 0x60f81) /*These two IDS are exception, they are G1. */ - printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); - else if (eax <= 0X60FF0) - printk(BIOS_INFO, "CPU Rev is K8_G0.\n"); - else if (eax <= 0x100000) - printk(BIOS_INFO, "CPU Rev is K8_G1.\n"); - else if (eax <= 0x100f00) - printk(BIOS_INFO, "CPU Rev is Fam 10.\n"); - else - printk(BIOS_INFO, "CPU Rev is K8_10.\n"); -} - -static u8 is_famly10(void) -{ - return (cpuid_eax(1) & 0xff00000) != 0; -} - -#if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */ -static u8 l3_cache(void) -{ - return (cpuid_edx(0x80000006) & (0x3FFF << 18)) != 0; -} - -static u8 cpu_core_number(void) -{ - return (cpuid_ecx(0x80000008) & 0xFF) + 1; -} -#endif - -static u8 get_nb_rev(device_t nb_dev) -{ - u8 reg; - reg = pci_read_config8(nb_dev, 0x89); /* copy from CIM, can't find in doc */ - switch(reg & 3) - { - case 0x01: - reg = REV_RS780_A12; - break; - case 0x02: - reg = REV_RS780_A13; - break; - default: - reg = REV_RS780_A11; - break; - } - return reg; -} - -/***************************************** - * Init HT link speed/width for rs780 -- k8 link - * 1: Check CPU Family, Family10? - * 2: Get CPU's HT speed and width - * 3: Decide HT mode 1 or 3 by HT Speed. >1GHz: HT3, else HT1 - *****************************************/ -static const u8 rs780_ibias[] = { - /* 1, 3 are reserved. */ - [0x0] = 0x4C, /* 200Mhz HyperTransport 1 only */ - [0x2] = 0x4C, /* 400Mhz HyperTransport 1 only */ - [0x4] = 0xB6, /* 600Mhz HyperTransport 1 only */ - [0x5] = 0x4C, /* 800Mhz HyperTransport 1 only */ - [0x6] = 0x9D, /* 1Ghz HyperTransport 1 only */ - /* HT3 for Family 10 */ - [0x7] = 0xB6, /* 1.2Ghz HyperTransport 3 only */ - [0x8] = 0x2B, /* 1.4Ghz HyperTransport 3 only */ - [0x9] = 0x4C, /* 1.6Ghz HyperTransport 3 only */ - [0xa] = 0x6C, /* 1.8Ghz HyperTransport 3 only */ - [0xb] = 0x9D, /* 2.0Ghz HyperTransport 3 only */ - [0xc] = 0xAD, /* 2.2Ghz HyperTransport 3 only */ - [0xd] = 0xB6, /* 2.4Ghz HyperTransport 3 only */ - [0xe] = 0xC6, /* 2.6Ghz HyperTransport 3 only */ -}; - -static void rs780_htinit(void) -{ - /* - * About HT, it has been done in enumerate_ht_chain(). - */ - device_t cpu_f0, rs780_f0, clk_f1; - u32 reg; - u8 cpu_ht_freq, ibias; - - cpu_f0 = PCI_DEV(0, 0x18, 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. - * The link frequency field (Frq) is cleared by cold reset. SW can write a nonzero - * value to this reg, and that value takes effect on the next warm reset or - * LDTSTOP_L disconnect sequence. - * please see the table rs780_ibias about the value and its corresponding frequency. - ************************/ - reg = pci_read_config32(cpu_f0, 0x88); - cpu_ht_freq = (reg & 0xf00) >> 8; - printk(BIOS_INFO, "rs780_htinit cpu_ht_freq=%x.\n", cpu_ht_freq); - rs780_f0 = PCI_DEV(0, 0, 0); - //set_nbcfg_enable_bits(rs780_f0, 0xC8, 0x7<<24 | 0x7<<28, 1<<24 | 1<<28); - - clk_f1 = PCI_DEV(0, 0, 1); /* We need to make sure the F1 is accessible. */ - - ibias = rs780_ibias[cpu_ht_freq]; - - /* If HT freq>1GHz, we assume the CPU is fam10, else it is K8. - * Is it appropriate? - * Frequency is 1GHz, i.e. cpu_ht_freq is 6, in most cases. - * So we check 6 only, it would be faster. */ - if ((cpu_ht_freq == 0x6) || (cpu_ht_freq == 0x5) || (cpu_ht_freq == 0x4) || - (cpu_ht_freq == 0x2) || (cpu_ht_freq == 0x0)) { - printk(BIOS_INFO, "rs780_htinit: HT1 mode\n"); - - /* HT1 mode, RPR 8.4.2 */ - /* set IBIAS code */ - set_nbcfg_enable_bits(clk_f1, 0xD8, 0x3FF, ibias); - /* Optimizes chipset HT transmitter drive strength */ - set_htiu_enable_bits(rs780_f0, 0x2A, 0x3, 0x1); - } else if ((cpu_ht_freq > 0x6) && (cpu_ht_freq < 0xf)) { - printk(BIOS_INFO, "rs780_htinit: HT3 mode\n"); - - #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 /* save some spaces */ - /* HT3 mode, RPR 8.4.3 */ - set_nbcfg_enable_bits(rs780_f0, 0x9c, 0x3 << 16, 0); - - /* set IBIAS code */ - set_nbcfg_enable_bits(clk_f1, 0xD8, 0x3FF, ibias); - /* Optimizes chipset HT transmitter drive strength */ - set_htiu_enable_bits(rs780_f0, 0x2A, 0x3, 0x1); - /* Enables error-retry mode */ - set_nbcfg_enable_bits(rs780_f0, 0x44, 0x1, 0x1); - /* Enables scrambling and Disalbes command throttling */ - set_nbcfg_enable_bits(rs780_f0, 0xac, (1 << 3) | (1 << 14), (1 << 3) | (1 << 14)); - /* Enables transmitter de-emphasis */ - set_nbcfg_enable_bits(rs780_f0, 0xa4, 1 << 31, 1 << 31); - /* Enabels transmitter de-emphasis level */ - /* Sets training 0 time */ - set_nbcfg_enable_bits(rs780_f0, 0xa0, 0x3F, 0x14); - - /* Enables strict TM4 detection */ - set_htiu_enable_bits(rs780_f0, 0x15, 0x1 << 22, 0x1 << 22); - /* Enables proprer DLL reset sequence */ - set_htiu_enable_bits(rs780_f0, 0x16, 0x1 << 10, 0x1 << 10); - - /* 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); - /* Enables scrambling */ - set_fam10_ext_cfg_enable_bits(cpu_f0, 0x170, 1 << 3, 1 << 3); - /* Enables transmitter de-emphasis - * This depends on the PCB design and the trace */ - /* TODO: */ - /* 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); - /* TODO: */ - #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); - - /* 8.6.6 K8 Buffer Allocation Settings */ - 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, 3 << 26, 3 << 26); - 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); - 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 */ -static void fam10_optimization(void) -{ - device_t cpu_f0, cpu_f2, cpu_f3; - u32 val; - - printk(BIOS_INFO, "fam10_optimization()\n"); - - cpu_f0 = PCI_DEV(0, 0x18, 0); - cpu_f2 = PCI_DEV(0, 0x18, 2); - cpu_f3 = PCI_DEV(0, 0x18, 3); - - /* 8.6.4.1 */ - /* Table 8-13 */ - pci_write_config32(cpu_f0, 0x90, 0x808502D0); - /* Table 8-14 */ - pci_write_config32(cpu_f0, 0x94, 0x00000000); - - /* Table 8-15 */ - val = pci_read_config32(cpu_f0, 0x68); - val |= 1 << 24; - pci_write_config32(cpu_f0, 0x68, val); - - /* Table 8-16 */ - val = pci_read_config32(cpu_f0, 0x84); - val &= ~(1 << 12); - pci_write_config32(cpu_f0, 0x84, val); - - /* Table 8-17 */ - val = pci_read_config32(cpu_f2, 0x90); - val &= ~(1 << 10); - pci_write_config32(cpu_f2, 0x90, val); - - /* Table 8-18 */ - pci_write_config32(cpu_f3, 0x6C, 0x60018051); - /* Table 8-19 */ - pci_write_config32(cpu_f3, 0x70, 0x60321151); - /* Table 8-20 */ - pci_write_config32(cpu_f3, 0x74, 0x00980101); - /* Table 8-21 */ - pci_write_config32(cpu_f3, 0x78, 0x00200C14); - /* Table 8-22 */ - pci_write_config32(cpu_f3, 0x7C, 0x00070811); /* TODO: Check if L3 Cache is enabled. */ - - /* Table 8-23 */ - Set_NB32(cpu_f3, 0x140, 0x00D33656); - /* Table 8-24 */ - Set_NB32(cpu_f3, 0x144, 0x00000036); - /* Table 8-25 */ - Set_NB32(cpu_f3, 0x148, 0x8000832A); - /* Table 8-26 */ - Set_NB32(cpu_f3, 0x158, 0); - /* L3 Disabled: L3 Enabled: */ - /* cores: 2 3 4 2 3 4 */ - /* bit8:4 28 26 24 24 20 16 */ - if (!l3_cache()) { - Set_NB32(cpu_f3, 0x1A0, 4 << 12 | (24 + 2*(4-cpu_core_number())) << 4 | 2); - } else { - Set_NB32(cpu_f3, 0x1A0, 4 << 12 | (16 + 4*(4-cpu_core_number())) << 4 | 4); - } -} -#else -#define fam10_optimization() do{}while(0) -#endif /* #if CONFIG_NORTHBRIDGE_AMD_AMDFAM10 == 1 */ - -/***************************************** -* rs780_por_pcicfg_init() -*****************************************/ -static void rs780_por_pcicfg_init(device_t nb_dev) -{ - /* enable PCI Memory Access */ - set_nbcfg_enable_bits_8(nb_dev, 0x04, (u8)(~0xFD), 0x02); - /* Set RCRB Enable */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x1); - /* allow decode of 640k-1MB */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xEF), 0x10); - /* Enable PM2_CNTL(BAR2) IO mapped cfg write access to be broadcast to both NB and SB */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x4); - /* Power Management Register Enable */ - set_nbcfg_enable_bits_8(nb_dev, 0x84, (u8)(~0xFF), 0x80); - - /* Reg4Ch[1]=1 (APIC_ENABLE) force cpu request with address 0xFECx_xxxx to south-bridge - * Reg4Ch[6]=1 (BMMsgEn) enable BM_Set message generation - * BMMsgEn */ - set_nbcfg_enable_bits_8(nb_dev, 0x4C, (u8)(~0x00), 0x42 | 1); - - /* Reg4Ch[16]=1 (WakeC2En) enable Wake_from_C2 message generation. - * Reg4Ch[18]=1 (P4IntEnable) Enable north-bridge to accept MSI with address 0xFEEx_xxxx from south-bridge */ - set_nbcfg_enable_bits_8(nb_dev, 0x4E, (u8)(~0xFF), 0x05); - /* Reg94h[4:0] = 0x0 P drive strength offset 0 - * Reg94h[6:5] = 0x2 P drive strength additive adjust */ - set_nbcfg_enable_bits_8(nb_dev, 0x94, (u8)(~0x80), 0x40); - - /* Reg94h[20:16] = 0x0 N drive strength offset 0 - * Reg94h[22:21] = 0x2 N drive strength additive adjust */ - set_nbcfg_enable_bits_8(nb_dev, 0x96, (u8)(~0x80), 0x40); - - /* Reg80h[4:0] = 0x0 Termination offset - * Reg80h[6:5] = 0x2 Termination additive adjust */ - set_nbcfg_enable_bits_8(nb_dev, 0x80, (u8)(~0x80), 0x40); - - /* Reg80h[14] = 0x1 Enable receiver termination control */ - set_nbcfg_enable_bits_8(nb_dev, 0x81, (u8)(~0xFF), 0x40); - - /* Reg94h[15] = 0x1 Enables HT transmitter advanced features to be turned on - * Reg94h[14] = 0x1 Enable drive strength control */ - set_nbcfg_enable_bits_8(nb_dev, 0x95, (u8)(~0x3F), 0xC4); - - /* Reg94h[31:29] = 0x7 Enables HT transmitter de-emphasis */ - set_nbcfg_enable_bits_8(nb_dev, 0x97, (u8)(~0x1F), 0xE0); - - /* Reg8Ch[9] enables Gfx Debug BAR programming - * Reg8Ch[10] enables Gfx Debug BAR operation - * Enable programming of the debug bar now, but enable - * operation only after it has been programmed */ - set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x02); -} - -static void rs780_por_mc_index_init(device_t nb_dev) -{ - set_nbmc_enable_bits(nb_dev, 0x7A, ~0xFFFFFF80, 0x0000005F); - set_nbmc_enable_bits(nb_dev, 0xD8, ~0x00000000, 0x00600060); - set_nbmc_enable_bits(nb_dev, 0xD9, ~0x00000000, 0x00600060); - set_nbmc_enable_bits(nb_dev, 0xE0, ~0x00000000, 0x00000000); - set_nbmc_enable_bits(nb_dev, 0xE1, ~0x00000000, 0x00000000); - set_nbmc_enable_bits(nb_dev, 0xE8, ~0x00000000, 0x003E003E); - set_nbmc_enable_bits(nb_dev, 0xE9, ~0x00000000, 0x003E003E); -} - -static void rs780_por_misc_index_init(device_t nb_dev) -{ - /* NB_MISC_IND_WR_EN + IOC_PCIE_CNTL - * Block non-snoop DMA request if PMArbDis is set. - * Set BMSetDis */ - set_nbmisc_enable_bits(nb_dev, 0x0B, ~0xFFFF0000, 0x00000180); - set_nbmisc_enable_bits(nb_dev, 0x01, ~0xFFFFFFFF, 0x00000040); - - /* NBCFG (NBMISCIND 0x0): NB_CNTL - - * HIDE_NB_AGP_CAP ([0], default=1)HIDE - * HIDE_P2P_AGP_CAP ([1], default=1)HIDE - * HIDE_NB_GART_BAR ([2], default=1)HIDE - * AGPMODE30 ([4], default=0)DISABLE - * AGP30ENCHANCED ([5], default=0)DISABLE - * HIDE_AGP_CAP ([8], default=1)ENABLE */ - set_nbmisc_enable_bits(nb_dev, 0x00, ~0xFFFF0000, 0x00000506); /* set bit 10 for MSI */ - - /* NBMISCIND:0x6A[16]= 1 SB link can get a full swing - * set_nbmisc_enable_bits(nb_dev, 0x6A, 0ffffffffh, 000010000); - * NBMISCIND:0x6A[17]=1 Set CMGOOD_OVERRIDE. */ - set_nbmisc_enable_bits(nb_dev, 0x6A, ~0xffffffff, 0x00020000); - - /* NBMISIND:0x40 Bit[8]=1 and Bit[10]=1 following bits are required to set in order to allow LVDS or PWM features to work. */ - set_nbmisc_enable_bits(nb_dev, 0x40, ~0xffffffff, 0x00000500); - - /* NBMISIND:0xC Bit[13]=1 Enable GSM mode for C1e or C3 with pop-up. */ - set_nbmisc_enable_bits(nb_dev, 0x0C, ~0xffffffff, 0x00002000); - - /* Set NBMISIND:0x1F[3] to map NB F2 interrupt pin to INTB# */ - set_nbmisc_enable_bits(nb_dev, 0x1F, ~0xffffffff, 0x00000008); - - /* - * Enable access to DEV8 - * Enable setPower message for all ports - */ - set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 6, 1 << 6); - set_nbmisc_enable_bits(nb_dev, 0x0b, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x51, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x53, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x55, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x57, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x59, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x5B, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x5D, 1 << 20, 1 << 20); - set_nbmisc_enable_bits(nb_dev, 0x5F, 1 << 20, 1 << 20); - - set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 7, 1 << 7); - set_nbmisc_enable_bits(nb_dev, 0x07, 0x000000f0, 0x30); - - set_nbmisc_enable_bits(nb_dev, 0x01, 0xFFFFFFFF, 0x48); - /* Disable bus-master trigger event from SB and Enable set_slot_power message to SB */ - set_nbmisc_enable_bits(nb_dev, 0x0B, 0xffffffff, 0x500180); -} - -/***************************************** -* Some setting is from rpr. Some is from CIMx. -*****************************************/ -static void rs780_por_htiu_index_init(device_t nb_dev) -{ -#if 0 /* get from rpr. */ - set_htiu_enable_bits(nb_dev, 0x1C, 0x1<<17, 0x1<<17); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<0, 0x0<<0); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<1, 0x1<<1); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<9, 0x1<<9); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<13, 0x1<<13); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<17, 0x1<<17); - set_htiu_enable_bits(nb_dev, 0x06, 0x3<<15, 0x3<<15); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<25, 0x1<<25); - set_htiu_enable_bits(nb_dev, 0x06, 0x1<<30, 0x1<<30); - - set_htiu_enable_bits(nb_dev, 0x07, 0x1<<0, 0x1<<0); - set_htiu_enable_bits(nb_dev, 0x07, 0x1<<1, 0x0<<1); - set_htiu_enable_bits(nb_dev, 0x07, 0x1<<2, 0x0<<2); - set_htiu_enable_bits(nb_dev, 0x07, 0x1<<15, 0x1<<15); - - set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<0, 0x1<<0); - set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<2, 0x2<<2); - set_htiu_enable_bits(nb_dev, 0x0C, 0x3<<4, 0x0<<4); - - /* A12 only */ - set_htiu_enable_bits(nb_dev, 0x2D, 0x1<<4, 0x1<<4); - set_htiu_enable_bits(nb_dev, 0x2D, 0x1<<6, 0x1<<6); - set_htiu_enable_bits(nb_dev, 0x05, 0x1<<2, 0x1<<2); - - set_htiu_enable_bits(nb_dev, 0x1E, 0xFFFFFFFF, 0xFFFFFFFF); -#else /* get from CIM. It is more reliable than above. */ - set_htiu_enable_bits(nb_dev, 0x05, (1<<10|1<<9), 1<<10 | 1<<9); - set_htiu_enable_bits(nb_dev, 0x06, ~0xFFFFFFFE, 0x04203A202); - - set_htiu_enable_bits(nb_dev, 0x07, ~0xFFFFFFF9, 0x8001/* | 7 << 8 */); /* fam 10 */ - - set_htiu_enable_bits(nb_dev, 0x15, ~0xFFFFFFFF, 1<<31| 1<<30 | 1<<27); - set_htiu_enable_bits(nb_dev, 0x1C, ~0xFFFFFFFF, 0xFFFE0000); - - set_htiu_enable_bits(nb_dev, 0x4B, (1<<11), 1<<11); - - set_htiu_enable_bits(nb_dev, 0x0C, ~0xFFFFFFC0, 1<<0|1<<3); - - set_htiu_enable_bits(nb_dev, 0x17, (1<<27|1<<1), 0x1<<1); - set_htiu_enable_bits(nb_dev, 0x17, 0x1 << 30, 0x1<<30); - - set_htiu_enable_bits(nb_dev, 0x19, (0xFFFFF+(1<<31)), 0x186A0+(1<<31)); - - set_htiu_enable_bits(nb_dev, 0x16, (0x3F<<10), 0x7<<10); - - set_htiu_enable_bits(nb_dev, 0x23, 0xFFFFFFF, 1<<28); - - set_htiu_enable_bits(nb_dev, 0x1E, 0xFFFFFFFF, 0xFFFFFFFF); -#endif -} - -/***************************************** -* Configure RS780 registers to power-on default RPR. -* POR: Power On Reset -* RPR: Register Programming Requirements -*****************************************/ -static void rs780_por_init(device_t nb_dev) -{ - printk(BIOS_INFO, "rs780_por_init\n"); - /* ATINB_PCICFG_POR_TABLE, initialize the values for rs780 PCI Config registers */ - rs780_por_pcicfg_init(nb_dev); - - /* ATINB_MCIND_POR_TABLE */ - rs780_por_mc_index_init(nb_dev); - - /* ATINB_MISCIND_POR_TABLE */ - rs780_por_misc_index_init(nb_dev); - - /* ATINB_HTIUNBIND_POR_TABLE */ - rs780_por_htiu_index_init(nb_dev); - - /* ATINB_CLKCFG_PORT_TABLE */ - /* rs780 A11 SB Link full swing? */ -} - -/* enable CFG access to Dev8, which is the SB P2P Bridge */ -static void enable_rs780_dev8(void) -{ - set_nbmisc_enable_bits(PCI_DEV(0, 0, 0), 0x00, 1 << 6, 1 << 6); -} - -static void rs780_before_pci_init(void) -{ -} - -static void rs780_early_setup(void) -{ - device_t nb_dev = PCI_DEV(0, 0, 0); - printk(BIOS_INFO, "rs780_early_setup()\n"); - - get_cpu_rev(); - - /* The printk(BIOS_INFO, s) below cause the system unstable. */ - switch (get_nb_rev(nb_dev)) { - case REV_RS780_A11: - /* printk(BIOS_INFO, "NB Revision is A11.\n"); */ - break; - case REV_RS780_A12: - /* printk(BIOS_INFO, "NB Revision is A12.\n"); */ - break; - case REV_RS780_A13: - /* printk(BIOS_INFO, "NB Revision is A13.\n"); */ - break; - } - - if (is_famly10()) - fam10_optimization(); - else - k8_optimization(); - - rs780_por_init(nb_dev); -} diff --git a/src/southbridge/amd/rs780/rs780_gfx.c b/src/southbridge/amd/rs780/rs780_gfx.c deleted file mode 100644 index 1763c36047..0000000000 --- a/src/southbridge/amd/rs780/rs780_gfx.c +++ /dev/null @@ -1,1340 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 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 rs780 internal graphics device - * device id of internal grphics: - * RS780: 0x9610 - * RS780C: 0x9611 - * RS780M: 0x9612 - * RS780MC:0x9613 - * RS780E: 0x9615 - * RS785G: 0x9710 - just works, not much tested - */ -#include -#include -#include -#include -#include -#include -#include -#include "rs780.h" -extern int is_dev3_present(void); -void set_pcie_reset(void); -void set_pcie_dereset(void); - -extern uint64_t uma_memory_base, uma_memory_size; - -/* Trust the original resource allocation. Don't do it again. */ -#undef DONT_TRUST_RESOURCE_ALLOCATION -//#define DONT_TRUST_RESOURCE_ALLOCATION - -#define CLK_CNTL_INDEX 0x8 -#define CLK_CNTL_DATA 0xC - -/* The Integrated Info Table. */ -ATOM_INTEGRATED_SYSTEM_INFO_V2 vgainfo; - -#ifdef UNUSED_CODE -static u32 clkind_read(device_t dev, u32 index) -{ - u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; - - *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index & 0x7F; - return *(u32*)(gfx_bar2+CLK_CNTL_DATA); -} -#endif - -static void clkind_write(device_t dev, u32 index, u32 data) -{ - u32 gfx_bar2 = pci_read_config32(dev, 0x18) & ~0xF; - /* printk(BIOS_DEBUG, "gfx bar 2 %02x\n", gfx_bar2); */ - - *(u32*)(gfx_bar2+CLK_CNTL_INDEX) = index | 1<<7; - *(u32*)(gfx_bar2+CLK_CNTL_DATA) = data; -} - -/* -* pci_dev_read_resources thinks it is a IO type. -* We have to force it to mem type. -*/ -static void rs780_gfx_read_resources(device_t dev) -{ - printk(BIOS_DEBUG, "rs780_gfx_read_resources.\n"); - - /* The initial value of 0x24 is 0xFFFFFFFF, which is confusing. - Even if we write 0xFFFFFFFF into it, it will be 0xFFF00000, - which tells us it is a memory address base. - */ - pci_write_config32(dev, 0x24, 0x00000000); - - /* Get the normal pci resources of this device */ - pci_dev_read_resources(dev); - compact_resources(dev); -} - -typedef struct _MMIORANGE -{ - u32 Base; - u32 Limit; - u8 Attribute; -} MMIORANGE; - -MMIORANGE MMIO[8], CreativeMMIO[8]; - -#define CIM_STATUS u32 -#define CIM_SUCCESS 0x00000000 -#define CIM_ERROR 0x80000000 -#define CIM_UNSUPPORTED 0x80000001 -#define CIM_DISABLEPORT 0x80000002 - -#define MMIO_ATTRIB_NP_ONLY 1 -#define MMIO_ATTRIB_BOTTOM_TO_TOP 1<<1 -#define MMIO_ATTRIB_SKIP_ZERO 1<<2 - -#ifdef DONT_TRUST_RESOURCE_ALLOCATION -static MMIORANGE* AllocMMIO(MMIORANGE* pMMIO) -{ - int i; - for (i=0; i<8; i++) { - if (pMMIO[i].Limit == 0) - return &pMMIO[i]; - } - return 0; -} - -static void FreeMMIO(MMIORANGE* pMMIO) -{ - pMMIO->Base = 0; - pMMIO->Limit = 0; -} - -static u32 SetMMIO(u32 Base, u32 Limit, u8 Attribute, MMIORANGE *pMMIO) -{ - int i; - MMIORANGE * TempRange; - for(i=0; i<8; i++) - { - if(pMMIO[i].Attribute != Attribute && Base >= pMMIO[i].Base && Limit <= pMMIO[i].Limit) - { - TempRange = AllocMMIO(pMMIO); - if(TempRange == 0) return 0x80000000; - TempRange->Base = Limit; - TempRange->Limit = pMMIO[i].Limit; - TempRange->Attribute = pMMIO[i].Attribute; - pMMIO[i].Limit = Base; - } - } - TempRange = AllocMMIO(pMMIO); - if(TempRange == 0) return 0x80000000; - TempRange->Base = Base; - TempRange->Limit = Limit; - TempRange->Attribute = Attribute; - return 0; -} - -static u8 FinalizeMMIO(MMIORANGE *pMMIO) -{ - int i, j, n = 0; - for(i=0; i<8; i++) - { - if (pMMIO[i].Base == pMMIO[i].Limit) - { - FreeMMIO(&pMMIO[i]); - continue; - } - for(j=0; j> 8) & 0xFF; - BusEnd = (Value >> 16) & 0xFF; - for(Bus = BusStart; Bus <= BusEnd; Bus++) - { - for(Dev = 0; Dev <= 0x1f; Dev++) - { - tempdev = dev_find_slot(Bus, Dev << 3); - Value = pci_read_config32(tempdev, 0); - printk(BIOS_DEBUG, "Dev ID %x \n", Value); - if((Value & 0xffff) == 0x1102) - {//Creative - //Found Creative SB - u32 MMIOStart = 0xffffffff; - u32 MMIOLimit = 0; - for(Reg = 0x10; Reg < 0x20; Reg+=4) - { - u32 BaseA, LimitA; - BaseA = pci_read_config32(tempdev, Reg); - Value = BaseA; - if(!(Value & 0x01)) - { - Value = Value & 0xffffff00; - if(Value != 0) - { - if(MMIOStart > Value) - MMIOStart = Value; - LimitA = 0xffffffff; - //WritePCI(PciAddress,AccWidthUint32,&LimitA); - pci_write_config32(tempdev, Reg, LimitA); - //ReadPCI(PciAddress,AccWidthUint32,&LimitA); - LimitA = pci_read_config32(tempdev, Reg); - LimitA = Value + (~LimitA + 1); - //WritePCI(PciAddress,AccWidthUint32,&BaseA); - pci_write_config32(tempdev, Reg, BaseA); - if (LimitA > MMIOLimit) - MMIOLimit = LimitA; - } - } - } - printk(BIOS_DEBUG, " MMIOStart %x MMIOLimit %x \n", MMIOStart, MMIOLimit); - if (MMIOStart < MMIOLimit) - { - Status = SetMMIO(MMIOStart>>8, MMIOLimit>>8, 0x80, pMMIO); - if(Status == CIM_ERROR) return Status; - } - } - } - } - if(Status == CIM_SUCCESS) - { - //Lets optimize MMIO - if(FinalizeMMIO(pMMIO) > 4) - { - Status = CIM_ERROR; - } - } - - return Status; -} - -static void ProgramMMIO(MMIORANGE *pMMIO, u8 LinkID, u8 Attribute) -{ - int i, j, n = 7; - device_t k8_f1; - - k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); - - for(i = 0; i < 8; i++) - { - int k = 0, MmioReg; - u32 Base = 0; - u32 Limit = 0; - for(j = 0; j < 8; j++) - { - if (Base < pMMIO[j].Base) - { - Base = pMMIO[j].Base; - k = j; - } - } - if(pMMIO[k].Limit != 0) - { - if(Attribute & MMIO_ATTRIB_NP_ONLY && pMMIO[k].Attribute == 0 ) - { - Base = 0; - } - else - { - Base = pMMIO[k].Base | 0x3; - Limit= ((pMMIO[k].Limit - 1) & 0xffffff00) | pMMIO[k].Attribute | (LinkID << 4); - } - FreeMMIO(&pMMIO[k]); - } - if (Attribute & MMIO_ATTRIB_SKIP_ZERO && Base == 0 && Limit == 0) continue; - MmioReg = (Attribute & MMIO_ATTRIB_BOTTOM_TO_TOP)?n:(7-n); - n--; - //RWPCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x80+MmioReg*8),AccWidthUint32 |S3_SAVE,0x0,0x0); - pci_write_config32(k8_f1, 0x80+MmioReg*8, 0); - - //WritePCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x84+MmioReg*8),AccWidthUint32 |S3_SAVE,&Limit); - pci_write_config32(k8_f1, 0x84+MmioReg*8, Limit); - - //WritePCI(PCI_ADDRESS(0,CPU_DEV,CPU_F1,0x80+MmioReg*8),AccWidthUint32 |S3_SAVE,&Base); - pci_write_config32(k8_f1, 0x80+MmioReg*8, Base); - } -} -#endif - -static void internal_gfx_pci_dev_init(struct device *dev) -{ - unsigned char * bpointer; - volatile u32 * GpuF0MMReg; - volatile u32 * pointer; - int i; - u16 command; - u32 value; - u16 deviceid, vendorid; - device_t nb_dev = dev_find_slot(0, 0); - device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); - device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - static const u8 ht_freq_lookup [] = {2, 0, 4, 0, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 0, 0, 28, 30, 32}; - static const u8 ht_width_lookup [] = {8, 16, 0, 0, 2, 4, 0, 0}; - static const u16 memclk_lookup_fam0F [] = {100, 0, 133, 0, 0, 166, 0, 200}; - static const u16 memclk_lookup_fam10 [] = {200, 266, 333, 400, 533, 667, 800, 800}; - - /* We definetely will use this in future. Just leave it here. */ - /*struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)dev->chip_info;*/ - - deviceid = pci_read_config16(dev, PCI_DEVICE_ID); - vendorid = pci_read_config16(dev, PCI_VENDOR_ID); - printk(BIOS_DEBUG, "internal_gfx_pci_dev_init device=%x, vendor=%x.\n", - deviceid, vendorid); - - command = pci_read_config16(dev, 0x04); - command |= 0x7; - pci_write_config16(dev, 0x04, command); - - /* Clear vgainfo. */ - bpointer = (unsigned char *) &vgainfo; - for(i=0; i>8)|((value&0xff000000)>>8); - *(GpuF0MMReg + 0x2c04/4) = ((value&0xff00)<<8); - *(GpuF0MMReg + 0x5428/4) = ((value&0xffff0000)+0x10000)-((value&0xffff)<<16); - *(GpuF0MMReg + 0xF774/4) = 0xffffffff; - *(GpuF0MMReg + 0xF770/4) = 0x00000001; - *(GpuF0MMReg + 0x2000/4) = 0x00000011; - *(GpuF0MMReg + 0x200c/4) = 0x00000020; - *(GpuF0MMReg + 0x2010/4) = 0x10204810; - *(GpuF0MMReg + 0x2010/4) = 0x00204810; - *(GpuF0MMReg + 0x2014/4) = 0x10408810; - *(GpuF0MMReg + 0x2014/4) = 0x00408810; - *(GpuF0MMReg + 0x2414/4) = 0x00000080; - *(GpuF0MMReg + 0x2418/4) = 0x84422415; - *(GpuF0MMReg + 0x2418/4) = 0x04422415; - *(GpuF0MMReg + 0x5490/4) = 0x00000001; - *(GpuF0MMReg + 0x7de4/4) |= (1<<3) | (1<<4); - /* Force allow LDT_STOP Cool'n'Quiet workaround. */ - *(GpuF0MMReg + 0x655c/4) |= 1<<4; - - // disable write combining, needed for stability - // reference bios does this only for RS780 rev A11 - // need to figure out why we need it for all revs - *(GpuF0MMReg + 0x2000/4) = 0x00000010; - *(GpuF0MMReg + 0x2408/4) = 1 << 9; - *(GpuF0MMReg + 0x2000/4) = 0x00000011; - - /* GFX_InitFBAccess finished. */ - -#if (CONFIG_GFXUMA == 1) /* for UMA mode. */ - /* GFX_StartMC. */ - set_nbmc_enable_bits(nb_dev, 0x02, 0x00000000, 0x80000000); - set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000001); - set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000004); - set_nbmc_enable_bits(nb_dev, 0x01, 0x00040000, 0x00000000); - set_nbmc_enable_bits(nb_dev, 0xB1, 0xFFFF0000, 0x00000040); - set_nbmc_enable_bits(nb_dev, 0xC3, 0x00000000, 0x00000001); - set_nbmc_enable_bits(nb_dev, 0x07, 0xFFFFFFFF, 0x00000018); - set_nbmc_enable_bits(nb_dev, 0x06, 0xFFFFFFFF, 0x00000102); - set_nbmc_enable_bits(nb_dev, 0x09, 0xFFFFFFFF, 0x40000008); - set_nbmc_enable_bits(nb_dev, 0x06, 0x00000000, 0x80000000); - /* GFX_StartMC finished. */ -#else - /* for SP mode. */ - set_nbmc_enable_bits(nb_dev, 0xaa, 0xf0, 0x30); - set_nbmc_enable_bits(nb_dev, 0xce, 0xf0, 0x30); - set_nbmc_enable_bits(nb_dev, 0xca, 0xff000000, 0x47000000); - set_nbmc_enable_bits(nb_dev, 0xcb, 0x3f000000, 0x01000000); - set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<0); - set_nbmc_enable_bits(nb_dev, 0x04, 0, 1<<31); - set_nbmc_enable_bits(nb_dev, 0xb4, 0x3f, 0x3f); - set_nbmc_enable_bits(nb_dev, 0xb4, 0, 1<<6); - set_nbmc_enable_bits(nb_dev, 0xc3, 1<<11, 0); - set_nbmc_enable_bits(nb_dev, 0xa0, 1<<29, 0); - nbmc_write_index(nb_dev, 0xa4, 0x3484576f); - nbmc_write_index(nb_dev, 0xa5, 0x222222df); - nbmc_write_index(nb_dev, 0xa6, 0x00000000); - nbmc_write_index(nb_dev, 0xa7, 0x00000000); - set_nbmc_enable_bits(nb_dev, 0xc3, 1<<8, 0); - udelay(10); - set_nbmc_enable_bits(nb_dev, 0xc3, 1<<9, 0); - udelay(10); - set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<2); - udelay(200); - set_nbmc_enable_bits(nb_dev, 0x01, 0, 1<<3); - set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<31); - udelay(500); - set_nbmc_enable_bits(nb_dev, 0x02, 0, 1<<31); - set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<30); - set_nbmc_enable_bits(nb_dev, 0xa0, 1<<31, 0); - set_nbmc_enable_bits(nb_dev, 0xa0, 0, 1<<29); - nbmc_write_index(nb_dev, 0xa4, 0x23484576); - nbmc_write_index(nb_dev, 0xa5, 0x00000000); - nbmc_write_index(nb_dev, 0xa6, 0x00000000); - nbmc_write_index(nb_dev, 0xa7, 0x00000000); - /* GFX_StartMC finished. */ - - /* GFX_SPPowerManagment, don't care for new. */ - /* Post MC Init table programming. */ - set_nbmc_enable_bits(nb_dev, 0xac, ~(0xfffffff0), 0x0b); - - /* Do we need Write and Read Calibration? */ - /* GFX_Init finished. */ -#endif - - /* GFX_InitIntegratedInfo. */ - /* fill the Integrated Info Table. */ - vgainfo.sHeader.usStructureSize = sizeof(ATOM_INTEGRATED_SYSTEM_INFO_V2); - vgainfo.sHeader.ucTableFormatRevision = 1; - vgainfo.sHeader.ucTableContentRevision = 2; - -#if (CONFIG_GFXUMA == 0) /* SP mode. */ - // Side port support is incomplete, do not use it - // These parameters must match the motherboard - vgainfo.ulBootUpSidePortClock = 667*100; - vgainfo.ucMemoryType = 3; // 3=ddr3 sp mem, 2=ddr2 sp mem - vgainfo.ulMinSidePortClock = 333*100; -#endif - - vgainfo.ulBootUpEngineClock = 500 * 100; // setup option on reference BIOS, 500 is default - - // find the DDR memory frequency - if (is_family10h()) { - value = pci_read_config32(k8_f2, 0x94); // read channel 0 DRAM Configuration High Register - if (extractbit(value, 14)) // if channel 0 disabled, channel 1 must have memory - value = pci_read_config32(k8_f2, 0x194);// read channel 1 DRAM Configuration High Register - vgainfo.ulBootUpUMAClock = memclk_lookup_fam10 [extractbits (value, 0, 2)] * 100; - } - if (is_family0Fh()) { - value = pci_read_config32(k8_f2, 0x94); - vgainfo.ulBootUpUMAClock = memclk_lookup_fam0F [extractbits (value, 20, 22)] * 100; - } - - /* UMA Channel Number: 1 or 2. */ - vgainfo.ucUMAChannelNumber = 1; - if (is_family0Fh()) { - value = pci_read_config32(k8_f2, 0x90); - if (extractbit(value, 11)) // 128-bit mode - vgainfo.ucUMAChannelNumber = 2; - } - if (is_family10h()) { - u32 dch0 = pci_read_config32(k8_f2, 0x94); - u32 dch1 = pci_read_config32(k8_f2, 0x194); - if (extractbit(dch0, 14) == 0 && extractbit(dch1, 14) == 0) { // both channels enabled - value = pci_read_config32(k8_f2, 0x110); - if (extractbit(value, 4)) // ganged mode - vgainfo.ucUMAChannelNumber = 2; - } - } - - // processor type - if (is_family0Fh()) - vgainfo.ulCPUCapInfo = 3; - if (is_family10h()) - vgainfo.ulCPUCapInfo = 2; - - /* HT speed */ - value = pci_read_config8(nb_dev, 0xd1); - value = ht_freq_lookup [value] * 100; // HT link frequency in MHz - vgainfo.ulHTLinkFreq = value * 100; // HT frequency in units of 100 MHz - vgainfo.ulHighVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; - vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; - - if (value <= 1800) - vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq; - else { - int sblink, cpuLnkFreqCap, nbLnkFreqCap; - value = pci_read_config32(k8_f0, 0x64); - sblink = extractbits(value, 8, 10); - cpuLnkFreqCap = pci_read_config16(k8_f0, 0x8a + sblink * 0x20); - nbLnkFreqCap = pci_read_config16(nb_dev, 0xd2); - if (cpuLnkFreqCap & nbLnkFreqCap & (1 << 10)) // if both 1800 MHz capable - vgainfo.ulLowVoltageHTLinkFreq = 1800*100; - } - - /* HT width. */ - value = pci_read_config8(nb_dev, 0xcb); - vgainfo.usMinDownStreamHTLinkWidth = - vgainfo.usMaxDownStreamHTLinkWidth = - vgainfo.usMinUpStreamHTLinkWidth = - vgainfo.usMaxUpStreamHTLinkWidth = - vgainfo.usMinHTLinkWidth = - vgainfo.usMaxHTLinkWidth = ht_width_lookup [extractbits(value, 0, 2)]; - - if (is_family0Fh()) { - vgainfo.usUMASyncStartDelay = 322; - vgainfo.usUMADataReturnTime = 286; - } - - if (is_family10h()) { - static u16 t0mult_lookup [] = {10, 50, 200, 2000}; - int t0time, t0scale; - value = pci_read_config32(k8_f0, 0x16c); - t0time = extractbits(value, 0, 3); - t0scale = extractbits(value, 4, 5); - vgainfo.usLinkStatusZeroTime = t0mult_lookup [t0scale] * t0time; - vgainfo.usUMASyncStartDelay = 100; - if (vgainfo.ulHTLinkFreq < 1000 * 100) { // less than 1000 MHz - vgainfo.usUMADataReturnTime = 300; - vgainfo.usLinkStatusZeroTime = 6 * 100; // 6us for GH in HT1 mode - } - else { - int lssel; - value = pci_read_config32(nb_dev, 0xac); - lssel = extractbits (value, 7, 8); - vgainfo.usUMADataReturnTime = 1300; - if (lssel == 0) vgainfo.usUMADataReturnTime = 150; - } - } - - /* Transfer the Table to VBIOS. */ - pointer = (u32 *)&vgainfo; - for(i=0; i> 8; - if(Base32 < Limit32) - { - Status = GetCreativeMMIO(&CreativeMMIO[0]); - if(Status != CIM_ERROR) - SetMMIO(Base32, Limit32, 0x0, &MMIO[0]); - } - /* Set MMIO for prefetchable P2P. */ - if(Status != CIM_ERROR) - { - temp = pci_read_config32(dev0x14, 0x24); - - Base32 = (temp & 0x0fff0) <<8; - Limit32 = ((temp & 0x0fff00000) + 0x100000) >> 8; - if(Base32 < Limit32) - SetMMIO(Base32, Limit32, 0x0, &MMIO[0]); - } - - FinalizeMMIO(&MMIO[0]); - - ProgramMMIO(&CreativeMMIO[0], 0, MMIO_ATTRIB_NP_ONLY); - ProgramMMIO(&MMIO[0], 0, MMIO_ATTRIB_NP_ONLY | MMIO_ATTRIB_BOTTOM_TO_TOP | MMIO_ATTRIB_SKIP_ZERO); -#endif - - pci_dev_init(dev); - - /* clk ind */ - clkind_write(dev, 0x08, 0x01); - clkind_write(dev, 0x0C, 0x22); - clkind_write(dev, 0x0F, 0x0); - clkind_write(dev, 0x11, 0x0); - clkind_write(dev, 0x12, 0x0); - clkind_write(dev, 0x14, 0x0); - clkind_write(dev, 0x15, 0x0); - clkind_write(dev, 0x16, 0x0); - clkind_write(dev, 0x17, 0x0); - clkind_write(dev, 0x18, 0x0); - clkind_write(dev, 0x19, 0x0); - clkind_write(dev, 0x1A, 0x0); - clkind_write(dev, 0x1B, 0x0); - clkind_write(dev, 0x1C, 0x0); - clkind_write(dev, 0x1D, 0x0); - clkind_write(dev, 0x1E, 0x0); - clkind_write(dev, 0x26, 0x0); - clkind_write(dev, 0x27, 0x0); - clkind_write(dev, 0x28, 0x0); - clkind_write(dev, 0x5C, 0x0); -} - - -/* -* Set registers in RS780 and CPU to enable the internal GFX. -* Please refer to CIM source code and BKDG. -*/ - -static void rs780_internal_gfx_enable(device_t dev) -{ - u32 l_dword; - int i; - device_t nb_dev = dev_find_slot(0, 0); - msr_t sysmem; - -#if (CONFIG_GFXUMA == 0) - u32 FB_Start, FB_End; -#endif - - printk(BIOS_DEBUG, "rs780_internal_gfx_enable dev = 0x%p, nb_dev = 0x%p.\n", dev, nb_dev); - - sysmem = rdmsr(0xc001001a); - printk(BIOS_DEBUG, "sysmem = %x_%x\n", sysmem.hi, sysmem.lo); - - /* The system top memory in 780. */ - pci_write_config32(nb_dev, 0x90, sysmem.lo); - htiu_write_index(nb_dev, 0x30, 0); - htiu_write_index(nb_dev, 0x31, 0); - - /* Disable external GFX and enable internal GFX. */ - l_dword = pci_read_config32(nb_dev, 0x8c); - l_dword &= ~(1<<0); - l_dword |= 1<<1; - pci_write_config32(nb_dev, 0x8c, l_dword); - - /* NB_SetDefaultIndexes */ - pci_write_config32(nb_dev, 0x94, 0x7f); - pci_write_config32(nb_dev, 0x60, 0x7f); - pci_write_config32(nb_dev, 0xe0, 0); - - /* NB_InitEarlyNB finished. */ - - /* LPC DMA Deadlock workaround? */ - /* GFX_InitCommon*/ - device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - l_dword = pci_read_config32(k8_f0, 0x68); - l_dword &= ~(3 << 21); - l_dword |= (1 << 21); - pci_write_config32(k8_f0, 0x68, l_dword); - - /* GFX_InitCommon. */ - nbmc_write_index(nb_dev, 0x23, 0x00c00010); - set_nbmc_enable_bits(nb_dev, 0x16, 1<<15, 1<<15); - set_nbmc_enable_bits(nb_dev, 0x25, 0xffffffff, 0x111f111f); - set_htiu_enable_bits(nb_dev, 0x37, 1<<24, 1<<24); - -#if (CONFIG_GFXUMA == 1) - /* GFX_InitUMA. */ - /* Copy CPU DDR Controller to NB MC. */ - device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1)); - device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); - device_t k8_f4 = dev_find_slot(0, PCI_DEVFN(0x18, 4)); - for (i = 0; i < 12; i++) - { - l_dword = pci_read_config32(k8_f2, 0x40 + i * 4); - nbmc_write_index(nb_dev, 0x30 + i, l_dword); - } - - l_dword = pci_read_config32(k8_f2, 0x80); - nbmc_write_index(nb_dev, 0x3c, l_dword); - l_dword = pci_read_config32(k8_f2, 0x94); - set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<22))<<16); - set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<< 8))<<17); - l_dword = pci_read_config32(k8_f2, 0x90); - set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<10))<<18); - if (is_family10h()) - { - for (i = 0; i < 12; i++) - { - l_dword = pci_read_config32(k8_f2, 0x140 + i * 4); - nbmc_write_index(nb_dev, 0x3d + i, l_dword); - } - - l_dword = pci_read_config32(k8_f2, 0x180); - nbmc_write_index(nb_dev, 0x49, l_dword); - l_dword = pci_read_config32(k8_f2, 0x194); - set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<22))<<16); - set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<< 8))<<17); - l_dword = pci_read_config32(k8_f2, 0x190); - set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<10))<<18); - - l_dword = pci_read_config32(k8_f2, 0x110); - nbmc_write_index(nb_dev, 0x4a, l_dword); - l_dword = pci_read_config32(k8_f2, 0x114); - nbmc_write_index(nb_dev, 0x4b, l_dword); - l_dword = pci_read_config32(k8_f4, 0x44); - set_nbmc_enable_bits(nb_dev, 0x4a, 0, !!(l_dword & (1<<22))<<24); - l_dword = pci_read_config32(k8_f1, 0x40); - nbmc_write_index(nb_dev, 0x4c, l_dword); - l_dword = pci_read_config32(k8_f1, 0xf0); - nbmc_write_index(nb_dev, 0x4d, l_dword); - } - - - /* Set UMA in the 780 side. */ - /* UMA start address, size. */ - /* The UMA starts at 0xC0000000 of internal RS780 address space - [31:16] addr of last byte | [31:16] addr of first byte - */ - nbmc_write_index(nb_dev, 0x10, ((uma_memory_size - 1 + 0xC0000000) & (~0xffff)) | 0xc000); - nbmc_write_index(nb_dev, 0x11, uma_memory_base); - nbmc_write_index(nb_dev, 0x12, 0); - nbmc_write_index(nb_dev, 0xf0, uma_memory_size >> 20); - /* GFX_InitUMA finished. */ -#else - /* GFX_InitSP. */ - /* SP memory:Hynix HY5TQ1G631ZNFP. 128MB = 64M * 16. 667MHz. DDR3. */ - - /* Enable Async mode. */ - set_nbmc_enable_bits(nb_dev, 0x06, 7<<8, 1<<8); - set_nbmc_enable_bits(nb_dev, 0x08, 1<<10, 0); - /* The last item in AsynchMclkTaskFileIndex. Why? */ - /* MC_MPLL_CONTROL2. */ - nbmc_write_index(nb_dev, 0x07, 0x40100028); - /* MC_MPLL_DIV_CONTROL. */ - nbmc_write_index(nb_dev, 0x0b, 0x00000028); - /* MC_MPLL_FREQ_CONTROL. */ - set_nbmc_enable_bits(nb_dev, 0x09, 3<<12|15<<16|15<<8, 1<<12|4<<16|0<<8); - /* MC_MPLL_CONTROL3. For PM. */ - set_nbmc_enable_bits(nb_dev, 0x08, 0xff<<13, 1<<13|1<<18); - /* MPLL_CAL_TRIGGER. */ - set_nbmc_enable_bits(nb_dev, 0x06, 0, 1<<0); - udelay(200); /* time is long enough? */ - set_nbmc_enable_bits(nb_dev, 0x06, 0, 1<<1); - set_nbmc_enable_bits(nb_dev, 0x06, 1<<0, 0); - /* MCLK_SRC_USE_MPLL. */ - set_nbmc_enable_bits(nb_dev, 0x02, 0, 1<<20); - - /* Pre Init MC. */ - nbmc_write_index(nb_dev, 0x01, 0x88108280); - set_nbmc_enable_bits(nb_dev, 0x02, ~(1<<20), 0x00030200); - nbmc_write_index(nb_dev, 0x04, 0x08881018); - nbmc_write_index(nb_dev, 0x05, 0x000000bb); - nbmc_write_index(nb_dev, 0x0c, 0x0f00001f); - nbmc_write_index(nb_dev, 0xa1, 0x01f10000); - /* MCA_INIT_DLL_PM. */ - set_nbmc_enable_bits(nb_dev, 0xc9, 1<<24, 1<<24); - nbmc_write_index(nb_dev, 0xa2, 0x74f20000); - nbmc_write_index(nb_dev, 0xa3, 0x8af30000); - nbmc_write_index(nb_dev, 0xaf, 0x47d0a41c); - nbmc_write_index(nb_dev, 0xb0, 0x88800130); - nbmc_write_index(nb_dev, 0xb1, 0x00000040); - nbmc_write_index(nb_dev, 0xb4, 0x41247000); - nbmc_write_index(nb_dev, 0xb5, 0x00066664); - nbmc_write_index(nb_dev, 0xb6, 0x00000022); - nbmc_write_index(nb_dev, 0xb7, 0x00000044); - nbmc_write_index(nb_dev, 0xb8, 0xbbbbbbbb); - nbmc_write_index(nb_dev, 0xb9, 0xbbbbbbbb); - nbmc_write_index(nb_dev, 0xba, 0x55555555); - nbmc_write_index(nb_dev, 0xc1, 0x00000000); - nbmc_write_index(nb_dev, 0xc2, 0x00000000); - nbmc_write_index(nb_dev, 0xc3, 0x80006b00); - nbmc_write_index(nb_dev, 0xc4, 0x00066664); - nbmc_write_index(nb_dev, 0xc5, 0x00000000); - nbmc_write_index(nb_dev, 0xd2, 0x00000022); - nbmc_write_index(nb_dev, 0xd3, 0x00000044); - nbmc_write_index(nb_dev, 0xd6, 0x00050005); - nbmc_write_index(nb_dev, 0xd7, 0x00000000); - nbmc_write_index(nb_dev, 0xd8, 0x00700070); - nbmc_write_index(nb_dev, 0xd9, 0x00700070); - nbmc_write_index(nb_dev, 0xe0, 0x00200020); - nbmc_write_index(nb_dev, 0xe1, 0x00200020); - nbmc_write_index(nb_dev, 0xe8, 0x00200020); - nbmc_write_index(nb_dev, 0xe9, 0x00200020); - nbmc_write_index(nb_dev, 0xe0, 0x00180018); - nbmc_write_index(nb_dev, 0xe1, 0x00180018); - nbmc_write_index(nb_dev, 0xe8, 0x00180018); - nbmc_write_index(nb_dev, 0xe9, 0x00180018); - - /* Misc options. */ - /* Memory Termination. */ - set_nbmc_enable_bits(nb_dev, 0xa1, 0x0ff, 0x044); - set_nbmc_enable_bits(nb_dev, 0xb4, 0xf00, 0xb00); -#if 0 - /* Controller Termation. */ - set_nbmc_enable_bits(nb_dev, 0xb1, 0x77770000, 0x77770000); -#endif - - /* OEM Init MC. 667MHz. */ - nbmc_write_index(nb_dev, 0xa8, 0x7a5aaa78); - nbmc_write_index(nb_dev, 0xa9, 0x514a2319); - nbmc_write_index(nb_dev, 0xaa, 0x54400520); - nbmc_write_index(nb_dev, 0xab, 0x441460ff); - nbmc_write_index(nb_dev, 0xa0, 0x20f00a48); - set_nbmc_enable_bits(nb_dev, 0xa2, ~(0xffffffc7), 0x10); - nbmc_write_index(nb_dev, 0xb2, 0x00000303); - set_nbmc_enable_bits(nb_dev, 0xb1, ~(0xffffff70), 0x45); - /* Do it later. */ - /* set_nbmc_enable_bits(nb_dev, 0xac, ~(0xfffffff0), 0x0b); */ - - /* Init PM timing. */ - for(i=0; i<4; i++) - { - l_dword = nbmc_read_index(nb_dev, 0xa0+i); - nbmc_write_index(nb_dev, 0xc8+i, l_dword); - } - for(i=0; i<4; i++) - { - l_dword = nbmc_read_index(nb_dev, 0xa8+i); - nbmc_write_index(nb_dev, 0xcc+i, l_dword); - } - l_dword = nbmc_read_index(nb_dev, 0xb1); - set_nbmc_enable_bits(nb_dev, 0xc8, 0xff<<24, ((l_dword&0x0f)<<24)|((l_dword&0xf00)<<20)); - - /* Init MC FB. */ - /* FB_Start = ; FB_End = ; iSpSize = 0x0080, 128MB. */ - nbmc_write_index(nb_dev, 0x11, 0x40000000); - FB_Start = 0xc00 + 0x080; - FB_End = 0xc00 + 0x080; - nbmc_write_index(nb_dev, 0x10, (((FB_End&0xfff)<<20)-0x10000)|(((FB_Start&0xfff)-0x080)<<4)); - set_nbmc_enable_bits(nb_dev, 0x0d, ~0x000ffff0, (FB_Start&0xfff)<<20); - nbmc_write_index(nb_dev, 0x0f, 0); - nbmc_write_index(nb_dev, 0x0e, (FB_Start&0xfff)|(0xaaaa<<12)); -#endif - - /* GFX_InitSP finished. */ -} - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations pcie_ops = { - .read_resources = rs780_gfx_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = internal_gfx_pci_dev_init, /* The option ROM initializes the device. rs780_gfx_init, */ - .scan_bus = 0, - .enable = rs780_internal_gfx_enable, - .ops_pci = &lops_pci, -}; - -/* - * We should list all of them here. - * */ -static const struct pci_driver pcie_driver_780 __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS780_INT_GFX, -}; - -static const struct pci_driver pcie_driver_780c __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS780C_INT_GFX, -}; -static const struct pci_driver pcie_driver_780m __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS780M_INT_GFX, -}; -static const struct pci_driver pcie_driver_780mc __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS780MC_INT_GFX, -}; -static const struct pci_driver pcie_driver_780e __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS780E_INT_GFX, -}; -static const struct pci_driver pcie_driver_785g __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS785G_INT_GFX, -}; - -/* step 12 ~ step 14 from rpr */ -static void single_port_configuration(device_t nb_dev, device_t dev) -{ - u8 result, width; - u32 reg32; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration.\n"); - - /* step 12 training, releases hold training for GFX port 0 (device 2) */ - PcieReleasePortTraining(nb_dev, dev, 2); - result = PcieTrainPort(nb_dev, dev, 2); - printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step12.\n"); - - /* step 13 Power Down Control */ - /* step 13.1 Enables powering down transmitter and receiver pads along with PLL macros. */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); - - /* step 13.a Link Training was NOT successful */ - if (!result) { - set_nbmisc_enable_bits(nb_dev, 0x8, 0, 0x3 << 4); /* prevent from training. */ - set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x3 << 2); /* hide the GFX bridge. */ - if (cfg->gfx_tmds) - nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0); - else { - nbpcie_ind_write_index(nb_dev, 0x65, 0xffffffff); - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 3, 1 << 3); - } - } else { /* step 13.b Link Training was successful */ - set_pcie_enable_bits(dev, 0xA2, 0xFF, 0x1); - reg32 = nbpcie_p_read_index(dev, 0x29); - width = reg32 & 0xFF; - printk(BIOS_DEBUG, "GFX Inactive Lanes = 0x%x.\n", width); - switch (width) { - case 1: - case 2: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x7f7f : 0xccfefe); - break; - case 4: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x3f3f : 0xccfcfc); - break; - case 8: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x0f0f : 0xccf0f0); - break; - } - } - printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step13.\n"); - - /* step 14 Reset Enumeration Timer, disables the shortening of the enumeration timer */ - set_pcie_enable_bits(dev, 0x70, 1 << 19, 1 << 19); - printk(BIOS_DEBUG, "rs780_gfx_init single_port_configuration step14.\n"); -} - -static void dual_port_configuration(device_t nb_dev, device_t dev) -{ - u8 result, width; - u32 reg32, dev_ind = dev->path.pci.devfn >> 3; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - /* 5.4.1.2 Dual Port Configuration */ - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); - set_nbmisc_enable_bits(nb_dev, 0x08, 0xF << 8, 0x5 << 8); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); - - /* 5.7. Training for Device 2 */ - /* 5.7.1. Releases hold training for GFX port 0 (device 2) */ - PcieReleasePortTraining(nb_dev, dev, dev_ind); - /* 5.7.2- 5.7.9. PCIE Link Training Sequence */ - result = PcieTrainPort(nb_dev, dev, dev_ind); - - /* Power Down Control for Device 2 */ - /* Link Training was NOT successful */ - if (!result) { - /* Powers down all lanes for port A */ - /* nbpcie_ind_write_index(nb_dev, 0x65, 0x0f0f); */ - /* Note: I have to disable the slot where there isnt a device, - * otherwise the system will hang. I dont know why. */ - set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << dev_ind, 1 << dev_ind); - - } else { /* step 16.b Link Training was successful */ - reg32 = nbpcie_p_read_index(dev, 0xa2); - width = (reg32 >> 4) & 0x7; - printk(BIOS_DEBUG, "GFX LC_LINK_WIDTH = 0x%x.\n", width); - switch (width) { - case 1: - case 2: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x0707 : 0x0e0e); - break; - case 4: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x0303 : 0x0c0c); - break; - } - } -} - -/* For single port GFX configuration Only -* width: -* 000 = x16 -* 001 = x1 -* 010 = x2 -* 011 = x4 -* 100 = x8 -* 101 = x12 (not supported) -* 110 = x16 -*/ -static void dynamic_link_width_control(device_t nb_dev, device_t dev, u8 width) -{ - u32 reg32; - device_t sb_dev; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - /* step 5.9.1.1 */ - reg32 = nbpcie_p_read_index(dev, 0xa2); - - /* step 5.9.1.2 */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 1 << 0); - /* step 5.9.1.3 */ - set_pcie_enable_bits(dev, 0xa2, 3 << 0, width << 0); - /* step 5.9.1.4 */ - set_pcie_enable_bits(dev, 0xa2, 1 << 8, 1 << 8); - /* step 5.9.2.4 */ - if (0 == cfg->gfx_reconfiguration) - set_pcie_enable_bits(dev, 0xa2, 1 << 11, 1 << 11); - - /* step 5.9.1.5 */ - do { - reg32 = nbpcie_p_read_index(dev, 0xa2); - } - while (reg32 & 0x100); - - /* step 5.9.1.6 */ - sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0)); - do { - reg32 = pci_ext_read_config32(nb_dev, sb_dev, - PCIE_VC0_RESOURCE_STATUS); - } while (reg32 & VC_NEGOTIATION_PENDING); - - /* step 5.9.1.7 */ - reg32 = nbpcie_p_read_index(dev, 0xa2); - if (((reg32 & 0x70) >> 4) != 0x6) { - /* the unused lanes should be powered off. */ - } - - /* step 5.9.1.8 */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 0, 0 << 0); -} - -/* -* GFX Core initialization, dev2, dev3 -*/ -void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port) -{ - u32 reg32; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - printk(BIOS_DEBUG, "rs780_gfx_init, nb_dev=0x%p, dev=0x%p, port=0x%x.\n", - nb_dev, dev, port); - - /* GFX Core Initialization */ - //if (port == 2) return; - - /* step 2, TMDS, (only need if CMOS option is enabled) */ - if (cfg->gfx_tmds) { - } - -#if 1 /* external clock mode */ - /* table 5-22, 5.9.1. REFCLK */ - /* 5.9.1.1. Disables the GFX REFCLK transmitter so that the GFX - * REFCLK PAD can be driven by an external source. */ - /* 5.9.1.2. Enables GFX REFCLK receiver to receive the REFCLK from an external source. */ - set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28 | 1 << 26, 1 << 28); - - /* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */ - /* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */ - /* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */ - set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10, - 1 << 6 | 1 << 8 | 1 << 10); - reg32 = nbmisc_read_index(nb_dev, 0x28); - printk(BIOS_DEBUG, "misc 28 = %x\n", reg32); - - /* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */ - set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 1 << 31); -#else /* internal clock mode */ - /* table 5-23, 5.9.1. REFCLK */ - /* 5.9.1.1. Enables the GFX REFCLK transmitter so that the GFX - * REFCLK PAD can be driven by the SB REFCLK. */ - /* 5.9.1.2. Disables GFX REFCLK receiver from receiving the - * REFCLK from an external source.*/ - set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28, 1 << 29 | 0 << 28); - - /* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */ - /* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */ - /* 5.9.1.5 Selects the GFX REFCLK to be the source for PLL C. */ - set_nbmisc_enable_bits(nb_dev, 0x28, 3 << 6 | 3 << 8 | 3 << 10, - 0); - reg32 = nbmisc_read_index(nb_dev, 0x28); - printk(BIOS_DEBUG, "misc 28 = %x\n", reg32); - - /* 5.9.1.6.Selects the single ended GFX REFCLK to be the source for core logic. */ - set_nbmisc_enable_bits(nb_dev, 0x6C, 1 << 31, 0 << 31); -#endif - - /* step 5.9.3, GFX overclocking, (only need if CMOS option is enabled) */ - /* 5.9.3.1. Increases PLL BW for 6G operation.*/ - /* set_nbmisc_enable_bits(nb_dev, 0x36, 0x3FF << 4, 0xB5 << 4); */ - /* skip */ - - /* step 5.9.4, reset the GFX link */ - /* step 5.9.4.1 asserts both calibration reset and global reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); - - /* step 5.9.4.2 de-asserts calibration reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 14, 0 << 14); - - /* step 5.9.4.3 wait for at least 200us */ - udelay(300); - - /* step 5.9.4.4 de-asserts global reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 15, 0 << 15); - - /* 5.9.5 Reset PCIE_GFX Slot */ - /* It is done in mainboard.c */ - set_pcie_reset(); - mdelay(1); - set_pcie_dereset(); - - /* step 5.9.8 program PCIE memory mapped configuration space */ - /* done by enable_pci_bar3() before */ - - /* step 7 compliance state, (only need if CMOS option is enabled) */ - /* the compliance stete is just for test. refer to 4.2.5.2 of PCIe specification */ - if (cfg->gfx_compliance) { - /* force compliance */ - set_nbmisc_enable_bits(nb_dev, 0x32, 1 << 6, 1 << 6); - /* release hold training for device 2. GFX initialization is done. */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4); - dynamic_link_width_control(nb_dev, dev, cfg->gfx_link_width); - printk(BIOS_DEBUG, "rs780_gfx_init step7.\n"); - return; - } - - /* 5.9.12 Core Initialization. */ - /* 5.9.12.1 sets RCB timeout to be 25ms */ - /* 5.9.12.2. RCB Cpl timeout on link down. */ - set_pcie_enable_bits(dev, 0x70, 7 << 16 | 1 << 19, 4 << 16 | 1 << 19); - printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.1.\n"); - - /* step 5.9.12.3 disables slave ordering logic */ - set_pcie_enable_bits(nb_dev, 0x20, 1 << 8, 1 << 8); - printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.3.\n"); - - /* step 5.9.12.4 sets DMA payload size to 64 bytes */ - set_pcie_enable_bits(nb_dev, 0x10, 7 << 10, 4 << 10); - /* 5.9.12.5. Blocks DMA traffic during C3 state. */ - set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); - - /* 5.9.12.6. Disables RC ordering logic */ - set_pcie_enable_bits(nb_dev, 0x20, 1 << 9, 1 << 9); - - /* Enabels TLP flushing. */ - /* Note: It is got from RS690. The system will hang without this action. */ - set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19); - - /* 5.9.12.7. Ignores DLLPs during L1 so that txclk can be turned off */ - set_pcie_enable_bits(nb_dev, 0x2, 1 << 0, 1 << 0); - - /* 5.9.12.8 Prevents LC to go from L0 to Rcv_L0s if L1 is armed. */ - set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); - - /* 5.9.12.9 CMGOOD_OVERRIDE for end point initiated lane degradation. */ - set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17); - printk(BIOS_DEBUG, "rs780_gfx_init step5.9.12.9.\n"); - - /* 5.9.12.10 Sets the timer in Config state from 20us to */ - /* 5.9.12.11 De-asserts RX_EN in L0s. */ - /* 5.9.12.12 Enables de-assertion of PG2RX_CR_EN to lock clock - * recovery parameter when lane is in electrical idle in L0s.*/ - set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 << 23 | 1 << 19 | 1 << 28); - - /* 5.9.12.13. Turns off offset calibration. */ - /* 5.9.12.14. Enables Rx Clock gating in CDR */ - set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 10/* | 1 << 22 */, 1 << 10/* | 1 << 22 */); - - /* 5.9.12.15. Sets number of TX Clocks to drain TX Pipe to 3. */ - set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 3 << 4); - - /* 5.9.12.16. Lets PI use Electrical Idle from PHY when - * turning off PLL in L1 at Gen2 speed instead Inferred Electrical Idle. */ - set_pcie_enable_bits(nb_dev, 0x40, 3 << 14, 2 << 14); - - /* 5.9.12.17. Prevents the Electrical Idle from causing a transition from Rcv_L0 to Rcv_L0s. */ - set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20); - - /* 5.9.12.18. Prevents the LTSSM from going to Rcv_L0s if it has already - * acknowledged a request to go to L1. */ - set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); - - /* 5.9.12.19. LDSK only taking deskew on deskewing error detect */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 28, 0 << 28); - - /* 5.9.12.20. Bypasses lane de-skew logic if in x1 */ - set_pcie_enable_bits(nb_dev, 0xC2, 1 << 14, 1 << 14); - - /* 5.9.12.21. Sets Electrical Idle Threshold. */ - set_nbmisc_enable_bits(nb_dev, 0x35, 3 << 21, 2 << 21); - - /* 5.9.12.22. Advertises -6 dB de-emphasis value in TS1 Data Rate Identifier - * Only if CMOS Option in section. skip */ - - /* 5.9.12.23. Disables GEN2 capability of the device. */ - set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0); - - /* 5.9.12.24.Disables advertising Upconfigure Support. */ - set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13); - - /* 5.9.12.25. No comment in RPR. */ - set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 10, 0 << 10); - - /* 5.9.12.26. This capacity is required since links wider than x1 and/or multiple link - * speed are supported */ - set_pcie_enable_bits(nb_dev, 0xC1, 1 << 0, 1 << 0); - - /* 5.9.12.27. Enables NVG86 ECO. A13 above only. */ - if (get_nb_rev(nb_dev) == REV_RS780_A12) /* A12 */ - set_pcie_enable_bits(dev, 0x02, 1 << 11, 1 << 11); - - /* 5.9.12.28 Hides and disables the completion timeout method. */ - set_pcie_enable_bits(nb_dev, 0xC1, 1 << 2, 0 << 2); - - /* 5.9.12.29. Use the bif_core de-emphasis strength by default. */ - /* set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 28, 1 << 28); */ - - /* 5.9.12.30. Set TX arbitration algorithm to round robin */ - set_pcie_enable_bits(nb_dev, 0x1C, - 1 << 0 | 0x1F << 1 | 0x1F << 6, - 1 << 0 | 0x04 << 1 | 0x04 << 6); - - /* Single-port/Dual-port configureation. */ - switch (cfg->gfx_dual_slot) { - case 0: - /* step 1, lane reversal (only need if build config option is enabled) */ - if (cfg->gfx_lane_reversal) { - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); - } - printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); - - printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); - if((dev->path.pci.devfn >> 3) == 2) { - single_port_configuration(nb_dev, dev); - } else { - set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x2 << 2); /* hide the GFX bridge. */ - printk(BIOS_INFO, "Single port. Do nothing.\n"); // If dev3 - } - - break; - case 1: - /* step 1, lane reversal (only need if build config option is enabled) */ - if (cfg->gfx_lane_reversal) { - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); - } - printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); - /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ - /* AMD calls the configuration CrossFire */ - set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); - printk(BIOS_DEBUG, "rs780_gfx_init step2.\n"); - - printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); - dual_port_configuration(nb_dev, dev); - break; - - case 2: - - if(is_dev3_present()){ - /* step 1, lane reversal (only need if CMOS option is enabled) */ - if (cfg->gfx_lane_reversal) { - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); - } - printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); - /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ - /* AMD calls the configuration CrossFire */ - set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); - printk(BIOS_DEBUG, "rs780_gfx_init step2.\n"); - - - printk(BIOS_DEBUG, "device = %x\n", dev->path.pci.devfn >> 3); - dual_port_configuration(nb_dev, dev); - - }else{ - if (cfg->gfx_lane_reversal) { - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 1 << 31); - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 31, 0 << 31); - } - printk(BIOS_DEBUG, "rs780_gfx_init step1.\n"); - - if((dev->path.pci.devfn >> 3) == 2) - single_port_configuration(nb_dev, dev); - else{ - set_nbmisc_enable_bits(nb_dev, 0xc, 0, 0x2 << 2); /* hide the GFX bridge. */ - printk(BIOS_DEBUG, "If dev3.., single port. Do nothing.\n"); - } - } - - default: - printk(BIOS_INFO, "Incorrect configuration of external GFX slot.\n"); - break; - } -} diff --git a/src/southbridge/amd/rs780/rs780_ht.c b/src/southbridge/amd/rs780/rs780_ht.c deleted file mode 100644 index 03d4f84645..0000000000 --- a/src/southbridge/amd/rs780/rs780_ht.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 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 -#include -#include -#include -#include -#include "rs780.h" - -/* for UMA internal graphics */ -void avoid_lpc_dma_deadlock(device_t nb_dev, device_t sb_dev) -{ - device_t cpu_f0; - u8 reg; - - cpu_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - set_nbcfg_enable_bits(cpu_f0, 0x68, 3 << 21, 1 << 21); - - reg = nbpcie_p_read_index(sb_dev, 0x10); - reg |= 0x100; /* bit9=1 */ - nbpcie_p_write_index(sb_dev, 0x10, reg); - - reg = nbpcie_p_read_index(nb_dev, 0x10); - reg |= 0x100; /* bit9=1 */ - nbpcie_p_write_index(nb_dev, 0x10, reg); - - /* Enable NP protocol over PCIE for memory-mapped writes targeting LPC - * Set this bit to avoid a deadlock condition. */ - reg = htiu_read_index(nb_dev, 0x6); - reg |= 0x1000000; /* bit26 */ - htiu_write_index(nb_dev, 0x6, reg); -} - -static void pcie_init(struct device *dev) -{ - /* Enable pci error detecting */ - u32 dword; - - printk(BIOS_INFO, "pcie_init in rs780_ht.c\n"); - - /* System error enable */ - dword = pci_read_config32(dev, 0x04); - dword |= (1 << 8); /* System error enable */ - dword |= (1 << 30); /* Clear possible errors */ - pci_write_config32(dev, 0x04, dword); - - /* - * 1 is APIC enable - * 18 is enable nb to accept A4 interrupt request from SB. - */ - dword = pci_read_config32(dev, 0x4C); - dword |= 1 << 1 | 1 << 18; /* Clear possible errors */ - pci_write_config32(dev, 0x4C, dword); -} - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations ht_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = pcie_init, - .scan_bus = 0, - .ops_pci = &lops_pci, -}; - -static const struct pci_driver ht_driver __pci_driver = { - .ops = &ht_ops, - .vendor = PCI_VENDOR_ID_AMD, - .device = PCI_DEVICE_ID_AMD_RS780_HT, -}; diff --git a/src/southbridge/amd/rs780/rs780_pcie.c b/src/southbridge/amd/rs780/rs780_pcie.c deleted file mode 100644 index 9cbd832661..0000000000 --- a/src/southbridge/amd/rs780/rs780_pcie.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 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 -#include -#include -#include -#include -#include -#include "rs780.h" - -/*------------------------------------------------ -* Global variable -------------------------------------------------*/ -PCIE_CFG AtiPcieCfg = { - PCIE_ENABLE_STATIC_DEV_REMAP, /* Config */ - 0, /* ResetReleaseDelay */ - 0, /* Gfx0Width */ - 0, /* Gfx1Width */ - 0, /* GfxPayload */ - 0, /* GppPayload */ - 0, /* PortDetect, filled by GppSbInit */ - 0, /* PortHp */ - 0, /* DbgConfig */ - 0, /* DbgConfig2 */ - 0, /* GfxLx */ - 0, /* GppLx */ - 0, /* NBSBLx */ - 0, /* PortSlotInit */ - 0, /* Gfx0Pwr */ - 0, /* Gfx1Pwr */ - 0 /* GppPwr */ -}; - -static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port); -static void ValidatePortEn(device_t nb_dev); - -static void ValidatePortEn(device_t nb_dev) -{ -} - -/***************************************************************** -* Compliant with CIM_33's PCIEPowerOffGppPorts -* Power off unused GPP lines -*****************************************************************/ -static void PciePowerOffGppPorts(device_t nb_dev, device_t dev, u32 port) -{ - u32 reg; - u16 state_save; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - u8 state = cfg->port_enable; - - if (!(AtiPcieCfg.Config & PCIE_DISABLE_HIDE_UNUSED_PORTS)) - state &= AtiPcieCfg.PortDetect; - state = ~state; - state &= (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7); - state_save = state << 17; - state &= !(AtiPcieCfg.PortHp); - reg = nbmisc_read_index(nb_dev, 0x0c); - reg |= state; - nbmisc_write_index(nb_dev, 0x0c, reg); - - reg = nbmisc_read_index(nb_dev, 0x08); - reg |= state_save; - nbmisc_write_index(nb_dev, 0x08, reg); - - if ((AtiPcieCfg.Config & PCIE_OFF_UNUSED_GPP_LANES) - && !(AtiPcieCfg. - Config & (PCIE_DISABLE_HIDE_UNUSED_PORTS + - PCIE_GFX_COMPLIANCE))) { - } - /* step 3 Power Down Control for Southbridge */ - reg = nbpcie_p_read_index(dev, 0xa2); - - switch ((reg >> 4) & 0x7) { /* get bit 4-6, LC_LINK_WIDTH_RD */ - case 1: - nbpcie_ind_write_index(nb_dev, 0x65, 0x0e0e); - break; - case 2: - nbpcie_ind_write_index(nb_dev, 0x65, 0x0c0c); - break; - default: - break; - } -} - -/********************************************************************** -**********************************************************************/ -static void switching_gppsb_configurations(device_t nb_dev, device_t sb_dev) -{ - u32 reg; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - /* 5.5.7.1-3 enables GPP reconfiguration */ - reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); - reg |= - (RECONFIG_GPPSB_EN + RECONFIG_GPPSB_LINK_CONFIG + - RECONFIG_GPPSB_ATOMIC_RESET); - nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); - - /* 5.5.7.4a. De-asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ - reg = nbmisc_read_index(nb_dev, 0x66); - reg |= 1 << 31; - nbmisc_write_index(nb_dev, 0x66, reg); - /* 5.5.7.4b. sets desired GPPSB configurations, bit4-7 */ - reg = nbmisc_read_index(nb_dev, 0x67); - reg &= 0xFFFFff0f; /* clean */ - reg |= cfg->gppsb_configuration << 4; - nbmisc_write_index(nb_dev, 0x67, reg); - -#if 1 - /* NOTE: - * In CIMx 4.5.0 and RPR, 4c is done before 5 & 6. But in this way, - * a x4 device in port B (dev 4) of Configuration B can only be detected - * as x1, instead of x4. When the port B is being trained, the - * LC_CURRENT_STATE is 6 and the LC_LINK_WIDTH_RD is 1. We have - * to set the PCIEIND:0x65 as 0xE0E0 and reset the slot. Then the card - * seems to work in x1 mode. - * In the 2nd way below, we do the 5 & 6 before 4c. it conforms the - * CIMx 4.3.0. It conflicts with RPR. But based on the test result I've - * made so far, I haven't found any mistake. - */ - /* 5.5.7.4c. Asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ - reg = nbmisc_read_index(nb_dev, 0x66); - reg &= ~(1 << 31); - nbmisc_write_index(nb_dev, 0x66, reg); - - /* 5.5.7.5-6. read bit14 and write back its inverst value */ - reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); - reg ^= RECONFIG_GPPSB_GPPSB; - nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); -#else - /* 5.5.7.5-6. read bit14 and write back its inverst value */ - reg = nbmisc_read_index(nb_dev, PCIE_NBCFG_REG7); - reg ^= RECONFIG_GPPSB_GPPSB; - nbmisc_write_index(nb_dev, PCIE_NBCFG_REG7, reg); - - /* 5.5.7.4c. Asserts STRAP_BIF_all_valid for PCIE-GPPSB core */ - reg = nbmisc_read_index(nb_dev, 0x66); - reg &= ~(1 << 31); - nbmisc_write_index(nb_dev, 0x66, reg); -#endif - /* 5.5.7.7. delay 1ms */ - mdelay(1); - - /* 5.5.7.8. waits until SB has trained to L0, poll for bit0-5 = 0x10 */ - do { - reg = nbpcie_p_read_index(sb_dev, PCIE_LC_STATE0); - reg &= 0x3f; /* remain LSB [5:0] bits */ - } while (LC_STATE_RECONFIG_GPPSB != reg); - - /* 5.5.7.9.ensures that virtual channel negotiation is completed. poll for bit1 = 0 */ - do { - reg = - pci_ext_read_config32(nb_dev, sb_dev, - PCIE_VC0_RESOURCE_STATUS); - } while (reg & VC_NEGOTIATION_PENDING); -} - -static void switching_gpp_configurations(device_t nb_dev, device_t sb_dev) -{ - u32 reg; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - /* 5.6.2.1. De-asserts STRAP_BIF_all_valid for PCIE-GPP core */ - reg = nbmisc_read_index(nb_dev, 0x22); - reg |= 1 << 14; - nbmisc_write_index(nb_dev, 0x22, reg); - /* 5.6.2.2. sets desired GPPSB configurations, bit4-7 */ - reg = nbmisc_read_index(nb_dev, 0x2D); - reg &= ~(0xF << 7); /* clean */ - reg |= cfg->gpp_configuration << 7; - nbmisc_write_index(nb_dev, 0x2D, reg); - /* 5.6.2.3. Asserts STRAP_BIF_all_valid for PCIE-GPP core */ - reg = nbmisc_read_index(nb_dev, 0x22); - reg &= ~(1 << 14); - nbmisc_write_index(nb_dev, 0x22, reg); -} - -/***************************************************************** -* The rs780 uses NBCONFIG:0x1c (BAR3) to map the PCIE Extended Configuration -* Space to a 256MB range within the first 4GB of addressable memory. -*****************************************************************/ -void enable_pcie_bar3(device_t nb_dev) -{ - printk(BIOS_DEBUG, "enable_pcie_bar3()\n"); - set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 1 << 30); /* Enables writes to the BAR3 register. */ - set_nbcfg_enable_bits(nb_dev, 0x84, 7 << 16, 0 << 16); - - pci_write_config32(nb_dev, 0x1C, EXT_CONF_BASE_ADDRESS); /* PCIEMiscInit */ - pci_write_config32(nb_dev, 0x20, 0x00000000); - set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 1 << 28); /* PCIEMiscInit */ - ProgK8TempMmioBase(1, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); -} - -/***************************************************************** -* We should disable bar3 when we want to exit rs780_enable, because bar3 will be -* remapped in set_resource later. -*****************************************************************/ -void disable_pcie_bar3(device_t nb_dev) -{ - printk(BIOS_DEBUG, "disable_pcie_bar3()\n"); - pci_write_config32(nb_dev, 0x1C, 0); /* clear BAR3 address */ - set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3. */ - set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 0); /* disable bar3 decode */ - ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS); -} - -/***************************************** -* Compliant with CIM_33's PCIEGPPInit -* nb_dev: -* root bridge struct -* dev: -* p2p bridge struct -* port: -* p2p bridge number, 4-10 -*****************************************/ -void rs780_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) -{ - u32 gfx_gpp_sb_sel; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - printk(BIOS_DEBUG, "gpp_sb_init nb_dev=0x%x, dev=0x%x, port=0x%x\n", nb_dev->path.pci.devfn, dev->path.pci.devfn, port); - - gfx_gpp_sb_sel = port >= 4 && port <= 8 ? - PCIE_CORE_INDEX_GPPSB : /* 4,5,6,7,8 */ - PCIE_CORE_INDEX_GPP; /* 9,10 */ - /* init GPP core */ - /* 5.10.8.3. Disable slave ordering logic */ - set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 8, - 1 << 8); - /* 5.10.8.7. PCIE initialization 5.10.2: rpr 2.12*/ - set_pcie_enable_bits(nb_dev, 0x02 | gfx_gpp_sb_sel, 1 << 0, 1 << 0); /* no description in datasheet. */ - - /* init GPPSB port. rpr 5.10.8 */ - /* 5.10.8.1-5.10.8.2. Sets RCB timeout to be 100ms/4=25ms by setting bits[18:16] to 3 h4 - * and shortens the enumeration timer by setting bit[19] to 1 - */ - set_pcie_enable_bits(dev, 0x70, 0xF << 16, 0x4 << 16 | 1 << 19); - /* 5.10.8.4. Sets DMA payload size to 64 bytes. */ - set_pcie_enable_bits(nb_dev, 0x10 | gfx_gpp_sb_sel, 7 << 10, 4 << 10); - /* 5.10.8.6. Disable RC ordering logic */ - set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 9, 1 << 9); - /* 5.10.8.7. Ignores DLLs druing L1 */ - set_pcie_enable_bits(nb_dev, 0x02 | gfx_gpp_sb_sel, 1 << 0, 1 << 0); - /* 5.10.8.8. Prevents LCto go from L0 to Rcv_L0s if L1 is armed. */ - set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); - /* 5.10.8.9. Sets timer in Config state from 20us to 1us. - * 5.10.8.10. De-asserts RX_EN in L0s - * 5.10.8.11. Enables de-assertion of PG2RX_CR_EN to lock clock recovery parameter when .. */ - set_pcie_enable_bits(dev, 0xB1, 1 << 23 | 1 << 19 | 1 << 28, 1 <<23 | 1 << 19 | 1 << 28); - /* 5.10.8.12. Turns off offset calibration */ - /* 5.10.8.13. Enables Rx Clock gating in CDR */ - if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) - set_nbmisc_enable_bits(nb_dev, 0x67, 1 << 14 | 1 << 26, 1 << 14 | 1 << 26); /* 4,5,6,7 */ - else - set_nbmisc_enable_bits(nb_dev, 0x24, 1 << 29 | 1 << 28, 1 << 29 | 1 << 28); /* 9,10 */ - /* 5.10.8.14. Sets number of TX Clocks to drain TX Pipe to 3 */ - set_pcie_enable_bits(dev, 0xA0, 0xF << 4, 0x3 << 4); - /* 5.10.8.15. empty */ - /* 5.10.8.16. P_ELEC_IDLE_MODE */ - set_pcie_enable_bits(nb_dev, 0x40 | gfx_gpp_sb_sel, 0x3 << 14, 0x2 << 14); - /* 5.10.8.17. LC_BLOCK_EL_IDLE_IN_L0 */ - set_pcie_enable_bits(dev, 0xB1, 1 << 20, 1 << 20); - /* 5.10.8.18. LC_DONT_GO_TO_L0S_IFL1_ARMED */ - set_pcie_enable_bits(dev, 0xA1, 1 << 11, 1 << 11); - /* 5.10.8.19. RXP_REALIGN_ON_EACH_TSX_OR_SKP */ - set_pcie_enable_bits(nb_dev, 0x40 | gfx_gpp_sb_sel, 1 << 28, 0 << 28); - /* 5.10.8.20. Bypass lane de-skew logic if in x1 */ - set_pcie_enable_bits(nb_dev, 0xC2 | gfx_gpp_sb_sel, 1 << 14, 1 << 14); - /* 5.10.8.21. sets electrical idle threshold. */ - if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) - set_nbmisc_enable_bits(nb_dev, 0x6A, 3 << 22, 2 << 22); - else - set_nbmisc_enable_bits(nb_dev, 0x24, 3 << 16, 2 << 16); - - /* 5.10.8.22. Disable GEN2 */ - /* TODO: should be 2 seperated cases. */ - set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 31, 0 << 31); - set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 5, 0 << 5); - set_nbmisc_enable_bits(nb_dev, 0x34, 1 << 31, 0 << 31); - set_nbmisc_enable_bits(nb_dev, 0x37, 7 << 5, 0 << 5); - /* 5.10.8.23. Disables GEN2 capability of the device. RPR says enable? No! */ - set_pcie_enable_bits(dev, 0xA4, 1 << 0, 0 << 0); - /* 5.10.8.24. Disable advertising upconfigure support. */ - set_pcie_enable_bits(dev, 0xA2, 1 << 13, 1 << 13); - /* 5.10.8.25-26. STRAP_BIF_DSN_EN */ - if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) - set_nbmisc_enable_bits(nb_dev, 0x68, 1 << 19, 0 << 19); - else - set_nbmisc_enable_bits(nb_dev, 0x22, 1 << 3, 0 << 3); - /* 5.10.8.27-28. */ - set_pcie_enable_bits(nb_dev, 0xC1 | gfx_gpp_sb_sel, 1 << 0 | 1 << 2, 1 << 0 | 0 << 2); - /* 5.10.8.29. Uses the bif_core de-emphasis strength by default. */ - if (gfx_gpp_sb_sel == PCIE_CORE_INDEX_GPPSB) { - set_nbmisc_enable_bits(nb_dev, 0x67, 1 << 10, 1 << 10); - set_nbmisc_enable_bits(nb_dev, 0x36, 1 << 29, 1 << 29); - } - else { - set_nbmisc_enable_bits(nb_dev, 0x39, 1 << 30, 1 << 30); - } - /* 5.10.8.30. Set TX arbitration algorithm to round robin. */ - set_pcie_enable_bits(nb_dev, 0x1C | gfx_gpp_sb_sel, - 1 << 0 | 0x1F << 1 | 0x1F << 6, - 1 << 0 | 0x04 << 1 | 0x04 << 6); - - /* check compliance rpr step 2.1*/ - if (AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE) { - u32 tmp; - tmp = nbmisc_read_index(nb_dev, 0x67); - tmp |= 1 << 3; - nbmisc_write_index(nb_dev, 0x67, tmp); - } - - /* step 5: dynamic slave CPL buffer allocation. Disable it, otherwise linux hangs. Why? */ - /* set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 11, 1 << 11); */ - - /* step 5a: Training for GPP devices */ - /* init GPP */ - switch (port) { - case 4: /* GPP */ - case 5: - case 6: - case 7: - case 9: - case 10: - /* 5.10.8.5. Blocks DMA traffic during C3 state */ - set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); - /* Enabels TLP flushing */ - set_pcie_enable_bits(dev, 0x20, 1 << 19, 0 << 19); - - /* check port enable */ - if (cfg->port_enable & (1 << port)) { - PcieReleasePortTraining(nb_dev, dev, port); - if (!(AtiPcieCfg.Config & PCIE_GPP_COMPLIANCE)) { - u8 res = PcieTrainPort(nb_dev, dev, port); - printk(BIOS_DEBUG, "PcieTrainPort port=0x%x result=%d\n", port, res); - if (res) { - AtiPcieCfg.PortDetect |= 1 << port; - } - } - } - break; - case 8: /* SB */ - break; - } - PciePowerOffGppPorts(nb_dev, dev, port); -} - -/***************************************** -* Compliant with CIM_33's PCIEConfigureGPPCore -*****************************************/ -void config_gpp_core(device_t nb_dev, device_t sb_dev) -{ - u32 reg; - struct southbridge_amd_rs780_config *cfg = - (struct southbridge_amd_rs780_config *)nb_dev->chip_info; - - reg = nbmisc_read_index(nb_dev, 0x20); - if (AtiPcieCfg.Config & PCIE_ENABLE_STATIC_DEV_REMAP) - reg &= 0xfffffffd; /* set bit1 = 0 */ - else - reg |= 0x2; /* set bit1 = 1 */ - nbmisc_write_index(nb_dev, 0x20, reg); - - reg = nbmisc_read_index(nb_dev, 0x67); /* get STRAP_BIF_LINK_CONFIG_GPPSB at bit 4-7 */ - if (cfg->gppsb_configuration != ((reg >> 4) & 0xf)) - switching_gppsb_configurations(nb_dev, sb_dev); - reg = nbmisc_read_index(nb_dev, 0x2D); /* get STRAP_BIF_LINK_CONFIG_GPP at bit 7-10 */ - if (cfg->gpp_configuration != ((reg >> 7) & 0xf)) - switching_gpp_configurations(nb_dev, sb_dev); - ValidatePortEn(nb_dev); -} diff --git a/src/southbridge/amd/rs780/rs780_rev.h b/src/southbridge/amd/rs780/rs780_rev.h deleted file mode 100644 index 94ab752f9f..0000000000 --- a/src/southbridge/amd/rs780/rs780_rev.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2010 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 __RS780_REV_H__ -#define __RS780_REV_H__ - -#define REV_RS780_A11 0 -#define REV_RS780_A12 1 -#define REV_RS780_A13 2 - -#endif /* __RS780_REV_H__ */ -- cgit v1.2.3