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/rs690/Makefile.inc | 8 +- src/southbridge/amd/rs690/cmn.c | 324 +++++++++++++ src/southbridge/amd/rs690/early_setup.c | 484 ++++++++++++++++++++ src/southbridge/amd/rs690/gfx.c | 625 ++++++++++++++++++++++++++ src/southbridge/amd/rs690/ht.c | 90 ++++ src/southbridge/amd/rs690/pcie.c | 401 +++++++++++++++++ src/southbridge/amd/rs690/rs690_cmn.c | 324 ------------- src/southbridge/amd/rs690/rs690_early_setup.c | 484 -------------------- src/southbridge/amd/rs690/rs690_gfx.c | 625 -------------------------- src/southbridge/amd/rs690/rs690_ht.c | 90 ---- src/southbridge/amd/rs690/rs690_pcie.c | 401 ----------------- 11 files changed, 1928 insertions(+), 1928 deletions(-) create mode 100644 src/southbridge/amd/rs690/cmn.c create mode 100644 src/southbridge/amd/rs690/early_setup.c create mode 100644 src/southbridge/amd/rs690/gfx.c create mode 100644 src/southbridge/amd/rs690/ht.c create mode 100644 src/southbridge/amd/rs690/pcie.c delete mode 100644 src/southbridge/amd/rs690/rs690_cmn.c delete mode 100644 src/southbridge/amd/rs690/rs690_early_setup.c delete mode 100644 src/southbridge/amd/rs690/rs690_gfx.c delete mode 100644 src/southbridge/amd/rs690/rs690_ht.c delete mode 100644 src/southbridge/amd/rs690/rs690_pcie.c (limited to 'src/southbridge/amd/rs690') diff --git a/src/southbridge/amd/rs690/Makefile.inc b/src/southbridge/amd/rs690/Makefile.inc index c728be56a4..5849340ce0 100644 --- a/src/southbridge/amd/rs690/Makefile.inc +++ b/src/southbridge/amd/rs690/Makefile.inc @@ -1,5 +1,5 @@ driver-y += rs690.c -driver-y += rs690_cmn.c -driver-y += rs690_pcie.c -driver-y += rs690_ht.c -driver-y += rs690_gfx.c +driver-y += cmn.c +driver-y += pcie.c +driver-y += ht.c +driver-y += gfx.c diff --git a/src/southbridge/amd/rs690/cmn.c b/src/southbridge/amd/rs690/cmn.c new file mode 100644 index 0000000000..5e06d4f9d8 --- /dev/null +++ b/src/southbridge/amd/rs690/cmn.c @@ -0,0 +1,324 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 "rs690.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: /* GPP, bit20-24 */ + case 5: + case 6: + case 7: + set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, + 1 << (port + 17), 0 << (port + 17)); + 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; + int8_t current, res = 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 0x07: /* device is in compliance state (training sequence is doen). Move to train the next device */ + res = 1; /* TODO: CIM sets it to 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 rs690_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); +} + diff --git a/src/southbridge/amd/rs690/early_setup.c b/src/southbridge/amd/rs690/early_setup.c new file mode 100644 index 0000000000..f29d136791 --- /dev/null +++ b/src/southbridge/amd/rs690/early_setup.c @@ -0,0 +1,484 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008 Carl-Daniel Hailfinger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#define NBHTIU_INDEX 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); + } +} + +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); + } +} + +/* +* Compliant with CIM_33's ATINB_PrepareInit +*/ +static void get_cpu_rev(void) +{ + u32 eax, ebx, ecx, edx; + __asm__ volatile ("cpuid":"=a" (eax), "=b"(ebx), "=c"(ecx), "=d"(edx) + :"0"(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 + printk(BIOS_INFO, "CPU Rev is K8_10.\n"); +} + +static u8 get_nb_rev(device_t nb_dev) +{ + u32 reg; + reg = pci_read_config32(nb_dev, 0x00); + if (0x7911 == (reg >> 16)) + return 7; + reg = pci_read_config8(nb_dev, 0x89); /* copy from CIM, can't find in doc */ + if (reg & 0x2) /* check bit1 */ + return 7; + if (reg & 0x1) /* check bit0 */ + return 6; + else + return 5; +} + +/***************************************** +* Compliant with CIM_33's ATINB_HTInit +* Init HT link speed/width for rs690 -- k8 link +*****************************************/ +static void rs690_htinit(void) +{ + /* + * About HT, it has been done in enumerate_ht_chain(). + */ + device_t k8_f0, rs690_f0; + u32 reg; + u8 reg8; + u8 k8_ht_freq; + + k8_f0 = PCI_DEV(0, 0x18, 0); + /************************ + * get k8's ht freq, in k8'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. + * 0000b = 200Mhz + * 0010b = 400Mhz + * 0100b = 600Mhz + * 0101b = 800Mhz + * 0110b = 1Ghz + * 1111b = 1Ghz + ************************/ + reg = pci_read_config32(k8_f0, 0x88); + k8_ht_freq = (reg & 0xf00) >> 8; + printk(BIOS_SPEW, "rs690_htinit k8_ht_freq=%x.\n", k8_ht_freq); + rs690_f0 = PCI_DEV(0, 0, 0); + reg8 = pci_read_config8(rs690_f0, 0x9c); + printk(BIOS_SPEW, "rs690_htinit NB_CFG_Q_F1000_800=%x\n", reg8); + /* For 1000 MHz HT, NB_CFG_Q_F1000_800 bit 0 MUST be set. + * For any other HT frequency, NB_CFG_Q_F1000_800 bit 0 MUST NOT be set. + */ + if (((k8_ht_freq == 0x6) || (k8_ht_freq == 0xf)) && (!(reg8 & 0x1))) { + printk(BIOS_INFO, "rs690_htinit setting bit 0 in NB_CFG_Q_F1000_800 to use 1 GHz HT\n"); + reg8 |= 0x1; + pci_write_config8(rs690_f0, 0x9c, reg8); + } else if ((k8_ht_freq != 0x6) && (k8_ht_freq != 0xf) && (reg8 & 0x1)) { + printk(BIOS_INFO, "rs690_htinit clearing bit 0 in NB_CFG_Q_F1000_800 to not use 1 GHz HT\n"); + reg8 &= ~0x1; + pci_write_config8(rs690_f0, 0x9c, reg8); + } +} + +/******************************************************* +* Optimize k8 with UMA. +* See BKDG_NPT_0F guide for details. +* The processor node is addressed by its Node ID on the HT link and can be +* accessed with a device number in the PCI configuration space on Bus0. +* The Node ID 0 is mapped to Device 24 (0x18), the Node ID 1 is mapped +* to Device 25, and so on. +* The processor implements configuration registers in PCI configuration +* space using the following four headers +* Function0: HT technology configuration +* Function1: Address map configuration +* Function2: DRAM and HT technology Trace mode configuration +* Function3: Miscellaneous configuration +*******************************************************/ +static void k8_optimization(void) +{ + device_t k8_f0, k8_f2, k8_f3; + msr_t msr; + + printk(BIOS_INFO, "k8_optimization()\n"); + k8_f0 = PCI_DEV(0, 0x18, 0); + k8_f2 = PCI_DEV(0, 0x18, 2); + k8_f3 = PCI_DEV(0, 0x18, 3); + + pci_write_config32(k8_f0, 0x90, 0x01700178); /* CIM NPT_Optimization */ + set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 28, 0 << 28); + set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 26 | 1 << 27, + 1 << 26 | 1 << 27); + set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 11, 1 << 11); + set_nbcfg_enable_bits(k8_f0, 0x84, 1 << 11 | 1 << 13 | 1 << 15, 1 << 11 | 1 << 13 | 1 << 15); /* TODO */ + + pci_write_config32(k8_f3, 0x70, 0x51320111); /* CIM NPT_Optimization */ + pci_write_config32(k8_f3, 0x74, 0x50304021); + pci_write_config32(k8_f3, 0x78, 0x08002A00); + if (pci_read_config32(k8_f3, 0xE8) & 0x3<<12) + pci_write_config32(k8_f3, 0x7C, 0x0000211B); /* dual core */ + else + pci_write_config32(k8_f3, 0x7C, 0x0000211C); /* 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, 1 << 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); +} + +/***************************************** +* Compliant with CIM_33's ATINB_PCICFG_POR_TABLE +*****************************************/ +static void rs690_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[10:9] = 0x3 Enables Gfx Debug BAR, + * force this BAR as mem type in rs690_gfx.c */ + set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x03); + +} + +/***************************************** +* Compliant with CIM_33's ATINB_MCIndex_POR_TABLE +*****************************************/ +static void rs690_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); +} + +/***************************************** +* Compliant with CIM_33's ATINB_MISCIND_POR_TABLE +* Compliant with CIM_33's MISC_INIT_TBL +*****************************************/ +static void rs690_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); + + /* Compliant with CIM_33's MISC_INIT_TBL, except Hide NB_BAR3_PCIE + * 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, 0x00, 1 << 7, 1 << 7); + set_nbmisc_enable_bits(nb_dev, 0x07, 0x000000f0, 0x30); + /* Disable bus-master trigger event from SB and Enable set_slot_power message to SB */ + set_nbmisc_enable_bits(nb_dev, 0x0B, 0xffffffff, 0x500180); +} + +/***************************************** +* Compliant with CIM_33's ATINB_HTIUNBIND_POR_TABLE +*****************************************/ +static void rs690_por_htiu_index_init(device_t nb_dev) +{ + /* 0xBC: + * Enables GSM mode for C1e or C3 with pop-up + * Prevents AllowLdtStop from being asserted during HT link recovery + * Allows FID cycles to be serviced faster. Needed for RS690 A12. No harm in RS690 A11 */ + set_htiu_enable_bits(nb_dev, 0x05, ~0xffffffff, 0x0BC); + /* 0x4203A202: + * Enables writes to pass in-progress reads + * Enables streaming of CPU writes + * Enables extended write buffer for CPU writes + * Enables additional response buffers + * Enables special reads to pass writes + * Enables decoding of C1e/C3 and FID cycles + * Enables HTIU-display handshake bypass. + * Enables tagging fix */ + set_htiu_enable_bits(nb_dev, 0x06, ~0xFFFFFFFE, 0x4203A202); + + /* Enables byte-write optimization for IOC requests + * Disables delaying STPCLK de-assert during FID sequence. Needed when enhanced UMA arbitration is used. + * Disables upstream system-management delay */ + set_htiu_enable_bits(nb_dev, 0x07, ~0xFFFFFFF9, 0x001); + + /* HTIUNBIND 0x16 [1] = 0x1 Enable crc decoding fix */ + set_htiu_enable_bits(nb_dev, 0x16, ~0xFFFFFFFF, 0x2); +} + +/***************************************** +* Compliant with CIM_33's ATINB_POR_INIT_JMPDI +* Configure RS690 registers to power-on default RPR. +* POR: Power On Reset +* RPR: Register Programming Requirements +*****************************************/ +static void rs690_por_init(device_t nb_dev) +{ + printk(BIOS_INFO, "rs690_por_init\n"); + /* ATINB_PCICFG_POR_TABLE, initialize the values for rs690 PCI Config registers */ + rs690_por_pcicfg_init(nb_dev); + + /* ATINB_MCIND_POR_TABLE */ + rs690_por_mc_index_init(nb_dev); + + /* ATINB_MISCIND_POR_TABLE */ + rs690_por_misc_index_init(nb_dev); + + /* ATINB_HTIUNBIND_POR_TABLE */ + rs690_por_htiu_index_init(nb_dev); + + /* ATINB_CLKCFG_PORT_TABLE */ + /* rs690 A11 SB Link full swing? */ +} + +/* enable CFG access to Dev8, which is the SB P2P Bridge */ +static void enable_rs690_dev8(void) +{ + set_nbmisc_enable_bits(PCI_DEV(0, 0, 0), 0x00, 1 << 6, 1 << 6); +} + + + +/* +* Compliant with CIM_33's AtiNBInitEarlyPost (AtiInitNBBeforePCIInit). +*/ +static void rs690_before_pci_init(void) +{ +} + +/* +* The calling sequence is same as CIM. +*/ +static void rs690_early_setup(void) +{ + device_t nb_dev = PCI_DEV(0, 0, 0); + printk(BIOS_INFO, "rs690_early_setup()\n"); + + /*ATINB_PrepareInit */ + get_cpu_rev(); + switch (get_nb_rev(nb_dev)) { /* PCIEMiscInit */ + case 5: + printk(BIOS_INFO, "NB Revision is A11.\n"); + break; + case 6: + printk(BIOS_INFO, "NB Revision is A12.\n"); + break; + case 7: + printk(BIOS_INFO, "NB Revision is A21.\n"); + break; + } + + k8_optimization(); + rs690_por_init(nb_dev); +} diff --git a/src/southbridge/amd/rs690/gfx.c b/src/southbridge/amd/rs690/gfx.c new file mode 100644 index 0000000000..c55f2bc3d3 --- /dev/null +++ b/src/southbridge/amd/rs690/gfx.c @@ -0,0 +1,625 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 rs690 internal graphics device + * device id of internal grphics: + * RS690M/T: 0x791f + * RS690: 0x791e + */ +#include +#include +#include +#include +#include +#include +#include "rs690.h" + +#define CLK_CNTL_INDEX 0x8 +#define CLK_CNTL_DATA 0xC + +#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_INFO, "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 rs690_gfx_read_resources(device_t dev) +{ + printk(BIOS_INFO, "rs690_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); +} + +static void internal_gfx_pci_dev_init(struct device *dev) +{ + u16 deviceid, vendorid; + deviceid = pci_read_config16(dev, PCI_DEVICE_ID); + vendorid = pci_read_config16(dev, PCI_VENDOR_ID); + printk(BIOS_INFO, "internal_gfx_pci_dev_init device=%x, vendor=%x.\n", + deviceid, vendorid); + + 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 RS690 and CPU to enable the internal GFX. +* Please refer to CIM source code and BKDG. +*/ +static void rs690_internal_gfx_enable(device_t dev) +{ + u32 l_dword; + int i; + device_t k8_f0 = 0, k8_f2 = 0; + device_t nb_dev = dev_find_slot(0, 0); + + printk(BIOS_INFO, "rs690_internal_gfx_enable dev=0x%p, nb_dev=0x%p.\n", dev, + nb_dev); + + /* set APERTURE_SIZE, 128M. */ + l_dword = pci_read_config32(nb_dev, 0x8c); + printk(BIOS_INFO, "nb_dev, 0x8c=0x%x\n", l_dword); + l_dword &= 0xffffff8f; + pci_write_config32(nb_dev, 0x8c, l_dword); + + /* set TOM */ + rs690_set_tom(nb_dev); + + /* LPC DMA Deadlock workaround? */ + k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + l_dword = pci_read_config32(k8_f0, 0x68); + l_dword &= ~(1 << 22); + l_dword |= (1 << 21); + pci_write_config32(k8_f0, 0x68, l_dword); + + /* Enable 64bit mode. */ + set_nbmc_enable_bits(nb_dev, 0x5f, 0, 1 << 9); + set_nbmc_enable_bits(nb_dev, 0xb0, 0, 1 << 8); + + /* 64bit Latency. */ + set_nbmc_enable_bits(nb_dev, 0x5f, 0x7c00, 0x800); + + /* UMA dual channel control register. */ + nbmc_write_index(nb_dev, 0x86, 0x3d); + + /* check the setting later!! */ + set_htiu_enable_bits(nb_dev, 0x07, 1 << 7, 0); + + /* UMA mode, powerdown memory PLL. */ + set_nbmc_enable_bits(nb_dev, 0x74, 0, 1 << 31); + + /* Copy CPU DDR Controller to NB MC. */ + /* Why K8_MC_REG80 is special? */ + k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); + for (i = 0; i <= (0x80 - 0x40) / 4; i++) { + l_dword = pci_read_config32(k8_f2, 0x40 + i * 4); + nbmc_write_index(nb_dev, 0x63 + i, l_dword); + } + + /* Set K8 MC for UMA, Family F. */ + l_dword = pci_read_config32(k8_f2, 0xa0); + l_dword |= 0x2c; + pci_write_config32(k8_f2, 0xa0, l_dword); + l_dword = pci_read_config32(k8_f2, 0x94); + l_dword &= 0xf0ffffff; + l_dword |= 0x07000000; + pci_write_config32(k8_f2, 0x94, l_dword); + + /* set FB size and location. */ + nbmc_write_index(nb_dev, 0x1b, 0x00); + l_dword = nbmc_read_index(nb_dev, 0x1c); + l_dword &= 0xffff0; + l_dword |= 0x400 << 20; + l_dword |= 0x4; + nbmc_write_index(nb_dev, 0x1c, l_dword); + l_dword = nbmc_read_index(nb_dev, 0x1d); + l_dword &= 0xfffff000; + l_dword |= 0x0400; + nbmc_write_index(nb_dev, 0x1d, l_dword); + nbmc_write_index(nb_dev, 0x100, 0x3fff3800); + + /* Program MC table. */ + set_nbmc_enable_bits(nb_dev, 0x00, 0, 1 << 31); + l_dword = nbmc_read_index(nb_dev, 0x91); + l_dword |= 0x5; + nbmc_write_index(nb_dev, 0x91, l_dword); + set_nbmc_enable_bits(nb_dev, 0xb1, 0, 1 << 6); + set_nbmc_enable_bits(nb_dev, 0xc3, 0, 1); + + /* TODO: the optimization of voltage and frequency */ +} + +static struct pci_operations lops_pci = { + .set_subsystem = pci_dev_set_subsystem, +}; + +static struct device_operations pcie_ops = { + .read_resources = rs690_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. rs690_gfx_init, */ + .scan_bus = 0, + .enable = rs690_internal_gfx_enable, + .ops_pci = &lops_pci, +}; + +/* + * The dev id of 690G is 791E, while the id of 690M, 690T is 791F. + * We should list both of them here. + * */ +static const struct pci_driver pcie_driver_690t __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS690MT_INT_GFX, +}; + +static const struct pci_driver pcie_driver_690 __pci_driver = { + .ops = &pcie_ops, + .vendor = PCI_VENDOR_ID_ATI, + .device = PCI_DEVICE_ID_ATI_RS690_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_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + + printk(BIOS_INFO, "rs690_gfx_init single_port_configuration.\n"); + + /* step 12 training, releases hold training for GFX port 0 (device 2) */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0<<4); + PcieReleasePortTraining(nb_dev, dev, 2); + result = PcieTrainPort(nb_dev, dev, 2); + printk(BIOS_INFO, "rs690_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 */ + + 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 ? 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_INFO, "rs690_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, 0 << 19); + printk(BIOS_INFO, "rs690_gfx_init single_port_configuration step14.\n"); +} + +/* step 15 ~ step 18 from rpr */ +static void dual_port_configuration(device_t nb_dev, device_t dev) +{ + u8 result, width; + u32 reg32; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + + /* step 15: Training for Device 2 */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4); + /* Releases hold training for GFX port 0 (device 2) */ + PcieReleasePortTraining(nb_dev, dev, 2); + /* PCIE Link Training Sequence */ + result = PcieTrainPort(nb_dev, dev, 2); + + /* step 16: Power Down Control for Device 2 */ + /* step 16.a Link Training was NOT successful */ + if (!result) { + /* Powers down all lanes for port A */ + nbpcie_ind_write_index(nb_dev, 0x65, 0x0f0f); + } 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; + } + } + + /* step 17: Training for Device 3 */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 5, 0 << 5); + /* Releases hold training for GFX port 0 (device 3) */ + PcieReleasePortTraining(nb_dev, dev, 3); + /* PCIE Link Training Sequence */ + result = PcieTrainPort(nb_dev, dev, 3); + + /*step 18: Power Down Control for Device 3 */ + /* step 18.a Link Training was NOT successful */ + if (!result) { + /* Powers down all lanes for port B and PLL1 */ + nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0); + } else { /* step 18.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 ? 0x7070 : 0xe0e0); + break; + case 4: + nbpcie_ind_write_index(nb_dev, 0x65, + cfg->gfx_lane_reversal ? 0x3030 : 0xc0c0); + 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_rs690_config *cfg = + (struct southbridge_amd_rs690_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 rs690_gfx_init(device_t nb_dev, device_t dev, u32 port) +{ + u16 reg16; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + + printk(BIOS_INFO, "rs690_gfx_init, nb_dev=0x%p, dev=0x%p, port=0x%x.\n", + nb_dev, dev, port); + + /* step 0, REFCLK_SEL, skip A11 revision */ + set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 9, + cfg->gfx_dev2_dev3 ? 1 << 9 : 0 << 9); + printk(BIOS_INFO, "rs690_gfx_init step0.\n"); + + /* step 1, lane reversal (only need if CMOS option is enabled) */ + if (cfg->gfx_lane_reversal) { + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); + if (cfg->gfx_dual_slot) + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); + } + printk(BIOS_INFO, "rs690_gfx_init step1.\n"); + + /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ + /* AMD calls the configuration CrossFire */ + if (cfg->gfx_dual_slot) + set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); + printk(BIOS_INFO, "rs690_gfx_init step2.\n"); + + /* step 2, TMDS, (only need if CMOS option is enabled) */ + if (cfg->gfx_tmds) { + } + + /* step 3, GFX overclocking, (only need if CMOS option is enabled) */ + /* skip */ + + /* step 4, reset the GFX link */ + /* step 4.1 asserts both calibration reset and global reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); + + /* step 4.2 de-asserts calibration reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 14, 0 << 14); + + /* step 4.3 wait for at least 200us */ + udelay(200); + + /* step 4.4 de-asserts global reset */ + set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 15, 0 << 15); + + /* step 4.5 asserts both calibration reset and global reset */ + /* a weird step in RPR, don't do that */ + /* set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); */ + + /* step 4.6 bring external GFX device out of reset, wait for 1ms */ + mdelay(1); + printk(BIOS_INFO, "rs690_gfx_init step4.\n"); + + /* step 5 program PCIE memory mapped configuration space */ + /* done by enable_pci_bar3() before */ + + /* step 6 SBIOS compile flags */ + if (cfg->gfx_tmds) { + /* step 6.2.2 Clock-Muxing Control */ + /* step 6.2.2.1 */ + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 16, 1 << 16); + + /* step 6.2.2.2 */ + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 8, 1 << 8); + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 10, 1 << 10); + + /* step 6.2.2.3 */ + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 26, 1 << 26); + + /* step 6.2.3 Lane-Muxing Control */ + /* step 6.2.3.1 */ + set_nbmisc_enable_bits(nb_dev, 0x37, 0x3 << 8, 0x2 << 8); + + /* step 6.2.4 Received Data Control */ + /* step 6.2.4.1 */ + set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 16, 0x2 << 16); + + /* step 6.2.4.2 */ + set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 18, 0x3 << 18); + + /* step 6.2.4.3 */ + set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 20, 0x0 << 20); + + /* step 6.2.4.4 */ + set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 22, 0x1 << 22); + + /* step 6.2.5 PLL Power Down Control */ + /* step 6.2.5.1 */ + set_nbmisc_enable_bits(nb_dev, 0x35, 0x3 << 6, 0x0 << 6); + + /* step 6.2.6 Driving Strength Control */ + /* step 6.2.6.1 */ + set_nbmisc_enable_bits(nb_dev, 0x34, 0x1 << 24, 0x0 << 24); + + /* step 6.2.6.2 */ + set_nbmisc_enable_bits(nb_dev, 0x35, 0x3 << 2, 0x3 << 2); + } + + printk(BIOS_INFO, "rs690_gfx_init step6.\n"); + + /* 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_INFO, "rs690_gfx_init step7.\n"); + return; + } + + /* step 8 common initialization */ + /* step 8.1 sets RCB timeout to be 25ms */ + set_pcie_enable_bits(dev, 0x70, 7 << 16, 3 << 16); + printk(BIOS_INFO, "rs690_gfx_init step8.1.\n"); + + /* step 8.2 disables slave ordering logic */ + set_pcie_enable_bits(nb_dev, 0x20, 1 << 8, 1 << 8); + printk(BIOS_INFO, "rs690_gfx_init step8.2.\n"); + + /* step 8.3 sets DMA payload size to 64 bytes */ + set_pcie_enable_bits(nb_dev, 0x10, 7 << 10, 4 << 10); + printk(BIOS_INFO, "rs690_gfx_init step8.3.\n"); + + /* step 8.4 if the LTSSM could not see all 8 TS1 during Polling Active, it can still + * time out and go back to Detect Idle.*/ + set_pcie_enable_bits(dev, 0x02, 1 << 14, 1 << 14); + printk(BIOS_INFO, "rs690_gfx_init step8.4.\n"); + + /* step 8.5 shortens the enumeration timer */ + set_pcie_enable_bits(dev, 0x70, 1 << 19, 1 << 19); + printk(BIOS_INFO, "rs690_gfx_init step8.5.\n"); + + /* step 8.6 blocks DMA traffic during C3 state */ + set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); + printk(BIOS_INFO, "rs690_gfx_init step8.6.\n"); + + /* step 8.7 Do not gate the electrical idle form the PHY + * step 8.8 Enables the escape from L1L23 */ + set_pcie_enable_bits(dev, 0xa0, 3 << 30, 3 << 30); + printk(BIOS_INFO, "rs690_gfx_init step8.8.\n"); + + /* step 8.9 Setting this register to 0x1 will workaround a PCI Compliance failure reported by Vista DTM. + * SLOT_IMPLEMENTED@PCIE_CAP */ + reg16 = pci_read_config16(dev, 0x5a); + reg16 |= 0x100; + pci_write_config16(dev, 0x5a, reg16); + printk(BIOS_INFO, "rs690_gfx_init step8.9.\n"); + + /* step 8.10 Setting this register to 0x1 will hide the Advanced Error Rporting Capabilities in the PCIE Brider. + * This will workaround several failures reported by the PCI Compliance test under Vista DTM. */ + set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 31, 0 << 31); + printk(BIOS_INFO, "rs690_gfx_init step8.10.\n"); + + /* step 8.11 Sets REGS_DLP_IGNORE_IN_L1_EN to ignore DLLPs during L1 so that txclk can be turned off. */ + set_pcie_enable_bits(nb_dev, 0x02, 1 << 0, 1 << 0); + printk(BIOS_INFO, "rs690_gfx_init step8.11.\n"); + + /* step 8.12 Sets REGS_LC_DONT_GO_TO_L0S_IF_L1_ARMED to prevent lc to go to from L0 to Rcv_L0s if L1 is armed. */ + set_pcie_enable_bits(nb_dev, 0x02, 1 << 6, 1 << 6); + printk(BIOS_INFO, "rs690_gfx_init step8.12.\n"); + + /* step 8.13 Sets CMGOOD_OVERRIDE. */ + set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17); + printk(BIOS_INFO, "rs690_gfx_init step8.13.\n"); + + /* step 9 Enable TLP Flushing, for non-AMD GFX devices and Hot-Plug devices only. */ + /* skip */ + + /* step 10 Optional Features, only needed if CMOS option is enabled. */ + /* step 10.a: L0s */ + /* enabling L0s in the RS690 GFX port(s) */ + set_pcie_enable_bits(nb_dev, 0xF9, 3 << 13, 2 << 13); + set_pcie_enable_bits(dev, 0xA0, 0xf << 8, 8 << 8); + reg16 = pci_read_config16(dev, 0x68); + reg16 |= 1 << 0; + /* L0s is intended as a power saving state */ + /* pci_write_config16(dev, 0x68, reg16); */ + + /* enabling L0s in the External GFX Device(s) */ + + /* step 10.b: active state power management (ASPM L1) */ + /* TO DO */ + + /* step 10.c: turning off PLL During L1/L23 */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 3, 1 << 3); + set_pcie_enable_bits(nb_dev, 0x40, 1 << 9, 1 << 9); + + /* step 10.d: TXCLK clock gating */ + set_nbmisc_enable_bits(nb_dev, 0x7, 3, 3); + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 22, 1 << 22); + set_pcie_enable_bits(nb_dev, 0x11, 0xf << 4, 0xc << 4); + + /* step 10.e: LCLK clock gating, done in rs690_config_misc_clk() */ + + /* step 11 Poll GPIO to determine whether it is single-port or dual-port configuration. + * While details will be added later in the document, for now assue the single-port configuration. */ + /* skip */ + + /* Single-port/Dual-port configureation. */ + switch (cfg->gfx_dual_slot) { + case 0: + single_port_configuration(nb_dev, dev); + break; + case 1: + dual_port_configuration(nb_dev, dev); + break; + default: + printk(BIOS_INFO, "Incorrect configuration of external gfx slot.\n"); + break; + } +} diff --git a/src/southbridge/amd/rs690/ht.c b/src/southbridge/amd/rs690/ht.c new file mode 100644 index 0000000000..26824b5322 --- /dev/null +++ b/src/southbridge/amd/rs690/ht.c @@ -0,0 +1,90 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 "rs690.h" + +/* for UMA internal graphics */ +void avoid_lpc_dma_deadlock(device_t nb_dev, device_t sb_dev) +{ + device_t k8_f0; + u8 reg; + + k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); + set_nbcfg_enable_bits(k8_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 rs690_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_ATI, + .device = PCI_DEVICE_ID_ATI_RS690_HT, +}; diff --git a/src/southbridge/amd/rs690/pcie.c b/src/southbridge/amd/rs690/pcie.c new file mode 100644 index 0000000000..f02e0d73b4 --- /dev/null +++ b/src/southbridge/amd/rs690/pcie.c @@ -0,0 +1,401 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008 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 "rs690.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_rs690_config *cfg = + (struct southbridge_amd_rs690_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))) { + } + + if (!cfg->gfx_tmds){ + /* 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; + } + } +} + +#ifdef UNUSED_CODE +static void pcie_init(struct device *dev) +{ + /* Enable pci error detecting */ + u32 dword; + + printk(BIOS_DEBUG, "pcie_init in rs690_pcie.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); +} +#endif + +/********************************************************************** +**********************************************************************/ +static void switching_gpp_configurations(device_t nb_dev, device_t sb_dev) +{ + u32 reg; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + + /* 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); + + /* sets desired GPPSB configurations, bit4-7 */ + reg = nbmisc_read_index(nb_dev, 0x67); + reg &= 0xffffff0f; /* clean */ + reg |= cfg->gpp_configuration << 4; + nbmisc_write_index(nb_dev, 0x67, reg); + + /* 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); + + /* delay 1ms */ + mdelay(1); + + /* 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); + + /* 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); +} + +/***************************************************************** +* The rs690 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 rs690_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"); + set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3. */ + pci_write_config32(nb_dev, 0x1C, 0); /* clear BAR3 address */ + 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-8 +*****************************************/ +void rs690_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) +{ + u8 reg8; + u16 reg16; + device_t sb_dev; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_config *)nb_dev->chip_info; + printk(BIOS_DEBUG, "gpp_sb_init nb_dev=0x%p, dev=0x%p, port=0x%x\n", nb_dev, dev, port); + + /* init GPP core */ + set_pcie_enable_bits(nb_dev, 0x20 | PCIE_CORE_INDEX_GPPSB, 1 << 8, + 1 << 8); + /* PCIE initialization 5.10.2: rpr 2.12*/ + set_pcie_enable_bits(nb_dev, 0x02 | PCIE_CORE_INDEX_GPPSB, 1 << 0, 1 << 0); /* no description in datasheet. */ + + /* init GPPSB port */ + /* Sets RCB timeout to be 100ms by setting bits[18:16] to 3 b101 and shortens the enumeration timer by setting bit[19] to 1*/ + set_pcie_enable_bits(dev, 0x70, 0xF << 16, 0xd << 16); + /* PCIE initialization 5.10.2: rpr 2.4 */ + set_pcie_enable_bits(dev, 0x02, ~0xffffffff, 1 << 14); + /* Do not gate the electrical idle from the PHY and enables the escape from L1L23 */ + set_pcie_enable_bits(dev, 0xA0, ~0xffffffbf, (3 << 30) | (3 << 12) | (3 << 4)); + /* PCIE initialization 5.10.2: rpr 2.13 */ + set_pcie_enable_bits(dev, 0x02, ~0xffffffff, 1 << 6); + + /* SLOT_IMPLEMENTED in pcieConfig space */ + reg8 = pci_read_config8(dev, 0x5b); + reg8 |= 1 << 0; + pci_write_config8(dev, 0x5b, reg8); + + reg16 = pci_read_config16(dev, 0x5a); + reg16 |= 0x100; + pci_write_config16(dev, 0x5a, reg16); + nbmisc_write_index(nb_dev, 0x34, 0); + + /* 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 */ + set_pcie_enable_bits(nb_dev, 0x20 | PCIE_CORE_INDEX_GPPSB, 1 << 11, 1 << 11); + + /* step 5a: Training for GPP devices */ + /* init GPP */ + switch (port) { + case 4: /* GPP */ + case 5: + case 6: + case 7: + /* 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); + + /* step 5b: GFX devices in a GPP slot */ + + /* step 6a: VCI */ + sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0)); + if (port == 8) { + /* The code below between #if and #endif causes a hang on HDA init. + * So we skip it. */ +#if 0 + /* Clear bits 7:1 */ + pci_ext_write_config32(nb_dev, sb_dev, 0x114, 0x3f << 1, 0 << 1); + /* Maps Traffic Class 1-7 to VC1 */ + pci_ext_write_config32(nb_dev, sb_dev, 0x120, 0x7f << 1, 0x7f << 1); + /* Assigns VC ID to 1 */ + pci_ext_write_config32(nb_dev, sb_dev, 0x120, 7 << 24, 1 << 24); + /* Enables VC1 */ + pci_ext_write_config32(nb_dev, sb_dev, 0x120, 1 << 31, 1 << 31); + + do { + reg16 = pci_ext_read_config32(nb_dev, sb_dev, 0x124); + reg16 &= 0x2; + } while (reg16); /*bit[1] = 0 means VC1 flow control initialization is successful */ +#endif + } + + /* step 6b: L0s for the southbridge link */ + /* To enalbe L0s in the southbridage*/ + + /* step 6c: L0s for the GPP link(s) */ + /* To eable L0s in the RS690 for the GPP port(s) */ + set_pcie_enable_bits(nb_dev, 0xf9, 3 << 13, 2 << 13); + set_pcie_enable_bits(dev, 0xa0, 0xf << 8, 0x9 << 8); + reg16 = pci_read_config16(dev, 0x68); + reg16 |= 1 << 0; + pci_write_config16(dev, 0x68, reg16); + + /* step 6d: ASPM L1 for the southbridge link */ + /* To enalbe L1s in the southbridage*/ + + /* step 6e: ASPM L1 for GPP link(s) */; + set_pcie_enable_bits(nb_dev, 0xf9, 3 << 13, 2 << 13); + set_pcie_enable_bits(dev, 0xa0, 3 << 12, 3 << 12); + set_pcie_enable_bits(dev, 0xa0, 0xf << 4, 3 << 4); + reg16 = pci_read_config16(dev, 0x68); + reg16 &= ~0xff; + reg16 |= 1 << 1; + pci_write_config16(dev, 0x68, reg16); + + /* step 6f: Turning off PLL during L1/L23 */ + set_pcie_enable_bits(nb_dev, 0x40, 1 << 3, 1 << 3); + set_pcie_enable_bits(nb_dev, 0x40, 1 << 9, 1 << 9); + + /* step 6g: TXCLK clock gating */ + set_nbmisc_enable_bits(nb_dev, 0x7, 3 << 4, 3 << 4); + set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 22, 1 << 22); + set_pcie_enable_bits(nb_dev, 0x11, 0xf << 4, 0xc << 4); + + /* step 6h: LCLK clock gating, done in rs690_config_misc_clk() */ +} + +/***************************************** +* Compliant with CIM_33's PCIEConfigureGPPCore +*****************************************/ +void config_gpp_core(device_t nb_dev, device_t sb_dev) +{ + u32 reg; + struct southbridge_amd_rs690_config *cfg = + (struct southbridge_amd_rs690_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->gpp_configuration != ((reg >> 4) & 0xf)) + switching_gpp_configurations(nb_dev, sb_dev); + ValidatePortEn(nb_dev); +} + +#ifdef UNUSED_CODE +/***************************************** +* Compliant with CIM_33's PCIEMiscClkProg +*****************************************/ +void pcie_config_misc_clk(device_t nb_dev) +{ + u32 reg; + struct bus pbus; /* fake bus for dev0 fun1 */ + + reg = pci_read_config32(nb_dev, 0x4c); + reg |= 1 << 0; + pci_write_config32(nb_dev, 0x4c, reg); + + if (AtiPcieCfg.Config & PCIE_GFX_CLK_GATING) { + /* TXCLK Clock Gating */ + set_nbmisc_enable_bits(nb_dev, 0x07, 3 << 0, 3 << 0); + set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 22, 1 << 22); + set_pcie_enable_bits(nb_dev, 0x11 | PCIE_CORE_INDEX_GFX, (3 << 6) | (~0xf), 3 << 6); + + /* LCLK Clock Gating */ + reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94); + reg &= ~(1 << 16); + pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg); + } + + if (AtiPcieCfg.Config & PCIE_GPP_CLK_GATING) { + /* TXCLK Clock Gating */ + set_nbmisc_enable_bits(nb_dev, 0x07, 3 << 4, 3 << 4); + set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 22, 1 << 22); + set_pcie_enable_bits(nb_dev, 0x11 | PCIE_CORE_INDEX_GPPSB, (3 << 6) | (~0xf), 3 << 6); + + /* LCLK Clock Gating */ + reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94); + reg &= ~(1 << 24); + pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg); + } + + reg = pci_read_config32(nb_dev, 0x4c); + reg &= ~(1 << 0); + pci_write_config32(nb_dev, 0x4c, reg); +} +#endif diff --git a/src/southbridge/amd/rs690/rs690_cmn.c b/src/southbridge/amd/rs690/rs690_cmn.c deleted file mode 100644 index 5e06d4f9d8..0000000000 --- a/src/southbridge/amd/rs690/rs690_cmn.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 "rs690.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: /* GPP, bit20-24 */ - case 5: - case 6: - case 7: - set_nbmisc_enable_bits(nb_dev, PCIE_LINK_CFG, - 1 << (port + 17), 0 << (port + 17)); - 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; - int8_t current, res = 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 0x07: /* device is in compliance state (training sequence is doen). Move to train the next device */ - res = 1; /* TODO: CIM sets it to 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 rs690_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); -} - diff --git a/src/southbridge/amd/rs690/rs690_early_setup.c b/src/southbridge/amd/rs690/rs690_early_setup.c deleted file mode 100644 index f29d136791..0000000000 --- a/src/southbridge/amd/rs690/rs690_early_setup.c +++ /dev/null @@ -1,484 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - * Copyright (C) 2008 Carl-Daniel Hailfinger - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#define NBHTIU_INDEX 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); - } -} - -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); - } -} - -/* -* Compliant with CIM_33's ATINB_PrepareInit -*/ -static void get_cpu_rev(void) -{ - u32 eax, ebx, ecx, edx; - __asm__ volatile ("cpuid":"=a" (eax), "=b"(ebx), "=c"(ecx), "=d"(edx) - :"0"(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 - printk(BIOS_INFO, "CPU Rev is K8_10.\n"); -} - -static u8 get_nb_rev(device_t nb_dev) -{ - u32 reg; - reg = pci_read_config32(nb_dev, 0x00); - if (0x7911 == (reg >> 16)) - return 7; - reg = pci_read_config8(nb_dev, 0x89); /* copy from CIM, can't find in doc */ - if (reg & 0x2) /* check bit1 */ - return 7; - if (reg & 0x1) /* check bit0 */ - return 6; - else - return 5; -} - -/***************************************** -* Compliant with CIM_33's ATINB_HTInit -* Init HT link speed/width for rs690 -- k8 link -*****************************************/ -static void rs690_htinit(void) -{ - /* - * About HT, it has been done in enumerate_ht_chain(). - */ - device_t k8_f0, rs690_f0; - u32 reg; - u8 reg8; - u8 k8_ht_freq; - - k8_f0 = PCI_DEV(0, 0x18, 0); - /************************ - * get k8's ht freq, in k8'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. - * 0000b = 200Mhz - * 0010b = 400Mhz - * 0100b = 600Mhz - * 0101b = 800Mhz - * 0110b = 1Ghz - * 1111b = 1Ghz - ************************/ - reg = pci_read_config32(k8_f0, 0x88); - k8_ht_freq = (reg & 0xf00) >> 8; - printk(BIOS_SPEW, "rs690_htinit k8_ht_freq=%x.\n", k8_ht_freq); - rs690_f0 = PCI_DEV(0, 0, 0); - reg8 = pci_read_config8(rs690_f0, 0x9c); - printk(BIOS_SPEW, "rs690_htinit NB_CFG_Q_F1000_800=%x\n", reg8); - /* For 1000 MHz HT, NB_CFG_Q_F1000_800 bit 0 MUST be set. - * For any other HT frequency, NB_CFG_Q_F1000_800 bit 0 MUST NOT be set. - */ - if (((k8_ht_freq == 0x6) || (k8_ht_freq == 0xf)) && (!(reg8 & 0x1))) { - printk(BIOS_INFO, "rs690_htinit setting bit 0 in NB_CFG_Q_F1000_800 to use 1 GHz HT\n"); - reg8 |= 0x1; - pci_write_config8(rs690_f0, 0x9c, reg8); - } else if ((k8_ht_freq != 0x6) && (k8_ht_freq != 0xf) && (reg8 & 0x1)) { - printk(BIOS_INFO, "rs690_htinit clearing bit 0 in NB_CFG_Q_F1000_800 to not use 1 GHz HT\n"); - reg8 &= ~0x1; - pci_write_config8(rs690_f0, 0x9c, reg8); - } -} - -/******************************************************* -* Optimize k8 with UMA. -* See BKDG_NPT_0F guide for details. -* The processor node is addressed by its Node ID on the HT link and can be -* accessed with a device number in the PCI configuration space on Bus0. -* The Node ID 0 is mapped to Device 24 (0x18), the Node ID 1 is mapped -* to Device 25, and so on. -* The processor implements configuration registers in PCI configuration -* space using the following four headers -* Function0: HT technology configuration -* Function1: Address map configuration -* Function2: DRAM and HT technology Trace mode configuration -* Function3: Miscellaneous configuration -*******************************************************/ -static void k8_optimization(void) -{ - device_t k8_f0, k8_f2, k8_f3; - msr_t msr; - - printk(BIOS_INFO, "k8_optimization()\n"); - k8_f0 = PCI_DEV(0, 0x18, 0); - k8_f2 = PCI_DEV(0, 0x18, 2); - k8_f3 = PCI_DEV(0, 0x18, 3); - - pci_write_config32(k8_f0, 0x90, 0x01700178); /* CIM NPT_Optimization */ - set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 28, 0 << 28); - set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 26 | 1 << 27, - 1 << 26 | 1 << 27); - set_nbcfg_enable_bits(k8_f0, 0x68, 1 << 11, 1 << 11); - set_nbcfg_enable_bits(k8_f0, 0x84, 1 << 11 | 1 << 13 | 1 << 15, 1 << 11 | 1 << 13 | 1 << 15); /* TODO */ - - pci_write_config32(k8_f3, 0x70, 0x51320111); /* CIM NPT_Optimization */ - pci_write_config32(k8_f3, 0x74, 0x50304021); - pci_write_config32(k8_f3, 0x78, 0x08002A00); - if (pci_read_config32(k8_f3, 0xE8) & 0x3<<12) - pci_write_config32(k8_f3, 0x7C, 0x0000211B); /* dual core */ - else - pci_write_config32(k8_f3, 0x7C, 0x0000211C); /* 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, 1 << 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); -} - -/***************************************** -* Compliant with CIM_33's ATINB_PCICFG_POR_TABLE -*****************************************/ -static void rs690_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[10:9] = 0x3 Enables Gfx Debug BAR, - * force this BAR as mem type in rs690_gfx.c */ - set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x03); - -} - -/***************************************** -* Compliant with CIM_33's ATINB_MCIndex_POR_TABLE -*****************************************/ -static void rs690_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); -} - -/***************************************** -* Compliant with CIM_33's ATINB_MISCIND_POR_TABLE -* Compliant with CIM_33's MISC_INIT_TBL -*****************************************/ -static void rs690_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); - - /* Compliant with CIM_33's MISC_INIT_TBL, except Hide NB_BAR3_PCIE - * 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, 0x00, 1 << 7, 1 << 7); - set_nbmisc_enable_bits(nb_dev, 0x07, 0x000000f0, 0x30); - /* Disable bus-master trigger event from SB and Enable set_slot_power message to SB */ - set_nbmisc_enable_bits(nb_dev, 0x0B, 0xffffffff, 0x500180); -} - -/***************************************** -* Compliant with CIM_33's ATINB_HTIUNBIND_POR_TABLE -*****************************************/ -static void rs690_por_htiu_index_init(device_t nb_dev) -{ - /* 0xBC: - * Enables GSM mode for C1e or C3 with pop-up - * Prevents AllowLdtStop from being asserted during HT link recovery - * Allows FID cycles to be serviced faster. Needed for RS690 A12. No harm in RS690 A11 */ - set_htiu_enable_bits(nb_dev, 0x05, ~0xffffffff, 0x0BC); - /* 0x4203A202: - * Enables writes to pass in-progress reads - * Enables streaming of CPU writes - * Enables extended write buffer for CPU writes - * Enables additional response buffers - * Enables special reads to pass writes - * Enables decoding of C1e/C3 and FID cycles - * Enables HTIU-display handshake bypass. - * Enables tagging fix */ - set_htiu_enable_bits(nb_dev, 0x06, ~0xFFFFFFFE, 0x4203A202); - - /* Enables byte-write optimization for IOC requests - * Disables delaying STPCLK de-assert during FID sequence. Needed when enhanced UMA arbitration is used. - * Disables upstream system-management delay */ - set_htiu_enable_bits(nb_dev, 0x07, ~0xFFFFFFF9, 0x001); - - /* HTIUNBIND 0x16 [1] = 0x1 Enable crc decoding fix */ - set_htiu_enable_bits(nb_dev, 0x16, ~0xFFFFFFFF, 0x2); -} - -/***************************************** -* Compliant with CIM_33's ATINB_POR_INIT_JMPDI -* Configure RS690 registers to power-on default RPR. -* POR: Power On Reset -* RPR: Register Programming Requirements -*****************************************/ -static void rs690_por_init(device_t nb_dev) -{ - printk(BIOS_INFO, "rs690_por_init\n"); - /* ATINB_PCICFG_POR_TABLE, initialize the values for rs690 PCI Config registers */ - rs690_por_pcicfg_init(nb_dev); - - /* ATINB_MCIND_POR_TABLE */ - rs690_por_mc_index_init(nb_dev); - - /* ATINB_MISCIND_POR_TABLE */ - rs690_por_misc_index_init(nb_dev); - - /* ATINB_HTIUNBIND_POR_TABLE */ - rs690_por_htiu_index_init(nb_dev); - - /* ATINB_CLKCFG_PORT_TABLE */ - /* rs690 A11 SB Link full swing? */ -} - -/* enable CFG access to Dev8, which is the SB P2P Bridge */ -static void enable_rs690_dev8(void) -{ - set_nbmisc_enable_bits(PCI_DEV(0, 0, 0), 0x00, 1 << 6, 1 << 6); -} - - - -/* -* Compliant with CIM_33's AtiNBInitEarlyPost (AtiInitNBBeforePCIInit). -*/ -static void rs690_before_pci_init(void) -{ -} - -/* -* The calling sequence is same as CIM. -*/ -static void rs690_early_setup(void) -{ - device_t nb_dev = PCI_DEV(0, 0, 0); - printk(BIOS_INFO, "rs690_early_setup()\n"); - - /*ATINB_PrepareInit */ - get_cpu_rev(); - switch (get_nb_rev(nb_dev)) { /* PCIEMiscInit */ - case 5: - printk(BIOS_INFO, "NB Revision is A11.\n"); - break; - case 6: - printk(BIOS_INFO, "NB Revision is A12.\n"); - break; - case 7: - printk(BIOS_INFO, "NB Revision is A21.\n"); - break; - } - - k8_optimization(); - rs690_por_init(nb_dev); -} diff --git a/src/southbridge/amd/rs690/rs690_gfx.c b/src/southbridge/amd/rs690/rs690_gfx.c deleted file mode 100644 index c55f2bc3d3..0000000000 --- a/src/southbridge/amd/rs690/rs690_gfx.c +++ /dev/null @@ -1,625 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 rs690 internal graphics device - * device id of internal grphics: - * RS690M/T: 0x791f - * RS690: 0x791e - */ -#include -#include -#include -#include -#include -#include -#include "rs690.h" - -#define CLK_CNTL_INDEX 0x8 -#define CLK_CNTL_DATA 0xC - -#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_INFO, "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 rs690_gfx_read_resources(device_t dev) -{ - printk(BIOS_INFO, "rs690_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); -} - -static void internal_gfx_pci_dev_init(struct device *dev) -{ - u16 deviceid, vendorid; - deviceid = pci_read_config16(dev, PCI_DEVICE_ID); - vendorid = pci_read_config16(dev, PCI_VENDOR_ID); - printk(BIOS_INFO, "internal_gfx_pci_dev_init device=%x, vendor=%x.\n", - deviceid, vendorid); - - 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 RS690 and CPU to enable the internal GFX. -* Please refer to CIM source code and BKDG. -*/ -static void rs690_internal_gfx_enable(device_t dev) -{ - u32 l_dword; - int i; - device_t k8_f0 = 0, k8_f2 = 0; - device_t nb_dev = dev_find_slot(0, 0); - - printk(BIOS_INFO, "rs690_internal_gfx_enable dev=0x%p, nb_dev=0x%p.\n", dev, - nb_dev); - - /* set APERTURE_SIZE, 128M. */ - l_dword = pci_read_config32(nb_dev, 0x8c); - printk(BIOS_INFO, "nb_dev, 0x8c=0x%x\n", l_dword); - l_dword &= 0xffffff8f; - pci_write_config32(nb_dev, 0x8c, l_dword); - - /* set TOM */ - rs690_set_tom(nb_dev); - - /* LPC DMA Deadlock workaround? */ - k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - l_dword = pci_read_config32(k8_f0, 0x68); - l_dword &= ~(1 << 22); - l_dword |= (1 << 21); - pci_write_config32(k8_f0, 0x68, l_dword); - - /* Enable 64bit mode. */ - set_nbmc_enable_bits(nb_dev, 0x5f, 0, 1 << 9); - set_nbmc_enable_bits(nb_dev, 0xb0, 0, 1 << 8); - - /* 64bit Latency. */ - set_nbmc_enable_bits(nb_dev, 0x5f, 0x7c00, 0x800); - - /* UMA dual channel control register. */ - nbmc_write_index(nb_dev, 0x86, 0x3d); - - /* check the setting later!! */ - set_htiu_enable_bits(nb_dev, 0x07, 1 << 7, 0); - - /* UMA mode, powerdown memory PLL. */ - set_nbmc_enable_bits(nb_dev, 0x74, 0, 1 << 31); - - /* Copy CPU DDR Controller to NB MC. */ - /* Why K8_MC_REG80 is special? */ - k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); - for (i = 0; i <= (0x80 - 0x40) / 4; i++) { - l_dword = pci_read_config32(k8_f2, 0x40 + i * 4); - nbmc_write_index(nb_dev, 0x63 + i, l_dword); - } - - /* Set K8 MC for UMA, Family F. */ - l_dword = pci_read_config32(k8_f2, 0xa0); - l_dword |= 0x2c; - pci_write_config32(k8_f2, 0xa0, l_dword); - l_dword = pci_read_config32(k8_f2, 0x94); - l_dword &= 0xf0ffffff; - l_dword |= 0x07000000; - pci_write_config32(k8_f2, 0x94, l_dword); - - /* set FB size and location. */ - nbmc_write_index(nb_dev, 0x1b, 0x00); - l_dword = nbmc_read_index(nb_dev, 0x1c); - l_dword &= 0xffff0; - l_dword |= 0x400 << 20; - l_dword |= 0x4; - nbmc_write_index(nb_dev, 0x1c, l_dword); - l_dword = nbmc_read_index(nb_dev, 0x1d); - l_dword &= 0xfffff000; - l_dword |= 0x0400; - nbmc_write_index(nb_dev, 0x1d, l_dword); - nbmc_write_index(nb_dev, 0x100, 0x3fff3800); - - /* Program MC table. */ - set_nbmc_enable_bits(nb_dev, 0x00, 0, 1 << 31); - l_dword = nbmc_read_index(nb_dev, 0x91); - l_dword |= 0x5; - nbmc_write_index(nb_dev, 0x91, l_dword); - set_nbmc_enable_bits(nb_dev, 0xb1, 0, 1 << 6); - set_nbmc_enable_bits(nb_dev, 0xc3, 0, 1); - - /* TODO: the optimization of voltage and frequency */ -} - -static struct pci_operations lops_pci = { - .set_subsystem = pci_dev_set_subsystem, -}; - -static struct device_operations pcie_ops = { - .read_resources = rs690_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. rs690_gfx_init, */ - .scan_bus = 0, - .enable = rs690_internal_gfx_enable, - .ops_pci = &lops_pci, -}; - -/* - * The dev id of 690G is 791E, while the id of 690M, 690T is 791F. - * We should list both of them here. - * */ -static const struct pci_driver pcie_driver_690t __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS690MT_INT_GFX, -}; - -static const struct pci_driver pcie_driver_690 __pci_driver = { - .ops = &pcie_ops, - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_RS690_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_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - - printk(BIOS_INFO, "rs690_gfx_init single_port_configuration.\n"); - - /* step 12 training, releases hold training for GFX port 0 (device 2) */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0<<4); - PcieReleasePortTraining(nb_dev, dev, 2); - result = PcieTrainPort(nb_dev, dev, 2); - printk(BIOS_INFO, "rs690_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 */ - - 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 ? 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_INFO, "rs690_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, 0 << 19); - printk(BIOS_INFO, "rs690_gfx_init single_port_configuration step14.\n"); -} - -/* step 15 ~ step 18 from rpr */ -static void dual_port_configuration(device_t nb_dev, device_t dev) -{ - u8 result, width; - u32 reg32; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - - /* step 15: Training for Device 2 */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 4, 0 << 4); - /* Releases hold training for GFX port 0 (device 2) */ - PcieReleasePortTraining(nb_dev, dev, 2); - /* PCIE Link Training Sequence */ - result = PcieTrainPort(nb_dev, dev, 2); - - /* step 16: Power Down Control for Device 2 */ - /* step 16.a Link Training was NOT successful */ - if (!result) { - /* Powers down all lanes for port A */ - nbpcie_ind_write_index(nb_dev, 0x65, 0x0f0f); - } 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; - } - } - - /* step 17: Training for Device 3 */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 5, 0 << 5); - /* Releases hold training for GFX port 0 (device 3) */ - PcieReleasePortTraining(nb_dev, dev, 3); - /* PCIE Link Training Sequence */ - result = PcieTrainPort(nb_dev, dev, 3); - - /*step 18: Power Down Control for Device 3 */ - /* step 18.a Link Training was NOT successful */ - if (!result) { - /* Powers down all lanes for port B and PLL1 */ - nbpcie_ind_write_index(nb_dev, 0x65, 0xccf0f0); - } else { /* step 18.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 ? 0x7070 : 0xe0e0); - break; - case 4: - nbpcie_ind_write_index(nb_dev, 0x65, - cfg->gfx_lane_reversal ? 0x3030 : 0xc0c0); - 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_rs690_config *cfg = - (struct southbridge_amd_rs690_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 rs690_gfx_init(device_t nb_dev, device_t dev, u32 port) -{ - u16 reg16; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - - printk(BIOS_INFO, "rs690_gfx_init, nb_dev=0x%p, dev=0x%p, port=0x%x.\n", - nb_dev, dev, port); - - /* step 0, REFCLK_SEL, skip A11 revision */ - set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 9, - cfg->gfx_dev2_dev3 ? 1 << 9 : 0 << 9); - printk(BIOS_INFO, "rs690_gfx_init step0.\n"); - - /* step 1, lane reversal (only need if CMOS option is enabled) */ - if (cfg->gfx_lane_reversal) { - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 2, 1 << 2); - if (cfg->gfx_dual_slot) - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 3, 1 << 3); - } - printk(BIOS_INFO, "rs690_gfx_init step1.\n"); - - /* step 1.1, dual-slot gfx configuration (only need if CMOS option is enabled) */ - /* AMD calls the configuration CrossFire */ - if (cfg->gfx_dual_slot) - set_nbmisc_enable_bits(nb_dev, 0x0, 0xf << 8, 5 << 8); - printk(BIOS_INFO, "rs690_gfx_init step2.\n"); - - /* step 2, TMDS, (only need if CMOS option is enabled) */ - if (cfg->gfx_tmds) { - } - - /* step 3, GFX overclocking, (only need if CMOS option is enabled) */ - /* skip */ - - /* step 4, reset the GFX link */ - /* step 4.1 asserts both calibration reset and global reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); - - /* step 4.2 de-asserts calibration reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 14, 0 << 14); - - /* step 4.3 wait for at least 200us */ - udelay(200); - - /* step 4.4 de-asserts global reset */ - set_nbmisc_enable_bits(nb_dev, 0x8, 1 << 15, 0 << 15); - - /* step 4.5 asserts both calibration reset and global reset */ - /* a weird step in RPR, don't do that */ - /* set_nbmisc_enable_bits(nb_dev, 0x8, 0x3 << 14, 0x3 << 14); */ - - /* step 4.6 bring external GFX device out of reset, wait for 1ms */ - mdelay(1); - printk(BIOS_INFO, "rs690_gfx_init step4.\n"); - - /* step 5 program PCIE memory mapped configuration space */ - /* done by enable_pci_bar3() before */ - - /* step 6 SBIOS compile flags */ - if (cfg->gfx_tmds) { - /* step 6.2.2 Clock-Muxing Control */ - /* step 6.2.2.1 */ - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 16, 1 << 16); - - /* step 6.2.2.2 */ - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 8, 1 << 8); - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 10, 1 << 10); - - /* step 6.2.2.3 */ - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 26, 1 << 26); - - /* step 6.2.3 Lane-Muxing Control */ - /* step 6.2.3.1 */ - set_nbmisc_enable_bits(nb_dev, 0x37, 0x3 << 8, 0x2 << 8); - - /* step 6.2.4 Received Data Control */ - /* step 6.2.4.1 */ - set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 16, 0x2 << 16); - - /* step 6.2.4.2 */ - set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 18, 0x3 << 18); - - /* step 6.2.4.3 */ - set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 20, 0x0 << 20); - - /* step 6.2.4.4 */ - set_pcie_enable_bits(nb_dev, 0x40, 0x3 << 22, 0x1 << 22); - - /* step 6.2.5 PLL Power Down Control */ - /* step 6.2.5.1 */ - set_nbmisc_enable_bits(nb_dev, 0x35, 0x3 << 6, 0x0 << 6); - - /* step 6.2.6 Driving Strength Control */ - /* step 6.2.6.1 */ - set_nbmisc_enable_bits(nb_dev, 0x34, 0x1 << 24, 0x0 << 24); - - /* step 6.2.6.2 */ - set_nbmisc_enable_bits(nb_dev, 0x35, 0x3 << 2, 0x3 << 2); - } - - printk(BIOS_INFO, "rs690_gfx_init step6.\n"); - - /* 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_INFO, "rs690_gfx_init step7.\n"); - return; - } - - /* step 8 common initialization */ - /* step 8.1 sets RCB timeout to be 25ms */ - set_pcie_enable_bits(dev, 0x70, 7 << 16, 3 << 16); - printk(BIOS_INFO, "rs690_gfx_init step8.1.\n"); - - /* step 8.2 disables slave ordering logic */ - set_pcie_enable_bits(nb_dev, 0x20, 1 << 8, 1 << 8); - printk(BIOS_INFO, "rs690_gfx_init step8.2.\n"); - - /* step 8.3 sets DMA payload size to 64 bytes */ - set_pcie_enable_bits(nb_dev, 0x10, 7 << 10, 4 << 10); - printk(BIOS_INFO, "rs690_gfx_init step8.3.\n"); - - /* step 8.4 if the LTSSM could not see all 8 TS1 during Polling Active, it can still - * time out and go back to Detect Idle.*/ - set_pcie_enable_bits(dev, 0x02, 1 << 14, 1 << 14); - printk(BIOS_INFO, "rs690_gfx_init step8.4.\n"); - - /* step 8.5 shortens the enumeration timer */ - set_pcie_enable_bits(dev, 0x70, 1 << 19, 1 << 19); - printk(BIOS_INFO, "rs690_gfx_init step8.5.\n"); - - /* step 8.6 blocks DMA traffic during C3 state */ - set_pcie_enable_bits(dev, 0x10, 1 << 0, 0 << 0); - printk(BIOS_INFO, "rs690_gfx_init step8.6.\n"); - - /* step 8.7 Do not gate the electrical idle form the PHY - * step 8.8 Enables the escape from L1L23 */ - set_pcie_enable_bits(dev, 0xa0, 3 << 30, 3 << 30); - printk(BIOS_INFO, "rs690_gfx_init step8.8.\n"); - - /* step 8.9 Setting this register to 0x1 will workaround a PCI Compliance failure reported by Vista DTM. - * SLOT_IMPLEMENTED@PCIE_CAP */ - reg16 = pci_read_config16(dev, 0x5a); - reg16 |= 0x100; - pci_write_config16(dev, 0x5a, reg16); - printk(BIOS_INFO, "rs690_gfx_init step8.9.\n"); - - /* step 8.10 Setting this register to 0x1 will hide the Advanced Error Rporting Capabilities in the PCIE Brider. - * This will workaround several failures reported by the PCI Compliance test under Vista DTM. */ - set_nbmisc_enable_bits(nb_dev, 0x33, 1 << 31, 0 << 31); - printk(BIOS_INFO, "rs690_gfx_init step8.10.\n"); - - /* step 8.11 Sets REGS_DLP_IGNORE_IN_L1_EN to ignore DLLPs during L1 so that txclk can be turned off. */ - set_pcie_enable_bits(nb_dev, 0x02, 1 << 0, 1 << 0); - printk(BIOS_INFO, "rs690_gfx_init step8.11.\n"); - - /* step 8.12 Sets REGS_LC_DONT_GO_TO_L0S_IF_L1_ARMED to prevent lc to go to from L0 to Rcv_L0s if L1 is armed. */ - set_pcie_enable_bits(nb_dev, 0x02, 1 << 6, 1 << 6); - printk(BIOS_INFO, "rs690_gfx_init step8.12.\n"); - - /* step 8.13 Sets CMGOOD_OVERRIDE. */ - set_nbmisc_enable_bits(nb_dev, 0x6a, 1 << 17, 1 << 17); - printk(BIOS_INFO, "rs690_gfx_init step8.13.\n"); - - /* step 9 Enable TLP Flushing, for non-AMD GFX devices and Hot-Plug devices only. */ - /* skip */ - - /* step 10 Optional Features, only needed if CMOS option is enabled. */ - /* step 10.a: L0s */ - /* enabling L0s in the RS690 GFX port(s) */ - set_pcie_enable_bits(nb_dev, 0xF9, 3 << 13, 2 << 13); - set_pcie_enable_bits(dev, 0xA0, 0xf << 8, 8 << 8); - reg16 = pci_read_config16(dev, 0x68); - reg16 |= 1 << 0; - /* L0s is intended as a power saving state */ - /* pci_write_config16(dev, 0x68, reg16); */ - - /* enabling L0s in the External GFX Device(s) */ - - /* step 10.b: active state power management (ASPM L1) */ - /* TO DO */ - - /* step 10.c: turning off PLL During L1/L23 */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 3, 1 << 3); - set_pcie_enable_bits(nb_dev, 0x40, 1 << 9, 1 << 9); - - /* step 10.d: TXCLK clock gating */ - set_nbmisc_enable_bits(nb_dev, 0x7, 3, 3); - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 22, 1 << 22); - set_pcie_enable_bits(nb_dev, 0x11, 0xf << 4, 0xc << 4); - - /* step 10.e: LCLK clock gating, done in rs690_config_misc_clk() */ - - /* step 11 Poll GPIO to determine whether it is single-port or dual-port configuration. - * While details will be added later in the document, for now assue the single-port configuration. */ - /* skip */ - - /* Single-port/Dual-port configureation. */ - switch (cfg->gfx_dual_slot) { - case 0: - single_port_configuration(nb_dev, dev); - break; - case 1: - dual_port_configuration(nb_dev, dev); - break; - default: - printk(BIOS_INFO, "Incorrect configuration of external gfx slot.\n"); - break; - } -} diff --git a/src/southbridge/amd/rs690/rs690_ht.c b/src/southbridge/amd/rs690/rs690_ht.c deleted file mode 100644 index 26824b5322..0000000000 --- a/src/southbridge/amd/rs690/rs690_ht.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 "rs690.h" - -/* for UMA internal graphics */ -void avoid_lpc_dma_deadlock(device_t nb_dev, device_t sb_dev) -{ - device_t k8_f0; - u8 reg; - - k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); - set_nbcfg_enable_bits(k8_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 rs690_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_ATI, - .device = PCI_DEVICE_ID_ATI_RS690_HT, -}; diff --git a/src/southbridge/amd/rs690/rs690_pcie.c b/src/southbridge/amd/rs690/rs690_pcie.c deleted file mode 100644 index f02e0d73b4..0000000000 --- a/src/southbridge/amd/rs690/rs690_pcie.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 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 "rs690.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_rs690_config *cfg = - (struct southbridge_amd_rs690_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))) { - } - - if (!cfg->gfx_tmds){ - /* 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; - } - } -} - -#ifdef UNUSED_CODE -static void pcie_init(struct device *dev) -{ - /* Enable pci error detecting */ - u32 dword; - - printk(BIOS_DEBUG, "pcie_init in rs690_pcie.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); -} -#endif - -/********************************************************************** -**********************************************************************/ -static void switching_gpp_configurations(device_t nb_dev, device_t sb_dev) -{ - u32 reg; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - - /* 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); - - /* sets desired GPPSB configurations, bit4-7 */ - reg = nbmisc_read_index(nb_dev, 0x67); - reg &= 0xffffff0f; /* clean */ - reg |= cfg->gpp_configuration << 4; - nbmisc_write_index(nb_dev, 0x67, reg); - - /* 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); - - /* delay 1ms */ - mdelay(1); - - /* 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); - - /* 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); -} - -/***************************************************************** -* The rs690 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 rs690_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"); - set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3. */ - pci_write_config32(nb_dev, 0x1C, 0); /* clear BAR3 address */ - 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-8 -*****************************************/ -void rs690_gpp_sb_init(device_t nb_dev, device_t dev, u32 port) -{ - u8 reg8; - u16 reg16; - device_t sb_dev; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_config *)nb_dev->chip_info; - printk(BIOS_DEBUG, "gpp_sb_init nb_dev=0x%p, dev=0x%p, port=0x%x\n", nb_dev, dev, port); - - /* init GPP core */ - set_pcie_enable_bits(nb_dev, 0x20 | PCIE_CORE_INDEX_GPPSB, 1 << 8, - 1 << 8); - /* PCIE initialization 5.10.2: rpr 2.12*/ - set_pcie_enable_bits(nb_dev, 0x02 | PCIE_CORE_INDEX_GPPSB, 1 << 0, 1 << 0); /* no description in datasheet. */ - - /* init GPPSB port */ - /* Sets RCB timeout to be 100ms by setting bits[18:16] to 3 b101 and shortens the enumeration timer by setting bit[19] to 1*/ - set_pcie_enable_bits(dev, 0x70, 0xF << 16, 0xd << 16); - /* PCIE initialization 5.10.2: rpr 2.4 */ - set_pcie_enable_bits(dev, 0x02, ~0xffffffff, 1 << 14); - /* Do not gate the electrical idle from the PHY and enables the escape from L1L23 */ - set_pcie_enable_bits(dev, 0xA0, ~0xffffffbf, (3 << 30) | (3 << 12) | (3 << 4)); - /* PCIE initialization 5.10.2: rpr 2.13 */ - set_pcie_enable_bits(dev, 0x02, ~0xffffffff, 1 << 6); - - /* SLOT_IMPLEMENTED in pcieConfig space */ - reg8 = pci_read_config8(dev, 0x5b); - reg8 |= 1 << 0; - pci_write_config8(dev, 0x5b, reg8); - - reg16 = pci_read_config16(dev, 0x5a); - reg16 |= 0x100; - pci_write_config16(dev, 0x5a, reg16); - nbmisc_write_index(nb_dev, 0x34, 0); - - /* 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 */ - set_pcie_enable_bits(nb_dev, 0x20 | PCIE_CORE_INDEX_GPPSB, 1 << 11, 1 << 11); - - /* step 5a: Training for GPP devices */ - /* init GPP */ - switch (port) { - case 4: /* GPP */ - case 5: - case 6: - case 7: - /* 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); - - /* step 5b: GFX devices in a GPP slot */ - - /* step 6a: VCI */ - sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0)); - if (port == 8) { - /* The code below between #if and #endif causes a hang on HDA init. - * So we skip it. */ -#if 0 - /* Clear bits 7:1 */ - pci_ext_write_config32(nb_dev, sb_dev, 0x114, 0x3f << 1, 0 << 1); - /* Maps Traffic Class 1-7 to VC1 */ - pci_ext_write_config32(nb_dev, sb_dev, 0x120, 0x7f << 1, 0x7f << 1); - /* Assigns VC ID to 1 */ - pci_ext_write_config32(nb_dev, sb_dev, 0x120, 7 << 24, 1 << 24); - /* Enables VC1 */ - pci_ext_write_config32(nb_dev, sb_dev, 0x120, 1 << 31, 1 << 31); - - do { - reg16 = pci_ext_read_config32(nb_dev, sb_dev, 0x124); - reg16 &= 0x2; - } while (reg16); /*bit[1] = 0 means VC1 flow control initialization is successful */ -#endif - } - - /* step 6b: L0s for the southbridge link */ - /* To enalbe L0s in the southbridage*/ - - /* step 6c: L0s for the GPP link(s) */ - /* To eable L0s in the RS690 for the GPP port(s) */ - set_pcie_enable_bits(nb_dev, 0xf9, 3 << 13, 2 << 13); - set_pcie_enable_bits(dev, 0xa0, 0xf << 8, 0x9 << 8); - reg16 = pci_read_config16(dev, 0x68); - reg16 |= 1 << 0; - pci_write_config16(dev, 0x68, reg16); - - /* step 6d: ASPM L1 for the southbridge link */ - /* To enalbe L1s in the southbridage*/ - - /* step 6e: ASPM L1 for GPP link(s) */; - set_pcie_enable_bits(nb_dev, 0xf9, 3 << 13, 2 << 13); - set_pcie_enable_bits(dev, 0xa0, 3 << 12, 3 << 12); - set_pcie_enable_bits(dev, 0xa0, 0xf << 4, 3 << 4); - reg16 = pci_read_config16(dev, 0x68); - reg16 &= ~0xff; - reg16 |= 1 << 1; - pci_write_config16(dev, 0x68, reg16); - - /* step 6f: Turning off PLL during L1/L23 */ - set_pcie_enable_bits(nb_dev, 0x40, 1 << 3, 1 << 3); - set_pcie_enable_bits(nb_dev, 0x40, 1 << 9, 1 << 9); - - /* step 6g: TXCLK clock gating */ - set_nbmisc_enable_bits(nb_dev, 0x7, 3 << 4, 3 << 4); - set_nbmisc_enable_bits(nb_dev, 0x7, 1 << 22, 1 << 22); - set_pcie_enable_bits(nb_dev, 0x11, 0xf << 4, 0xc << 4); - - /* step 6h: LCLK clock gating, done in rs690_config_misc_clk() */ -} - -/***************************************** -* Compliant with CIM_33's PCIEConfigureGPPCore -*****************************************/ -void config_gpp_core(device_t nb_dev, device_t sb_dev) -{ - u32 reg; - struct southbridge_amd_rs690_config *cfg = - (struct southbridge_amd_rs690_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->gpp_configuration != ((reg >> 4) & 0xf)) - switching_gpp_configurations(nb_dev, sb_dev); - ValidatePortEn(nb_dev); -} - -#ifdef UNUSED_CODE -/***************************************** -* Compliant with CIM_33's PCIEMiscClkProg -*****************************************/ -void pcie_config_misc_clk(device_t nb_dev) -{ - u32 reg; - struct bus pbus; /* fake bus for dev0 fun1 */ - - reg = pci_read_config32(nb_dev, 0x4c); - reg |= 1 << 0; - pci_write_config32(nb_dev, 0x4c, reg); - - if (AtiPcieCfg.Config & PCIE_GFX_CLK_GATING) { - /* TXCLK Clock Gating */ - set_nbmisc_enable_bits(nb_dev, 0x07, 3 << 0, 3 << 0); - set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 22, 1 << 22); - set_pcie_enable_bits(nb_dev, 0x11 | PCIE_CORE_INDEX_GFX, (3 << 6) | (~0xf), 3 << 6); - - /* LCLK Clock Gating */ - reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94); - reg &= ~(1 << 16); - pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg); - } - - if (AtiPcieCfg.Config & PCIE_GPP_CLK_GATING) { - /* TXCLK Clock Gating */ - set_nbmisc_enable_bits(nb_dev, 0x07, 3 << 4, 3 << 4); - set_nbmisc_enable_bits(nb_dev, 0x07, 1 << 22, 1 << 22); - set_pcie_enable_bits(nb_dev, 0x11 | PCIE_CORE_INDEX_GPPSB, (3 << 6) | (~0xf), 3 << 6); - - /* LCLK Clock Gating */ - reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94); - reg &= ~(1 << 24); - pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg); - } - - reg = pci_read_config32(nb_dev, 0x4c); - reg &= ~(1 << 0); - pci_write_config32(nb_dev, 0x4c, reg); -} -#endif -- cgit v1.2.3