Remove southbridges after K8 board removals

Change-Id: Ib6935c026e2302b037fc82be64163f10bf775751
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/26672
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
Kyösti Mälkki
2018-05-24 00:26:26 +03:00
parent 1740230ace
commit 4979ffc5cb
84 changed files with 0 additions and 11467 deletions

View File

@@ -1,17 +0,0 @@
##
## This file is part of the coreboot project.
##
## Copyright (C) 2008-2009 coresystems GmbH
##
## 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.
##
config SOUTHBRIDGE_AMD_AMD8131
bool

View File

@@ -1,5 +0,0 @@
ifeq ($(CONFIG_SOUTHBRIDGE_AMD_AMD8131),y)
ramstage-y += bridge.c
endif

View File

@@ -1,441 +0,0 @@
/*
* This file is part of the coreboot project.
*
* (C) 2003-2004 Linux Networx
*
* 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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <pc80/mc146818rtc.h>
#include <device/pci_def.h>
#include <device/pcix.h>
#define NMI_OFF 0
#define NPUML 0xD9 /* Non prefetchable upper memory limit */
#define NPUMB 0xD8 /* Non prefetchable upper memory base */
static void amd8131_walk_children(struct bus *bus,
void (*visit)(struct device *dev, void *ptr), void *ptr)
{
struct device *child;
for (child = bus->children; child; child = child->sibling) {
if (child->path.type != DEVICE_PATH_PCI) {
continue;
}
if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
amd8131_walk_children(child->link_list, visit, ptr);
}
visit(child, ptr);
}
}
struct amd8131_bus_info {
unsigned sstatus;
unsigned rev;
int errata_56;
int master_devices;
int max_func;
};
static void amd8131_count_dev(struct device *dev, void *ptr)
{
struct amd8131_bus_info *info = ptr;
/* Don't count pci bridges */
if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
info->master_devices++;
}
if (PCI_FUNC(dev->path.pci.devfn) > info->max_func) {
info->max_func = PCI_FUNC(dev->path.pci.devfn);
}
}
static void amd8131_pcix_tune_dev(struct device *dev, void *ptr)
{
struct amd8131_bus_info *info = ptr;
unsigned cap;
unsigned status, cmd, orig_cmd;
unsigned max_read, max_tran;
int sib_funcs, sibs;
struct device *sib;
if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) {
return;
}
cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
if (!cap) {
return;
}
/* How many siblings does this device have? */
sibs = info->master_devices - 1;
/* Count how many sibling functions this device has */
sib_funcs = 0;
for (sib = dev->bus->children; sib; sib = sib->sibling) {
if (sib == dev) {
continue;
}
if (PCI_SLOT(sib->path.pci.devfn) != PCI_SLOT(dev->path.pci.devfn)) {
continue;
}
sib_funcs++;
}
printk(BIOS_DEBUG, "%s AMD8131 PCI-X tuning\n", dev_path(dev));
status = pci_read_config32(dev, cap + PCI_X_STATUS);
orig_cmd = cmd = pci_read_config16(dev,cap + PCI_X_CMD);
max_read = (status & PCI_X_STATUS_MAX_READ) >> 21;
max_tran = (status & PCI_X_STATUS_MAX_SPLIT) >> 23;
/* Errata #49 don't allow 4K transactions */
if (max_read >= 2) {
max_read = 2;
}
/* Errata #37 Limit the number of split transactions to avoid starvation */
if (sibs >= 2) {
/* At most 2 outstanding split transactions when we have
* 3 or more bus master devices on the bus.
*/
if (max_tran > 1) {
max_tran = 1;
}
}
else if (sibs == 1) {
/* At most 4 outstanding split transactions when we have
* 2 bus master devices on the bus.
*/
if (max_tran > 3) {
max_tran = 3;
}
}
else {
/* At most 8 outstanding split transactions when we have
* only one bus master device on the bus.
*/
if (max_tran > 4) {
max_tran = 4;
}
}
/* Errata #56 additional limits when the bus runs at 133Mhz */
if (info->errata_56 &&
(PCI_X_SSTATUS_MFREQ(info->sstatus) == PCI_X_SSTATUS_MODE1_133MHZ))
{
unsigned limit_read;
/* Look at the number of siblings and compute the
* largest legal read size.
*/
if (sib_funcs == 0) {
/* 2k reads */
limit_read = 2;
}
else if (sib_funcs <= 1) {
/* 1k reads */
limit_read = 1;
}
else {
/* 512 byte reads */
limit_read = 0;
}
if (max_read > limit_read) {
max_read = limit_read;
}
/* Look at the read size and the number of siblings
* and compute how many outstanding transactions I can have.
*/
if (max_read == 2) {
/* 2K reads */
if (max_tran > 0) {
/* Only 1 outstanding transaction allowed */
max_tran = 0;
}
}
else if (max_read == 1) {
/* 1K reads */
if (max_tran > (1 - sib_funcs)) {
/* At most 2 outstanding transactions */
max_tran = 1 - sib_funcs;
}
}
else {
/* 512 byte reads */
max_read = 0;
if (max_tran > (2 - sib_funcs)) {
/* At most 3 outstanding transactions */
max_tran = 2 - sib_funcs;
}
}
}
#if 0
printk(BIOS_DEBUG, "%s max_read: %d max_tran: %d sibs: %d sib_funcs: %d\n",
dev_path(dev), max_read, max_tran, sibs, sib_funcs, sib_funcs);
#endif
if (max_read != ((cmd & PCI_X_CMD_MAX_READ) >> 2)) {
cmd &= ~PCI_X_CMD_MAX_READ;
cmd |= max_read << 2;
}
if (max_tran != ((cmd & PCI_X_CMD_MAX_SPLIT) >> 4)) {
cmd &= ~PCI_X_CMD_MAX_SPLIT;
cmd |= max_tran << 4;
}
/* Don't attempt to handle PCI-X errors */
cmd &= ~PCI_X_CMD_DPERR_E;
/* The 8131 does not work properly with relax ordering enabled.
* Errata #58
*/
cmd &= ~PCI_X_CMD_ERO;
if (orig_cmd != cmd) {
pci_write_config16(dev, cap + PCI_X_CMD, cmd);
}
}
static void amd8131_scan_bus(struct bus *bus,
unsigned min_devfn, unsigned max_devfn)
{
struct amd8131_bus_info info;
struct bus *pbus;
unsigned pos;
/* Find the children on the bus */
pci_scan_bus(bus, min_devfn, max_devfn);
/* Find the revision of the 8131 */
info.rev = pci_read_config8(bus->dev, PCI_CLASS_REVISION);
/* See which errata apply */
info.errata_56 = info.rev <= 0x12;
/* Find the pcix capability and get the secondary bus status */
pos = pci_find_capability(bus->dev, PCI_CAP_ID_PCIX);
info.sstatus = pci_read_config16(bus->dev, pos + PCI_X_SEC_STATUS);
/* Print the PCI-X bus speed */
printk(BIOS_DEBUG, "PCI: %02x: %s\n", bus->secondary, pcix_speed(info.sstatus));
/* Examine the bus and find out how loaded it is */
info.max_func = 0;
info.master_devices = 0;
amd8131_walk_children(bus, amd8131_count_dev, &info);
/* Disable the bus if there are no devices on it or
* we are running at 133Mhz and have a 4 function device.
* see errata #56
*/
if (!bus->children ||
(info.errata_56 &&
(info.max_func >= 3) &&
(PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_MODE1_133MHZ)))
{
unsigned pcix_misc;
/* Disable all of my children */
disable_children(bus);
/* Remember the device is disabled */
bus->dev->enabled = 0;
/* Disable the PCI-X clocks */
pcix_misc = pci_read_config32(bus->dev, 0x40);
pcix_misc &= ~(0x1f << 16);
pci_write_config32(bus->dev, 0x40, pcix_misc);
return;
}
/* If we are in conventional PCI mode nothing more is necessary.
*/
if (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_CONVENTIONAL_PCI) {
return;
}
/* Tune the devices on the bus */
amd8131_walk_children(bus, amd8131_pcix_tune_dev, &info);
/* Don't allow the 8131 or any of it's parent busses to
* implement relaxed ordering. Errata #58
*/
for (pbus = bus; !pbus->disable_relaxed_ordering; pbus = pbus->dev->bus) {
printk(BIOS_SPEW, "%s disabling relaxed ordering\n",
bus_path(pbus));
pbus->disable_relaxed_ordering = 1;
}
}
static void amd8131_scan_bridge(struct device *dev)
{
do_pci_scan_bridge(dev, amd8131_scan_bus);
}
static void amd8131_pcix_init(struct device *dev)
{
uint32_t dword;
uint16_t word;
uint8_t byte;
int nmi_option;
/* Enable memory write and invalidate ??? */
byte = pci_read_config8(dev, 0x04);
byte |= 0x10;
pci_write_config8(dev, 0x04, byte);
/* Set drive strength */
word = pci_read_config16(dev, 0xe0);
word = 0x0404;
pci_write_config16(dev, 0xe0, word);
word = pci_read_config16(dev, 0xe4);
word = 0x0404;
pci_write_config16(dev, 0xe4, word);
/* Set impedance */
word = pci_read_config16(dev, 0xe8);
word = 0x0404;
pci_write_config16(dev, 0xe8, word);
/* Set discard unrequested prefetch data */
/* Errata #51 */
word = pci_read_config16(dev, 0x4c);
word |= 1;
pci_write_config16(dev, 0x4c, word);
/* Set split transaction limits */
word = pci_read_config16(dev, 0xa8);
pci_write_config16(dev, 0xaa, word);
word = pci_read_config16(dev, 0xac);
pci_write_config16(dev, 0xae, word);
/* Set up error reporting, enable all */
/* system error enable */
dword = pci_read_config32(dev, 0x04);
dword |= (1<<8);
pci_write_config32(dev, 0x04, dword);
/* system and error parity enable */
dword = pci_read_config32(dev, 0x3c);
dword |= (3<<16);
pci_write_config32(dev, 0x3c, dword);
/* NMI enable */
nmi_option = NMI_OFF;
get_option(&nmi_option, "nmi");
if (nmi_option) {
dword = pci_read_config32(dev, 0x44);
dword |= (1<<0);
pci_write_config32(dev, 0x44, dword);
}
/* Set up CRC flood enable */
dword = pci_read_config32(dev, 0xc0);
if (dword) { /* do device A only */
dword = pci_read_config32(dev, 0xc4);
dword |= (1<<1);
pci_write_config32(dev, 0xc4, dword);
dword = pci_read_config32(dev, 0xc8);
dword |= (1<<1);
pci_write_config32(dev, 0xc8, dword);
}
return;
}
#define BRIDGE_40_BIT_SUPPORT 0
#if BRIDGE_40_BIT_SUPPORT
static void bridge_read_resources(struct device *dev)
{
struct resource *res;
pci_bus_read_resources(dev);
res = find_resource(dev, PCI_MEMORY_BASE);
if (res) {
res->limit = 0xffffffffffULL;
}
}
static void bridge_set_resources(struct device *dev)
{
struct resource *res;
res = find_resource(dev, PCI_MEMORY_BASE);
if (res) {
resource_t base, end;
/* set the memory range */
dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
res->flags |= IORESOURCE_STORED;
base = res->base;
end = resource_end(res);
pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16);
pci_write_config8(dev, NPUML, (base >> 32) & 0xff);
pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16);
pci_write_config8(dev, NPUMB, (end >> 32) & 0xff);
report_resource_stored(dev, res, "");
}
pci_dev_set_resources(dev);
}
#endif /* BRIDGE_40_BIT_SUPPORT */
static struct device_operations pcix_ops = {
#if BRIDGE_40_BIT_SUPPORT
.read_resources = bridge_read_resources,
.set_resources = bridge_set_resources,
#else
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
#endif
.enable_resources = pci_bus_enable_resources,
.init = amd8131_pcix_init,
.scan_bus = amd8131_scan_bridge,
.reset_bus = pci_bus_reset,
};
static const struct pci_driver pcix_driver __pci_driver = {
.ops = &pcix_ops,
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x7450,
};
static void ioapic_enable(struct device *dev)
{
uint32_t value;
value = pci_read_config32(dev, 0x44);
if (dev->enabled) {
value |= ((1 << 1) | (1 << 0));
} else {
value &= ~((1 << 1) | (1 << 0));
}
pci_write_config32(dev, 0x44, value);
}
static struct pci_operations pci_ops_pci_dev = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations ioapic_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = 0,
.scan_bus = 0,
.enable = ioapic_enable,
.ops_pci = &pci_ops_pci_dev,
};
static const struct pci_driver ioapic_driver __pci_driver = {
.ops = &ioapic_ops,
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x7451,
};

View File

@@ -1,2 +0,0 @@
config SOUTHBRIDGE_AMD_AMD8151
bool

View File

@@ -1,5 +0,0 @@
ifeq ($(CONFIG_SOUTHBRIDGE_AMD_AMD8151),y)
ramstage-y += agp3.c
endif

View File

@@ -1,86 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2003 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
*
* 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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
static void agp3bridge_init(struct device *dev)
{
uint8_t byte;
/* Enable BM, MEM and IO */
byte = pci_read_config32(dev, 0x04);
byte |= 0x07;
pci_write_config8(dev, 0x04, byte);
return;
}
static struct device_operations agp3bridge_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.init = agp3bridge_init,
.scan_bus = pci_scan_bridge,
};
static const struct pci_driver agp3bridge_driver __pci_driver = {
.ops = &agp3bridge_ops,
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x7455, // AGP Bridge
};
static void agp3dev_enable(struct device *dev)
{
uint32_t value;
/* AGP enable */
value = pci_read_config32(dev, 0xa8);
value |= (3<<8)|2; //AGP 8x
pci_write_config32(dev, 0xa8, value);
/* enable BM and MEM */
value = pci_read_config32(dev, 0x4);
value |= 6;
pci_write_config32(dev, 0x4, value);
#if 0
/* FIXME: should we add agp aperture base and size here ?
* or it is done by AGP drivers */
#endif
}
static struct pci_operations pci_ops_pci_dev = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations agp3dev_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = 0,
.scan_bus = 0,
.enable = agp3dev_enable,
.ops_pci = &pci_ops_pci_dev,
};
static const struct pci_driver agp3dev_driver __pci_driver = {
.ops = &agp3dev_ops,
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x7454, //AGP Device
};

View File

@@ -1,25 +0,0 @@
##
## This file is part of the coreboot project.
##
## Copyright (C) 2008-2009 coresystems GmbH
##
## 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.
##
config SOUTHBRIDGE_AMD_RS690
bool
if SOUTHBRIDGE_AMD_RS690
config EXT_CONF_SUPPORT
def_bool n
help
Select if RS690 should be setup to support MMCONF.
endif

View File

@@ -1,9 +0,0 @@
ifeq ($(CONFIG_SOUTHBRIDGE_AMD_RS690),y)
ramstage-y += rs690.c
ramstage-y += cmn.c
ramstage-y += pcie.c
ramstage-y += ht.c
ramstage-y += gfx.c
endif

View File

@@ -1,33 +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.
*/
#ifndef RS690_CHIP_H
#define RS690_CHIP_H
/* Member variables are defined in devicetree.cb. */
struct southbridge_amd_rs690_config
{
u8 gpp_configuration; /* The configuration of General Purpose Port, A/B/C/D/E. */
u8 port_enable; /* Which port is enabled? GFX(2,3), GPP(4,5,6,7) */
u8 gfx_dev2_dev3; /* for GFX Core initialization REFCLK_SEL */
u8 gfx_dual_slot; /* Is it dual graphics slots */
u8 gfx_lane_reversal; /* Single/Dual slot lan reversal */
u8 gfx_tmds; /* whether support TMDS? */
u8 gfx_compliance; /* whether support compliance? */
u8 gfx_reconfiguration; /* Dynamic Link Width Control */
u8 gfx_link_width; /* Desired width of lane 2 */
};
#endif /* RS690_CHIP_H */

View File

@@ -1,325 +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.
*/
#include <console/console.h>
#include <arch/io.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
#include <delay.h>
#include "rs690.h"
static u32 nb_read_index(struct device *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(struct device *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(struct device *nb_dev, struct device *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(struct device *nb_dev, struct device *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(struct device *nb_dev, u32 index)
{
return nb_read_index((nb_dev), NBMISC_INDEX, (index));
}
void nbmisc_write_index(struct device *nb_dev, u32 index, u32 data)
{
nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data));
}
u32 nbpcie_p_read_index(struct device *dev, u32 index)
{
return nb_read_index((dev), NBPCIE_INDEX, (index));
}
void nbpcie_p_write_index(struct device *dev, u32 index, u32 data)
{
nb_write_index((dev), NBPCIE_INDEX, (index), (data));
}
u32 nbpcie_ind_read_index(struct device *nb_dev, u32 index)
{
return nb_read_index((nb_dev), NBPCIE_INDEX, (index));
}
void nbpcie_ind_write_index(struct device *nb_dev, u32 index, u32 data)
{
nb_write_index((nb_dev), NBPCIE_INDEX, (index), (data));
}
u32 htiu_read_index(struct device *nb_dev, u32 index)
{
return nb_read_index((nb_dev), NBHTIU_INDEX, (index));
}
void htiu_write_index(struct device *nb_dev, u32 index, u32 data)
{
nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data));
}
u32 nbmc_read_index(struct device *nb_dev, u32 index)
{
return nb_read_index((nb_dev), NBMC_INDEX, (index));
}
void nbmc_write_index(struct device *nb_dev, u32 index, u32 data)
{
nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data));
}
void set_nbcfg_enable_bits(struct device *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(struct device *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(struct device *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(struct device *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(struct device *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(struct device *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 */
struct device *k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1));
struct device *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(struct device *nb_dev, struct device *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(struct device *nb_dev, struct device *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 done). 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) & 0x07; /* get bit4-6 */
reg &= 0xfff8; /* clear bit0-2 */
reg += tmp; /* merge */
reg |= 1 << 8;
nbpcie_p_write_index(dev, PCIE_LC_LINK_WIDTH, reg);
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(struct device *nb_dev)
{
/* set TOM */
#if IS_ENABLED(CONFIG_GFXUMA)
pci_write_config32(nb_dev, 0x90, uma_memory_base);
nbmc_write_index(nb_dev, 0x1e, uma_memory_base);
#else
/* 1GB system memory supposed */
pci_write_config32(nb_dev, 0x90, 0x38000000);
nbmc_write_index(nb_dev, 0x1e, 0x38000000);
#endif
}

View File

@@ -1,480 +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.
*/
#define NBHTIU_INDEX 0xA8
#define NBMISC_INDEX 0x60
#define NBMC_INDEX 0xE8
static u32 nb_read_index(pci_devfn_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(pci_devfn_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(pci_devfn_t nb_dev, u32 index)
{
return nb_read_index((nb_dev), NBMISC_INDEX, (index));
}
static void nbmisc_write_index(pci_devfn_t nb_dev, u32 index, u32 data)
{
nb_write_index((nb_dev), NBMISC_INDEX, ((index) | 0x80), (data));
}
static u32 htiu_read_index(pci_devfn_t nb_dev, u32 index)
{
return nb_read_index((nb_dev), NBHTIU_INDEX, (index));
}
static void htiu_write_index(pci_devfn_t nb_dev, u32 index, u32 data)
{
nb_write_index((nb_dev), NBHTIU_INDEX, ((index) | 0x100), (data));
}
static u32 nbmc_read_index(pci_devfn_t nb_dev, u32 index)
{
return nb_read_index((nb_dev), NBMC_INDEX, (index));
}
static void nbmc_write_index(pci_devfn_t nb_dev, u32 index, u32 data)
{
nb_write_index((nb_dev), NBMC_INDEX, ((index) | 1 << 9), (data));
}
static void set_htiu_enable_bits(pci_devfn_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(pci_devfn_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(pci_devfn_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(pci_devfn_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(pci_devfn_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(pci_devfn_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().
*/
pci_devfn_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)
{
pci_devfn_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(pci_devfn_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(pci_devfn_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(pci_devfn_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(pci_devfn_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(pci_devfn_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)
{
pci_devfn_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);
}

View File

@@ -1,621 +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.
*/
/*
* for rs690 internal graphics device
* device id of internal graphics:
* RS690M/T: 0x791f
* RS690: 0x791e
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <delay.h>
#include "rs690.h"
#define CLK_CNTL_INDEX 0x8
#define CLK_CNTL_DATA 0xC
#ifdef UNUSED_CODE
static u32 clkind_read(struct device *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(struct device *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(struct device *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(struct device *dev)
{
u32 l_dword;
int i;
struct device *k8_f2 = NULL;
struct device *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);
/* 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 void gfx_dev_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x4c, ((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = gfx_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(struct device *nb_dev, struct device *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(struct device *nb_dev, struct device *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(struct device *nb_dev,
struct device *dev, u8 width)
{
u32 reg32;
struct device *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(struct device *nb_dev, struct device *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 state 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 Reporting Capabilities in the PCIE Bridge.
* 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;
}
}

View File

@@ -1,197 +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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <lib.h>
#include <arch/acpi.h>
#include "rs690.h"
static void ht_dev_set_resources(struct device *dev)
{
#if IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)
unsigned reg;
struct device *k8_f1;
resource_t rbase, rend;
u32 base, limit;
struct resource *resource;
printk(BIOS_DEBUG,"%s %s\n", dev_path(dev), __func__);
resource = probe_resource(dev, 0x1C);
if (resource) {
set_nbmisc_enable_bits(dev, 0x0, 1 << 3, 0 << 3); // make bar3 visible
set_nbcfg_enable_bits(dev, 0x7C, 1 << 30, 1 << 30); /* Enables writes to the BAR3 register. */
set_nbcfg_enable_bits(dev, 0x84, 7 << 16, 0 << 16); // program bus range: 255 busses
pci_write_config32(dev, 0x1C, resource->base);
/* Enable MMCONFIG decoding. */
set_htiu_enable_bits(dev, 0x32, 1 << 28, 1 << 28); /* PCIEMiscInit */
set_nbcfg_enable_bits(dev, 0x7C, 1 << 30, 0 << 30); /* Disable writes to the BAR3 register. */
set_nbmisc_enable_bits(dev, 0x0, 1 << 3, 1 << 3); // hide bar 3
// setup resource nonposted in k8 mmio
/* Get the base address */
rbase = resource->base;
/* Get the limit (rounded up) */
rend = resource_end(resource);
printk(BIOS_DEBUG,"%s: %s[0x1C] base = %0llx limit = %0llx\n", __func__, dev_path(dev), rbase, rend);
k8_f1 = dev_find_slot(0,PCI_DEVFN(0x18,1));
// find a not assigned resource
for ( reg = 0xb8; reg >= 0x80; reg -= 8 ) {
base = pci_read_config32(k8_f1,reg);
limit = pci_read_config32(k8_f1,reg+4);
if ( !(base & 3) ) break; // found a not assigned resource
}
if ( !(base & 3) ) {
u32 sblk;
struct device *k8_f0 =
dev_find_slot(0, PCI_DEVFN(0x18, 0));
/* Remember this resource has been stored. */
resource->flags |= IORESOURCE_STORED;
report_resource_stored(dev, resource, " <mmconfig>");
/* Get SBLink value (HyperTransport I/O Hub Link ID). */
sblk = (pci_read_config32(k8_f0, 0x64) >> 8) & 0x3;
base &= 0x000000f0;
base |= ((rbase >> 8) & 0xffffff00);
base |= 3;
limit &= 0x00000048;
limit |= ((rend >> 8) & 0xffffff00);
limit |= (sblk << 4);
limit |= (1 << 7);
printk(BIOS_INFO, "%s <- index %x base %04x limit %04x\n", dev_path(k8_f1), reg, base, limit);
pci_write_config32(k8_f1, reg+4, limit);
pci_write_config32(k8_f1, reg, base);
}
}
#endif
pci_dev_set_resources(dev);
}
unsigned long acpi_fill_mcfg(unsigned long current)
{
#if IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)
struct resource *res;
resource_t mmconf_base = EXT_CONF_BASE_ADDRESS; // default
struct device *dev = dev_find_slot(0,PCI_DEVFN(0,0));
// we report mmconf base
res = probe_resource(dev, 0x1C);
if ( res )
mmconf_base = res->base;
current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current, mmconf_base, 0x0, 0x0, 0x1f); // Fix me: should i reserve 255 busses ?
#endif
return current;
}
static void ht_dev_read_resources(struct device *dev)
{
#if IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)
struct resource *res;
printk(BIOS_DEBUG,"%s %s\n", dev_path(dev), __func__);
set_nbmisc_enable_bits(dev, 0x0, 1 << 3, 1 << 3); // hide bar 3
#endif
pci_dev_read_resources(dev);
#if IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)
/* Add an MMCONFIG resource. */
res = new_resource(dev, 0x1C);
res->base = EXT_CONF_BASE_ADDRESS;
res->size = 256 * 1024 * 1024; // 256 busses, 1MB memory space each
res->align = log2(res->size);
res->gran = log2(res->size);
res->limit = 0xffffffffffffffffULL; /* 64bit */
res->flags = IORESOURCE_FIXED | IORESOURCE_MEM | IORESOURCE_PCI64 |
IORESOURCE_ASSIGNED | IORESOURCE_RESERVE;
compact_resources(dev);
#endif
}
/* for UMA internal graphics */
void avoid_lpc_dma_deadlock(struct device *nb_dev, struct device *sb_dev)
{
struct device *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 void ht_dev_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x50, ((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = ht_dev_set_subsystem,
};
static struct device_operations ht_ops = {
.read_resources = ht_dev_read_resources,
.set_resources = ht_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,
};

View File

@@ -1,400 +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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <delay.h>
#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(struct device *nb_dev, struct device *dev,
u32 port);
static void ValidatePortEn(struct device *nb_dev);
static void ValidatePortEn(struct device *nb_dev)
{
}
/*****************************************************************
* Compliant with CIM_33's PCIEPowerOffGppPorts
* Power off unused GPP lines
*****************************************************************/
static void PciePowerOffGppPorts(struct device *nb_dev, struct device *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(struct device *nb_dev,
struct device *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 inverted 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(struct device *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(struct device *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(struct device *nb_dev, struct device *dev, u32 port)
{
u8 reg8;
u16 reg16;
struct device *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);
/* Enables 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 enable L0s in the southbridge*/
/* step 6c: L0s for the GPP link(s) */
/* To enable 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 enable L1s in the southbridge*/
/* 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(struct device *nb_dev, struct device *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(struct device *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

View File

@@ -1,194 +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.
*/
#include <console/console.h>
#include <arch/io.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
#include "rs690.h"
/*****************************************
* Compliant with CIM_33's ATINB_MiscClockCtrl
*****************************************/
void static rs690_config_misc_clk(struct device *nb_dev)
{
u32 reg;
u16 word;
/* u8 byte; */
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);
word = pci_cf8_conf1.read16(&pbus, 0, 1, 0xf8);
word &= 0xf00;
pci_cf8_conf1.write16(&pbus, 0, 1, 0xf8, word);
word = pci_cf8_conf1.read16(&pbus, 0, 1, 0xe8);
word &= ~((1 << 12) | (1 << 13) | (1 << 14));
word |= 1 << 13;
pci_cf8_conf1.write16(&pbus, 0, 1, 0xe8, word);
reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x94);
reg &= ~((1 << 16) | (1 << 24) | (1 << 28));
pci_cf8_conf1.write32(&pbus, 0, 1, 0x94, reg);
reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x8c);
reg &= ~((1 << 13) | (1 << 14) | (1 << 24) | (1 << 25));
reg |= 1 << 13;
pci_cf8_conf1.write32(&pbus, 0, 1, 0x8c, reg);
reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0xcc);
reg |= 1 << 24;
pci_cf8_conf1.write32(&pbus, 0, 1, 0xcc, reg);
reg = nbmc_read_index(nb_dev, 0x7a);
reg &= ~0x3f;
reg |= 1 << 2;
reg &= ~(1 << 6);
set_htiu_enable_bits(nb_dev, 0x05, 1 << 11, 1 << 11);
nbmc_write_index(nb_dev, 0x7a, reg);
/* Powering Down efuse and strap block clocks after boot-up. GFX Mode. */
reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0xcc);
reg &= ~(1 << 23);
reg |= 1 << 24;
pci_cf8_conf1.write32(&pbus, 0, 1, 0xcc, reg);
#if 0
/* Powerdown reference clock to graphics core PLL in northbridge only mode */
reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0x8c);
reg |= 1 << 21;
pci_cf8_conf1.write32(&pbus, 0, 1, 0x8c, reg);
/* Powering Down efuse and strap block clocks after boot-up. NB Only Mode. */
reg = pci_cf8_conf1.read32(&pbus, 0, 1, 0xcc);
reg |= (1 << 23) | (1 << 24);
pci_cf8_conf1.write32(&pbus, 0, 1, 0xcc, reg);
/* Powerdown clock to memory controller in northbridge only mode */
byte = pci_cf8_conf1.read8(&pbus, 0, 1, 0xe4);
byte |= 1 << 0;
pci_cf8_conf1.write8(&pbus, 0, 1, 0xe4, reg);
/* CLKCFG:0xE8 Bit[17] = 0x1 Powerdown clock to IOC GFX block in no external graphics mode */
/* TODO: */
#endif
reg = pci_read_config32(nb_dev, 0x4c);
reg &= ~(1 << 0);
pci_write_config32(nb_dev, 0x4c, reg);
set_htiu_enable_bits(nb_dev, 0x05, 7 << 8, 7 << 8);
}
static u32 get_vid_did(struct device *dev)
{
return pci_read_config32(dev, 0);
}
/***********************************************
* 0:00.0 NBCFG :
* 0:00.1 CLK : bit 0 of nb_cfg 0x4c : 0 - disable, default
* 0:01.0 P2P Internal:
* 0:02.0 P2P : bit 2 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
* 0:03.0 P2P : bit 3 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
* 0:04.0 P2P : bit 4 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
* 0:05.0 P2P : bit 5 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
* 0:06.0 P2P : bit 6 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
* 0:07.0 P2P : bit 7 of nbmiscind 0x0c : 0 - enable, default + 32 * 2
* 0:08.0 NB2SB : bit 6 of nbmiscind 0x00 : 0 - disable, default + 32 * 1
* case 0 will be called twice, one is by CPU in hypertransport.c line458,
* the other is by rs690.
***********************************************/
void rs690_enable(struct device *dev)
{
struct device *nb_dev = NULL, *sb_dev = NULL;
int dev_ind;
printk(BIOS_INFO, "rs690_enable: dev=%p, VID_DID=0x%x\n", dev, get_vid_did(dev));
nb_dev = dev_find_slot(0, PCI_DEVFN(0, 0));
if (!nb_dev) {
die("rs690_enable: CAN NOT FIND RS690 DEVICE, HALT!\n");
/* NOT REACHED */
}
/* sb_dev (dev 8) is a bridge that links to southbridge. */
sb_dev = dev_find_slot(0, PCI_DEVFN(8, 0));
if (!sb_dev) {
die("rs690_enable: CAN NOT FIND SB bridge, HALT!\n");
/* NOT REACHED */
}
dev_ind = dev->path.pci.devfn >> 3;
switch (dev_ind) {
case 0: /* bus0, dev0, fun0; */
printk(BIOS_INFO, "Bus-0, Dev-0, Fun-0.\n");
enable_pcie_bar3(nb_dev); /* PCIEMiscInit */
config_gpp_core(nb_dev, sb_dev);
rs690_gpp_sb_init(nb_dev, sb_dev, 8);
/* set SB payload size: 64byte */
set_pcie_enable_bits(nb_dev, 0x10 | PCIE_CORE_INDEX_GPPSB, 3 << 11, 2 << 11);
/* Bus0Dev0Fun1Clock control init, we have to do it here, for dev0 Fun1 doesn't have a vendor or device ID */
rs690_config_misc_clk(nb_dev);
break;
case 1: /* bus0, dev1 */
printk(BIOS_INFO, "Bus-0, Dev-1, Fun-0.\n");
break;
case 2: /* bus0, dev2,3, two GFX */
case 3:
printk(BIOS_INFO, "Bus-0, Dev-2,3, Fun-0. enable=%d\n", dev->enabled);
set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << dev_ind,
(dev->enabled ? 0 : 1) << dev_ind);
if (dev->enabled)
rs690_gfx_init(nb_dev, dev, dev_ind);
break;
case 4: /* bus0, dev4-7, four GPP */
case 5:
case 6:
case 7:
printk(BIOS_INFO, "Bus-0, Dev-4,5,6,7, Fun-0. enable=%d\n",
dev->enabled);
set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << dev_ind,
(dev->enabled ? 0 : 1) << dev_ind);
if (dev->enabled)
rs690_gpp_sb_init(nb_dev, dev, dev_ind);
break;
case 8: /* bus0, dev8, SB */
printk(BIOS_INFO, "Bus-0, Dev-8, Fun-0. enable=%d\n", dev->enabled);
set_nbmisc_enable_bits(nb_dev, 0x00, 1 << 6,
(dev->enabled ? 1 : 0) << 6);
if (dev->enabled)
rs690_gpp_sb_init(nb_dev, dev, dev_ind);
disable_pcie_bar3(nb_dev);
break;
default:
printk(BIOS_DEBUG, "unknown dev: %s\n", dev_path(dev));
}
}
struct chip_operations southbridge_amd_rs690_ops = {
CHIP_NAME("ATI RS690")
.enable_dev = rs690_enable,
};

View File

@@ -1,144 +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.
*/
#ifndef __RS690_H__
#define __RS690_H__
#include <stdint.h>
#include <device/pci_ids.h>
#include "chip.h"
#define NBMISC_INDEX 0x60
#define NBHTIU_INDEX 0xA8
#define NBMC_INDEX 0xE8
#define NBPCIE_INDEX 0xE0
#define EXT_CONF_BASE_ADDRESS 0xE0000000
#define TEMP_MMIO_BASE_ADDRESS 0xC0000000
typedef struct __PCIE_CFG__ {
u16 Config;
u8 ResetReleaseDelay;
u8 Gfx0Width;
u8 Gfx1Width;
u8 GfxPayload;
u8 GppPayload;
u8 PortDetect;
u8 PortHp; /* hot plug */
u16 DbgConfig;
u32 DbgConfig2;
u8 GfxLx;
u8 GppLx;
u8 NBSBLx;
u8 PortSlotInit;
u8 Gfx0Pwr;
u8 Gfx1Pwr;
u8 GppPwr;
} PCIE_CFG;
/* PCIE config flags */
#define PCIE_DUALSLOT_CONFIG (1 << 0)
#define PCIE_OVERCLOCK_ENABLE (1 << 1)
#define PCIE_GPP_CLK_GATING (1 << 2)
#define PCIE_ENABLE_STATIC_DEV_REMAP (1 << 3)
#define PCIE_OFF_UNUSED_GFX_LANES (1 << 4)
#define PCIE_OFF_UNUSED_GPP_LANES (1 << 5)
#define PCIE_DISABLE_HIDE_UNUSED_PORTS (1 << 7)
#define PCIE_GFX_CLK_GATING (1 << 11)
#define PCIE_GFX_COMPLIANCE (1 << 14)
#define PCIE_GPP_COMPLIANCE (1 << 15)
typedef enum _NB_REVISION_ {
REV_RS690_A11 = 5,
REV_RS690_A12 = 6,
REV_RS690_A21 = 7,
} NB_REVISION;
/* -------------------- ----------------------
* NBMISCIND
------------------- -----------------------*/
#define PCIE_LINK_CFG 0x8
#define PCIE_NBCFG_REG7 0x37
#define STRAPS_OUTPUT_MUX_7 0x67
#define STRAPS_OUTPUT_MUX_A 0x6a
/* -------------------- ----------------------
* PCIEIND
------------------- -----------------------*/
#define PCIE_CI_CNTL 0x20
#define PCIE_LC_LINK_WIDTH 0xa2
#define PCIE_LC_STATE0 0xa5
#define PCIE_VC0_RESOURCE_STATUS 0x11a /* 16bit read only */
#define PCIE_CORE_INDEX_GFX (0 << 16) /* see 5.2.2 */
#define PCIE_CORE_INDEX_GPPSB (1 << 16)
/* contents of PCIE_NBCFG_REG7 */
#define RECONFIG_GPPSB_EN (1 << 12)
#define RECONFIG_GPPSB_GPPSB (1 << 14)
#define RECONFIG_GPPSB_LINK_CONFIG (1 << 15)
#define RECONFIG_GPPSB_ATOMIC_RESET (1 << 17)
/* contents of PCIE_VC0_RESOURCE_STATUS */
#define VC_NEGOTIATION_PENDING (1 << 1)
#define LC_STATE_RECONFIG_GPPSB 0x10
/* ------------------------------------------------
* Global variable
* ------------------------------------------------- */
extern PCIE_CFG AtiPcieCfg;
/* ----------------- export functions ----------------- */
u32 nbmisc_read_index(struct device *nb_dev, u32 index);
void nbmisc_write_index(struct device *nb_dev, u32 index, u32 data);
u32 nbpcie_p_read_index(struct device *dev, u32 index);
void nbpcie_p_write_index(struct device *dev, u32 index, u32 data);
u32 nbpcie_ind_read_index(struct device *nb_dev, u32 index);
void nbpcie_ind_write_index(struct device *nb_dev, u32 index, u32 data);
u32 htiu_read_index(struct device *nb_dev, u32 index);
void htiu_write_index(struct device *nb_dev, u32 index, u32 data);
u32 nbmc_read_index(struct device *nb_dev, u32 index);
void nbmc_write_index(struct device *nb_dev, u32 index, u32 data);
u32 pci_ext_read_config32(struct device *nb_dev, struct device *dev, u32 reg);
void pci_ext_write_config32(struct device *nb_dev, struct device *dev, u32 reg,
u32 mask, u32 val);
void set_nbcfg_enable_bits(struct device *nb_dev, u32 reg_pos, u32 mask,
u32 val);
void set_nbcfg_enable_bits_8(struct device *nb_dev, u32 reg_pos, u8 mask,
u8 val);
void set_nbmc_enable_bits(struct device *nb_dev, u32 reg_pos, u32 mask,
u32 val);
void set_htiu_enable_bits(struct device *nb_dev, u32 reg_pos, u32 mask,
u32 val);
void set_nbmisc_enable_bits(struct device *nb_dev, u32 reg_pos, u32 mask,
u32 val);
void set_pcie_enable_bits(struct device *dev, u32 reg_pos, u32 mask, u32 val);
void rs690_set_tom(struct device *nb_dev);
void ProgK8TempMmioBase(u8 in_out, u32 pcie_base_add, u32 mmio_base_add);
void enable_pcie_bar3(struct device *nb_dev);
void disable_pcie_bar3(struct device *nb_dev);
void rs690_enable(struct device *dev);
void rs690_gpp_sb_init(struct device *nb_dev, struct device *dev, u32 port);
void rs690_gfx_init(struct device *nb_dev, struct device *dev, u32 port);
void avoid_lpc_dma_deadlock(struct device *nb_dev, struct device *sb_dev);
void config_gpp_core(struct device *nb_dev, struct device *sb_dev);
void PcieReleasePortTraining(struct device *nb_dev, struct device *dev,
u32 port);
u8 PcieTrainPort(struct device *nb_dev, struct device *dev, u32 port);
#endif /* __RS690_H__ */

View File

@@ -1,54 +0,0 @@
##
## This file is part of the coreboot project.
##
## Copyright (C) 2008-2009 coresystems GmbH
##
## 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.
##
config SOUTHBRIDGE_AMD_SB600
bool
select IOAPIC
select HAVE_USBDEBUG
select HAVE_HARD_RESET
if SOUTHBRIDGE_AMD_SB600
config BOOTBLOCK_SOUTHBRIDGE_INIT
string
default "southbridge/amd/sb600/bootblock.c"
config EHCI_BAR
hex
default 0xfef00000
choice
prompt "SATA Mode"
default SATA_MODE_IDE
help
Select the mode in which SATA should be driven. IDE or AHCI.
The default is IDE.
config SATA_MODE_IDE
bool "IDE"
config SATA_MODE_AHCI
bool "AHCI"
endchoice
config SATA_MODE
int
default 1 if SATA_MODE_IDE
default 0 if SATA_MODE_AHCI
config HPET_MIN_TICKS
hex
default 0x14
endif

View File

@@ -1,16 +0,0 @@
ifeq ($(CONFIG_SOUTHBRIDGE_AMD_SB600),y)
ramstage-y += sb600.c
ramstage-y += usb.c
ramstage-y += lpc.c
ramstage-y += sm.c
ramstage-y += ide.c
ramstage-y += sata.c
ramstage-y += hda.c
ramstage-y += ac97.c
ramstage-y += pci.c
ramstage-y += reset.c
romstage-$(CONFIG_USBDEBUG_IN_ROMSTAGE) += enable_usbdebug.c
ramstage-$(CONFIG_USBDEBUG) += enable_usbdebug.c
endif

View File

@@ -1,57 +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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include "sb600.h"
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations ac97audio_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
/* .enable = sb600_enable, */
.init = 0,
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const struct pci_driver ac97audio_driver __pci_driver = {
.ops = &ac97audio_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB600_ACI,
};
static struct device_operations ac97modem_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
/* .enable = sb600_enable, */
.init = 0,
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const struct pci_driver ac97modem_driver __pci_driver = {
.ops = &ac97modem_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB600_MCI,
};

View File

@@ -1,65 +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.
*/
#include <stdint.h>
#include <arch/io.h>
#include <device/pci_ids.h>
/*
* Enable 4MB (LPC) ROM access at 0xFFC00000 - 0xFFFFFFFF.
*
* Hardware should enable LPC ROM by pin straps. This function does not
* handle the theoretically possible PCI ROM, FWH, or SPI ROM configurations.
*
* The SB600 power-on default is to map 256K ROM space.
*
* Details: AMD SB600 BIOS Developer's Guide (BDG), page 15.
*/
static void sb600_enable_rom(void)
{
u8 reg8;
pci_devfn_t dev;
dev = pci_io_locate_device(PCI_ID(PCI_VENDOR_ID_ATI,
PCI_DEVICE_ID_ATI_SB600_LPC), 0);
/* Decode variable LPC ROM address ranges 1 and 2. */
reg8 = pci_io_read_config8(dev, 0x48);
reg8 |= (1 << 3) | (1 << 4);
pci_io_write_config8(dev, 0x48, reg8);
/* LPC ROM address range 1: */
/* Enable LPC ROM range mirroring start at 0x000e(0000). */
pci_io_write_config16(dev, 0x68, 0x000e);
/* Enable LPC ROM range mirroring end at 0x000f(ffff). */
pci_io_write_config16(dev, 0x6a, 0x000f);
/* LPC ROM address range 2: */
/*
* Enable LPC ROM range start at:
* 0xfff8(0000): 512KB
* 0xfff0(0000): 1MB
* 0xffe0(0000): 2MB
* 0xffc0(0000): 4MB
*/
pci_io_write_config16(dev, 0x6c, 0x10000 - (CONFIG_COREBOOT_ROMSIZE_KB >> 6)); /* 4 MB */
/* Enable LPC ROM range end at 0xffff(ffff). */
pci_io_write_config16(dev, 0x6e, 0xffff);
}
static void bootblock_southbridge_init(void)
{
sb600_enable_rom();
}

View File

@@ -1,24 +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.
*/
#ifndef SB600_CHIP_H
#define SB600_CHIP_H
struct southbridge_amd_sb600_config
{
u32 hda_viddid;
};
#endif /* SB600_CHIP_H */

View File

@@ -1,636 +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.
*/
#include <reset.h>
#include <arch/cpu.h>
#include "sb600.h"
#include "smbus.c"
#define SMBUS_IO_BASE 0x1000 /* Is it a temporary SMBus I/O base address? */
/*SIZE 0x40 */
static void pmio_write(u8 reg, u8 value)
{
outb(reg, PM_INDEX);
outb(value, PM_INDEX + 1);
}
static u8 pmio_read(u8 reg)
{
outb(reg, PM_INDEX);
return inb(PM_INDEX + 1);
}
/* RPR 2.1: Get SB ASIC Revision. */
static u8 get_sb600_revision(void)
{
pci_devfn_t dev;
dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0);
if (dev == PCI_DEV_INVALID) {
die("SMBUS controller not found\n");
/* NOT REACHED */
}
return pci_read_config8(dev, 0x08);
}
/***************************************
* Legacy devices are mapped to LPC space.
* Serial port 0, 1
* KBC Port
* ACPI Micro-controller port
* This function does not change port 0x80 decoding.
* Console output through any port besides 0x2f8/0x3f8 is unsupported.
* If you use FWH ROMs, you have to setup IDSEL.
* Reviewed-by: Carl-Daniel Hailfinger
* Reviewed against AMD SB600 Register Reference Manual rev. 3.03, section 3.1
* (LPC ISA Bridge)
***************************************/
static void sb600_lpc_init(void)
{
u8 reg8;
u32 reg32;
pci_devfn_t dev;
dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); /* SMBUS controller */
/* NOTE: Set BootTimerDisable, otherwise it would keep rebooting!!
* This bit has no meaning if debug strap is not enabled. So if the
* board keeps rebooting and the code fails to reach here, we could
* disable the debug strap first. */
reg32 = pci_read_config32(dev, 0x4C);
reg32 |= 1 << 31;
pci_write_config32(dev, 0x4C, reg32);
/* Enable lpc controller */
reg32 = pci_read_config32(dev, 0x64);
reg32 |= 1 << 20;
pci_write_config32(dev, 0x64, reg32);
dev = pci_locate_device(PCI_ID(0x1002, 0x438d), 0); /* LPC Controller */
/* Decode port 0x3f8-0x3ff (Serial 0), 0x2f8-0x2ff (Serial 1) */
reg8 = pci_read_config8(dev, 0x44);
reg8 |= (1 << 6) | (1 << 7);
pci_write_config8(dev, 0x44, reg8);
/* Decode port 0x60 & 0x64 (PS/2 keyboard) and port 0x62 & 0x66 (ACPI)*/
reg8 = pci_read_config8(dev, 0x47);
reg8 |= (1 << 5) | (1 << 6);
pci_write_config8(dev, 0x47, reg8);
/* Super I/O, RTC */
reg8 = pci_read_config8(dev, 0x48);
/* Decode ports 0x2e-0x2f, 0x4e-0x4f (SuperI/O configuration) */
reg8 |= (1 << 1) | (1 << 0);
/* Decode port 0x70-0x73 (RTC) */
reg8 |= (1 << 6);
pci_write_config8(dev, 0x48, reg8);
}
/* what is its usage? */
static u32 get_sbdn(u32 bus)
{
pci_devfn_t dev;
/* Find the device. */
dev = pci_locate_device_on_bus(PCI_ID(0x1002, 0x4385), bus);
return (dev >> 15) & 0x1f;
}
static u8 dual_core(void)
{
return (pci_read_config32(PCI_DEV(0, 0x18, 3), 0xE8) & (0x3<<12)) != 0;
}
/*
* SB600 VFSMAF (VID/FID System Management Action Field) is 010b by default.
* RPR 2.3.3 C-state and VID/FID change for the K8 platform.
*/
static void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn)
{
u8 byte;
byte = pmio_read(0x9a);
byte &= ~0x34;
if (dual_core())
byte |= 0x34;
else
byte |= 0x04;
pmio_write(0x9a, byte);
byte = pmio_read(0x8f);
byte &= ~0x30;
byte |= 0x20;
pmio_write(0x8f, byte);
pmio_write(0x8b, 0x01);
pmio_write(0x8a, 0x90);
if (get_sb600_revision() > 0x13)
pmio_write(0x88, 0x10);
else
pmio_write(0x88, 0x06);
byte = pmio_read(0x7c);
byte &= ~0x01;
byte |= 0x01;
pmio_write(0x7c, byte);
/* Must be 0 for K8 platform. */
byte = pmio_read(0x68);
byte &= ~0x01;
pmio_write(0x68, byte);
/* Must be 0 for K8 platform. */
byte = pmio_read(0x8d);
byte &= ~(1<<6);
pmio_write(0x8d, byte);
byte = pmio_read(0x61);
byte &= ~0x04;
pmio_write(0x61, byte);
byte = pmio_read(0x42);
byte &= ~0x04;
pmio_write(0x42, byte);
if (get_sb600_revision() == 0x14) {
pmio_write(0x89, 0x10);
byte = pmio_read(0x52);
byte |= 0x80;
pmio_write(0x52, byte);
}
}
void do_hard_reset(void)
{
set_bios_reset();
/* full reset */
outb(0x0a, 0x0cf9);
outb(0x0e, 0x0cf9);
}
void do_soft_reset(void)
{
set_bios_reset();
/* link reset */
outb(0x06, 0x0cf9);
}
void sb600_pci_port80(void)
{
u8 byte;
pci_devfn_t dev;
/* P2P Bridge */
dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0);
/* Chip Control: Enable subtractive decoding */
byte = pci_read_config8(dev, 0x40);
byte |= 1 << 5;
pci_write_config8(dev, 0x40, byte);
/* Misc Control: Enable subtractive decoding if 0x40 bit 5 is set */
byte = pci_read_config8(dev, 0x4B);
byte |= 1 << 7;
pci_write_config8(dev, 0x4B, byte);
/* The same IO Base and IO Limit here is meaningful because we set the
* bridge to be subtractive. During early setup stage, we have to make
* sure that data can go through port 0x80.
*/
/* IO Base: 0xf000 */
byte = pci_read_config8(dev, 0x1C);
byte |= 0xF << 4;
pci_write_config8(dev, 0x1C, byte);
/* IO Limit: 0xf000 */
byte = pci_read_config8(dev, 0x1D);
byte |= 0xF << 4;
pci_write_config8(dev, 0x1D, byte);
/* PCI Command: Enable IO response */
byte = pci_read_config8(dev, 0x04);
byte |= 1 << 0;
pci_write_config8(dev, 0x04, byte);
/* LPC controller */
dev = pci_locate_device(PCI_ID(0x1002, 0x438D), 0);
byte = pci_read_config8(dev, 0x4A);
byte &= ~(1 << 5); /* disable lpc port 80 */
pci_write_config8(dev, 0x4A, byte);
}
void sb600_lpc_port80(void)
{
u8 byte;
pci_devfn_t dev;
u32 reg32;
/* Enable LPC controller */
dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0);
reg32 = pci_read_config32(dev, 0x64);
reg32 |= 0x00100000; /* lpcEnable */
pci_write_config32(dev, 0x64, reg32);
/* Enable port 80 LPC decode in pci function 3 configuration space. */
dev = pci_locate_device(PCI_ID(0x1002, 0x438d), 0);
byte = pci_read_config8(dev, 0x4a);
byte |= 1 << 5; /* enable port 80 */
pci_write_config8(dev, 0x4a, byte);
}
/* sbDevicesPorInitTable */
static void sb600_devices_por_init(void)
{
pci_devfn_t dev;
u8 byte;
printk(BIOS_INFO, "sb600_devices_por_init()\n");
/* SMBus Device, BDF:0-20-0 */
printk(BIOS_INFO, "sb600_devices_por_init(): SMBus Device, BDF:0-20-0\n");
dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0);
if (dev == PCI_DEV_INVALID) {
die("SMBUS controller not found\n");
/* NOT REACHED */
}
printk(BIOS_INFO, "SMBus controller enabled, sb revision is 0x%x\n",
get_sb600_revision());
/* sbPorAtStartOfTblCfg */
/* Set A-Link bridge access address. This address is set at device 14h, function 0, register 0xf0.
* This is an I/O address. The I/O address must be on 16-byte boundary. */
pci_write_config32(dev, 0xf0, AB_INDX);
/* To enable AB/BIF DMA access, a specific register inside the BIF register space needs to be configured first. */
/*Enables the SB600 to send transactions upstream over A-Link Express interface. */
axcfg_reg(0x04, 1 << 2, 1 << 2);
axindxc_reg(0x21, 0xff, 0);
/* 2.3.5:Enabling Non-Posted Memory Write for the K8 Platform */
axindxc_reg(0x10, 1 << 9, 1 << 9);
/* END of sbPorAtStartOfTblCfg */
/* sbDevicesPorInitTables */
/* set smbus iobase */
pci_write_config32(dev, 0x10, SMBUS_IO_BASE | 1);
/* enable smbus controller interface */
byte = pci_read_config8(dev, 0xd2);
byte |= (1 << 0);
pci_write_config8(dev, 0xd2, byte);
/* set smbus 1, ASF 2.0 (Alert Standard Format), iobase */
pci_write_config16(dev, 0x58, SMBUS_IO_BASE | 0x11);
/* TODO: I don't know the usage of followed two lines. I copied them from CIM. */
pci_write_config8(dev, 0x0a, 0x1);
pci_write_config8(dev, 0x0b, 0x6);
/* KB2RstEnable */
pci_write_config8(dev, 0x40, 0xd4);
/* Enable ISA Address 0-960K decoding */
pci_write_config8(dev, 0x48, 0x0f);
/* Enable ISA Address 0xC0000-0xDFFFF decode */
pci_write_config8(dev, 0x49, 0xff);
/* Enable decode cycles to IO C50, C51, C52 GPM controls. */
byte = pci_read_config8(dev, 0x41);
byte &= 0x80;
byte |= 0x33;
pci_write_config8(dev, 0x41, byte);
/* Legacy DMA Prefetch Enhancement, CIM masked it. */
/* pci_write_config8(dev, 0x43, 0x1); */
/* Disabling Legacy USB Fast SMI# */
byte = pci_read_config8(dev, 0x62);
byte |= 0x24;
pci_write_config8(dev, 0x62, byte);
/* Features Enable */
pci_write_config32(dev, 0x64, 0x829E7DBF); /* bit10: Enables the HPET interrupt. */
/* SerialIrq Control */
pci_write_config8(dev, 0x69, 0x90);
/* Test Mode, PCIB_SReset_En Mask is set. */
pci_write_config8(dev, 0x6c, 0x20);
/* IO Address Enable, CIM set 0x78 only and masked 0x79. */
/*pci_write_config8(dev, 0x79, 0x4F); */
pci_write_config8(dev, 0x78, 0xFF);
/* This register is not used on sb600. It came from older chipset. */
/*pci_write_config8(dev, 0x95, 0xFF); */
/* Set smbus iospace enable, I don't know why write 0x04 into reg5 that is reserved */
pci_write_config16(dev, 0x4, 0x0407);
/* clear any lingering errors, so the transaction will run */
outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
/* IDE Device, BDF:0-20-1 */
printk(BIOS_INFO, "sb600_devices_por_init(): IDE Device, BDF:0-20-1\n");
dev = pci_locate_device(PCI_ID(0x1002, 0x438C), 0);
/* Disable prefetch */
byte = pci_read_config8(dev, 0x63);
byte |= 0x1;
pci_write_config8(dev, 0x63, byte);
/* LPC Device, BDF:0-20-3 */
printk(BIOS_INFO, "sb600_devices_por_init(): LPC Device, BDF:0-20-3\n");
dev = pci_locate_device(PCI_ID(0x1002, 0x438D), 0);
/* DMA enable */
pci_write_config8(dev, 0x40, 0x04);
/* LPC Sync Timeout */
pci_write_config8(dev, 0x49, 0xFF);
/* Enable Tpm12_en and Tpm_legacy. I don't know what is its usage and copied from CIM. */
pci_write_config8(dev, 0x7C, 0x05);
/* P2P Bridge, BDF:0-20-4, the configuration of the registers in this dev are copied from CIM,
* TODO: I don't know what are their mean? */
printk(BIOS_INFO, "sb600_devices_por_init(): P2P Bridge, BDF:0-20-4\n");
dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0);
/* I don't know why CIM tried to write into a read-only reg! */
/*pci_write_config8(dev, 0x0c, 0x20); */
/* Arbiter enable. */
pci_write_config8(dev, 0x43, 0xff);
/* Set PCDMA request into height priority list. */
/* pci_write_config8(dev, 0x49, 0x1); */
pci_write_config8(dev, 0x40, 0x26);
/* I don't know why CIM set reg0x1c as 0x11.
* System will block at sdram_initialize() if I set it before call sdram_initialize().
* If it is necessary to set reg0x1c as 0x11, please call this function after sdram_initialize().
* pci_write_config8(dev, 0x1c, 0x11);
* pci_write_config8(dev, 0x1d, 0x11);*/
/*CIM set this register; but I didn't find its description in RPR.
On DBM690T platform, I didn't find different between set and skip this register.
But on Filbert platform, the DEBUG message from serial port on Peanut board can't be displayed
after the bit0 of this register is set.
pci_write_config8(dev, 0x04, 0x21);
*/
pci_write_config8(dev, 0x0d, 0x40);
pci_write_config8(dev, 0x1b, 0x40);
/* Enable PCIB_DUAL_EN_UP will fix potential problem with PCI cards. */
pci_write_config8(dev, 0x50, 0x01);
/* SATA Device, BDF:0-18-0, Non-Raid-5 SATA controller */
printk(BIOS_INFO, "sb600_devices_por_init(): SATA Device, BDF:0-18-0\n");
dev = pci_locate_device(PCI_ID(0x1002, 0x4380), 0);
/*PHY Global Control, we are using A14.
* default: 0x2c40 for ASIC revision A12 and below
* 0x2c00 for ASIC revision A13 and above.*/
pci_write_config16(dev, 0x86, 0x2C00);
/* PHY Port0-3 Control */
pci_write_config32(dev, 0x88, 0xB400DA);
pci_write_config32(dev, 0x8c, 0xB400DA);
pci_write_config32(dev, 0x90, 0xB400DA);
pci_write_config32(dev, 0x94, 0xB400DA);
/* Port0-3 BIST Control/Status */
pci_write_config8(dev, 0xa5, 0xB8);
pci_write_config8(dev, 0xad, 0xB8);
pci_write_config8(dev, 0xb5, 0xB8);
pci_write_config8(dev, 0xbd, 0xB8);
}
/* sbPmioPorInitTable, Pre-initializing PMIO register space
* The power management (PM) block is resident in the PCI/LPC/ISA bridge.
* The PM regs are accessed via IO mapped regs 0xcd6 and 0xcd7.
* The index address is first programmed into IO reg 0xcd6.
* Read or write values are accessed through IO reg 0xcd7.
*/
static void sb600_pmio_por_init(void)
{
u8 byte;
printk(BIOS_INFO, "sb600_pmio_por_init()\n");
/* K8KbRstEn, KB_RST# control for K8 system. */
byte = pmio_read(0x66);
byte |= 0x20;
pmio_write(0x66, byte);
/* RPR2.3.4 S3/S4/S5 Function for the K8 Platform. */
byte = pmio_read(0x52);
byte &= 0xc0;
byte |= 0x08;
pmio_write(0x52, byte);
/* C state enable and SLP enable in C states. */
byte = pmio_read(0x67);
byte |= 0x6;
pmio_write(0x67, byte);
/* CIM sets 0x0e, but bit2 is for P4 system. */
byte = pmio_read(0x68);
byte &= 0xf0;
byte |= 0x0c;
pmio_write(0x68, byte);
/* Watch Dog Timer Control
* Set watchdog time base to 0xfec000f0 to avoid SCSI card boot failure.
* But I don't find WDT is enabled in SMBUS 0x41 bit3 in CIM.
*/
pmio_write(0x6c, 0xf0);
pmio_write(0x6d, 0x00);
pmio_write(0x6e, 0xc0);
pmio_write(0x6f, 0xfe);
/* rpr2.14: Enables HPET periodical mode */
byte = pmio_read(0x9a);
byte |= 1 << 7;
pmio_write(0x9a, byte);
byte = pmio_read(0x9f);
byte |= 1 << 5;
pmio_write(0x9f, byte);
byte = pmio_read(0x9e);
byte |= (1 << 6) | (1 << 7);
pmio_write(0x9e, byte);
/* rpr2.14: Hides SM bus controller Bar1 where stores HPET MMIO base address */
/* We have to clear this bit here, otherwise the kernel hangs. */
byte = pmio_read(0x55);
byte |= 1 << 7;
byte |= 1 << 1;
pmio_write(0x55, byte);
/* rpr2.14: Make HPET MMIO decoding controlled by the memory enable bit in command register of LPC ISA bridge */
byte = pmio_read(0x52);
byte |= 1 << 6;
pmio_write(0x52, byte);
/* rpr2.22: PLL Reset */
byte = pmio_read(0x86);
byte |= 1 << 7;
pmio_write(0x86, byte);
/* rpr2.3.3 */
/* This provides 16us delay before the assertion of LDTSTP# when C3 is entered.
* The delay will allow USB DMA to go on in a continuous manner
*/
pmio_write(0x89, 0x10);
/* Set this bit to allow pop-up request being latched during the minimum LDTSTP# assertion time */
byte = pmio_read(0x52);
byte |= 1 << 7;
pmio_write(0x52, byte);
/* rpr2.15: ASF Remote Control Action */
byte = pmio_read(0x9f);
byte |= 1 << 6;
pmio_write(0x9f, byte);
/* rpr2.19: Enabling Spread Spectrum */
byte = pmio_read(0x42);
byte |= 1 << 7;
pmio_write(0x42, byte);
}
/*
* Compliant with CIM_48's sbPciCfg.
* Add any south bridge setting.
*/
static void sb600_pci_cfg(void)
{
pci_devfn_t dev;
u8 byte;
/* SMBus Device, BDF:0-20-0 */
dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0);
/* Enable the hidden revision ID, available after A13. */
byte = pci_read_config8(dev, 0x70);
byte |= (1 << 8);
pci_write_config8(dev, 0x70, byte);
/* rpr2.20 Disable Timer IRQ Enhancement for proper operation of the 8254 timer, 0xae[5]. */
byte = pci_read_config8(dev, 0xae);
byte |= (1 << 5);
pci_write_config8(dev, 0xae, byte);
/* Enable watchdog decode timer */
byte = pci_read_config8(dev, 0x41);
byte |= (1 << 3);
pci_write_config8(dev, 0x41, byte);
/* Set to 1 to reset USB on the software (such as IO-64 or IO-CF9 cycles)
* generated PCIRST#. */
byte = pmio_read(0x65);
byte |= (1 << 4);
pmio_write(0x65, byte);
/*For A13 and above. */
if (get_sb600_revision() > 0x12) {
/* rpr2.16 C-State Reset, PMIO 0x9f[7]. */
byte = pmio_read(0x9f);
byte |= (1 << 7);
pmio_write(0x9f, byte);
/* rpr2.17 PCI Clock Period will increase to 30.8ns. 0x53[7]. */
byte = pmio_read(0x53);
byte |= (1 << 7);
pmio_write(0x53, byte);
}
/* IDE Device, BDF:0-20-1 */
dev = pci_locate_device(PCI_ID(0x1002, 0x438C), 0);
/* Enable IDE Explicit prefetch, 0x63[0] clear */
byte = pci_read_config8(dev, 0x63);
byte &= 0xfe;
pci_write_config8(dev, 0x63, byte);
/* LPC Device, BDF:0-20-3 */
dev = pci_locate_device(PCI_ID(0x1002, 0x438D), 0);
/* rpr7.2 Enabling LPC DMA function. */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 2);
pci_write_config8(dev, 0x40, byte);
/* rpr7.3 Disabling LPC TimeOut. 0x48[7] clear. */
byte = pci_read_config8(dev, 0x48);
byte &= 0x7f;
pci_write_config8(dev, 0x48, byte);
/* rpr7.5 Disabling LPC MSI Capability, 0x78[1] clear. */
byte = pci_read_config8(dev, 0x78);
byte &= 0xfd;
pci_write_config8(dev, 0x78, byte);
/* SATA Device, BDF:0-18-0, Non-Raid-5 SATA controller */
dev = pci_locate_device(PCI_ID(0x1002, 0x4380), 0);
/* rpr6.8 Disabling SATA MSI Capability, for A13 and above, 0x42[7]. */
if (0x12 < get_sb600_revision()) {
u32 reg32;
reg32 = pci_read_config32(dev, 0x40);
reg32 |= (1 << 23);
pci_write_config32(dev, 0x40, reg32);
}
/* EHCI Device, BDF:0-19-5, ehci usb controller */
dev = pci_locate_device(PCI_ID(0x1002, 0x4386), 0);
/* rpr5.10 Disabling USB EHCI MSI Capability. 0x50[6]. */
byte = pci_read_config8(dev, 0x50);
byte |= (1 << 6);
pci_write_config8(dev, 0x50, byte);
/* OHCI0 Device, BDF:0-19-0, ohci usb controller #0 */
dev = pci_locate_device(PCI_ID(0x1002, 0x4387), 0);
/* rpr5.11 Disabling USB OHCI MSI Capability. 0x40[12:8]=0x1f. */
byte = pci_read_config8(dev, 0x41);
byte |= 0x1f;
pci_write_config8(dev, 0x41, byte);
}
/*
* Compliant with CIM_48's ATSBPowerOnResetInitJSP
*/
static void sb600_por_init(void)
{
/* sbDevicesPorInitTable + sbK8PorInitTable */
sb600_devices_por_init();
/* sbPmioPorInitTable + sbK8PmioPorInitTable */
sb600_pmio_por_init();
}
/*
* Compliant with CIM_48's AtiSbBeforePciInit
* It should be called during early POST after memory detection and BIOS shadowing but before PCI bus enumeration.
*/
static void sb600_before_pci_init(void)
{
sb600_pci_cfg();
}
/*
* This function should be called after enable_sb600_smbus().
*/
static void sb600_early_setup(void)
{
printk(BIOS_INFO, "sb600_early_setup()\n");
sb600_por_init();
}
static int smbus_read_byte(u32 device, u32 address)
{
return do_smbus_read_byte(SMBUS_IO_BASE, device, address);
}

View File

@@ -1,34 +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.
*/
// Use simple device model for this file even in ramstage
#define __SIMPLE_DEVICE__
#include <stdint.h>
#include <arch/io.h>
#include <device/pci_ehci.h>
#include <device/pci_def.h>
#include "sb600.h"
pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
{
return PCI_DEV(0, 0x13, 5); /* USB EHCI, D19:F5 */
}
/* Required for successful build, but currently empty. */
void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
{
/* TODO: Allow changing the physical USB port used as Debug Port. */
}

View File

@@ -1,325 +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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
#include <delay.h>
#include "sb600.h"
#define HDA_ICII_REG 0x68
#define HDA_ICII_BUSY (1 << 0)
#define HDA_ICII_VALID (1 << 1)
static int set_bits(void *port, u32 mask, u32 val)
{
u32 dword;
int count;
/* Write (val & ~mask) to port */
val &= mask;
dword = read32(port);
dword &= ~mask;
dword |= val;
write32(port, dword);
/* Wait for readback of register to
* match what was just written to it
*/
count = 50;
do {
/* Wait 1ms based on BKDG wait time */
mdelay(1);
dword = read32(port);
dword &= mask;
} while ((dword != val) && --count);
/* Timeout occurred */
if (!count)
return -1;
return 0;
}
static u32 codec_detect(void *base)
{
u32 dword;
/* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */
if (set_bits(base + 0x08, 1, 0) == -1)
goto no_codec;
/* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
if (set_bits(base + 0x08, 1, 1) == -1)
goto no_codec;
/* Delay for 1 ms since the BKDG does */
mdelay(1);
/* Read in Codec location (BAR + 0xe)[3..0]*/
dword = read32(base + 0xe);
dword &= 0x0F;
if (!dword)
goto no_codec;
return dword;
no_codec:
/* Codec Not found */
/* Put HDA back in reset (BAR + 0x8) [0] */
set_bits(base + 0x08, 1, 0);
printk(BIOS_DEBUG, "No codec!\n");
return 0;
}
static u32 cim_verb_data[] = {
0x01471c10,
0x01471d40,
0x01471e01,
0x01471f01,
/* 1 */
0x01571c12,
0x01571d10,
0x01571e01,
0x01571f01,
/* 2 */
0x01671c11,
0x01671d60,
0x01671e01,
0x01671f01,
/* 3 */
0x01771c14,
0x01771d20,
0x01771e01,
0x01771f01,
/* 4 */
0x01871c30,
0x01871d90,
0x01871ea1,
0x01871f01,
/* 5 */
0x01971cf0,
0x01971d11,
0x01971e11,
0x01971f41,
/* 6 */
0x01a71c80,
0x01a71d30,
0x01a71e81,
0x01a71f01,
/* 7 */
0x01b71cf0,
0x01b71d11,
0x01b71e11,
0x01b71f41,
/* 8 */
0x01c71cf0,
0x01c71d11,
0x01c71e11,
0x01c71f41,
/* 9 */
0x01d71cf0,
0x01d71d11,
0x01d71e11,
0x01d71f41,
/* 10 */
0x01e71c50,
0x01e71d11,
0x01e71e44,
0x01e71f01,
/* 11 */
0x01f71c60,
0x01f71d61,
0x01f71ec4,
0x01f71f01,
};
static u32 find_verb(u32 viddid, u32 ** verb)
{
struct device *azalia_dev = dev_find_slot(0, PCI_DEVFN(0x14, 2));
struct southbridge_amd_sb600_config *cfg =
(struct southbridge_amd_sb600_config *)azalia_dev->chip_info;
if (!cfg)
return 0;
printk(BIOS_DEBUG, "Dev=%s\n", dev_path(azalia_dev));
printk(BIOS_DEBUG, "Default viddid=%x\n", cfg->hda_viddid);
printk(BIOS_DEBUG, "Reading viddid=%x\n", viddid);
if (viddid != cfg->hda_viddid)
return 0;
*verb = (u32 *) cim_verb_data;
return sizeof(cim_verb_data) / sizeof(u32);
}
/**
* Wait 50usec for the codec to indicate it is ready
* no response would imply that the codec is non-operative
*/
static int wait_for_ready(void *base)
{
/* Use a 50 usec timeout - the Linux kernel uses the
* same duration */
int timeout = 50;
while (timeout--) {
u32 dword = read32(base + HDA_ICII_REG);
if (!(dword & HDA_ICII_BUSY))
return 0;
udelay(1);
}
return -1;
}
/**
* Wait 50usec for the codec to indicate that it accepted
* the previous command. No response would imply that the code
* is non-operative
*/
static int wait_for_valid(void *base)
{
/* Use a 50 usec timeout - the Linux kernel uses the
* same duration */
int timeout = 50;
while (timeout--) {
u32 dword = read32(base + HDA_ICII_REG);
if ((dword & (HDA_ICII_VALID | HDA_ICII_BUSY)) ==
HDA_ICII_VALID)
return 0;
udelay(1);
}
return -1;
}
static void codec_init(void *base, int addr)
{
u32 dword;
u32 *verb;
u32 verb_size;
int i;
/* 1 */
if (wait_for_ready(base) == -1)
return;
dword = (addr << 28) | 0x000f0000;
write32(base + 0x60, dword);
if (wait_for_valid(base) == -1)
return;
dword = read32(base + 0x64);
/* 2 */
printk(BIOS_DEBUG, "codec viddid: %08x\n", dword);
verb_size = find_verb(dword, &verb);
if (!verb_size) {
printk(BIOS_DEBUG, "No verb!\n");
return;
}
printk(BIOS_DEBUG, "verb_size: %d\n", verb_size);
/* 3 */
for (i = 0; i < verb_size; i++) {
if (wait_for_ready(base) == -1)
return;
write32(base + 0x60, verb[i]);
if (wait_for_valid(base) == -1)
return;
}
printk(BIOS_DEBUG, "verb loaded!\n");
}
static void codecs_init(void *base, u32 codec_mask)
{
int i;
for (i = 2; i >= 0; i--) {
if (codec_mask & (1 << i))
codec_init(base, i);
}
}
static void hda_init(struct device *dev)
{
u8 byte;
u32 dword;
void *base;
struct resource *res;
u32 codec_mask;
struct device *sm_dev;
/* Enable azalia - PM_io 0x59[4], disable ac97 - PM_io 0x59[1..0] */
pm_iowrite(0x59, 0xB);
/* Find the SMBus */
sm_dev = dev_find_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SB600_SM, 0);
/* Set routing pin - SMBus ExtFunc (0xf8/0xfc) */
pci_write_config32(sm_dev, 0xf8, 0x00);
pci_write_config8(sm_dev, 0xfc, 0xAA);
/* Set INTA - SMBus 0x63 [2..0] */
byte = pci_read_config8(sm_dev, 0x63);
byte &= ~0x7;
byte |= 0x0; /* INTA:0x0 - INTH:0x7 */
pci_write_config8(sm_dev, 0x63, byte);
/* Program the 2C to 0x437b1002 */
dword = 0x437b1002;
pci_write_config32(dev, 0x2c, dword);
/* Read in BAR */
/* Is this right? HDA allows for a 64-bit BAR
* but this is only setup for a 32-bit one
*/
res = find_resource(dev, 0x10);
if (!res)
return;
base = res2mmio(res, 0, 0);
printk(BIOS_DEBUG, "base = 0x%p\n", base);
codec_mask = codec_detect(base);
if (codec_mask) {
printk(BIOS_DEBUG, "codec_mask = %02x\n", codec_mask);
codecs_init(base, codec_mask);
}
}
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations hda_audio_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
/*.enable = sb600_enable, */
.init = hda_init,
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const struct pci_driver hdaaudio_driver __pci_driver = {
.ops = &hda_audio_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB600_HDA,
};

View File

@@ -1,63 +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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include "sb600.h"
static void ide_init(struct device *dev)
{
/* Enable ide devices so the linux ide driver will work */
u32 dword;
u8 byte;
/* RPR10.1 disable MSI */
dword = pci_read_config32(dev, 0x70);
dword &= ~(1 << 16);
pci_write_config32(dev, 0x70, dword);
/* Enable UDMA on all devices, it will become UDMA0 (default PIO is PIO0) */
byte = pci_read_config8(dev, 0x54);
byte |= 0xf;
pci_write_config8(dev, 0x54, byte);
/* Enable I/O Access&& Bus Master */
dword = pci_read_config16(dev, 0x4);
dword |= 1 << 2;
pci_write_config16(dev, 0x4, dword);
}
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations ide_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = ide_init,
.scan_bus = 0,
/* .enable = sb600_enable, */
.ops_pci = &lops_pci,
};
static const struct pci_driver ide_driver __pci_driver = {
.ops = &ide_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB600_IDE,
};

View File

@@ -1,254 +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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pnp.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <pc80/mc146818rtc.h>
#include <pc80/i8254.h>
#include <pc80/i8259.h>
#include <arch/acpi.h>
#include <arch/acpigen.h>
#include <pc80/isa-dma.h>
#include <arch/io.h>
#include <arch/ioapic.h>
#include <arch/acpi.h>
#include <cpu/amd/powernow.h>
#include "sb600.h"
static void lpc_init(struct device *dev)
{
u8 byte;
u32 dword;
struct device *sm_dev;
/* Enable the LPC Controller */
sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
dword = pci_read_config32(sm_dev, 0x64);
dword |= 1 << 20;
pci_write_config32(sm_dev, 0x64, dword);
/* Initialize isa dma */
isa_dma_init();
/* RPR 7.2 Enable DMA transaction on the LPC bus */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 2);
pci_write_config8(dev, 0x40, byte);
/* RPR 7.3 Disable the timeout mechanism on LPC */
byte = pci_read_config8(dev, 0x48);
byte &= ~(1 << 7);
pci_write_config8(dev, 0x48, byte);
/* RPR 7.5 Disable LPC MSI Capability */
byte = pci_read_config8(dev, 0x78);
byte &= ~(1 << 1);
pci_write_config8(dev, 0x78, byte);
cmos_check_update_date();
setup_i8259(); /* Initialize i8259 pic */
setup_i8254(); /* Initialize i8254 timers */
}
static void sb600_lpc_read_resources(struct device *dev)
{
struct resource *res;
/* Get the normal pci resources of this device */
pci_dev_read_resources(dev); /* We got one for APIC, or one more for TRAP */
pci_get_resource(dev, 0xA0); /* SPI ROM base address */
/* Add an extra subtractive resource for both memory and I/O. */
res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
res->base = 0;
res->size = 0x1000;
res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
res->base = 0xff800000;
res->size = 0x00800000; /* 8 MB for flash */
res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
res = new_resource(dev, 3); /* IOAPIC */
res->base = IO_APIC_ADDR;
res->size = 0x00001000;
res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
compact_resources(dev);
}
/**
* @brief Enable resources for children devices
*
* @param dev the device whose children's resources are to be enabled
*
*/
static void sb600_lpc_enable_childrens_resources(struct device *dev)
{
struct bus *link;
u32 reg, reg_x;
int var_num = 0;
u16 reg_var[3] = {0x0, 0x0, 0x0};
u8 wiosize = pci_read_config8(dev, 0x74);
reg = pci_read_config32(dev, 0x44);
reg_x = pci_read_config32(dev, 0x48);
for (link = dev->link_list; link; link = link->next) {
struct device *child;
for (child = link->children; child;
child = child->sibling) {
if (child->enabled
&& (child->path.type == DEVICE_PATH_PNP)) {
struct resource *res;
for (res = child->resource_list; res; res = res->next) {
u32 base, end; /* don't need long long */
if (!(res->flags & IORESOURCE_IO))
continue;
base = res->base;
end = resource_end(res);
printk(BIOS_DEBUG, "sb600 lpc decode:%s, base=0x%08x, end=0x%08x\n",
dev_path(child), base, end);
switch (base) {
case 0x60: /* KB */
case 0x64: /* MS */
reg |= (1 << 29);
break;
case 0x3f8: /* COM1 */
reg |= (1 << 6);
break;
case 0x2f8: /* COM2 */
reg |= (1 << 7);
break;
case 0x378: /* Parallel 1 */
reg |= (1 << 0);
reg |= (1 << 1); /* + 0x778 for ECP */
break;
case 0x3f0: /* FD0 */
reg |= (1 << 26);
break;
case 0x220: /* Audio 0 */
reg |= (1 << 8);
break;
case 0x300: /* Midi 0 */
reg |= (1 << 18);
break;
case 0x400:
reg_x |= (1 << 16);
break;
case 0x480:
reg_x |= (1 << 17);
break;
case 0x500:
reg_x |= (1 << 18);
break;
case 0x580:
reg_x |= (1 << 19);
break;
case 0x4700:
reg_x |= (1 << 22);
break;
case 0xfd60:
reg_x |= (1 << 23);
break;
default:
if (var_num >= 3)
continue; /* only 3 var ; compact them ? */
switch (var_num) {
case 0:
reg_x |= (1 << 2);
if ((end - base) < 16)
wiosize |= (1 << 0);
break;
case 1:
reg_x |= (1 << 24);
if ((end - base) < 16)
wiosize |= (1 << 2);
break;
case 2:
reg_x |= (1 << 25);
reg_x |= (1 << 24);
if ((end - base) < 16)
wiosize |= (1 << 3);
break;
}
reg_var[var_num++] =
base & 0xffff;
}
}
}
}
}
pci_write_config32(dev, 0x44, reg);
pci_write_config32(dev, 0x48, reg_x);
/* Set WideIO for as many IOs found (fall through is on purpose) */
switch (var_num) {
case 2:
pci_write_config16(dev, 0x90, reg_var[2]);
case 1:
pci_write_config16(dev, 0x66, reg_var[1]);
case 0:
pci_write_config16(dev, 0x64, reg_var[0]);
break;
}
pci_write_config8(dev, 0x74, wiosize);
}
static void sb600_lpc_enable_resources(struct device *dev)
{
pci_dev_enable_resources(dev);
sb600_lpc_enable_childrens_resources(dev);
}
#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
extern u16 pm_base;
static void southbridge_acpi_fill_ssdt_generator(struct device *device) {
amd_generate_powernow(pm_base + 8, 6, 1);
}
#endif
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations lpc_ops = {
.read_resources = sb600_lpc_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = sb600_lpc_enable_resources,
#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
.write_acpi_tables = acpi_write_hpet,
.acpi_fill_ssdt_generator = southbridge_acpi_fill_ssdt_generator,
#endif
.init = lpc_init,
.scan_bus = scan_lpc_bus,
/* .enable = sb600_enable, */
.ops_pci = &lops_pci,
};
static const struct pci_driver lpc_driver __pci_driver = {
.ops = &lpc_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB600_LPC,
};

View File

@@ -1,138 +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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include "sb600.h"
static void pci_init(struct device *dev)
{
u32 dword;
u16 word;
u8 byte;
/* RPR 4.1 Enables the PCI-bridge subtractive decode */
/* This setting is strongly recommended since it supports some legacy PCI add-on cards,such as BIOS debug cards */
byte = pci_read_config8(dev, 0x4B);
byte |= 1 << 7;
pci_write_config8(dev, 0x4B, byte);
byte = pci_read_config8(dev, 0x40);
byte |= 1 << 5;
pci_write_config8(dev, 0x40, byte);
/* RPR4.2 PCI-bridge upstream dual address window */
/* this setting is applicable if the system memory is more than 4GB,and the PCI device can support dual address access */
byte = pci_read_config8(dev, 0x50);
byte |= 1 << 0;
pci_write_config8(dev, 0x50, byte);
/* RPR 4.3 PCI bus 64-byte DMA read access */
/* Enhance the PCI bus DMA performance */
byte = pci_read_config8(dev, 0x4B);
byte |= 1 << 4;
pci_write_config8(dev, 0x4B, byte);
/* RPR 4.4 Enables the PCIB writes to be cacheline aligned. */
/* The size of the writes will be set in the Cacheline Register */
byte = pci_read_config8(dev, 0x40);
byte |= 1 << 1;
pci_write_config8(dev, 0x40, byte);
/* RPR 4.5 Enables the PCIB to retain ownership of the bus on the Primary side and on the Secondary side when GNT# is deasserted */
pci_write_config8(dev, 0x0D, 0x40);
pci_write_config8(dev, 0x1B, 0x40);
/* RPR 4.6 Enable the command matching checking function on "Memory Read" & "Memory Read Line" commands */
byte = pci_read_config8(dev, 0x4B);
byte |= 1 << 6;
pci_write_config8(dev, 0x4B, byte);
/* RPR 4.7 When enabled, the PCI arbiter checks for the Bus Idle before asserting GNT# */
byte = pci_read_config8(dev, 0x4B);
byte |= 1 << 0;
pci_write_config8(dev, 0x4B, byte);
/* RPR 4.8 Adjusts the GNT# de-assertion time */
word = pci_read_config16(dev, 0x64);
word |= 1 << 12;
pci_write_config16(dev, 0x64, word);
/* RPR 4.9 Fast Back to Back transactions support */
byte = pci_read_config8(dev, 0x48);
byte |= 1 << 2;
pci_write_config8(dev, 0x48, byte);
/* RPR 4.10 Enable Lock Operation */
byte = pci_read_config8(dev, 0x48);
byte |= 1 << 3;
pci_write_config8(dev, 0x48, byte);
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 2);
pci_write_config8(dev, 0x40, byte);
/* RPR 4.11 Enable additional optional PCI clock */
word = pci_read_config16(dev, 0x64);
word |= 1 << 8;
pci_write_config16(dev, 0x64, word);
/* rpr4.12 Disable Fewer-Retry Mode for A11-A13 only. 0x64[5:4] clear */
byte = pci_read_config8(dev, 0x64);
byte &= 0xcf;
pci_write_config8(dev, 0x64, byte);
/* rpr4.14 Disabling Downstream Flush, for A12 only, 0x64[18]. */
dword = pci_read_config32(dev, 0x64);
dword |= (1 << 18);
pci_write_config32(dev, 0x64, dword);
/* RPR 4.13 Enable One-Prefetch-Channel Mode */
dword = pci_read_config32(dev, 0x64);
dword |= 1 << 20;
pci_write_config32(dev, 0x64, dword);
/* RPR 4.15 Disable PCIB MSI Capability */
byte = pci_read_config8(dev, 0x40);
byte &= ~(1 << 3);
pci_write_config8(dev, 0x40, byte);
/* rpr4.16 Adjusting CLKRUN# */
dword = pci_read_config32(dev, 0x64);
dword |= (1 << 15);
pci_write_config32(dev, 0x64, dword);
}
static struct pci_operations lops_pci = {
.set_subsystem = 0,
};
static struct device_operations pci_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.init = pci_init,
.scan_bus = pci_scan_bridge,
/* .enable = sb600_enable, */
.reset_bus = pci_bus_reset,
.ops_pci = &lops_pci,
};
static const struct pci_driver pci_driver __pci_driver = {
.ops = &pci_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB600_PCI,
};

View File

@@ -1,31 +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.
*/
// Use simple device model for this file even in ramstage
#define __SIMPLE_DEVICE__
#include <arch/io.h>
#include <reset.h>
#include <northbridge/amd/amdk8/reset_test.c>
void do_hard_reset(void)
{
set_bios_reset();
/* Try rebooting through port 0xcf9 */
/* Actually it is not a real hard_reset --- it only reset coherent link table, but not reset link freq and width */
outb((0 << 3) | (0 << 2) | (1 << 1), 0xcf9);
outb((0 << 3) | (1 << 2) | (1 << 1), 0xcf9);
}

View File

@@ -1,271 +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.
*/
#include <console/console.h>
#include <device/device.h>
#include <delay.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
#include "sb600.h"
#include <pc80/mc146818rtc.h>
#define SATA_MODE_IDE 1
#define SATA_MODE_AHCI 0
static int sata_drive_detect(int portnum, u16 iobar)
{
u8 byte, byte2;
int i = 0;
outb(0xA0 + 0x10 * (portnum % 2), iobar + 0x6);
while (byte = inb(iobar + 0x6), byte2 = inb(iobar + 0x7),
(byte != (0xA0 + 0x10 * (portnum % 2))) ||
((byte2 & 0x88) != 0)) {
printk(BIOS_SPEW, "0x6=%x, 0x7=%x\n", byte, byte2);
if (byte != (0xA0 + 0x10 * (portnum % 2))) {
/* This will happen at the first iteration of this loop
* if the first SATA port is unpopulated and the
* second SATA port is populated.
*/
printk(BIOS_DEBUG, "drive no longer selected after %i ms, "
"retrying init\n", i * 10);
return 1;
} else
printk(BIOS_SPEW, "drive detection not yet completed, "
"waiting...\n");
mdelay(10);
i++;
}
printk(BIOS_SPEW, "drive detection done after %i ms\n", i * 10);
return 0;
}
static void sata_init(struct device *dev)
{
u8 byte;
u16 word;
u32 dword;
void *sata_bar5;
u16 sata_bar0, sata_bar1, sata_bar2, sata_bar3, sata_bar4;
int i, j;
struct southbridge_ati_sb600_config *conf;
conf = dev->chip_info;
struct device *sm_dev;
/* SATA SMBus Disable */
/* sm_dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0); */
sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
/* Disable SATA SMBUS */
byte = pci_read_config8(sm_dev, 0xad);
byte |= (1 << 1);
/* Enable SATA and power saving */
byte = pci_read_config8(sm_dev, 0xad);
byte |= (1 << 0);
byte |= (1 << 5);
pci_write_config8(sm_dev, 0xad, byte);
/* Set the interrupt Mapping to INTG# */
byte = pci_read_config8(sm_dev, 0xaf);
byte = 0x6 << 2;
pci_write_config8(sm_dev, 0xaf, byte);
/* get base address */
sata_bar5 = (void *)(pci_read_config32(dev, 0x24) & ~0x3FF);
sata_bar0 = pci_read_config16(dev, 0x10) & ~0x7;
sata_bar1 = pci_read_config16(dev, 0x14) & ~0x3;
sata_bar2 = pci_read_config16(dev, 0x18) & ~0x7;
sata_bar3 = pci_read_config16(dev, 0x1C) & ~0x3;
sata_bar4 = pci_read_config16(dev, 0x20) & ~0xf;
printk(BIOS_SPEW, "sata_bar0=%x\n", sata_bar0); /* 3030 */
printk(BIOS_SPEW, "sata_bar1=%x\n", sata_bar1); /* 3070 */
printk(BIOS_SPEW, "sata_bar2=%x\n", sata_bar2); /* 3040 */
printk(BIOS_SPEW, "sata_bar3=%x\n", sata_bar3); /* 3080 */
printk(BIOS_SPEW, "sata_bar4=%x\n", sata_bar4); /* 3000 */
printk(BIOS_SPEW, "sata_bar5=%p\n", sata_bar5); /* e0309000 */
/* SERR-Enable */
word = pci_read_config16(dev, 0x04);
word |= (1 << 8);
pci_write_config16(dev, 0x04, word);
/* Dynamic power saving */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 2);
pci_write_config8(dev, 0x40, byte);
/* Set SATA Operation Mode */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 0);
byte |= (1 << 4);
pci_write_config8(dev, 0x40, byte);
// 1 means IDE, 0 means AHCI
i = CONFIG_SATA_MODE;
get_option(&i, "sata_mode");
printk(BIOS_INFO, "%s: setting sata mode = %s\n", __func__, (i == SATA_MODE_IDE)?"ide":"ahci" );
dword = pci_read_config32(dev, 0x8);
dword &= 0xff0000ff;
if (i == SATA_MODE_IDE)
dword |= 0x00018f00; // IDE mode
else
dword |= 0x00060100; // AHCI mode
pci_write_config32(dev, 0x8, dword);
byte = pci_read_config8(dev, 0x40);
byte &= ~(1 << 0);
pci_write_config8(dev, 0x40, byte);
/* Enable the SATA watchdog counter */
byte = pci_read_config8(dev, 0x44);
byte |= (1 << 0);
pci_write_config8(dev, 0x44, byte);
/* Program the watchdog counter to 0x10 */
byte = 0x10;
pci_write_config8(dev, 0x46, byte);
/* RPR6.5 Program the PHY Global Control to 0x2C00 for A13 */
word = 0x2c00;
pci_write_config16(dev, 0x86, word);
/* RPR6.5 Program the Phy Tuning4Ports */
dword = 0x00B401D6;
pci_write_config32(dev, 0x88, dword);
pci_write_config32(dev, 0x8c, dword);
pci_write_config32(dev, 0x90, dword);
pci_write_config32(dev, 0x94, dword);
byte = 0xB8;
pci_write_config8(dev, 0xA5, byte);
pci_write_config8(dev, 0xAD, byte);
pci_write_config8(dev, 0xB5, byte);
pci_write_config8(dev, 0xBD, byte);
/* RPR 6.8 */
word = pci_read_config16(dev, 0x42);
word |= 1 << 7;
pci_write_config16(dev, 0x42, word);
/* RPR 6.9 */
dword = pci_read_config32(dev, 0x40);
dword |= 1 << 25;
pci_write_config32(dev, 0x40, dword);
/* Enable the I/O, MM, BusMaster access for SATA */
byte = pci_read_config8(dev, 0x4);
byte |= 7 << 0;
pci_write_config8(dev, 0x4, byte);
/* RPR6.6 SATA drive detection. */
/* Use BAR5+0x128,BAR0 for Primary Slave */
/* Use BAR5+0x1A8,BAR0 for Primary Slave */
/* Use BAR5+0x228,BAR2 for Secondary Master */
/* Use BAR5+0x2A8,BAR2 for Secondary Slave */
for (i = 0; i < 4; i++) {
byte = read8(sata_bar5 + 0x128 + 0x80 * i);
printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte);
byte &= 0xF;
if ( byte == 0x1 ) {
/* If the drive status is 0x1 then we see it but we aren't talking to it. */
/* Try to do something about it. */
printk(BIOS_SPEW, "SATA device detected but not talking. Trying lower speed.\n");
/* Read in Port-N Serial ATA Control Register */
byte = read8(sata_bar5 + 0x12C + 0x80 * i);
/* Set Reset Bit and 1.5g bit */
byte |= 0x11;
write8((sata_bar5 + 0x12C + 0x80 * i), byte);
/* Wait 1ms */
mdelay(1);
/* Clear Reset Bit */
byte &= ~0x01;
write8((sata_bar5 + 0x12C + 0x80 * i), byte);
/* Wait 1ms */
mdelay(1);
/* Reread status */
byte = read8(sata_bar5 + 0x128 + 0x80 * i);
printk(BIOS_SPEW, "SATA port %i status = %x\n", i, byte);
byte &= 0xF;
}
if (byte == 0x3) {
for (j = 0; j < 10; j++) {
if (!sata_drive_detect(i, ((i / 2) == 0) ? sata_bar0 : sata_bar2))
break;
}
printk(BIOS_DEBUG, "%s %s device is %sready after %i tries\n",
(i / 2) ? "Secondary" : "Primary",
(i % 2 ) ? "Slave" : "Master",
(j == 10) ? "not " : "",
(j == 10) ? j : j + 1);
} else {
printk(BIOS_DEBUG, "No %s %s SATA drive on Slot%i\n",
(i / 2) ? "Secondary" : "Primary",
(i % 2 ) ? "Slave" : "Master", i);
}
}
/* Below is CIM InitSataLateFar */
/* Enable interrupts from the HBA */
byte = read8(sata_bar5 + 0x4);
byte |= 1 << 1;
write8((sata_bar5 + 0x4), byte);
/* Clear error status */
write32((sata_bar5 + 0x130), 0xFFFFFFFF);
write32((sata_bar5 + 0x1b0), 0xFFFFFFFF);
write32((sata_bar5 + 0x230), 0xFFFFFFFF);
write32((sata_bar5 + 0x2b0), 0xFFFFFFFF);
/* Clear SATA status,Firstly we get the AcpiGpe0BlkAddr */
/* ????? why CIM does not set the AcpiGpe0BlkAddr , but use it??? */
/* word = 0x0000; */
/* word = pm_ioread(0x28); */
/* byte = pm_ioread(0x29); */
/* word |= byte<<8; */
/* printk(BIOS_DEBUG, "AcpiGpe0Blk addr = %x\n", word); */
/* write32(word, 0x80000000); */
}
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations sata_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
/* .enable = sb600_enable, */
.init = sata_init,
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const struct pci_driver sata0_driver __pci_driver = {
.ops = &sata_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB600_SATA,
};

View File

@@ -1,227 +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.
*/
#include <console/console.h>
#include <arch/io.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include "sb600.h"
static struct device *find_sm_dev(struct device *dev, u32 devfn)
{
struct device *sm_dev;
sm_dev = dev_find_slot(dev->bus->secondary, devfn);
if (!sm_dev)
return sm_dev;
if ((sm_dev->vendor != PCI_VENDOR_ID_ATI) ||
((sm_dev->device != PCI_DEVICE_ID_ATI_SB600_SM))) {
u32 id;
id = pci_read_config32(sm_dev, PCI_VENDOR_ID);
if ((id !=
(PCI_VENDOR_ID_ATI | (PCI_DEVICE_ID_ATI_SB600_SM << 16))))
{
sm_dev = 0;
}
}
return sm_dev;
}
void set_sm_enable_bits(struct device *sm_dev, u32 reg_pos, u32 mask, u32 val)
{
u32 reg_old, reg;
reg = reg_old = pci_read_config32(sm_dev, reg_pos);
reg &= ~mask;
reg |= val;
if (reg != reg_old) {
pci_write_config32(sm_dev, reg_pos, reg);
}
}
static void pmio_write_index(u16 port_base, u8 reg, u8 value)
{
outb(reg, port_base);
outb(value, port_base + 1);
}
static u8 pmio_read_index(u16 port_base, u8 reg)
{
outb(reg, port_base);
return inb(port_base + 1);
}
void pm_iowrite(u8 reg, u8 value)
{
pmio_write_index(PM_INDEX, reg, value);
}
u8 pm_ioread(u8 reg)
{
return pmio_read_index(PM_INDEX, reg);
}
void pm2_iowrite(u8 reg, u8 value)
{
pmio_write_index(PM2_INDEX, reg, value);
}
u8 pm2_ioread(u8 reg)
{
return pmio_read_index(PM2_INDEX, reg);
}
static void set_pmio_enable_bits(struct device *sm_dev, u32 reg_pos, u32 mask,
u32 val)
{
u8 reg_old, reg;
reg = reg_old = pm_ioread(reg_pos);
reg &= ~mask;
reg |= val;
if (reg != reg_old) {
pm_iowrite(reg_pos, reg);
}
}
void sb600_enable(struct device *dev)
{
struct device *sm_dev = NULL;
struct device *bus_dev = NULL;
int index = -1;
u32 deviceid;
u32 vendorid;
/* struct southbridge_ati_sb600_config *conf; */
/* conf = dev->chip_info; */
int i;
u32 devfn;
printk(BIOS_DEBUG, "sb600_enable()\n");
/*
* 0:12.0 SATA bit 8 of sm_dev 0xac : 1 - enable, default + 32 * 3
* 0:13.1 USB-1 bit 2 of sm_dev 0x68
* 0:13.2 USB-2 bit 3 of sm_dev 0x68
* 0:13.3 USB-3 bit 4 of sm_dev 0x68
* 0:13.4 USB-4 bit 5 of sm_dev 0x68
* 0:13.5 USB2 bit 0 of sm_dev 0x68 : 1 - enable, default
* 0:14.0 SMBUS 0
* 0:14.1 IDE 1
* 0:14.2 HDA bit 3 of pm_io 0x59 : 1 - enable, default + 32 * 4
* 0:14.3 LPC bit 20 of sm_dev 0x64 : 0 - disable, default + 32 * 1
* 0:14.4 PCI 4
* 0:14.5 ACI bit 0 of pm_io 0x59 : 0 - enable, default
* 0:14.6 MCI bit 1 of pm_io 0x59 : 0 - enable, default
*/
if (dev->device == 0x0000) {
vendorid = pci_read_config32(dev, PCI_VENDOR_ID);
deviceid = (vendorid >> 16) & 0xffff;
vendorid &= 0xffff;
} else {
vendorid = dev->vendor;
deviceid = dev->device;
}
bus_dev = dev->bus->dev;
if ((bus_dev->vendor == PCI_VENDOR_ID_ATI) &&
(bus_dev->device == PCI_DEVICE_ID_ATI_SB600_PCI)) {
devfn = (bus_dev->path.pci.devfn) & ~7;
sm_dev = find_sm_dev(bus_dev, devfn);
if (!sm_dev)
return;
/* something under 00:01.0 */
switch (dev->path.pci.devfn) {
case 5 << 3:
;
}
return;
}
i = (dev->path.pci.devfn) & ~7;
i += (2 << 3);
for (devfn = (0x14 << 3); devfn <= i; devfn += (1 << 3)) {
sm_dev = find_sm_dev(dev, devfn);
if (sm_dev)
break;
}
if (!sm_dev)
return;
switch (dev->path.pci.devfn - (devfn - (0x14 << 3))) {
case (0x12 << 3) | 0:
index = 8;
set_sm_enable_bits(sm_dev, 0xac, 1 << index,
(dev->enabled ? 1 : 0) << index);
index += 32 * 3;
break;
case (0x13 << 3) | 0:
case (0x13 << 3) | 1:
case (0x13 << 3) | 2:
case (0x13 << 3) | 3:
case (0x13 << 3) | 4:
case (0x13 << 3) | 5:
index = dev->path.pci.devfn & 7;
index++;
index %= 6;
set_sm_enable_bits(sm_dev, 0x68, 1 << index,
(dev->enabled ? 1 : 0) << index);
index += 32 * 2;
break;
case (0x14 << 3) | 0:
index = 0;
break;
case (0x14 << 3) | 1:
index = 1;
break;
case (0x14 << 3) | 2:
index = 3;
set_pmio_enable_bits(sm_dev, 0x59, 1 << index,
(dev->enabled ? 1 : 0) << index);
index += 32 * 4;
break;
case (0x14 << 3) | 3:
index = 20;
set_sm_enable_bits(sm_dev, 0x64, 1 << index,
(dev->enabled ? 1 : 0) << index);
index += 32 * 1;
break;
case (0x14 << 3) | 4:
index = 4;
break;
case (0x14 << 3) | 5:
case (0x14 << 3) | 6:
index = dev->path.pci.devfn & 7;
index -= 5;
set_pmio_enable_bits(sm_dev, 0x59, 1 << index,
(dev->enabled ? 0 : 1) << index);
index += 32 * 4;
break;
default:
printk(BIOS_DEBUG, "unknown dev: %s deviceid=%4x\n", dev_path(dev),
deviceid);
}
}
struct chip_operations southbridge_amd_sb600_ops = {
CHIP_NAME("ATI SB600")
.enable_dev = sb600_enable,
};

View File

@@ -1,48 +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.
*/
#ifndef SB600_H
#define SB600_H
#ifndef __ACPI__
#include <device/pci_ids.h>
#include "chip.h"
#endif
/* Power management index/data registers */
#define PM_INDEX 0xcd6
#define PM_DATA 0xcd7
#define PM2_INDEX 0xcd0
#define PM2_DATA 0xcd1
#define HPET_BASE_ADDRESS 0xfed00000
#ifndef __ACPI__
extern void pm_iowrite(u8 reg, u8 value);
extern u8 pm_ioread(u8 reg);
extern void pm2_iowrite(u8 reg, u8 value);
extern u8 pm2_ioread(u8 reg);
#ifndef __SIMPLE_DEVICE__
extern void set_sm_enable_bits(struct device *sm_dev, u32 reg_pos, u32 mask,
u32 val);
void sb600_enable(struct device *dev);
#endif
void sb600_lpc_port80(void);
void sb600_pci_port80(void);
#endif /* __ACPI__ */
#endif /* SB600_H */

View File

@@ -1,370 +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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <device/smbus.h>
#include <pc80/mc146818rtc.h>
#include <arch/io.h>
#include <cpu/x86/lapic.h>
#include <arch/ioapic.h>
#include <stdlib.h>
#include "sb600.h"
#include "smbus.c"
#define NMI_OFF 0
#define MAINBOARD_POWER_OFF 0
#define MAINBOARD_POWER_ON 1
#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL
#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
#endif
/*
* SB600 enables all USB controllers by default in SMBUS Control.
* SB600 enables SATA by default in SMBUS Control.
*/
static void sm_init(struct device *dev)
{
u8 byte;
u8 byte_old;
u32 dword;
u32 ioapic_base;
u32 on;
u32 nmi_option;
printk(BIOS_INFO, "sm_init().\n");
ioapic_base = pci_read_config32(dev, 0x74) & (0xffffffe0); /* some like mem resource, but does not have enable bit */
/* Don't rename APIC ID */
clear_ioapic((void *)ioapic_base);
dword = pci_read_config8(dev, 0x62);
dword |= 1 << 2;
pci_write_config8(dev, 0x62, dword);
dword = pci_read_config32(dev, 0x78);
dword |= 1 << 9;
pci_write_config32(dev, 0x78, dword); /* enable 0xCD6 0xCD7 */
/* bit 10: MultiMediaTimerIrqEn */
dword = pci_read_config8(dev, 0x64);
dword |= 1 << 10;
pci_write_config8(dev, 0x64, dword);
/* enable serial irq */
byte = pci_read_config8(dev, 0x69);
byte |= 1 << 7; /* enable serial irq function */
byte &= ~(0xF << 2);
byte |= 4 << 2; /* set NumSerIrqBits=4 */
pci_write_config8(dev, 0x69, byte);
byte = pm_ioread(0x61);
byte |= 1 << 1; /* Set to enable NB/SB handshake during IOAPIC interrupt for AMD K8/K7 */
pm_iowrite(0x61, byte);
/* disable SMI */
byte = pm_ioread(0x53);
byte |= 1 << 3;
pm_iowrite(0x53, byte);
/* power after power fail */
on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
get_option(&on, "power_on_after_fail");
byte = pm_ioread(0x74);
byte &= ~0x03;
if (on) {
byte |= 1 << 0;
}
byte |= 1 << 2;
pm_iowrite(0x74, byte);
printk(BIOS_INFO, "set power %s after power fail\n", on ? "on" : "off");
/* sb600 rpr:2.3.3: */
byte = pm_ioread(0x9A);
byte |= 1 << 5 | 1 << 4 | 1 << 2;
pm_iowrite(0x9A, byte);
byte = pm_ioread(0x8F);
byte |= 1 << 5;
byte &= ~(1 << 4);
pm_iowrite(0x8F, byte);
pm_iowrite(0x8B, 0x01);
pm_iowrite(0x8A, 0x90);
pm_iowrite(0x88, 0x10); /* A21 */
byte = pm_ioread(0x7C);
byte |= 1 << 0;
pm_iowrite(0x7C, byte);
byte = pm_ioread(0x68);
byte &= ~(1 << 1);
/* 2.6 */
byte |= 1 << 2;
pm_iowrite(0x68, byte);
/* 2.6 */
byte = pm_ioread(0x65);
byte &= ~(1 << 7);
pm_iowrite(0x65, byte);
/* 2.3.4 */
byte = pm_ioread(0x52);
byte &= ~0x2F;
byte |= 0x8;
pm_iowrite(0x52, byte);
byte = pm_ioread(0x8D);
byte &= ~(1 << 6);
pm_iowrite(0x8D, byte);
byte = pm_ioread(0x61);
byte &= ~(1 << 2);
pm_iowrite(0x61, byte);
byte = pm_ioread(0x42);
byte &= ~(1 << 2);
pm_iowrite(0x42, byte);
/* Set up NMI on errors */
byte = inb(0x70); /* RTC70 */
byte_old = byte;
nmi_option = NMI_OFF;
get_option(&nmi_option, "nmi");
if (nmi_option) {
byte &= ~(1 << 7); /* set NMI */
printk(BIOS_INFO, "++++++++++set NMI+++++\n");
} else {
byte |= (1 << 7); /* Can not mask NMI from PCI-E and NMI_NOW */
printk(BIOS_INFO, "++++++++++no set NMI+++++\n");
}
byte &= ~(1 << 7);
if (byte != byte_old) {
outb(byte, 0x70);
}
/* 2.10 IO Trap Settings */
abcfg_reg(0x10090, 1 << 16, 1 << 16);
/* ab index */
pci_write_config32(dev, 0xF0, AB_INDX);
/* Initialize the real time clock */
cmos_init(0);
/*3.4 Enabling IDE/PCIB Prefetch for Performance Enhancement */
abcfg_reg(0x10060, 9 << 17, 9 << 17);
abcfg_reg(0x10064, 9 << 17, 9 << 17);
/* 3.5 Enabling OHCI Prefetch for Performance Enhancement */
abcfg_reg(0x80, 1 << 0, 1<< 0);
/* 3.6 B-Link Client's Credit Variable Settings for the Downstream Arbitration Equation */
/* 3.7 Enabling Additional Address Bits Checking in Downstream */
abcfg_reg(0x9c, 3 << 0, 3 << 0);
/* 3.8 Set B-Link Prefetch Mode */
abcfg_reg(0x80, 3 << 17, 3 << 17);
/* 3.9 Enabling Detection of Upstream Interrupts */
abcfg_reg(0x94, 1 << 20,1 << 20);
/* 3.10: Enabling Downstream Posted Transactions to Pass Non-Posted
* Transactions for the K8 Platform (for All Revisions) */
abcfg_reg(0x10090, 1 << 8, 1 << 8);
/* 3.11:Programming Cycle Delay for AB and BIF Clock Gating */
/* 3.12: Enabling AB and BIF Clock Gating */
abcfg_reg(0x10054, 0xFFFF0000, 0x1040000);
abcfg_reg(0x54, 0xFF << 16, 4 << 16);
printk(BIOS_INFO, "3.11, ABCFG:0x54\n");
abcfg_reg(0x54, 1 << 24, 1 << 24);
printk(BIOS_INFO, "3.12, ABCFG:0x54\n");
abcfg_reg(0x98, 0x0000FF00, 0x00004700);
/* 3.13:Enabling AB Int_Arbiter Enhancement (for All Revisions) */
abcfg_reg(0x10054, 0x0000FFFF, 0x07FF);
/* 3.14:Enabling L1 on A-link Express */
axcfg_reg(0x68, 0x00000003, 0x2);
axindxp_reg(0xa0, 0x0000F000, 0x6000);
abcfg_reg(0x10098, 0xFFFFFFFF, 0x4000);
abcfg_reg(0x04, 0xFFFFFFFF, 0x6);
printk(BIOS_INFO, "sm_init() end\n");
/* Enable NbSb virtual channel */
axcfg_reg(0x114, 0x3f << 1, 0 << 1);
axcfg_reg(0x120, 0x7f << 1, 0x7f << 1);
axcfg_reg(0x120, 7 << 24, 1 << 24);
axcfg_reg(0x120, 1 << 31, 1 << 31);
abcfg_reg(0x50, 1 << 3, 1 << 3);
}
static int lsmbus_recv_byte(struct device *dev)
{
u32 device;
struct resource *res;
struct bus *pbus;
device = dev->path.i2c.device;
pbus = get_pbus_smbus(dev);
res = find_resource(pbus->dev, 0x10);
return do_smbus_recv_byte(res->base, device);
}
static int lsmbus_send_byte(struct device *dev, u8 val)
{
u32 device;
struct resource *res;
struct bus *pbus;
device = dev->path.i2c.device;
pbus = get_pbus_smbus(dev);
res = find_resource(pbus->dev, 0x10);
return do_smbus_send_byte(res->base, device, val);
}
static int lsmbus_read_byte(struct device *dev, u8 address)
{
u32 device;
struct resource *res;
struct bus *pbus;
device = dev->path.i2c.device;
pbus = get_pbus_smbus(dev);
res = find_resource(pbus->dev, 0x10);
return do_smbus_read_byte(res->base, device, address);
}
static int lsmbus_write_byte(struct device *dev, u8 address, u8 val)
{
u32 device;
struct resource *res;
struct bus *pbus;
device = dev->path.i2c.device;
pbus = get_pbus_smbus(dev);
res = find_resource(pbus->dev, 0x10);
return do_smbus_write_byte(res->base, device, address, val);
}
static struct smbus_bus_operations lops_smbus_bus = {
.recv_byte = lsmbus_recv_byte,
.send_byte = lsmbus_send_byte,
.read_byte = lsmbus_read_byte,
.write_byte = lsmbus_write_byte,
};
static void sb600_sm_read_resources(struct device *dev)
{
struct resource *res;
u8 byte;
/* rpr2.14: Hides SM bus controller Bar1 where stores HPET MMIO base address */
byte = pm_ioread(0x55);
byte |= 1 << 7;
pm_iowrite(0x55, byte);
/* Get the normal pci resources of this device */
/* pci_dev_read_resources(dev); */
byte = pm_ioread(0x55);
byte &= ~(1 << 7);
pm_iowrite(0x55, byte);
/* apic */
res = new_resource(dev, 0x74);
res->base = IO_APIC_ADDR;
res->size = 256 * 0x10;
res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */
res->align = 8;
res->gran = 8;
res->flags = IORESOURCE_MEM | IORESOURCE_FIXED;
res = new_resource(dev, 0x14); /* hpet */
res->base = HPET_BASE_ADDRESS; /* reset hpet to widely accepted address */
res->size = 0x400;
res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */
res->align = 8;
res->gran = 8;
res->flags = IORESOURCE_MEM | IORESOURCE_FIXED;
/* dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; */
/* smbus */
res = new_resource(dev, 0x10);
res->base = 0xB00;
res->size = 0x10;
res->limit = 0xFFFFUL; /* res->base + res->size -1; */
res->align = 8;
res->gran = 8;
res->flags = IORESOURCE_IO | IORESOURCE_FIXED;
compact_resources(dev);
}
static void sb600_sm_set_resources(struct device *dev)
{
struct resource *res;
u8 byte;
pci_dev_set_resources(dev);
/* rpr2.14: Make HPET MMIO decoding controlled by the memory enable bit in command register of LPC ISA bridge */
byte = pm_ioread(0x52);
byte |= 1 << 6;
pm_iowrite(0x52, byte);
res = find_resource(dev, 0x74);
pci_write_config32(dev, 0x74, res->base | 1 << 3);
res = find_resource(dev, 0x14);
pci_write_config32(dev, 0x14, res->base);
res = find_resource(dev, 0x10);
pci_write_config32(dev, 0x10, res->base | 1);
}
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations smbus_ops = {
.read_resources = sb600_sm_read_resources,
.set_resources = sb600_sm_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = sm_init,
.scan_bus = scan_smbus,
/* .enable = sb600_enable, */
.ops_pci = &lops_pci,
.ops_smbus_bus = &lops_smbus_bus,
};
static const struct pci_driver smbus_driver __pci_driver = {
.ops = &smbus_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB600_SM,
};

View File

@@ -1,210 +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.
*/
#include "smbus.h"
static inline void smbus_delay(void)
{
outb(0x80, 0x80);
}
static int smbus_wait_until_ready(u32 smbus_io_base)
{
u32 loops;
loops = SMBUS_TIMEOUT;
do {
u8 val;
val = inb(smbus_io_base + SMBHSTSTAT);
val &= 0x1f;
if (val == 0) { /* ready now */
return 0;
}
outb(val, smbus_io_base + SMBHSTSTAT);
} while (--loops);
return -2; /* time out */
}
static int smbus_wait_until_done(u32 smbus_io_base)
{
u32 loops;
loops = SMBUS_TIMEOUT;
do {
u8 val;
val = inb(smbus_io_base + SMBHSTSTAT);
val &= 0x1f; /* mask off reserved bits */
if (val & 0x1c) {
return -5; /* error */
}
if (val == 0x02) {
outb(val, smbus_io_base + SMBHSTSTAT); /* clear status */
return 0;
}
} while (--loops);
return -3; /* timeout */
}
int do_smbus_recv_byte(u32 smbus_io_base, u32 device)
{
u8 byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) {
return -2; /* not ready */
}
/* set the device I'm talking to */
outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
byte = inb(smbus_io_base + SMBHSTCTRL);
byte &= 0xe3; /* Clear [4:2] */
byte |= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */
outb(byte, smbus_io_base + SMBHSTCTRL);
/* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return -3; /* timeout or error */
}
/* read results of transaction */
byte = inb(smbus_io_base + SMBHSTCMD);
return byte;
}
int do_smbus_send_byte(u32 smbus_io_base, u32 device, u8 val)
{
u8 byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) {
return -2; /* not ready */
}
/* set the command... */
outb(val, smbus_io_base + SMBHSTCMD);
/* set the device I'm talking to */
outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
byte = inb(smbus_io_base + SMBHSTCTRL);
byte &= 0xe3; /* Clear [4:2] */
byte |= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */
outb(byte, smbus_io_base + SMBHSTCTRL);
/* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return -3; /* timeout or error */
}
return 0;
}
int do_smbus_read_byte(u32 smbus_io_base, u32 device, u32 address)
{
u8 byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) {
return -2; /* not ready */
}
/* set the command/address... */
outb(address & 0xff, smbus_io_base + SMBHSTCMD);
/* set the device I'm talking to */
outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
byte = inb(smbus_io_base + SMBHSTCTRL);
byte &= 0xe3; /* Clear [4:2] */
byte |= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */
outb(byte, smbus_io_base + SMBHSTCTRL);
/* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return -3; /* timeout or error */
}
/* read results of transaction */
byte = inb(smbus_io_base + SMBHSTDAT0);
return byte;
}
int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address, u8 val)
{
u8 byte;
if (smbus_wait_until_ready(smbus_io_base) < 0) {
return -2; /* not ready */
}
/* set the command/address... */
outb(address & 0xff, smbus_io_base + SMBHSTCMD);
/* set the device I'm talking to */
outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
/* output value */
outb(val, smbus_io_base + SMBHSTDAT0);
byte = inb(smbus_io_base + SMBHSTCTRL);
byte &= 0xe3; /* Clear [4:2] */
byte |= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */
outb(byte, smbus_io_base + SMBHSTCTRL);
/* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return -3; /* timeout or error */
}
return 0;
}
static void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val)
{
u32 tmp;
outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX);
tmp = inl(AB_DATA);
tmp &= ~mask;
tmp |= val;
/* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<30 | reg_addr); */
outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX); /* probably we don't have to do it again. */
outl(tmp, AB_DATA);
}
/* space = 0: AX_INDXC, AX_DATAC
* space = 1: AX_INDXP, AX_DATAP
*/
static void alink_ax_indx(u32 space /*c or p? */ , u32 axindc,
u32 mask, u32 val)
{
u32 tmp;
/* read axindc to tmp */
outl(space << 30 | space << 3 | 0x30, AB_INDX);
outl(axindc, AB_DATA);
outl(space << 30 | space << 3 | 0x34, AB_INDX);
tmp = inl(AB_DATA);
tmp &= ~mask;
tmp |= val;
/* write tmp */
outl(space << 30 | space << 3 | 0x30, AB_INDX);
outl(axindc, AB_DATA);
outl(space << 30 | space << 3 | 0x34, AB_INDX);
outl(tmp, AB_DATA);
}

View File

@@ -1,60 +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.
*/
#ifndef SB600_SMBUS_H
#define SB600_SMBUS_H
#define SMBHSTSTAT 0x0
#define SMBSLVSTAT 0x1
#define SMBHSTCTRL 0x2
#define SMBHSTCMD 0x3
#define SMBHSTADDR 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBHSTBLKDAT 0x7
#define SMBSLVCTRL 0x8
#define SMBSLVCMD_SHADOW 0x9
#define SMBSLVEVT 0xa
#define SMBSLVDAT 0xc
#define AX_INDXC 0
#define AX_INDXP 1
#define AXCFG 2
#define ABCFG 3
#define AB_INDX 0xCD8
#define AB_DATA (AB_INDX+4)
/* Between 1-10 seconds, We should never timeout normally
* Longer than this is just painful when a timeout condition occurs.
*/
#define SMBUS_TIMEOUT (100*1000*10)
#define abcfg_reg(reg, mask, val) \
alink_ab_indx((ABCFG), (reg), (mask), (val))
#define axcfg_reg(reg, mask, val) \
alink_ab_indx((AXCFG), (reg), (mask), (val))
#define axindxc_reg(reg, mask, val) \
alink_ax_indx(0, (reg), (mask), (val))
#define axindxp_reg(reg, mask, val) \
alink_ax_indx(1, (reg), (mask), (val))
int do_smbus_recv_byte(u32 smbus_io_base, u32 device);
int do_smbus_send_byte(u32 smbus_io_base, u32 device, u8 val);
int do_smbus_read_byte(u32 smbus_io_base, u32 device, u32 address);
int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address, u8 val);
#endif

View File

@@ -1,168 +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.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <device/pci_ehci.h>
#include <arch/io.h>
#include "sb600.h"
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static void usb_init(struct device *dev)
{
u8 byte;
u16 word;
u32 dword;
/* Enable OHCI0-4 and EHCI Controllers */
struct device *sm_dev;
sm_dev = dev_find_slot(0, PCI_DEVFN(0x14, 0));
byte = pci_read_config8(sm_dev, 0x68);
byte |= 0x3F;
pci_write_config8(sm_dev, 0x68, byte);
/* RPR 5.2 Enables the USB PME Event,Enable USB resume support */
byte = pm_ioread(0x61);
byte |= 1 << 6;
pm_iowrite(0x61, byte);
byte = pm_ioread(0x65);
byte |= 1 << 2;
pm_iowrite(0x65, byte);
/* RPR 5.3 Support USB device wakeup from the S4/S5 state */
byte = pm_ioread(0x65);
byte &= ~(1 << 0);
pm_iowrite(0x65, byte);
/* RPR 5.6 Enable the USB controller to get reset by any software that generate a PCIRst# condition */
byte = pm_ioread(0x65);
byte |= (1 << 4);
pm_iowrite(0x65, byte);
/* RPR 5.11 Disable OHCI MSI Capability */
word = pci_read_config16(dev, 0x40);
word |= (0x1F << 8);
pci_write_config16(dev, 0x40, word);
/* RPR 5.8 Disable the OHCI Dynamic Power Saving feature */
dword = pci_read_config32(dev, 0x50);
dword &= ~(1 << 16);
pci_write_config32(dev, 0x50, dword);
/* RPR 5.12 Enable prevention of OHCI accessing the invalid system memory address range */
word = pci_read_config16(dev, 0x50);
word |= 1 << 15;
pci_write_config16(dev, 0x50, word);
/* RPR 5.15 Disable SMI handshake in between USB and ACPI for USB legacy support. */
/* The BIOS should always set this bit to prevent the malfunction on USB legacy keyboard/mouse support */
word = pci_read_config16(dev, 0x50);
word |= 1 << 12;
pci_write_config16(dev, 0x50, word);
}
static void usb_init2(struct device *dev)
{
u8 byte;
u16 word;
u32 dword;
void *usb2_bar0;
/* dword = pci_read_config32(dev, 0xf8); */
/* dword |= 40; */
/* pci_write_config32(dev, 0xf8, dword); */
usb2_bar0 = (void *)(pci_read_config32(dev, 0x10) & ~0xFF);
printk(BIOS_INFO, "usb2_bar0=0x%p\n", usb2_bar0);
/* RPR5.4 Enables the USB PHY auto calibration resister to match 45ohm resistance */
dword = 0x00020F00;
write32(usb2_bar0 + 0xC0, dword);
/* RPR5.5 Sets In/OUT FIFO threshold for best performance */
dword = 0x00200040;
write32(usb2_bar0 + 0xA4, dword);
/* RPR5.9 Disable the EHCI Dynamic Power Saving feature */
word = read16(usb2_bar0 + 0xBC);
word &= ~(1 << 12);
write16(usb2_bar0 + 0xBC, word);
/* RPR5.10 Disable EHCI MSI support */
byte = pci_read_config8(dev, 0x50);
byte |= (1 << 6);
pci_write_config8(dev, 0x50, byte);
/* RPR5.13 Disable C3 time enhancement feature */
dword = pci_read_config32(dev, 0x50);
dword &= ~(1 << 28);
pci_write_config32(dev, 0x50, dword);
/* EHCI Erratum (adapted from Linux) */
dword = pci_read_config32(dev, 0x53);
dword |= (1 << 3);
pci_write_config32(dev, 0x53, dword);
/* RPR5.14 Disable USB PHY PLL Reset signal to come from ACPI */
byte = pci_read_config8(dev, 0x54);
byte &= ~(1 << 0);
pci_write_config8(dev, 0x54, byte);
}
static struct device_operations usb_ops = {
.read_resources = pci_ehci_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = usb_init,
/*.enable = sb600_enable, */
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const unsigned short usb_ids[] = {
PCI_DEVICE_ID_ATI_SB600_USB_0,
PCI_DEVICE_ID_ATI_SB600_USB_1,
PCI_DEVICE_ID_ATI_SB600_USB_2,
PCI_DEVICE_ID_ATI_SB600_USB_3,
PCI_DEVICE_ID_ATI_SB600_USB_4,
0,
};
static const struct pci_driver usb_0_driver __pci_driver = {
.ops = &usb_ops,
.vendor = PCI_VENDOR_ID_ATI,
.devices= usb_ids,
};
static struct device_operations usb_ops2 = {
.read_resources = pci_ehci_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = usb_init2,
/*.enable = sb600_enable, */
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const struct pci_driver usb_5_driver __pci_driver = {
.ops = &usb_ops2,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB600_USB2,
};