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

@ -155,10 +155,6 @@ static uint16_t ht_read_freq_cap(pci_devfn_t dev, uint8_t pos)
printk(BIOS_SPEW, "pos=0x%x, filtered freq_cap=0x%x\n", pos, freq_cap);
#if IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8M890)
freq_cap &= 0x3f;
printk(BIOS_INFO, "Limiting HT to 800/600/400/200 MHz until K8M890 HT1000 is fixed.\n");
#endif
return freq_cap;
}

View File

@ -20,8 +20,6 @@
#include <arch/early_variables.h>
#if IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700)
#include <southbridge/amd/sb700/sb700.h>
#else /* IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_K8T890) */
#include <southbridge/via/k8t890/k8t890.h>
#endif
//0: mean no debug info

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,
};

View File

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

View File

@ -1,7 +0,0 @@
ifeq ($(CONFIG_SOUTHBRIDGE_BROADCOM_BCM5870),y)
ramstage-y += nic.c
ramstage-y += pcix.c
ramstage-y += pcie.c
endif

View File

@ -1,54 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
*
* 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 lpci_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x40,
((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = lpci_set_subsystem,
};
static struct device_operations nic_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = pci_dev_init,
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const struct pci_driver nic_driver __pci_driver = {
.ops = &nic_ops,
.vendor = PCI_VENDOR_ID_BROADCOM,
.device = PCI_DEVICE_ID_BROADCOM_BCM5780_NIC,
};
static const struct pci_driver nic1_driver __pci_driver = {
.ops = &nic_ops,
.vendor = PCI_VENDOR_ID_BROADCOM,
.device = PCI_DEVICE_ID_BROADCOM_BCM5780_NIC1,
};

View File

@ -1,56 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
*
* 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 pcie_init(struct device *dev)
{
/* Enable pci error detecting */
uint32_t dword;
/* 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);
}
static struct pci_operations lops_pci = {
.set_subsystem = 0,
};
static struct device_operations pcie_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.init = pcie_init,
.scan_bus = pci_scan_bridge,
.reset_bus = pci_bus_reset,
.ops_pci = &lops_pci,
};
static const struct pci_driver pcie_driver __pci_driver = {
.ops = &pcie_ops,
.vendor = PCI_VENDOR_ID_SERVERWORKS,
.device = PCI_DEVICE_ID_SERVERWORKS_BCM5780_PCIE,
};

View File

@ -1,49 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
*
* 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 lpci_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x40,
((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = lpci_set_subsystem,
};
static struct device_operations ht_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.init = 0 ,
.scan_bus = pci_scan_bridge,
.reset_bus = pci_bus_reset,
.ops_pci = &lops_pci,
};
static const struct pci_driver ht_driver __pci_driver = {
.ops = &ht_ops,
.vendor = PCI_VENDOR_ID_SERVERWORKS,
.device = PCI_DEVICE_ID_SERVERWORKS_BCM5780_PXB,
};

View File

@ -1,17 +0,0 @@
config SOUTHBRIDGE_SIS_SIS966
bool
select IOAPIC
select HAVE_USBDEBUG
select HAVE_HARD_RESET
if SOUTHBRIDGE_SIS_SIS966
config BOOTBLOCK_SOUTHBRIDGE_INIT
string
default "southbridge/sis/sis966/bootblock.c"
config EHCI_BAR
hex
default 0xfef00000
endif

View File

@ -1,21 +0,0 @@
ifeq ($(CONFIG_SOUTHBRIDGE_SIS_SIS966),y)
ramstage-y += sis761.c
ramstage-y += sis966.c
ramstage-y += lpc.c
ramstage-y += ide.c
ramstage-y += usb.c
ramstage-y += usb2.c
ramstage-y += nic.c
ramstage-y += sata.c
ramstage-y += pcie.c
ramstage-y += aza.c
ramstage-y += reset.c
romstage-$(CONFIG_USBDEBUG_IN_ROMSTAGE) += enable_usbdebug.c
ramstage-$(CONFIG_USBDEBUG) += enable_usbdebug.c
bootblock-y += romstrap.ld
bootblock-y += romstrap.S
endif

View File

@ -1,323 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "sis966.h"
u8 SiS_SiS7502_init[7][3]={
{0x04, 0xFF, 0x07},
{0x2C, 0xFF, 0x39},
{0x2D, 0xFF, 0x10},
{0x2E, 0xFF, 0x91},
{0x2F, 0xFF, 0x01},
{0x04, 0xFF, 0x06},
{0x00, 0x00, 0x00} //End of table
};
static int set_bits(void *port, u32 mask, u32 val)
{
u32 dword;
int count;
val &= mask;
dword = read32(port);
dword &= ~mask;
dword |= val;
write32(port, dword);
count = 50;
do {
dword = read32(port);
dword &= mask;
udelay(100);
} while ((dword != val) && --count);
if (!count) return -1;
udelay(500);
return 0;
}
static u32 send_verb(u8 *base, u32 verb)
{
u32 dword;
dword = read32(base + 0x68);
dword = dword|(unsigned long)0x0002;
write32(base + 0x68, dword);
do {
dword = read32(base + 0x68);
} while ((dword & 1) != 0);
write32(base + 0x60, verb);
udelay(500);
dword = read32(base + 0x68);
dword = (dword |0x1);
write32(base + 0x68, dword);
do {
udelay(100);
dword = read32(base + 0x68);
} while ((dword & 3) != 2);
dword = read32(base + 0x64);
return dword;
}
static int codec_detect(u8 *base)
{
u32 dword;
int idx = 0;
/* 1 */ // controller reset
printk(BIOS_DEBUG, "controller reset\n");
set_bits(base + 0x08, 1, 1);
do {
dword = read32(base + 0x08)&0x1;
if (idx++>1000) { printk(BIOS_DEBUG, "controller reset fail !!!\n"); break;}
} while (dword !=1);
dword=send_verb(base,0x000F0000); // get codec VendorId and DeviceId
if (dword == 0) {
printk(BIOS_DEBUG, "No codec!\n");
return 0;
}
printk(BIOS_DEBUG, "Codec ID = %x\n", dword);
dword = 0x1;
return dword;
}
static u32 verb_data[] = {
//14
0x01471c10,
0x01471d40,
0x01471e01,
0x01471f01,
//15
0x01571c12,
0x01571d10,
0x01571e01,
0x01571f01,
//16
0x01671c11,
0x01671d60,
0x01671e01,
0x01671f01,
//17
0x01771c14,
0x01771d20,
0x01771e01,
0x01771f01,
//18
0x01871c40,
0x01871d98,
0x01871ea1,
0x01871f01,
//19
0x01971c50,
0x01971d98,
0x01971ea1,
0x01971f02,
//1a
0x01a71c4f,
0x01a71d30,
0x01a71e81,
0x01a71f01,
//1b
0x01b71c20,
0x01b71d40,
0x01b71e01,
0x01b71f02,
//1c
0x01c71cf0,
0x01c71d01,
0x01c71e33,
0x01c71f59,
//1d
0x01d71c01,
0x01d71de6,
0x01d71e05,
0x01d71f40,
//1e
0x01e71c30,
0x01e71d11,
0x01e71e44,
0x01e71f01,
//1f
0x01f71c60,
0x01f71d61,
0x01f71ec4,
0x01f71f01,
};
static unsigned find_verb(u32 viddid, u32 **verb)
{
if ((viddid == 0x10ec0883) || (viddid == 0x10ec0882) || (viddid == 0x10ec0880)) return 0;
*verb = (u32 *)verb_data;
return sizeof(verb_data)/sizeof(u32);
}
static void codec_init(u8 *base, int addr)
{
u32 dword;
u32 *verb;
unsigned verb_size;
int i;
/* 1 */
do {
dword = read32(base + 0x68);
} while (dword & 1);
dword = (addr << 28) | 0x000f0000;
write32(base + 0x60, dword);
do {
dword = read32(base + 0x68);
} while ((dword & 3) != 2);
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++) {
send_verb(base,verb[i]);
}
printk(BIOS_DEBUG, "verb loaded!\n");
}
static void codecs_init(u8 *base, u32 codec_mask)
{
codec_init(base, 0);
return;
}
static void aza_init(struct device *dev)
{
u8 *base;
struct resource *res;
u32 codec_mask;
printk(BIOS_DEBUG, "AZALIA_INIT:---------->\n");
//-------------- enable AZA (SiS7502) -------------------------
{
u8 temp8;
int i=0;
while (SiS_SiS7502_init[i][0] != 0)
{
temp8 = pci_read_config8(dev, SiS_SiS7502_init[i][0]);
temp8 &= SiS_SiS7502_init[i][1];
temp8 |= SiS_SiS7502_init[i][2];
pci_write_config8(dev, SiS_SiS7502_init[i][0], temp8);
i++;
};
}
//-----------------------------------------------------------
// put audio to D0 state
pci_write_config8(dev, 0x54,0x00);
#if DEBUG_AZA
{
int i;
printk(BIOS_DEBUG, "****** Azalia PCI config ******");
printk(BIOS_DEBUG, "\n 03020100 07060504 0B0A0908 0F0E0D0C");
for (i=0; i<0xff; i+=4){
if ((i%16)==0){
printk(BIOS_DEBUG, "\n%02x: ", i);
}
printk(BIOS_DEBUG, "%08x ", pci_read_config32(dev,i));
}
printk(BIOS_DEBUG, "\n");
}
#endif
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);
}
printk(BIOS_DEBUG, "AZALIA_INIT:<----------\n");
}
static void lpci_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x40,
((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = lpci_set_subsystem,
};
static struct device_operations aza_audio_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
// .enable = sis966_enable,
.init = aza_init,
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const struct pci_driver azaaudio_driver __pci_driver = {
.ops = &aza_audio_ops,
.vendor = PCI_VENDOR_ID_SIS,
.device = PCI_DEVICE_ID_SIS_SIS966_HD_AUDIO,
};

View File

@ -1,42 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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>
#include "sis966.h"
static void sis966_enable_rom(void)
{
pci_devfn_t addr;
/* Enable 4MB ROM access at 0xFFC00000 - 0xFFFFFFFF. */
addr = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS,
PCI_DEVICE_ID_SIS_SIS966_LPC), 0);
/* Set the 4MB enable bit(s). */
pci_write_config8(addr, 0x40, pci_read_config8(addr, 0x40) | 0x11);
}
static void bootblock_southbridge_init(void)
{
sis966_enable_rom();
}

View File

@ -1,31 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 SIS966_CHIP_H
#define SIS966_CHIP_H
struct southbridge_sis_sis966_config
{
unsigned int ide0_enable : 1;
unsigned int ide1_enable : 1;
unsigned int sata0_enable : 1;
unsigned int sata1_enable : 1;
unsigned int mac_eeprom_smbus;
unsigned int mac_eeprom_addr;
};
#endif /* SIS966_CHIP_H */

View File

@ -1,55 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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>
static unsigned get_sbdn(unsigned bus)
{
pci_devfn_t dev;
/* Find the device. */
dev = pci_locate_device_on_bus(
PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS761),
bus);
return (dev>>15) & 0x1f;
}
void do_hard_reset(void)
{
set_bios_reset();
/* full reset */
outb(0x0a, 0x0cf9);
outb(0x0e, 0x0cf9);
}
static void enable_fid_change_on_sb(unsigned sbbusn, unsigned sbdn)
{
/* default value for sis966 is good */
/* set VFSMAF ( VID/FID System Management Action Field) to 2 */
}
void do_soft_reset(void)
{
set_bios_reset();
/* link reset */
outb(0x02, 0x0cf9);
outb(0x06, 0x0cf9);
}

View File

@ -1,58 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2006 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
void sis966_early_pcie_setup(unsigned busnx, unsigned devnx, unsigned anactrl_io_base, unsigned pci_e_x)
{
uint32_t tgio_ctrl;
uint32_t pll_ctrl;
uint32_t dword;
int i;
pci_devfn_t dev;
dev = PCI_DEV(busnx, devnx+1, 1);
dword = pci_read_config32(dev, 0xe4);
dword |= 0x3f0; // disable it at first
pci_write_config32(dev, 0xe4, dword);
for (i=0; i<3; i++) {
tgio_ctrl = inl(anactrl_io_base + 0xcc);
tgio_ctrl &= ~(3<<9);
tgio_ctrl |= (i<<9);
outl(tgio_ctrl, anactrl_io_base + 0xcc);
pll_ctrl = inl(anactrl_io_base + 0x30);
pll_ctrl |= (1<<31);
outl(pll_ctrl, anactrl_io_base + 0x30);
do {
pll_ctrl = inl(anactrl_io_base + 0x30);
} while (!(pll_ctrl & 1));
}
tgio_ctrl = inl(anactrl_io_base + 0xcc);
tgio_ctrl &= ~((7<<4)|(1<<8));
tgio_ctrl |= (pci_e_x<<4)|(1<<8);
outl(tgio_ctrl, anactrl_io_base + 0xcc);
// wait 100us
udelay(100);
dword = pci_read_config32(dev, 0xe4);
dword &= ~(0x3f0); // enable
pci_write_config32(dev, 0xe4, dword);
// need to wait 100ms
mdelay(100);
}

View File

@ -1,216 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
static const unsigned int pcie_ss_tbl[] = {
0x0C504103f,
0x0C504103f,
0x0C504103f,
0x0C5042040,
0x0C5042040,
0x0C5042040,
0x0C5043041,
0x0C5043041,
0x0C5043041,
0x0C5043041,
0x0C5044042,
0x0C5044042,
0x0C5044042,
0x0C5045043,
0x0C5045043,
0x0C5045043,
0x0C5045043,
0x0C5045043,
0x0C5046044,
0x0C5046044,
0x0C5046044,
0x0C5046044,
0x0C5047045,
0x0C5047045,
0x0C5047045,
0x0C5047045,
0x0C5047045,
0x0C5048046,
0x0C5048046,
0x0C5048046,
0x0C5048046,
0x0C5049047,
0x0C5049047,
0x0C5049047,
0x0C504a048,
0x0C504a048,
0x0C504b049,
0x0C504b049,
0x0C504a048,
0x0C504a048,
0x0C5049047,
0x0C5049047,
0x0C5048046,
0x0C5048046,
0x0C5048046,
0x0C5047045,
0x0C5047045,
0x0C5047045,
0x0C5047045,
0x0C5047045,
0x0C5046044,
0x0C5046044,
0x0C5046044,
0x0C5046044,
0x0C5045043,
0x0C5045043,
0x0C5045043,
0x0C5044042,
0x0C5044042,
0x0C5044042,
0x0C5043041,
0x0C5043041,
0x0C5042040,
0x0C5042040,
};
static const unsigned int sata_ss_tbl[] = {
0x0c9044042,
0x0c9044042,
0x0c9044042,
0x0c9045043,
0x0c9045043,
0x0c9045043,
0x0c9045043,
0x0c9045043,
0x0c9046044,
0x0c9046044,
0x0c9046044,
0x0c9046044,
0x0c9047045,
0x0c9047045,
0x0c9047045,
0x0c9047045,
0x0c9047045,
0x0c9048046,
0x0c9048046,
0x0c9048046,
0x0c9048046,
0x0c9049047,
0x0c9049047,
0x0c9049047,
0x0c9049047,
0x0c904a048,
0x0c904a048,
0x0c904a048,
0x0c904a048,
0x0c904b049,
0x0c904b049,
0x0c904b049,
0x0c904b049,
0x0c904b049,
0x0c904b049,
0x0c904a048,
0x0c904a048,
0x0c904a048,
0x0c904a048,
0x0c9049047,
0x0c9049047,
0x0c9049047,
0x0c9049047,
0x0c9048046,
0x0c9048046,
0x0c9048046,
0x0c9048046,
0x0c9047045,
0x0c9047045,
0x0c9047045,
0x0c9047045,
0x0c9047045,
0x0c9046044,
0x0c9046044,
0x0c9046044,
0x0c9046044,
0x0c9045043,
0x0c9045043,
0x0c9045043,
0x0c9045043,
0x0c9045043,
0x0c9044042,
0x0c9044042,
0x0c9044042,
};
static const unsigned int cpu_ss_tbl[] = {
0x0C5038036,
0x0C5038036,
0x0C5038036,
0x0C5037035,
0x0C5037035,
0x0C5037035,
0x0C5037035,
0x0C5036034,
0x0C5036034,
0x0C5036034,
0x0C5036034,
0x0C5036034,
0x0C5035033,
0x0C5035033,
0x0C5035033,
0x0C5035033,
0x0C5035033,
0x0C5035033,
0x0C5034032,
0x0C5034032,
0x0C5034032,
0x0C5034032,
0x0C5034032,
0x0C5034032,
0x0C5035033,
0x0C5035033,
0x0C5035033,
0x0C5035033,
0x0C5035033,
0x0C5036034,
0x0C5036034,
0x0C5036034,
0x0C5036034,
0x0C5036034,
0x0C5037035,
0x0C5037035,
0x0C5037035,
0x0C5037035,
0x0C5038036,
0x0C5038036,
0x0C5038036,
0x0C5038036,
0x0C5039037,
0x0C5039037,
0x0C5039037,
0x0C5039037,
0x0C503a038,
0x0C503a038,
0x0C503a038,
0x0C503a038,
0x0C503b039,
0x0C503b039,
0x0C503b039,
0x0C503b039,
0x0C503b039,
0x0C503a038,
0x0C503a038,
0x0C503a038,
0x0C503a038,
0x0C503a038,
0x0C5039037,
0x0C5039037,
0x0C5039037,
0x0C5039037,
};

View File

@ -1,739 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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"
#define SMBUS0_IO_BASE 0x8D0
static inline void smbus_delay(void)
{
outb(0x80, 0x80);
}
int smbus_wait_until_ready(unsigned smbus_io_base)
{
unsigned long loops;
loops = SMBUS_TIMEOUT;
do {
unsigned char val;
smbus_delay();
val = inb(smbus_io_base + SMBHSTSTAT);
val &= 0x1f;
if (val == 0) {
return 0;
}
outb(val,smbus_io_base + SMBHSTSTAT);
} while (--loops);
return -2;
}
int smbus_wait_until_done(unsigned smbus_io_base)
{
unsigned long loops;
loops = SMBUS_TIMEOUT;
do {
unsigned char val;
smbus_delay();
val = inb(smbus_io_base + 0x00);
if ( (val & 0xff) != 0x02) {
return 0;
}
} while (--loops);
return -3;
}
int do_smbus_recv_byte(unsigned smbus_io_base, unsigned device)
{
unsigned char global_status_register;
unsigned char byte;
/* set the device I'm talking to */
outb(((device & 0x7f) << 1)|1 , smbus_io_base + SMBXMITADD);
smbus_delay();
/* byte data recv */
outb(0x05, smbus_io_base + SMBHSTPRTCL);
smbus_delay();
/* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return -3;
}
global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */
/* read results of transaction */
byte = inb(smbus_io_base + SMBHSTCMD);
if (global_status_register != 0x80) { // lose check, otherwise it should be 0
return -1;
}
return byte;
}
int do_smbus_send_byte(unsigned smbus_io_base, unsigned device, unsigned char val)
{
unsigned global_status_register;
outb(val, smbus_io_base + SMBHSTDAT0);
smbus_delay();
/* set the command... */
outb(val, smbus_io_base + SMBHSTCMD);
smbus_delay();
/* set the device I'm talking to */
outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
smbus_delay();
/* set up for a byte data write */
outb(0x04, smbus_io_base + SMBHSTPRTCL);
smbus_delay();
/* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return -3;
}
global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */
if (global_status_register != 0x80) {
return -1;
}
return 0;
}
static inline int do_smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
{
unsigned char global_status_register;
unsigned char byte;
outb(0xff, smbus_io_base + 0x00);
smbus_delay();
outb(0x20, smbus_io_base + 0x03);
smbus_delay();
outb(((device & 0x7f) << 1)|1 , smbus_io_base + 0x04);
smbus_delay();
outb(address & 0xff, smbus_io_base + 0x05);
smbus_delay();
outb(0x12, smbus_io_base + 0x03);
smbus_delay();
int i, j;
for (i = 0;i < 0x1000; i++) {
if (inb(smbus_io_base + 0x00) != 0x08) {
smbus_delay();
for (j=0;j<0xFFFF;j++);
}
}
global_status_register = inb(smbus_io_base + 0x00);
byte = inb(smbus_io_base + 0x08);
if (global_status_register != 0x08) { // lose check, otherwise it should be 0
printk(BIOS_DEBUG, "Fail\r\t");
return -1;
}
printk(BIOS_DEBUG, "Success\r\t");
return byte;
}
static inline int do_smbus_write_byte(unsigned smbus_io_base, unsigned device, unsigned address, unsigned char val)
{
unsigned global_status_register;
outb(val, smbus_io_base + SMBHSTDAT0);
smbus_delay();
/* set the device I'm talking to */
outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBXMITADD);
smbus_delay();
outb(address & 0xff, smbus_io_base + SMBHSTCMD);
smbus_delay();
/* set up for a byte data write */
outb(0x06, smbus_io_base + SMBHSTPRTCL);
smbus_delay();
/* poll for transaction completion */
if (smbus_wait_until_done(smbus_io_base) < 0) {
return -3;
}
global_status_register = inb(smbus_io_base + SMBHSTSTAT) & 0x80; /* lose check */
if (global_status_register != 0x80) {
return -1;
}
return 0;
}
static const uint8_t SiS_LPC_init[34][3]={
{0x04, 0xF8, 0x07}, //Reg 0x04
{0x45, 0x00, 0x00}, //Reg 0x45 //Enable Rom Flash
{0x46, 0x00, 0x3D}, //Reg 0x46
{0x47, 0x00, 0xDD}, //Reg 0x47
{0x48, 0x00, 0x12}, //Reg 0x48
{0x64, 0x00, 0xFF}, //Reg 0x64
{0x65, 0x00, 0xC1}, //Reg 0x65
{0x68, 0x00, 0x89}, //Reg 0x68 //SB.ASM, START POST
{0x69, 0x00, 0x80}, //Reg 0x69
{0x6B, 0x00, 0x00}, //Reg 0x6B //SBBB.ASM
{0x6C, 0xFF, 0x97}, //Reg 0x6C //SBBB.ASM
{0x6E, 0x00, 0x00}, //Reg 0x6E //SBBB.ASM But in Early Post sets 0x04.
{0x6F, 0xFF, 0x14}, //Reg 0x6F //SBBB.ASM
{0x77, 0x00, 0x0E}, //Reg 0x77 //SBOEM.ASM, EARLY POST
{0x78, 0x00, 0x20}, //Reg 0x78
{0x7B, 0x00, 0x88}, //Reg 0x7B
{0x7F, 0x00, 0x40}, //Reg 0x7F //SBOEM.ASM, EARLY POST
{0xC1, 0x00, 0xF0}, //Reg 0xC1
{0xC2, 0x00, 0x01}, //Reg 0xC2
{0xC3, 0x00, 0x00}, //Reg 0xC3 //NBAGPBB.ASM
{0xC9, 0x00, 0x80}, //Reg 0xC9
{0xCF, 0x00, 0x45}, //Reg 0xCF
{0xD0, 0x00, 0x02}, //Reg 0xD0
{0xD4, 0x00, 0x44}, //Reg 0xD4
{0xD5, 0x00, 0x62}, //Reg 0xD5
{0xD6, 0x00, 0x32}, //Reg 0xD6
{0xD8, 0x00, 0x45}, //Reg 0xD8
{0xDA, 0x00, 0xDA}, //Reg 0xDA
{0xDB, 0x00, 0x61}, //Reg 0xDB
{0xDC, 0x00, 0xAA}, //Reg 0xDC
{0xDD, 0x00, 0xAA}, //Reg 0xDD
{0xDE, 0x00, 0xAA}, //Reg 0xDE
{0xDF, 0x00, 0xAA}, //Reg 0xDF
{0x00, 0x00, 0x00} //End of table
};
static const uint8_t SiS_NBPCIE_init[43][3]={
{0x3D, 0x00, 0x00}, //Reg 0x3D
{0x1C, 0xFE, 0x01}, //Reg 0x1C
{0x1D, 0xFE, 0x01}, //Reg 0x1D
{0x24, 0xFE, 0x01}, //Reg 0x24
{0x26, 0xFE, 0x01}, //Reg 0x26
{0x40, 0xFF, 0x10}, //Reg 0x40
{0x43, 0xFF, 0x78}, //Reg 0x43
{0x44, 0xFF, 0x02}, //Reg 0x44
{0x45, 0xFF, 0x10}, //Reg 0x45
{0x48, 0xFF, 0x52}, //Reg 0x48
{0x49, 0xFF, 0xE3}, //Reg 0x49
{0x5A, 0x00, 0x00}, //Reg 0x4A
{0x4B, 0x00, 0x16}, //Reg 0x4B
{0x4C, 0x00, 0x80}, //Reg 0x4C
{0x4D, 0x00, 0x02}, //Reg 0x4D
{0x4E, 0x00, 0x00}, //Reg 0x4E
{0x5C, 0x00, 0x52}, //Reg 0x5C
{0x5E, 0x00, 0x10}, //Reg 0x5E
{0x34, 0x00, 0xD0}, //Reg 0x34
{0xD0, 0x00, 0x01}, //Reg 0xD0
{0x4F, 0x00, 0x80}, //Reg 0x4F
{0xA1, 0x00, 0xF4}, //Reg 0xA1
{0xA2, 0x7F, 0x00}, //Reg 0xA2
{0xBD, 0x00, 0xA0}, //Reg 0xBD
{0xD1, 0xFF, 0x00}, //Reg 0xD1
{0xD3, 0xFE, 0x01}, //Reg 0xD3
{0xD4, 0x18, 0x20}, //Reg 0xD4
{0xD5, 0xF0, 0x00}, //Reg 0xD5
{0xDD, 0xFF, 0x00}, //Reg 0xDD
{0xDE, 0xEC, 0x10}, //Reg 0xDE
{0xDF, 0xFF, 0x00}, //Reg 0xDF
{0xE0, 0xF7, 0x00}, //Reg 0xE0
{0xE3, 0xEF, 0x10}, //Reg 0xE3
{0xE4, 0x7F, 0x80}, //Reg 0xE4
{0xE5, 0xFF, 0x00}, //Reg 0xE5
{0xE6, 0x06, 0x00}, //Reg 0xE6
{0xE7, 0xFF, 0x00}, //Reg 0xE7
{0xF5, 0x00, 0x00}, //Reg 0xF5
{0xF6, 0x3F, 0x00}, //Reg 0xF6
{0xF7, 0xFF, 0x00}, //Reg 0xF7
{0xFD, 0xFF, 0x00}, //Reg 0xFD
{0x4F, 0x00, 0x00}, //Reg 0x4F
{0x00, 0x00, 0x00} //End of table
};
static const uint8_t SiS_ACPI_init[10][3]={
{0x1B, 0xBF, 0x40}, //Reg 0x1B
{0x84, 0x00, 0x0E}, //Reg 0x84
{0x85, 0x00, 0x29}, //Reg 0x85
{0x86, 0x00, 0xCB}, //Reg 0x86
{0x87, 0x00, 0x55}, //Reg 0x87
{0x6B, 0x00, 0x00}, //Reg 0x6B
{0x6C, 0x68, 0x97}, //Reg 0x6C
{0x6E, 0x00, 0x00}, //Reg 0x6E
{0x6F, 0xFF, 0x14}, //Reg 0x6F
{0x00, 0x00, 0x00} //End of table
};
static const uint8_t SiS_SBPCIE_init[13][3]={
{0x48, 0x00 ,0x07}, //Reg 0x48
{0x49, 0x00 ,0x06}, //Reg 0x49
{0x4A, 0x00 ,0x0C}, //Reg 0x4A
{0x4B, 0x00 ,0x00}, //Reg 0x4B
{0x4E, 0x00 ,0x20}, //Reg 0x4E
{0x1C, 0x00 ,0xF1}, //Reg 0x1C
{0x1D, 0x00 ,0x01}, //Reg 0x1D
{0x24, 0x00 ,0x01}, //Reg 0x24
{0x26, 0x00 ,0x01}, //Reg 0x26
{0xF6, 0x00 ,0x02}, //Reg 0xF6
{0xF7, 0x00 ,0xC8}, //Reg 0xF7
{0x5B, 0x00 ,0x40}, //Reg 0x5B
{0x00, 0x00, 0x00} //End of table
};
static const uint8_t SiS_NB_init[56][3]={
{0x04, 0x00 ,0x07}, //Reg 0x04
{0x05, 0x00 ,0x00}, //Reg 0x05 // alex
{0x0D, 0x00 ,0x20}, //Reg 0x0D
{0x2C, 0x00 ,0x39}, //Reg 0x2C
{0x2D, 0x00 ,0x10}, //Reg 0x2D
{0x2E, 0x00 ,0x61}, //Reg 0x2E
{0x2F, 0x00 ,0x07}, //Reg 0x2F
{0x34, 0x00 ,0xA0}, //Reg 0x34
{0x40, 0x00 ,0x36}, //Reg 0x40
{0x42, 0x00 ,0xB9}, //Reg 0x42
{0x43, 0x00 ,0x8B}, //Reg 0x43
{0x44, 0x00 ,0x05}, //Reg 0x44
{0x45, 0x00 ,0xFF}, //Reg 0x45
{0x46, 0x00 ,0x90}, //Reg 0x46
{0x47, 0x00 ,0xA0}, //Reg 0x47
//{0x4C, 0xFF ,0x09}, //Reg 0x4C // SiS307 enable
{0x4E, 0x00 ,0x00}, //Reg 0x4E
{0x4F, 0x00 ,0x02}, //Reg 0x4F
{0x5B, 0x00 ,0x44}, //Reg 0x5B
{0x5D, 0x00 ,0x00}, //Reg 0x5D
{0x5E, 0x00 ,0x25}, //Reg 0x5E
{0x61, 0x00 ,0xB0}, //Reg 0x61
{0x65, 0x00 ,0xB0}, //Reg 0x65
{0x68, 0x00 ,0x4C}, //Reg 0x68
{0x69, 0x00 ,0xD0}, //Reg 0x69
{0x6B, 0x00 ,0x07}, //Reg 0x6B
{0x6C, 0x00 ,0xDD}, //Reg 0x6C
{0x6D, 0x00 ,0xAD}, //Reg 0x6D
{0x6E, 0x00 ,0xE8}, //Reg 0x6E
{0x6F, 0x00 ,0x4D}, //Reg 0x6F
{0x70, 0x00 ,0x00}, //Reg 0x70
{0x71, 0x00 ,0x80}, //Reg 0x71
{0x72, 0x00 ,0x00}, //Reg 0x72
{0x73, 0x00 ,0x00}, //Reg 0x73
{0x74, 0x00 ,0x01}, //Reg 0x74
{0x75, 0x00 ,0x10}, //Reg 0x75
{0x7E, 0x00 ,0x29}, //Reg 0x7E
{0x8B, 0x00 ,0x10}, //Reg 0x8B
{0x8D, 0x00 ,0x03}, //Reg 0x8D
{0xA1, 0x00 ,0xD0}, //Reg 0xA1
{0xA2, 0x00 ,0x30}, //Reg 0xA2
{0xA4, 0x00 ,0x0B}, //Reg 0xA4
{0xA9, 0x00 ,0x02}, //Reg 0xA9
{0xB0, 0x00 ,0x30}, //Reg 0xB0
{0xB4, 0x00 ,0x30}, //Reg 0xB4
{0x90, 0x00 ,0x00}, //Reg 0x90
{0x91, 0x00 ,0x00}, //Reg 0x91
{0x92, 0x00 ,0x00}, //Reg 0x92
{0x93, 0x00 ,0x00}, //Reg 0x93
{0x94, 0x00 ,0x00}, //Reg 0x94
{0x95, 0x00 ,0x00}, //Reg 0x95
{0x96, 0x00 ,0x00}, //Reg 0x96
{0x97, 0x00 ,0x00}, //Reg 0x97
{0x98, 0x00 ,0x00}, //Reg 0x98
{0x99, 0x00 ,0x00}, //Reg 0x99
{0x00, 0x00, 0x00} //End of table
};
static const uint8_t SiS_NBAGP_init[34][3]={
{0xCF, 0xDF, 0x00}, //HT issue
{0x06, 0xDF, 0x20},
{0x1E, 0xDF, 0x20},
{0x50, 0x00, 0x02},
{0x51, 0x00, 0x00},
{0x54, 0x00, 0x09},
{0x55, 0x00, 0x00},
{0x56, 0x00, 0x80},
{0x58, 0x00, 0x08},
{0x60, 0x00, 0xB1},
{0x61, 0x00, 0x02},
{0x62, 0x00, 0x60},
{0x63, 0x00, 0x60},
{0x64, 0x00, 0xAA},
{0x65, 0x00, 0x18},
{0x68, 0x00, 0x23},
{0x69, 0x00, 0x23},
{0x6A, 0x00, 0xC8},
{0x6B, 0x00, 0x08},
{0x6C, 0x00, 0x00},
{0x6D, 0x00, 0x00},
{0x6E, 0x00, 0x08},
{0x6F, 0x00, 0x00},
{0xBB, 0x00, 0x00},
{0xB5, 0x00, 0x30},
{0xB0, 0x00, 0xDB},
{0xB6, 0x00, 0x73},
{0xB7, 0x00, 0x50},
{0xBA, 0xBF, 0x41},
{0xB4, 0x3F, 0xC0},
{0xBF, 0xF9, 0x06},
{0xBA, 0x00, 0x61},
{0xBD, 0x7F, 0x80},
{0x00, 0x00, 0x00} //End of table
};
static const uint8_t SiS_ACPI_2_init[56][3]={
{0x00, 0x00, 0xFF}, //Reg 0x00
{0x01, 0x00, 0xFF}, //Reg 0x01
{0x02, 0x00, 0x00}, //Reg 0x02
{0x03, 0x00, 0x00}, //Reg 0x03
{0x16, 0x00, 0x00}, //Reg 0x16
{0x20, 0x00, 0xFF}, //Reg 0x20
{0x21, 0x00, 0xFF}, //Reg 0x21
{0x22, 0x00, 0x00}, //Reg 0x22
{0x23, 0x00, 0x00}, //Reg 0x23
{0x24, 0x00, 0x55}, //Reg 0x24
{0x25, 0x00, 0x55}, //Reg 0x25
{0x26, 0x00, 0x55}, //Reg 0x26
{0x27, 0x00, 0x55}, //Reg 0x27
{0x2A, 0x00, 0x40}, //Reg 0x2A
{0x2B, 0x00, 0x10}, //Reg 0x2B
{0x2E, 0x00, 0xFF}, //Reg 0x2E
{0x30, 0x00, 0xFF}, //Reg 0x30
{0x31, 0x00, 0xFF}, //Reg 0x31
{0x32, 0x00, 0x00}, //Reg 0x32
{0x33, 0x00, 0x00}, //Reg 0x33
{0x40, 0x00, 0xFF}, //Reg 0x40
{0x41, 0x00, 0xFF}, //Reg 0x41
{0x42, 0x00, 0x00}, //Reg 0x42
{0x43, 0x00, 0x00}, //Reg 0x43
{0x4A, 0x00, 0x00}, //Reg 0x4A
{0x4E, 0x00, 0x0F}, //Reg 0x4E
{0x5A, 0x00, 0x00}, //Reg 0x5A
{0x5B, 0x00, 0x00}, //Reg 0x5B
{0x62, 0x00, 0x00}, //Reg 0x62
{0x63, 0x00, 0x04}, //Reg 0x63
{0x68, 0x00, 0xFF}, //Reg 0x68
{0x76, 0x00, 0xA0}, //Reg 0x76
{0x77, 0x00, 0x22}, //Reg 0x77
{0x78, 0xDF, 0x20}, //Reg 0x78
{0x7A, 0x00, 0x10}, //Reg 0x7A
{0x7C, 0x00, 0x45}, //Reg 0x7C
{0x7D, 0x00, 0xB8}, //Reg 0x7D
{0x7F, 0x00, 0x00}, //Reg 0x7F
{0x80, 0x00, 0x1C}, //Reg 0x80
{0x82, 0x00, 0x01}, //Reg 0x82
{0x84, 0x00, 0x0E}, //Reg 0x84
{0x85, 0x00, 0x29}, //Reg 0x85
{0x86, 0x00, 0xCB}, //Reg 0x86
{0x87, 0x00, 0x55}, //Reg 0x87
{0x88, 0x00, 0x04}, //Reg 0x88
{0x96, 0x00, 0x80}, //Reg 0x96
{0x99, 0x00, 0x80}, //Reg 0x99
{0x9A, 0x00, 0x15}, //Reg 0x9A
{0x9D, 0x00, 0x05}, //Reg 0x9D
{0x9E, 0x00, 0x00}, //Reg 0x9E
{0x9F, 0x00, 0x04}, //Reg 0x9F
{0xB0, 0x00, 0x6D}, //Reg 0xB0
{0xB1, 0x00, 0x8C}, //Reg 0xB1
{0xB9, 0x00, 0xFF}, //Reg 0xB9
{0xBA, 0x00, 0x3F}, //Reg 0xBA
{0x00, 0x00, 0x00} //End of table
};
static const uint8_t SiS_SiS1183_init[44][3]={
{0x04, 0x00, 0x05},
{0x09, 0x00, 0x05},
{0x2C, 0x00, 0x39},
{0x2D, 0x00, 0x10},
{0x2E, 0x00, 0x83},
{0x2F, 0x00, 0x11},
{0x90, 0x00, 0x40},
{0x91, 0x00, 0x00}, // set mode
{0x50, 0x00, 0xA2},
{0x52, 0x00, 0xA2},
{0x55, 0x00, 0x96},
{0x52, 0x00, 0xA2},
{0x55, 0xF7, 0x00},
{0x56, 0x00, 0xC0},
{0x57, 0x00, 0x14},
{0x67, 0x00, 0x28},
{0x81, 0x00, 0xB3},
{0x82, 0x00, 0x72},
{0x83, 0x00, 0x40},
{0x85, 0x00, 0xB3},
{0x86, 0x00, 0x72},
{0x87, 0x00, 0x40},
{0x88, 0x00, 0xDE}, // after set mode
{0x89, 0x00, 0xB3},
{0x8A, 0x00, 0x72},
{0x8B, 0x00, 0x40},
{0x8C, 0x00, 0xDE},
{0x8D, 0x00, 0xB3},
{0x8E, 0x00, 0x92},
{0x8F, 0x00, 0x40},
{0x93, 0x00, 0x00},
{0x94, 0x00, 0x80},
{0x95, 0x00, 0x08},
{0x96, 0x00, 0x80},
{0x97, 0x00, 0x08},
{0x9C, 0x00, 0x80},
{0x9D, 0x00, 0x08},
{0x9E, 0x00, 0x80},
{0x9F, 0x00, 0x08},
{0xA0, 0x00, 0x15},
{0xA1, 0x00, 0x15},
{0xA2, 0x00, 0x15},
{0xA3, 0x00, 0x15},
{0x00, 0x00, 0x00} //End of table
};
/* In => Share Memory size
* => 00h : 0MBytes
* => 02h : 32MBytes
* => 03h : 64MBytes
* => 03h : 64MBytes
* => 04h : 128MBytes
* => Others: Reserved
*/
static void Init_Share_Memory(uint8_t ShareSize)
{
pci_devfn_t dev;
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS,
PCI_DEVICE_ID_SIS_SIS761), 0);
pci_write_config8(dev, 0x4C, (pci_read_config8(dev, 0x4C) & 0x1F) |
(ShareSize << 5));
}
/* In: => Aperture size
* => 00h : 32MBytes
* => 01h : 64MBytes
* => 02h : 128MBytes
* => 03h : 256MBytes
* => 04h : 512MBytes
* => Others: Reserved
*/
static void Init_Aper_Size(uint8_t AperSize)
{
pci_devfn_t dev;
uint16_t SiSAperSizeTable[]={0x0F38, 0x0F30, 0x0F20, 0x0F00, 0x0E00};
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_AMD, 0x1103), 0);
pci_write_config8(dev, 0x90, AperSize << 1);
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS761), 0);
pci_write_config16(dev, 0xB4, SiSAperSizeTable[AperSize]);
}
static void sis_init_stage1(void)
{
pci_devfn_t dev;
uint8_t temp8;
int i;
uint8_t GUI_En;
// SiS_Chipset_Initialization
// ========================== NB =============================
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS761), 0);
i=0;
while (SiS_NB_init[i][0] != 0) {
temp8 = pci_read_config8(dev, SiS_NB_init[i][0]);
temp8 &= SiS_NB_init[i][1];
temp8 |= SiS_NB_init[i][2];
pci_write_config8(dev, SiS_NB_init[i][0], temp8);
i++;
};
// ========================== LPC =============================
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS966_LPC), 0);
i=0;
while (SiS_LPC_init[i][0] != 0) {
temp8 = pci_read_config8(dev, SiS_LPC_init[i][0]);
temp8 &= SiS_LPC_init[i][1];
temp8 |= SiS_LPC_init[i][2];
pci_write_config8(dev, SiS_LPC_init[i][0], temp8);
i++;
};
// ========================== ACPI =============================
i=0;
while (SiS_ACPI_init[i][0] != 0) {
temp8 = inb(0x800 + SiS_ACPI_init[i][0]);
temp8 &= SiS_ACPI_init[i][1];
temp8 |= SiS_ACPI_init[i][2];
outb(temp8, 0x800 + SiS_ACPI_init[i][0]);
i++;
};
// ========================== NBPCIE =============================
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS761), 0); //Disable Internal GUI enable bit
temp8 = pci_read_config8(dev, 0x4C);
GUI_En = temp8 & 0x10;
pci_write_config8(dev, 0x4C, temp8 & (~0x10));
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS761_PCIE), 0);
i=0;
while (SiS_NBPCIE_init[i][0] != 0) {
temp8 = pci_read_config8(dev, SiS_NBPCIE_init[i][0]);
temp8 &= SiS_NBPCIE_init[i][1];
temp8 |= SiS_NBPCIE_init[i][2];
pci_write_config8(dev, SiS_NBPCIE_init[i][0], temp8);
i++;
};
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS761), 0); //Restore Internal GUI enable bit
temp8 = pci_read_config8(dev, 0x4C);
pci_write_config8(dev, 0x4C, temp8 | GUI_En);
return;
}
static void sis_init_stage2(void)
{
pci_devfn_t dev;
msr_t msr;
int i;
uint8_t temp8;
uint16_t temp16;
// ========================== NB_AGP =============================
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS761), 0); //Enable Internal GUI enable bit
pci_write_config8(dev, 0x4C, pci_read_config8(dev, 0x4C) | 0x10);
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_AGP), 0);
i=0;
while (SiS_NBAGP_init[i][0] != 0) {
temp8 = pci_read_config8(dev, SiS_NBAGP_init[i][0]);
temp8 &= SiS_NBAGP_init[i][1];
temp8 |= SiS_NBAGP_init[i][2];
pci_write_config8(dev, SiS_NBAGP_init[i][0], temp8);
i++;
};
/**
* Share Memory size
* => 00h : 0MBytes
* => 02h : 32MBytes
* => 03h : 64MBytes
* => 04h : 128MBytes
* => Others: Reserved
*
* Aperture size
* => 00h : 32MBytes
* => 01h : 64MBytes
* => 02h : 128MBytes
* => 03h : 256MBytes
* => 04h : 512MBytes
* => Others: Reserved
*/
Init_Share_Memory(0x02); //0x02 : 32M
Init_Aper_Size(0x01); //0x1 : 64M
// ========================== NB =============================
printk(BIOS_DEBUG, "Init NorthBridge sis761 -------->\n");
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS761), 0);
msr = rdmsr(0xC001001A);
printk(BIOS_DEBUG, "Memory Top Bound %x\n",msr.lo );
temp16=(pci_read_config8(dev, 0x4C) & 0xE0) >> 5;
temp16=0x0001<<(temp16-1);
temp16<<=8;
printk(BIOS_DEBUG, "Integrated VGA Shared memory size=%dM bytes\n", temp16 >> 4);
pci_write_config16(dev, 0x8E, (msr.lo >> 16) -temp16*1);
pci_write_config8(dev, 0x7F, 0x08); // ACPI Base
outb(inb(0x856) | 0x40, 0x856); // Auto-Reset Function
// ========================== ACPI =============================
i=0;
printk(BIOS_DEBUG, "Init ACPI -------->\n");
do {
temp8 = inb(0x800 + SiS_ACPI_2_init[i][0]);
temp8 &= SiS_ACPI_2_init[i][1];
temp8 |= SiS_ACPI_2_init[i][2];
outb(temp8, 0x800 + SiS_ACPI_2_init[i][0]);
i++;
} while (SiS_ACPI_2_init[i][0] != 0);
// ========================== Misc =============================
printk(BIOS_DEBUG, "Init Misc -------->\n");
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS966_LPC), 0);
/* R77h Internal PCI Device Enable 1 (Power On Value = 0h)
* bit5 : USB Emulation (1=enable)
* bit3 : Internal Keyboard Controller Port Access Control enable (1=enable)
* bit2 : Reserved
* bit1 : Mask USB A20M# Event (1:K8, 0:P4/K7)
*/
pci_write_config8(dev, 0x77, 0x2E);
/* R7Ch Internal PCI Device Enable 2 (Power On Value = 0h)
* bit4 : SATA Controller Enable (0=enable)
* bit3 : IDE Controller Enable (0=enable)
* bit2 : MAC Controller Enable (0=enable)
* bit1 : MODEM Controller Enable (1=disable)
* bit0 : AC97 Controller Enable (1=disable)
*/
pci_write_config8(dev, 0x7C, 0x03);
/* R7Eh Enable Azalia (Power On Value = 08h)
* bit3 : Azalia Controller Enable (0=enable)
*/
pci_write_config8(dev, 0x7E, 0x00); // azalia controller enable
temp8=inb(0x878)|0x4; //bit2=1 enable Azalia =0 enable AC97
outb(temp8, 0x878); // ACPI select AC97 or HDA controller
printk(BIOS_DEBUG, "Audio select %x\n",inb(0x878));
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS966_SATA), 0);
if (!dev)
printk(BIOS_DEBUG, "SiS 1183 does not exist !!");
// SATA Set Mode
pci_write_config8(dev, 0x90, (pci_read_config8(dev, 0x90)&0x3F) | 0x40);
}
static void enable_smbus(void)
{
pci_devfn_t dev;
uint8_t temp8;
printk(BIOS_DEBUG, "enable_smbus -------->\n");
dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS_SIS966_LPC), 0);
/* set smbus iobase && enable ACPI Space*/
pci_write_config16(dev, 0x74, 0x0800); // Set ACPI Base
temp8=pci_read_config8(dev, 0x40); // Enable ACPI Space
pci_write_config8(dev, 0x40, temp8 | 0x80);
temp8=pci_read_config8(dev, 0x76); // Enable SMBUS
pci_write_config8(dev, 0x76, temp8 | 0x03);
printk(BIOS_DEBUG, "enable_smbus <--------\n");
}
int smbus_read_byte(unsigned device, unsigned address)
{
return do_smbus_read_byte(SMBUS0_IO_BASE, device, address);
}
int smbus_write_byte(unsigned device, unsigned address, unsigned char val)
{
return do_smbus_write_byte(SMBUS0_IO_BASE, device, address, val);
}

View File

@ -1,45 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
/* TODO: Check whether this actually works (might be copy-paste leftover). */
// 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 "sis966.h"
pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
{
return PCI_DEV(0, SIS966_DEVN_BASE + 2, 1); /* USB EHCI */
}
void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
{
u32 dword;
/* Write the port number to 0x74[15:12]. */
dword = pci_read_config32(dev, 0x74);
dword &= ~(0xf << 12);
dword |= (port << 12);
pci_write_config32(dev, 0x74, dword);
}

View File

@ -1,185 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "sis966.h"
#include "chip.h"
uint8_t SiS_SiS5513_init[49][3]={
{0x04, 0xFF, 0x05},
{0x0D, 0xFF, 0x80},
{0x2C, 0xFF, 0x39},
{0x2D, 0xFF, 0x10},
{0x2E, 0xFF, 0x13},
{0x2F, 0xFF, 0x55},
{0x50, 0xFF, 0xA2},
{0x51, 0xFF, 0x21},
{0x53, 0xFF, 0x21},
{0x54, 0xFF, 0x2A},
{0x55, 0xFF, 0x96},
{0x52, 0xFF, 0xA2},
{0x56, 0xFF, 0x81},
{0x57, 0xFF, 0xC0},
{0x60, 0xFF, 0xFB},
{0x61, 0xFF, 0xAA},
{0x62, 0xFF, 0xFB},
{0x63, 0xFF, 0xAA},
{0x81, 0xFF, 0xB3},
{0x82, 0xFF, 0x72},
{0x83, 0xFF, 0x40},
{0x85, 0xFF, 0xB3},
{0x86, 0xFF, 0x72},
{0x87, 0xFF, 0x40},
{0x94, 0xFF, 0xC0},
{0x95, 0xFF, 0x08},
{0x96, 0xFF, 0xC0},
{0x97, 0xFF, 0x08},
{0x98, 0xFF, 0xCC},
{0x99, 0xFF, 0x04},
{0x9A, 0xFF, 0x0C},
{0x9B, 0xFF, 0x14},
{0xA0, 0xFF, 0x11},
{0x57, 0xFF, 0xD0},
{0xD8, 0xFE, 0x01}, // Com reset
{0xC8, 0xFE, 0x01},
{0xC4, 0xFF, 0xFF}, // Clear status
{0xC5, 0xFF, 0xFF},
{0xC6, 0xFF, 0xFF},
{0xC7, 0xFF, 0xFF},
{0xD4, 0xFF, 0xFF},
{0xD5, 0xFF, 0xFF},
{0xD6, 0xFF, 0xFF},
{0xD7, 0xFF, 0xFF},
{0x2C, 0xFF, 0x39}, // set subsystem ID
{0x2D, 0xFF, 0x10},
{0x2E, 0xFF, 0x13},
{0x2F, 0xFF, 0x55},
{0x00, 0x00, 0x00} //End of table
};
static void ide_init(struct device *dev)
{
struct southbridge_sis_sis966_config *conf;
/* Enable ide devices so the linux ide driver will work */
uint32_t dword;
uint16_t word;
uint8_t byte;
conf = dev->chip_info;
printk(BIOS_DEBUG, "IDE_INIT:---------->\n");
//-------------- enable IDE (SiS5513) -------------------------
{
uint8_t temp8;
int i=0;
while (SiS_SiS5513_init[i][0] != 0) {
temp8 = pci_read_config8(dev, SiS_SiS5513_init[i][0]);
temp8 &= SiS_SiS5513_init[i][1];
temp8 |= SiS_SiS5513_init[i][2];
pci_write_config8(dev, SiS_SiS5513_init[i][0], temp8);
i++;
};
}
//-----------------------------------------------------------
word = pci_read_config16(dev, 0x50);
/* Ensure prefetch is disabled */
word &= ~((1 << 15) | (1 << 13));
if (conf->ide1_enable) {
/* Enable secondary ide interface */
word |= (1<<0);
printk(BIOS_DEBUG, "IDE1\t");
}
if (conf->ide0_enable) {
/* Enable primary ide interface */
word |= (1<<1);
printk(BIOS_DEBUG, "IDE0\n");
}
word |= (1<<12);
word |= (1<<14);
pci_write_config16(dev, 0x50, word);
byte = 0x20; // Latency: 64-->32
pci_write_config8(dev, 0xd, byte);
dword = pci_read_config32(dev, 0xf8);
dword |= 12;
pci_write_config32(dev, 0xf8, dword);
#if DEBUG_IDE
{
int i;
printk(BIOS_DEBUG, "****** IDE PCI config ******");
printk(BIOS_DEBUG, "\n 03020100 07060504 0B0A0908 0F0E0D0C");
for (i=0;i<0xff;i+=4) {
if ((i%16)==0)
printk(BIOS_DEBUG, "\n%02x: ", i);
printk(BIOS_DEBUG, "%08x ", pci_read_config32(dev,i));
}
printk(BIOS_DEBUG, "\n");
}
#endif
printk(BIOS_DEBUG, "IDE_INIT:<----------\n");
}
static void lpci_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x40,
((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = lpci_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 = sis966_enable,
.ops_pci = &lops_pci,
};
static const struct pci_driver ide_driver __pci_driver = {
.ops = &ide_ops,
.vendor = PCI_VENDOR_ID_SIS,
.device = PCI_DEVICE_ID_SIS_SIS966_IDE,
};

View File

@ -1,279 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2003 Linux Networx
* Copyright (C) 2003 SuSE Linux AG
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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/isa-dma.h>
#include <arch/io.h>
#include <arch/ioapic.h>
#include <cpu/x86/lapic.h>
#include <stdlib.h>
#include "sis966.h"
#include <pc80/keyboard.h>
#define NMI_OFF 0
// 0x7a or e3
#define PREVIOUS_POWER_STATE 0x7A
#define MAINBOARD_POWER_OFF 0
#define MAINBOARD_POWER_ON 1
#define SLOW_CPU_OFF 0
#define SLOW_CPU__ON 1
#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL
#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
#endif
#undef SLAVE_INIT
static void lpc_common_init(struct device *dev)
{
uint8_t byte;
void *ioapic_base;
/* IO APIC initialization */
byte = pci_read_config8(dev, 0x74);
byte |= (1<<0); // enable APIC
pci_write_config8(dev, 0x74, byte);
ioapic_base = (void *)pci_read_config32(dev, PCI_BASE_ADDRESS_1); // 0x14
setup_ioapic(ioapic_base, 0); // Don't rename IO APIC ID
}
#ifdef SLAVE_INIT
static void lpc_slave_init(struct device *dev)
{
lpc_common_init(dev);
}
#endif
static void lpc_usb_legacy_init(struct device *dev)
{
uint16_t acpi_base;
acpi_base = (pci_read_config8(dev,0x75) << 8);
outb(inb(acpi_base + 0xbb) |0x80, acpi_base + 0xbb);
outb(inb(acpi_base + 0xba) |0x80, acpi_base + 0xba);
}
static void lpc_init(struct device *dev)
{
uint8_t byte;
uint8_t byte_old;
int on;
int nmi_option;
printk(BIOS_DEBUG, "LPC_INIT -------->\n");
pc_keyboard_init(NO_AUX_DEVICE);
lpc_usb_legacy_init(dev);
lpc_common_init(dev);
/* power after power fail */
on = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
get_option(&on, "power_on_after_fail");
byte = pci_read_config8(dev, PREVIOUS_POWER_STATE);
byte &= ~0x40;
if (!on) {
byte |= 0x40;
}
pci_write_config8(dev, PREVIOUS_POWER_STATE, byte);
printk(BIOS_INFO, "set power %s after power fail\n", on?"on":"off");
/* Throttle the CPU speed down for testing */
on = SLOW_CPU_OFF;
get_option(&on, "slow_cpu");
if (on) {
uint16_t pm10_bar;
uint32_t dword;
pm10_bar = (pci_read_config16(dev, 0x60)&0xff00);
outl(((on<<1)+0x10) ,(pm10_bar + 0x10));
dword = inl(pm10_bar + 0x10);
on = 8-on;
printk(BIOS_DEBUG, "Throttling CPU %2d.%1.1d percent.\n",
(on*12)+(on>>1),(on&1)*5);
}
/* Enable Error reporting */
/* Set up sync flood detected */
byte = pci_read_config8(dev, 0x47);
byte |= (1 << 1);
pci_write_config8(dev, 0x47, 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 */
} else {
byte |= ( 1 << 7); // Can not mask NMI from PCI-E and NMI_NOW
}
if ( byte != byte_old) {
outb(byte, 0x70);
}
/* Initialize the real time clock */
cmos_init(0);
/* Initialize isa dma */
isa_dma_init();
printk(BIOS_DEBUG, "LPC_INIT <--------\n");
}
static void sis966_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
/* 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;
}
/**
* Enable resources for children devices.
*
* @param dev The device whose children's resources are to be enabled.
*/
static void sis966_lpc_enable_childrens_resources(struct device *dev)
{
struct bus *link;
uint32_t reg, reg_var[4];
int i;
int var_num = 0;
reg = pci_read_config32(dev, 0xa0);
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) {
unsigned long base, end; // don't need long long
if (!(res->flags & IORESOURCE_IO)) continue;
base = res->base;
end = resource_end(res);
printk(BIOS_DEBUG, "sis966 lpc decode:%s, base=0x%08lx, end=0x%08lx\n",dev_path(child),base, end);
switch (base) {
case 0x3f8: // COM1
reg |= (1<<0); break;
case 0x2f8: // COM2
reg |= (1<<1); break;
case 0x378: // Parallel 1
reg |= (1<<24); break;
case 0x3f0: // FD0
reg |= (1<<20); break;
case 0x220: // Audio 0
reg |= (1<<8); break;
case 0x300: // Midi 0
reg |= (1<<12); break;
}
if ( (base == 0x290) || (base >= 0x400)) {
if (var_num>=4) continue; // only 4 var ; compact them ?
reg |= (1<<(28+var_num));
reg_var[var_num++] = (base & 0xffff)|((end & 0xffff)<<16);
}
}
}
}
}
pci_write_config32(dev, 0xa0, reg);
for (i=0;i<var_num;i++) {
pci_write_config32(dev, 0xa8 + i*4, reg_var[i]);
}
}
static void sis966_lpc_enable_resources(struct device *dev)
{
pci_dev_enable_resources(dev);
sis966_lpc_enable_childrens_resources(dev);
}
static void lpci_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x40,
((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = lpci_set_subsystem,
};
static struct device_operations lpc_ops = {
.read_resources = sis966_lpc_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = sis966_lpc_enable_resources,
.init = lpc_init,
.scan_bus = scan_lpc_bus,
// .enable = sis966_enable,
.ops_pci = &lops_pci,
};
static const struct pci_driver lpc_driver __pci_driver = {
.ops = &lpc_ops,
.vendor = PCI_VENDOR_ID_SIS,
.device = PCI_DEVICE_ID_SIS_SIS966_LPC,
};
#ifdef SLAVE_INIT // No device?
static struct device_operations lpc_slave_ops = {
.read_resources = sis966_lpc_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = lpc_slave_init,
// .enable = sis966_enable,
.ops_pci = &lops_pci,
};
#endif

View File

@ -1,339 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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/smbus.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <arch/io.h>
#include <delay.h>
#include "sis966.h"
u8 SiS_SiS191_init[6][3]={
{0x04, 0xFF, 0x07},
{0x2C, 0xFF, 0x39},
{0x2D, 0xFF, 0x10},
{0x2E, 0xFF, 0x91},
{0x2F, 0xFF, 0x01},
{0x00, 0x00, 0x00} //End of table
};
#define StatusReg 0x1
#define SMI_READ 0x0
#define SMI_REQUEST 0x10
#define TRUE 1
#define FALSE 0
u16 MacAddr[3];
static void writeApcByte(int addr, u8 value)
{
outb(addr, 0x78);
outb(value, 0x79);
}
static u8 readApcByte(int addr)
{
u8 value;
outb(addr, 0x78);
value = inb(0x79);
return(value);
}
static void readApcMacAddr(void)
{
u8 i;
// enable APC in south bridge sis966 D2F0
outl(0x80001048, 0xcf8);
outl((inl(0xcfc) & 0xfffffffd), 0xcfc ); // enable IO78/79h for APC Index/Data
printk(BIOS_DEBUG, "MAC addr in APC = ");
for (i = 0x9; i <= 0xe; i++)
printk(BIOS_DEBUG, "%2.2x",readApcByte(i));
printk(BIOS_DEBUG, "\n");
/* Set APC Reload */
writeApcByte(0x7, readApcByte(0x7) & 0xf7);
writeApcByte(0x7, readApcByte(0x7) | 0x0a);
/* disable APC in south bridge */
outl(0x80001048, 0xcf8);
outl(inl(0xcfc) & 0xffffffbf, 0xcfc);
}
static void set_apc(struct device *dev)
{
u16 addr;
u16 i;
u8 bTmp;
/* enable APC in south bridge sis966 D2F0 */
outl(0x80001048, 0xcf8);
outl((inl(0xcfc) & 0xfffffffd), 0xcfc ); // enable IO78/79h for APC Index/Data
for (i = 0; i < 3; i++) {
addr = 0x9 + 2*i;
writeApcByte(addr, (u8)(MacAddr[i] & 0xFF));
writeApcByte(addr+1L, (u8)((MacAddr[i] >> 8) & 0xFF));
// printf("%x - ", readMacAddrByte(0x59 + i));
}
/* Set APC Reload */
writeApcByte(0x7, readApcByte(0x7) & 0xf7);
writeApcByte(0x7, readApcByte(0x7) | 0x0a);
/* disable APC in south bridge */
outl(0x80001048, 0xcf8);
outl(inl(0xcfc) & 0xffffffbf, 0xcfc);
// CFG reg0x73 bit = 1, tell driver MAC Address load to APC
bTmp = pci_read_config8(dev, 0x73);
bTmp |= 0x1;
pci_write_config8(dev, 0x73, bTmp);
}
/**
* Read one word out of the serial EEPROM.
*
* @param dev TODO
* @param base TODO
* @param Reg EEPROM word to read.
* @return Contents of EEPROM word (Reg).
*/
#define LoopNum 200
static unsigned long ReadEEprom(struct device *dev, u8 *base, u32 Reg)
{
u32 data;
u32 i;
u32 ulValue;
ulValue = (0x80 | (0x2 << 8) | (Reg << 10)); //BIT_7
write32(base + 0x3c, ulValue);
mdelay(10);
for (i = 0; i <= LoopNum; i++) {
ulValue = read32(base + 0x3c);
if (!(ulValue & 0x0080)) //BIT_7
break;
mdelay(100);
}
mdelay(50);
if (i == LoopNum)
data = 0x10000;
else {
ulValue = read32(base + 0x3c);
data = ((ulValue & 0xffff0000) >> 16);
}
return data;
}
static int phy_read(u8 *base, unsigned phy_addr, unsigned phy_reg)
{
u32 ulValue;
u32 Read_Cmd;
u16 usData;
Read_Cmd = ((phy_reg << 11) |
(phy_addr << 6) |
SMI_READ |
SMI_REQUEST);
// SmiMgtInterface Reg is the SMI management interface register(offset 44h) of MAC
write32(base + 0x44, Read_Cmd);
// Polling SMI_REQ bit to be deasserted indicated read command completed
do {
// Wait 20 usec before checking status
mdelay(20);
ulValue = read32(base + 0x44);
} while ((ulValue & SMI_REQUEST) != 0);
//printk(BIOS_DEBUG, "base %x cmd %lx ret val %lx\n", tmp,Read_Cmd,ulValue);
usData = (ulValue >> 16);
return usData;
}
// Detect a valid PHY
// If there exist a valid PHY then return TRUE, else return FALSE
static int phy_detect(u8 *base,u16 *PhyAddr) //BOOL PHY_Detect()
{
int bFoundPhy = FALSE;
u16 usData;
int PhyAddress = 0;
// Scan all PHY address(0 ~ 31) to find a valid PHY
for (PhyAddress = 0; PhyAddress < 32; PhyAddress++) {
// Status register is a PHY's register(offset 01h)
usData = phy_read(base,PhyAddress,StatusReg);
// Found a valid PHY
if ((usData != 0x0) && (usData != 0xffff)) {
bFoundPhy = TRUE;
break;
}
}
if (!bFoundPhy)
printk(BIOS_DEBUG, "PHY not found !!!!\n");
*PhyAddr = PhyAddress;
return bFoundPhy;
}
static void nic_init(struct device *dev)
{
int val;
u16 PhyAddr;
u8 *base;
struct resource *res;
printk(BIOS_DEBUG, "NIC_INIT:---------->\n");
//-------------- enable NIC (SiS19x) -------------------------
{
u8 temp8;
int i = 0;
while (SiS_SiS191_init[i][0] != 0) {
temp8 = pci_read_config8(dev, SiS_SiS191_init[i][0]);
temp8 &= SiS_SiS191_init[i][1];
temp8 |= SiS_SiS191_init[i][2];
pci_write_config8(dev, SiS_SiS191_init[i][0], temp8);
i++;
};
}
//-----------------------------------------------------------
{
unsigned long i;
unsigned long ulValue;
res = find_resource(dev, 0x10);
if (!res) {
printk(BIOS_DEBUG, "NIC Cannot find resource..\n");
return;
}
base = res2mmio(res, 0, 0);
printk(BIOS_DEBUG, "NIC base address %p\n",base);
if (!(val = phy_detect(base, &PhyAddr))) {
printk(BIOS_DEBUG, "PHY detect fail !!!!\n");
return;
}
ulValue = read32(base + 0x38L); // check EEPROM existing
if (ulValue & 0x0002) {
// read MAC address from EEPROM at first
// if that is valid we will use that
printk(BIOS_DEBUG, "EEPROM contents %lx\n",ReadEEprom(dev, base, 0LL));
for (i = 0; i < 3; i++) {
//status = smbus_read_byte(dev_eeprom, i);
ulValue = ReadEEprom(dev, base, i + 3L);
if (ulValue == 0x10000)
break; // error
MacAddr[i] = ulValue & 0xFFFF;
}
} else {
// read MAC address from firmware
printk(BIOS_DEBUG, "EEPROM invalid!!\nReg 0x38h=%.8lx\n",ulValue);
MacAddr[0] = read16((u16 *)0xffffffc0); // mac address store at here
MacAddr[1] = read16((u16 *)0xffffffc2);
MacAddr[2] = read16((u16 *)0xffffffc4);
}
set_apc(dev);
readApcMacAddr();
#if DEBUG_NIC
{
int i;
printk(BIOS_DEBUG, "****** NIC PCI config ******");
printk(BIOS_DEBUG, "\n 03020100 07060504 0B0A0908 0F0E0D0C");
for (i = 0; i < 0xff; i += 4) {
if ((i%16) == 0)
printk(BIOS_DEBUG, "\n%02x: ", i);
printk(BIOS_DEBUG, "%08x ", pci_read_config32(dev, i));
}
printk(BIOS_DEBUG, "\n");
}
#endif
}
printk(BIOS_DEBUG, "NIC_INIT:<----------\n");
return;
}
static void lpci_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x40,
((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = lpci_set_subsystem,
};
static struct device_operations nic_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = nic_init,
.scan_bus = 0,
// .enable = sis966_enable,
.ops_pci = &lops_pci,
};
static const struct pci_driver nic_driver __pci_driver = {
.ops = &nic_ops,
.vendor = PCI_VENDOR_ID_SIS,
.device = PCI_DEVICE_ID_SIS_SIS966_NIC,
};

View File

@ -1,61 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "sis966.h"
static void pcie_init(struct device *dev)
{
/* Enable pci error detecting */
uint32_t dword;
/* 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);
}
static struct pci_operations lops_pci = {
.set_subsystem = 0,
};
static struct device_operations pcie_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.init = pcie_init,
.scan_bus = pci_scan_bridge,
// .enable = sis966_enable,
.ops_pci = &lops_pci,
};
static const struct pci_driver pciebc_driver __pci_driver = {
.ops = &pcie_ops,
.vendor = PCI_VENDOR_ID_SIS,
.device = PCI_DEVICE_ID_SIS_SIS966_PCIE,
};

View File

@ -1,34 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 __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,62 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
.section ".romstrap", "a", @progbits
.globl __romstrap_start
__romstrap_start:
rstables:
.long 0x2b16d065
.long 0x0
.long 0x0
.long linkedlist
linkedlist:
.long 0x0003001C // 10h
.long 0x08000000 // 14h
.long 0x00000000 // 18h
.long 0xFFFFFFFF // 1Ch
.long 0xFFFFFFFF // 20h
.long 0xFFFFFFFF // 24h
.long 0xFFFFFFFF // 28h
.long 0xFFFFFFFF // 2Ch
.long 0x56341200 // 30h, MAC address low 4 byte ---> keep it in 0xffffffc0
.long 0x00009078 // 34h, MAC address high 4 byte
.long 0x002309CE // 38h, UUID low 4 byte
.long 0x00E08100 // 3Ch, UUID high 4 byte
.long 0x00402000 //Firmware trap for SiS761+966
.long 0xE043A800
.long 0x00180000
.long 0x1421C402
rspointers:
.long rstables // It will be 0xffffffe0
.long rstables
.long rstables
.long rstables
.globl __romstrap_end
__romstrap_end:
.previous

View File

@ -1,23 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
SECTIONS {
. = (0xffffffff - 0x10) - (__romstrap_end - __romstrap_start) + 1;
.romstrap (.): {
KEEP(*(.romstrap))
}
}

View File

@ -1,173 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "sis966.h"
#include <arch/io.h>
uint8_t SiS_SiS1183_init[68][3] = {
{0x04, 0x00, 0x05},
{0x09, 0x00, 0x05},
{0x2C, 0x00, 0x39},
{0x2D, 0x00, 0x10},
{0x2E, 0x00, 0x83},
{0x2F, 0x00, 0x11},
{0x90, 0x00, 0x40},
{0x91, 0x00, 0x00}, // set mode
{0x50, 0x00, 0xA2},
{0x52, 0x00, 0xA2},
{0x55, 0x00, 0x96},
{0x52, 0x00, 0xA2},
{0x55, 0xF7, 0x00},
{0x56, 0x00, 0xC0},
{0x57, 0x00, 0x14},
{0x67, 0x00, 0x28},
{0x81, 0x00, 0xB3},
{0x82, 0x00, 0x72},
{0x83, 0x00, 0x40},
{0x85, 0x00, 0xB3},
{0x86, 0x00, 0x72},
{0x87, 0x00, 0x40},
{0x88, 0x00, 0xDE}, // after set mode
{0x89, 0x00, 0xB3},
{0x8A, 0x00, 0x72},
{0x8B, 0x00, 0x40},
{0x8C, 0x00, 0xDE},
{0x8D, 0x00, 0xB3},
{0x8E, 0x00, 0x92},
{0x8F, 0x00, 0x40},
{0x93, 0x00, 0x00},
{0x94, 0x00, 0x80},
{0x95, 0x00, 0x08},
{0x96, 0x00, 0x80},
{0x97, 0x00, 0x08},
{0x9C, 0x00, 0x80},
{0x9D, 0x00, 0x08},
{0x9E, 0x00, 0x80},
{0x9F, 0x00, 0x08},
{0xA0, 0x00, 0x15},
{0xA1, 0x00, 0x15},
{0xA2, 0x00, 0x15},
{0xA3, 0x00, 0x15},
{0xD8, 0xFE, 0x01}, // Com reset
{0xC8, 0xFE, 0x01},
{0xE8, 0xFE, 0x01},
{0xF8, 0xFE, 0x01},
{0xD8, 0xFE, 0x00}, // Com reset
{0xC8, 0xFE, 0x00},
{0xE8, 0xFE, 0x00},
{0xF8, 0xFE, 0x00},
{0xC4, 0xFF, 0xFF}, // Clear status
{0xC5, 0xFF, 0xFF},
{0xC6, 0xFF, 0xFF},
{0xC7, 0xFF, 0xFF},
{0xD4, 0xFF, 0xFF},
{0xD5, 0xFF, 0xFF},
{0xD6, 0xFF, 0xFF},
{0xD7, 0xFF, 0xFF},
{0xE4, 0xFF, 0xFF}, // Clear status
{0xE5, 0xFF, 0xFF},
{0xE6, 0xFF, 0xFF},
{0xE7, 0xFF, 0xFF},
{0xF4, 0xFF, 0xFF},
{0xF5, 0xFF, 0xFF},
{0xF6, 0xFF, 0xFF},
{0xF7, 0xFF, 0xFF},
{0x00, 0x00, 0x00} // End of table
};
static void sata_init(struct device *dev)
{
struct southbridge_sis_sis966_config *conf;
int i;
uint32_t temp32;
uint8_t temp8;
conf = dev->chip_info;
printk(BIOS_DEBUG, "SATA_INIT:---------->\n");
/* Enable IDE (SiS1183) */
i = 0;
while (SiS_SiS1183_init[i][0] != 0) {
temp8 = pci_read_config8(dev, SiS_SiS1183_init[i][0]);
temp8 &= SiS_SiS1183_init[i][1];
temp8 |= SiS_SiS1183_init[i][2];
pci_write_config8(dev, SiS_SiS1183_init[i][0], temp8);
i++;
};
for (i = 0; i < 10; i++) {
temp32 = pci_read_config32(dev, 0xC0);
printk(BIOS_DEBUG, "status= %x\n", temp32);
if (((temp32 & 0xF) == 0x3) || ((temp32 & 0xF) == 0x0))
break;
}
#if DEBUG_SATA
printk(BIOS_DEBUG, "****** SATA PCI config ******");
printk(BIOS_DEBUG, "\n 03020100 07060504 0B0A0908 0F0E0D0C");
for (i = 0; i < 0xff; i += 4) {
if ((i % 16) == 0)
printk(BIOS_DEBUG, "\n%02x: ", i);
printk(BIOS_DEBUG, "%08x ", pci_read_config32(dev, i));
}
printk(BIOS_DEBUG, "\n");
#endif
printk(BIOS_DEBUG, "SATA_INIT:<----------\n");
}
static void lpci_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x40,
((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = lpci_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 = sis966_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_SIS,
.device = PCI_DEVICE_ID_SIS_SIS966_SATA,
};

View File

@ -1,124 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
/*
* Turn off machine check triggers when reading
* pci space where there are no devices.
* This is necessary when scanning the bus for
* devices which is done by the kernel
*
* written in 2003 by Eric Biederman
*
* - Athlon64 workarounds by Stefan Reinauer
* - "reset once" logic by Yinghai Lu
*/
#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 <cpu/amd/model_fxx_rev.h>
#include <arch/io.h>
typedef struct msr_struct
{
unsigned lo;
unsigned hi;
} msr_t;
static inline msr_t rdmsr(unsigned index)
{
msr_t result;
result.lo = 0;
result.hi = 0;
return result;
}
/**
* Read resources for AGP aperture.
*
* There is only one AGP aperture resource needed. The resource is added to
* the northbridge of BSP.
*
* The same trick can be used to augment legacy VGA resources which can
* be detect by generic PCI resource allocator for VGA devices.
* BAD: it is more tricky than I think, the resource allocation code is
* implemented in a way to NOT DOING legacy VGA resource allocation on
* purpose :-(.
*
* @param dev TODO
*/
static void sis761_read_resources(struct device *dev)
{
/* Read the generic PCI resources */
printk(BIOS_DEBUG, "sis761_read_resources ------->\n");
pci_dev_read_resources(dev);
/* If we are not the first processor don't allocate the gart aperture */
if (dev->path.pci.devfn != PCI_DEVFN(0x0, 0)) {
printk(BIOS_DEBUG, "sis761_not_the_first_processor !!!\n");
return;
}
printk(BIOS_DEBUG, "sis761_read_resources <-------\n");
return;
}
static void sis761_set_resources(struct device *dev)
{
printk(BIOS_DEBUG, "sis761_set_resources ------->\n");
/* Set the generic PCI resources */
pci_dev_set_resources(dev);
printk(BIOS_DEBUG, "sis761_set_resources <-------\n");
}
static void sis761_init(struct device *dev)
{
int needs_reset;
msr_t msr;
needs_reset = 0;
printk(BIOS_DEBUG, "sis761_init: ---------->\n");
msr = rdmsr(0xC001001A);
pci_write_config16(dev, 0x8E, msr.lo >> 16); // Topbound
pci_write_config8(dev, 0x7F, 0x08); // ACPI Base
outb(inb(0x856) | 0x40, 0x856); // Auto-Reset Function
printk(BIOS_DEBUG, "sis761_init: <----------\n");
}
static struct device_operations sis761_ops = {
.read_resources = sis761_read_resources,
.set_resources = sis761_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = sis761_init,
.scan_bus = 0,
.ops_pci = 0,
};
static const struct pci_driver sis761_driver __pci_driver = {
.ops = &sis761_ops,
.vendor = PCI_VENDOR_ID_SIS,
.device = PCI_DEVICE_ID_SIS_SIS761,
};

View File

@ -1,201 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "sis966.h"
static uint32_t final_reg;
static struct device *find_lpc_dev( struct device *dev, unsigned devfn)
{
struct device *lpc_dev;
lpc_dev = dev_find_slot(dev->bus->secondary, devfn);
if ( !lpc_dev ) return lpc_dev;
if ((lpc_dev->vendor != PCI_VENDOR_ID_SIS) || (
(lpc_dev->device != PCI_DEVICE_ID_SIS_SIS966_LPC)
) ) {
uint32_t id;
id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
if ( (id < (PCI_VENDOR_ID_SIS | (PCI_DEVICE_ID_SIS_SIS966_LPC << 16)))
) {
lpc_dev = 0;
}
}
return lpc_dev;
}
void sis966_enable(struct device *dev)
{
struct device *lpc_dev = NULL;
struct device *sm_dev = NULL;
uint16_t index = 0;
uint16_t index2 = 0;
uint32_t reg_old, reg;
uint8_t byte;
uint16_t deviceid;
uint16_t vendorid;
uint16_t devfn;
struct southbridge_sis_sis966_config *conf;
conf = dev->chip_info;
int i;
if (dev->device == 0x0000) {
reg = pci_read_config32(dev, PCI_VENDOR_ID);
deviceid = (reg >> 16) & 0xffff;
vendorid = reg & 0xffff;
} else {
// vendorid = dev->vendor;
deviceid = dev->device;
}
devfn = (dev->path.pci.devfn) & ~7;
switch (deviceid) {
case PCI_DEVICE_ID_SIS_SIS966_USB:
devfn -= (1<<3);
index = 8;
break;
case PCI_DEVICE_ID_SIS_SIS966_USB2:
devfn -= (1<<3);
index = 20;
break;
case PCI_DEVICE_ID_SIS_SIS966_NIC:
devfn -= (7<<3);
index = 10;
for (i=0;i<2;i++) {
lpc_dev = find_lpc_dev(dev, devfn - (i<<3));
if (!lpc_dev) continue;
index -= i;
devfn -= (i<<3);
break;
}
break;
case PCI_DEVICE_ID_SIS_SIS966_HD_AUDIO:
devfn -= (5<<3);
index = 11;
break;
case PCI_DEVICE_ID_SIS_SIS966_IDE:
devfn -= (3<<3);
index = 14;
break;
case PCI_DEVICE_ID_SIS_SIS966_SATA:
devfn -= (4<<3);
index = 22;
i = (dev->path.pci.devfn) & 7;
if (i>0) {
index -= (i+3);
}
break;
case PCI_DEVICE_ID_SIS_SIS966_PCIE:
devfn -= (0x9<<3); // to LPC
index2 = 9;
break;
default:
index = 0;
}
if (!lpc_dev)
lpc_dev = find_lpc_dev(dev, devfn);
if ( !lpc_dev ) return;
if (index2!=0) {
sm_dev = dev_find_slot(dev->bus->secondary, devfn + 1);
if (!sm_dev) return;
if ( sm_dev ) {
reg_old = reg = pci_read_config32(sm_dev, 0xe4);
if (!dev->enabled) { //disable it
reg |= (1<<index2);
}
if (reg != reg_old) {
pci_write_config32(sm_dev, 0xe4, reg);
}
}
index2 = 0;
return;
}
if ( index == 0) { // for LPC
// expose ioapic base
byte = pci_read_config8(lpc_dev, 0x74);
byte |= ((1<<1)); // expose the BAR
pci_write_config8(dev, 0x74, byte);
// expose trap base
byte = pci_read_config8(lpc_dev, 0xdd);
byte |= ((1<<0)|(1<<3)); // expose the BAR and enable write
pci_write_config8(dev, 0xdd, byte);
return;
}
if ( index == 16) {
sm_dev = dev_find_slot(dev->bus->secondary, devfn + 1);
if (!sm_dev) return;
final_reg = pci_read_config32(sm_dev, 0xe8);
final_reg &= ~0x0057cf00;
pci_write_config32(sm_dev, 0xe8, final_reg); //enable all at first
}
if (!dev->enabled) {
final_reg |= (1 << index);// disable it
/*
* The reason for using final_reg is that if func 1 is disabled,
* then func 2 will become func 1.
* Because of this, we need loop through disabling them all at
* the same time.
*/
}
if (index == 9 ) { //NIC1 is the final, We need update final reg to 0xe8
sm_dev = dev_find_slot(dev->bus->secondary, devfn + 1);
if (!sm_dev) return;
reg_old = pci_read_config32(sm_dev, 0xe8);
if (final_reg != reg_old) {
pci_write_config32(sm_dev, 0xe8, final_reg);
}
}
}
struct chip_operations southbridge_sis_sis966_ops = {
CHIP_NAME("SiS SiS966 Southbridge")
.enable_dev = sis966_enable,
};

View File

@ -1,38 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 SIS966_H
#define SIS966_H
#if CONFIG_HT_CHAIN_END_UNITID_BASE < CONFIG_HT_CHAIN_UNITID_BASE
#define SIS966_DEVN_BASE CONFIG_HT_CHAIN_END_UNITID_BASE
#else
#define SIS966_DEVN_BASE CONFIG_HT_CHAIN_UNITID_BASE
#endif
#define DEBUG_AZA 0
#define DEBUG_NIC 0
#define DEBUG_IDE 0
#define DEBUG_SATA 0
#define DEBUG_USB 0
#define DEBUG_USB2 0
#ifndef __SIMPLE_DEVICE__
void sis966_enable(struct device *dev);
#endif
#endif /* SIS966_H */

View File

@ -1,41 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <device/smbus_def.h>
#define SMBHSTSTAT 0x1
#define SMBHSTPRTCL 0x0
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x2
#define SMBHSTDAT0 0x4
#define SMBHSTDAT1 0x5
/* 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)
int smbus_wait_until_ready(unsigned smbus_io_base);
int smbus_wait_until_done(unsigned smbus_io_base);
int do_smbus_recv_byte(unsigned smbus_io_base, unsigned device);
int do_smbus_send_byte(unsigned smbus_io_base, unsigned device, unsigned char val);
int smbus_read_byte(unsigned device, unsigned address);
int smbus_write_byte(unsigned device, unsigned address, unsigned char val);

View File

@ -1,113 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "sis966.h"
uint8_t SiS_SiS7001_init[16][3]={
{0x04, 0x00, 0x07},
{0x0C, 0x00, 0x08},
{0x0D, 0x00, 0x20},
{0x2C, 0xFF, 0x39},
{0x2D, 0xFF, 0x10},
{0x2E, 0xFF, 0x01},
{0x2F, 0xFF, 0x70},
{0x44, 0x00, 0x54},
{0x45, 0x00, 0xAD},
{0x46, 0x00, 0x01},
{0x47, 0x00, 0x00},
{0x48, 0x00, 0x73},
{0x49, 0x00, 0x02},
{0x4A, 0x00, 0x00},
{0x4B, 0x00, 0x00},
{0x00, 0x00, 0x00} //End of table
};
static void usb_init(struct device *dev)
{
printk(BIOS_DEBUG, "USB 1.1 INIT:---------->\n");
//-------------- enable USB1.1 (SiS7001) -------------------------
{
uint8_t temp8;
int i=0;
while (SiS_SiS7001_init[i][0] != 0) {
temp8 = pci_read_config8(dev, SiS_SiS7001_init[i][0]);
temp8 &= SiS_SiS7001_init[i][1];
temp8 |= SiS_SiS7001_init[i][2];
pci_write_config8(dev, SiS_SiS7001_init[i][0], temp8);
i++;
};
}
//-----------------------------------------------------------
#if DEBUG_USB
{
int i;
printk(BIOS_DEBUG, "****** USB 1.1 PCI config ******");
printk(BIOS_DEBUG, "\n 03020100 07060504 0B0A0908 0F0E0D0C");
for (i=0;i<0xff;i+=4) {
if ((i%16)==0)
printk(BIOS_DEBUG, "\n%02x: ", i);
printk(BIOS_DEBUG, "%08x ", pci_read_config32(dev,i));
}
printk(BIOS_DEBUG, "\n");
}
#endif
printk(BIOS_DEBUG, "USB 1.1 INIT:<----------\n");
}
static void lpci_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x40,
((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = lpci_set_subsystem,
};
static struct device_operations usb_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = usb_init,
// .enable = sis966_enable,
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const struct pci_driver usb_driver __pci_driver = {
.ops = &usb_ops,
.vendor = PCI_VENDOR_ID_SIS,
.device = PCI_DEVICE_ID_SIS_SIS966_USB,
};

View File

@ -1,131 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
* Copyright (C) 2006,2007 AMD
* Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
* Copyright (C) 2007 Silicon Integrated Systems Corp. (SiS)
* Written by Morgan Tsai <my_tsai@sis.com> for SiS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "sis966.h"
#include <device/pci_ehci.h>
static const u8 SiS_SiS7002_init[22][3]={
{0x04, 0x00, 0x06},
{0x0D, 0x00, 0x00},
{0x2C, 0xFF, 0x39},
{0x2D, 0xFF, 0x10},
{0x2E, 0xFF, 0x02},
{0x2F, 0xFF, 0x70},
{0x74, 0x00, 0x00},
{0x75, 0x00, 0x00},
{0x76, 0x00, 0x00},
{0x77, 0x00, 0x00},
{0x7A, 0x00, 0x00},
{0x7B, 0x00, 0x00},
{0x40, 0x00, 0x20},
{0x41, 0x00, 0x00},
{0x42, 0x00, 0x00},
{0x43, 0x00, 0x08},
{0x44, 0x00, 0x04},
{0x48, 0x00, 0x10},
{0x49, 0x00, 0x80},
{0x4A, 0x00, 0x07},
{0x4B, 0x00, 0x00},
{0x00, 0x00, 0x00} //End of table
};
static void usb2_init(struct device *dev)
{
u8 *base;
struct resource *res;
int i;
u8 temp8;
printk(BIOS_DEBUG, "USB 2.0 INIT:---------->\n");
//-------------- enable USB2.0 (SiS7002) ----------------------
i = 0;
while (SiS_SiS7002_init[i][0] != 0) {
temp8 = pci_read_config8(dev, SiS_SiS7002_init[i][0]);
temp8 &= SiS_SiS7002_init[i][1];
temp8 |= SiS_SiS7002_init[i][2];
pci_write_config8(dev, SiS_SiS7002_init[i][0], temp8);
i++;
};
res = find_resource(dev, 0x10);
if (!res)
return;
base = res2mmio(res, 0, 0);
printk(BIOS_DEBUG, "base = 0x%p\n", base);
write32(base + 0x20, 0x2);
//-------------------------------------------------------------
#if DEBUG_USB2
printk(BIOS_DEBUG, "****** USB 2.0 PCI config ******");
printk(BIOS_DEBUG, "\n 03020100 07060504 0B0A0908 0F0E0D0C");
for (i=0;i<0xff;i+=4) {
if ((i%16)==0)
printk(BIOS_DEBUG, "\n%02x: ", i);
printk(BIOS_DEBUG, "%08x ", pci_read_config32(dev,i));
}
printk(BIOS_DEBUG, "\n");
#endif
printk(BIOS_DEBUG, "USB 2.0 INIT:<----------\n");
}
static void lpci_set_subsystem(struct device *dev, unsigned vendor,
unsigned device)
{
pci_write_config32(dev, 0x40,
((device & 0xffff) << 16) | (vendor & 0xffff));
}
static struct pci_operations lops_pci = {
.set_subsystem = lpci_set_subsystem,
};
static struct device_operations usb2_ops = {
.read_resources = pci_ehci_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = usb2_init,
// .enable = sis966_enable,
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const struct pci_driver usb2_driver __pci_driver = {
.ops = &usb2_ops,
.vendor = PCI_VENDOR_ID_SIS,
.device = PCI_DEVICE_ID_SIS_SIS966_USB2,
};

View File

@ -1,54 +0,0 @@
config SOUTHBRIDGE_VIA_K8T890
bool
if SOUTHBRIDGE_VIA_K8T890
config SOUTHBRIDGE_VIA_SUBTYPE_K8M800 # not tested
def_bool n
config SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD # not tested, lspci lists B188 and 3188
def_bool n
config SOUTHBRIDGE_VIA_SUBTYPE_K8T800 # lspci lists 0282, 1282, 2282, 3282, and 7282
def_bool n
config SOUTHBRIDGE_VIA_SUBTYPE_K8T800PRO # lspci lists 0282, 1282, 2282, 3282, and 7282
def_bool n
config SOUTHBRIDGE_VIA_SUBTYPE_K8M890
def_bool n
config SOUTHBRIDGE_VIA_SUBTYPE_K8T890
def_bool n
config SOUTHBRIDGE_VIA_K8M890_VGA_EN
bool "Enable onboard K8M890 graphics"
default y
depends on SOUTHBRIDGE_VIA_SUBTYPE_K8M890
select VGA
select GFXUMA
choice
prompt "Framebuffer size"
default K8M890_VIDEO_MB_32MB
depends on SOUTHBRIDGE_VIA_K8M890_VGA_EN
config K8M890_VIDEO_MB_32MB
bool "32MB"
config K8M890_VIDEO_MB_64MB
bool "64MB"
config K8M890_VIDEO_MB_128MB
bool "128MB"
config K8M890_VIDEO_MB_256MB
bool "256MB"
config K8M890_VIDEO_MB_CMOS
bool "Use CMOS option"
endchoice
config VIDEO_MB
int
default 32 if K8M890_VIDEO_MB_32MB
default 64 if K8M890_VIDEO_MB_64MB
default 128 if K8M890_VIDEO_MB_128MB
default 256 if K8M890_VIDEO_MB_256MB
default -1 if K8M890_VIDEO_MB_CMOS
depends on SOUTHBRIDGE_VIA_K8M890_VGA_EN
endif # SOUTHBRIDGE_K8T890

View File

@ -1,16 +0,0 @@
ifeq ($(CONFIG_SOUTHBRIDGE_VIA_K8T890),y)
ramstage-y += ctrl.c
ramstage-y += dram.c
ramstage-y += bridge.c
ramstage-y += host.c
ramstage-y += host_ctrl.c
ramstage-y += pcie.c
ramstage-y += traf_ctrl.c
ramstage-y += error.c
ramstage-y += chrome.c
bootblock-y += romstrap.ld
bootblock-y += romstrap.S
endif

View File

@ -1,31 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
*
* 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.
*/
/* S1 support: bit 0, S2 Support: bit 1, etc. S0 & S5 assumed */
#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
Name (SSFG, 0x04)
#else
Name (SSFG, 0x00)
#endif
/* Supported sleep states: */
Name(\_S0, Package () {0x00, 0x00, 0x00, 0x00} ) /* (S0) - working state */
If (And(SSFG, 0x04)) {
Name(\_S3, Package () {0x01, 0x01, 0x00, 0x00} ) /* (S3) - Suspend to RAM */
}
Name(\_S5, Package () {0x02, 0x02, 0x00, 0x00} ) /* (S5) - Soft Off */

View File

@ -1,80 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@gmail.com>
* 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 <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <console/console.h>
#include "k8x8xx.h"
static void bridge_enable(struct device *dev)
{
u8 tmp;
printk(BIOS_DEBUG, "B188 device dump\n");
/* VIA recommends this, sorry no known info. */
writeback(dev, 0x40, 0x91);
writeback(dev, 0x41, 0x40);
writeback(dev, 0x43, 0x44);
#if IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
writeback(dev, 0x42, 0x80);
writeback(dev, 0x44, 0x35);
#else
writeback(dev, 0x44, 0x31); /* K8M890 should have 0x35 datasheet
* says it is reserved
*/
#endif
writeback(dev, 0x45, 0x3a);
writeback(dev, 0x46, 0x88); /* PCI ID lo */
writeback(dev, 0x47, 0xb1); /* PCI ID hi */
/* Bridge control, K8M890 bit 3 should be set to enable VGA on AGP
* (Forward VGA compatible memory and I/O cycles )
*/
#if IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
writeback(dev, 0x3e, 0x0a);
#else
writeback(dev, 0x3e, 0x16);
#endif
dump_south(dev);
/* disable I/O and memory decode, or it freezes PCI bus during BAR sizing */
tmp = pci_read_config8(dev, PCI_COMMAND);
tmp &= ~0x3;
pci_write_config8(dev, PCI_COMMAND, tmp);
}
static const struct device_operations bridge_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.enable = bridge_enable,
.scan_bus = pci_scan_bridge,
.reset_bus = pci_bus_reset,
.ops_pci = 0,
};
/*
* K8T890 and K8T800 both use device B188 as the bridge, so no need to
* add a separate driver
*/
static const struct pci_driver northbridge_driver_890 __pci_driver = {
.ops = &bridge_ops,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T890CE_BR,
};

View File

@ -1,173 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 Luc Verhaegen <libv@skynet.be>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <string.h> /* for memset */
#include "k8x8xx.h"
#include <pc80/vga_io.h>
#include <pc80/vga.h>
#include <arch/io.h>
/*
*
*/
static void
chrome_vga_init(struct device *dev)
{
vga_sr_write(0x10, 0x01); /* unlock extended regs */
vga_sr_mask(0x1A, 0x02, 0x02); /* enable mmio */
vga_sr_mask(0x1A, 0x40, 0x40); /* Software Reset */
vga_cr_mask(0x6A, 0x00, 0xC8); /* Disable CRTC2 & Simultaneous */
/* Make sure that non of the primary VGA overflow registers are set */
vga_cr_write(0x33, 0x00);
vga_cr_write(0x35, 0x00);
vga_cr_mask(0x11, 0x00, 0x30);
vga_sr_mask(0x16, 0x00, 0x40); /* Wire CRT to CRTC1 */
vga_cr_mask(0x36, 0x00, 0x30); /* Power on CRT */
/* Disable Extended Display Mode */
vga_sr_mask(0x15, 0x00, 0x02);
/* Disable Wrap-around */
vga_sr_mask(0x15, 0x00, 0x20);
/* Disable Extended Mode memory access */
vga_sr_mask(0x1A, 0x00, 0x08);
/* Make sure that we only touch CRTC1s DAC */
vga_sr_mask(0x1A, 0x00, 0x01);
/* Set up power to the clocks/crtcs */
vga_sr_mask(0x19, 0x7F, 0x7F); /* enable clock gating for all. */
vga_sr_mask(0x1B, 0xC0, 0xC0); /* secondary clock according to pm */
vga_sr_mask(0x1B, 0x20, 0x30); /* primary clock is always on */
/* set everything according to PM/Engine idle state except pci dma */
vga_sr_write(0x2D, 0xFF); /* Power management control 1 */
vga_sr_write(0x2E, 0xFB); /* Power management control 2 */
vga_sr_write(0x3F, 0xFF); /* Power management control 3 */
/* now set up the engine clock. */
vga_sr_write(0x47, 0xB8);
vga_sr_write(0x48, 0x08);
vga_sr_write(0x49, 0x03);
/* trigger engine clock setting */
vga_sr_mask(0x40, 0x01, 0x01);
vga_sr_mask(0x40, 0, 0x01);
vga_cr_mask(0x30, 0x04, 0x04); /* Enable PowerNow in primary path */
vga_cr_mask(0x36, 0x01, 0x01); /* Enable PCI Power Management */
/* Power now indicators... */
vga_cr_write(0x41, 0xB9);
vga_cr_write(0x42, 0xB4);
/* could these be the CRTC2 power now indicators? */
vga_cr_write(0x9D, 0x80); /* Power Now Ending position enable */
vga_cr_write(0x9E, 0xB4); /* Power Now Control 3 */
/* primary fifo setting */
vga_sr_mask(0x16, 0x28, 0xBF); /* pthreshold: 160 */
vga_sr_write(0x17, 0x60); /* max depth: 194 */
vga_sr_mask(0x18, 0x0E, 0xBF); /* high priority threshold: 56 */
vga_sr_write(0x1C, 0x54); /* Fetch count */
vga_sr_write(0x20, 0x40); /* display queue typical arbiter control 0 */
vga_sr_write(0x21, 0x40); /* display queue typical arbiter control 1 */
vga_sr_mask(0x22, 0x14, 0x1F); /* display queue expire number */
/* Typical Arbiter Control */
vga_sr_mask(0x41, 0x40, 0xF0); /* Request threshold */
vga_sr_mask(0x42, 0x20, 0x20); /* Support Fetch Cycle with Length 2 */
vga_sr_write(0x50, 0x1F); /* AGP Control Register */
vga_sr_write(0x51, 0xF5); /* AGP FIFO Control 1 */
vga_cr_mask(0x33, 0x08, 0x08); /* Enable Prefetch Mode */
}
/*
*
*/
static void
chrome_init(struct device *dev)
{
uint32_t fb_size, fb_address;
fb_size = k8m890_host_fb_size_get();
if (!fb_size) {
printk(BIOS_WARNING, "Chrome: Device has not been initialised in the"
" ramcontroller!\n");
return;
}
fb_address = pci_read_config32(dev, 0x10);
fb_address &= ~0x0F;
if (!fb_address) {
printk(BIOS_WARNING, "Chrome: No FB BAR assigned!\n");
return;
}
printk(BIOS_INFO, "Chrome: Using %dMB Framebuffer at 0x%08X.\n",
fb_size, fb_address);
//k8m890_host_fb_direct_set(fb_address);
if (IS_ENABLED(SOUTHBRIDGE_VIA_K8M890_VGA_EN)) {
/* Now set up the VGA console */
vga_io_init(); /* Enable full IO access */
chrome_vga_init(dev);
vga_textmode_init();
printk(BIOS_INFO, "Chrome VGA Textmode initialized.\n");
/* if we don't have console, at least print something... */
vga_line_write(0, "Chrome VGA Textmode initialized.");
}
}
static struct device_operations
chrome_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = chrome_init,
.scan_bus = 0,
.enable = 0,
};
static const struct pci_driver unichrome_driver_800 __pci_driver = {
.ops = &chrome_ops,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8M800_CHROME,
};
static const struct pci_driver unichrome_driver_890 __pci_driver = {
.ops = &chrome_ops,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8M890_CHROME,
};

View File

@ -1,206 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@gmail.com>
*
* 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 <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <device/pci_ids.h>
#include <console/console.h>
#include "k8x8xx.h"
void k8x8xx_vt8237_mirrored_regs_fill(struct k8x8xx_vt8237_mirrored_regs *regs)
{
msr_t msr;
regs->rom_shadow_ctrl_pg_c = 0xff;
regs->rom_shadow_ctrl_pg_d = 0xff;
regs->rom_shadow_ctrl_pg_e_memhole_smi_decoding = 0xff;
regs->rom_shadow_ctrl_pg_f_memhole = 0x30;
regs->smm_apic_decoding = 0x19;
msr = rdmsr(TOP_MEM);
regs->shadow_mem_ctrl = msr.lo >> 24;
regs->low_top_address = msr.lo >> 16;
}
/* We support here K8M890/K8T890 and VT8237R PCI1/Vlink which setup is not in separate
* PCI device 0:11.7, but it is mapped to PCI 0:0.7 (0x70-0x7c for PCI1)
*/
void k8x8xx_vt8237r_cfg(struct device *dev, struct device *devsb)
{
u8 regm3;
struct k8x8xx_vt8237_mirrored_regs mregs;
pci_write_config8(dev, 0x70, 0xc2);
/* PCI Control */
#if !IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
pci_write_config8(dev, 0x72, 0xee);
#endif
pci_write_config8(dev, 0x73, 0x01);
#if IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
pci_write_config8(dev, 0x74, 0x64);
pci_write_config8(dev, 0x75, 0x3f);
#else
pci_write_config8(dev, 0x74, 0x24);
pci_write_config8(dev, 0x75, 0x0f);
#endif
pci_write_config8(dev, 0x76, 0x50);
#if !IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
pci_write_config8(dev, 0x77, 0x08);
#endif
pci_write_config8(dev, 0x78, 0x01);
/* APIC on HT */
pci_write_config8(dev, 0x7c, 0x7f);
pci_write_config8(dev, 0x7f, 0x02);
k8x8xx_vt8237_mirrored_regs_fill(&mregs);
pci_write_config8(dev, 0x57, mregs.shadow_mem_ctrl); /* Shadow mem CTRL */
pci_write_config8(dev, 0x61, mregs.rom_shadow_ctrl_pg_c); /* Shadow page C */
pci_write_config8(dev, 0x62, mregs.rom_shadow_ctrl_pg_d); /* Shadow page D */
pci_write_config8(dev, 0xe6, mregs.smm_apic_decoding); /* SMM and APIC decoding */
regm3 = mregs.rom_shadow_ctrl_pg_e_memhole_smi_decoding; /* Shadow page E */
/*
* All access bits for 0xE0000-0xEFFFF encode as just 2 bits!
* So the NB reg is quite inconsistent, we expect there only 0xff or 0x00,
* and write them to 0x63 7-6 but! VIA 8237A has the mirror at 0x64!
*/
if (regm3 == 0xff)
regm3 = 0xc0;
else
regm3 = 0x0;
/* Shadow page F + memhole copy */
pci_write_config8(dev, 0x63, regm3 | (mregs.rom_shadow_ctrl_pg_f_memhole & 0x3F));
}
/**
* Setup the V-Link for VT8237R, 8X mode.
*
* For K8T890CF VIA recommends what is in VIA column, AW is award 8X:
*
* REG DEF AW VIA-8X VIA-4X
* -----------------------------
* NB V-Link Manual Driving Control strobe 0xb5 0x46 0x46 0x88 0x88
* NB V-Link Manual Driving Control - Data 0xb6 0x46 0x46 0x88 0x88
* NB V-Link Receiving Strobe Delay 0xb7 0x02 0x02 0x61 0x01
* NB V-Link Compensation Control bit4,0 (b5,b6) 0xb4 0x10 0x10 0x11 0x11
* SB V-Link Strobe Drive Control 0xb9 0x00 0xa5 0x98 0x98
* SB V-Link Data drive Control???? 0xba 0x00 0xbb 0x77 0x77
* SB V-Link Receive Strobe Delay???? 0xbb 0x04 0x11 0x11 0x11
* SB V-Link Compensation Control bit0 (use b9) 0xb8 0x00 0x01 0x01 0x01
* V-Link CKG Control 0xb0 0x05 0x05 0x06 0x03
* V-Link CKG Control 0xb1 0x05 0x05 0x01 0x03
*/
static void vt8237r_vlink_init(struct device *dev)
{
u8 reg;
/*
* This init code is valid only for the VT8237R! For different
* southbridges (e.g. VT8237A, VT8237S, VT8237 (without plus R)
* and VT8251) a different init code is required.
*/
pci_write_config8(dev, 0xb5, 0x88);
pci_write_config8(dev, 0xb6, 0x88);
pci_write_config8(dev, 0xb7, 0x61);
reg = pci_read_config8(dev, 0xb4);
reg |= 0x11;
pci_write_config8(dev, 0xb4, reg);
pci_write_config8(dev, 0xb9, 0x98);
pci_write_config8(dev, 0xba, 0x77);
pci_write_config8(dev, 0xbb, 0x11);
reg = pci_read_config8(dev, 0xb8);
reg |= 0x1;
pci_write_config8(dev, 0xb8, reg);
pci_write_config8(dev, 0xb0, 0x06);
pci_write_config8(dev, 0xb1, 0x01);
/* Program V-link 8X 16bit full duplex, parity enabled. */
pci_write_config8(dev, 0x48, 0xa3);
}
static void ctrl_init(struct device *dev)
{
printk(BIOS_DEBUG, "K8x8xx: Initializing V-Link to VT8237R sb: ");
/* TODO: Fix some ordering issue for V-link set Rx77[6] and PCI1_Rx4F[0]
should to 1 */
/* C2P Read ACK Return Priority */
/* PCI CFG Address bits[27:24] are used as extended register address
bit[11:8] */
#if !IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
pci_write_config8(dev, 0x47, 0x30);
#endif
/* VT8237R specific configuration other SB are done in their own directories */
struct device *devsb = dev_find_device(PCI_VENDOR_ID_VIA,
PCI_DEVICE_ID_VIA_VT8237R_LPC,
0);
if (devsb) {
vt8237r_vlink_init(dev);
k8x8xx_vt8237r_cfg(dev, devsb);
} else {
printk(BIOS_DEBUG, "VT8237R LPC not found !\n");
return;
}
printk(BIOS_DEBUG, " Done\n");
printk(BIOS_DEBUG, " VIA_X_7 device dump:\n");
dump_south(dev);
}
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static const struct device_operations ctrl_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = ctrl_init,
.ops_pci = &lops_pci,
};
static const unsigned short ctrl_ids[] = {
PCI_DEVICE_ID_VIA_K8T800_NB_SB_CTR,
PCI_DEVICE_ID_VIA_K8M800_NB_SB_CTR,
PCI_DEVICE_ID_VIA_K8T890CE_7,
PCI_DEVICE_ID_VIA_K8T890CF_7,
PCI_DEVICE_ID_VIA_K8M890CE_7,
0
};
static const struct pci_driver northbridge_driver_t800 __pci_driver = {
.ops = &ctrl_ops,
.vendor = PCI_VENDOR_ID_VIA,
.devices= ctrl_ids,
};

View File

@ -1,197 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@gmail.com>
*
* 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 <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
#include <pc80/mc146818rtc.h>
#include <lib.h>
#include "k8x8xx.h"
static void dram_enable(struct device *dev)
{
u16 reg;
struct k8x8xx_vt8237_mirrored_regs mregs;
k8x8xx_vt8237_mirrored_regs_fill(&mregs);
/*
* Enable Lowest Interrupt arbitration for APIC, enable NB APIC
* decoding, MSI support, no SMRAM, compatible SMM.
*/
pci_write_config8(dev, 0x86, mregs.smm_apic_decoding);
/*
* We want to use the 0xC0000-0xEFFFF as RAM mark area as RW, even if
* memory is doing K8 the DMA from SB will fail if we have it wrong,
* AND even we have it here, we must later copy it to SB to make it work :/
*/
/* For CC000-CFFFF, bits 7:6 (10 = REn, 01 = WEn) bits 1:0 for
* C0000-C3FFF etc.
*/
pci_write_config8(dev, 0x80, mregs.rom_shadow_ctrl_pg_c);
/* For page D0000-DFFFF */
pci_write_config8(dev, 0x81, mregs.rom_shadow_ctrl_pg_d);
/* For page E0000-EFFFF */
pci_write_config8(dev, 0x82, mregs.rom_shadow_ctrl_pg_e_memhole_smi_decoding);
pci_write_config8(dev, 0x83, mregs.rom_shadow_ctrl_pg_f_memhole);
reg = pci_read_config16(dev, 0x84);
reg &= 0xf;
pci_write_config16(dev, 0x84, mregs.low_top_address | reg);
reg = pci_read_config16(dev, 0x88);
reg &= 0xf800;
/* The Address Next to the Last Valid DRAM Address */
pci_write_config16(dev, 0x88, reg | mregs.shadow_mem_ctrl);
printk(BIOS_DEBUG, " VIA_X_3 device dump:\n");
dump_south(dev);
}
static void dram_enable_k8m890(struct device *dev)
{
#if IS_ENABLED(CONFIG_GFXUMA)
msr_t msr;
int ret;
unsigned int fbbits;
/* use CMOS */
if (CONFIG_VIDEO_MB == -1) {
ret = get_option(&fbbits, "videoram_size");
if (ret) {
printk(BIOS_WARNING, "Failed to get videoram size (error %d), using default.\n", ret);
fbbits = 5;
}
if ((fbbits < 1) || (fbbits > 7)) {
printk(BIOS_WARNING, "Invalid videoram size (%d), using default.\n",
4 << fbbits);
fbbits = 5;
}
uma_memory_size = 4 << (fbbits + 20);
} else {
uma_memory_size = (CONFIG_VIDEO_MB << 20);
}
msr = rdmsr(TOP_MEM);
uma_memory_base = msr.lo - uma_memory_size;
printk(BIOS_INFO, "K8M890: UMA base is %llx size is %u (MB)\n", uma_memory_base,
(u32) (uma_memory_size / 1024 / 1024));
/* enable VGA, so the bridges gets VGA_EN and resources are set */
pci_write_config8(dev, 0xa1, 0x80);
#endif
dram_enable(dev);
}
int
k8m890_host_fb_size_get(void)
{
struct device *dev = dev_find_device(PCI_VENDOR_ID_VIA,
PCI_DEVICE_ID_VIA_K8M800_DRAM, 0);
if (!dev) dev = dev_find_device(PCI_VENDOR_ID_VIA,
PCI_DEVICE_ID_VIA_K8M890CE_3, 0);
unsigned char tmp;
tmp = pci_read_config8(dev, 0xA1);
tmp >>= 4;
if (tmp & 0x08)
return 4 << (tmp & 7);
else
return 0;
}
static void dram_init_fb(struct device *dev)
{
#if IS_ENABLED(CONFIG_GFXUMA)
/* Important bits:
* Enable the internal GFX bit 7 of reg 0xa1 plus in same reg:
* bits 6:4 X fbuffer size will be 2^(X+2) or 100 = 64MB, 101 = 128MB
* bits 3:0 BASE [31:28]
* reg 0xa0 bits 7:1 BASE [27:21] bit0 enable CPU access
*/
unsigned int fbbits = 0;
u8 tmp;
fbbits = ((log2(uma_memory_size >> 20) - 2) << 4);
printk(BIOS_INFO, "K8M890: Using a %dMB framebuffer.\n", (unsigned int) (uma_memory_size >> 20));
/* Step 1: enable UMA but no FB */
pci_write_config8(dev, 0xa1, 0x80);
/* Step 2: enough is just the FB size, the CPU accessible address is not needed */
tmp = fbbits | 0x80;
pci_write_config8(dev, 0xa1, tmp);
/* TODO K8 needs some UMA fine tuning too maybe call some generic routine here? */
#endif
}
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static const struct device_operations dram_ops_t = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.enable = dram_enable,
.ops_pci = &lops_pci,
};
static const struct device_operations dram_ops_m = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.enable = dram_enable_k8m890,
.init = dram_init_fb,
.ops_pci = &lops_pci,
};
static const struct pci_driver northbridge_driver_t800 __pci_driver = {
.ops = &dram_ops_t,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T800_DRAM,
};
static const struct pci_driver northbridge_driver_m800 __pci_driver = {
.ops = &dram_ops_m,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8M800_DRAM,
};
static const struct pci_driver northbridge_driver_t890 __pci_driver = {
.ops = &dram_ops_t,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T890CE_3,
};
static const struct pci_driver northbridge_driver_t890cf __pci_driver = {
.ops = &dram_ops_t,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T890CF_3,
};
static const struct pci_driver northbridge_driver_m890 __pci_driver = {
.ops = &dram_ops_m,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8M890CE_3,
};

View File

@ -1,185 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@gmail.com>
*
* 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.
*/
/*
* Seems the link and width of HT link needs to be setup too, you need to
* generate PCI reset or LDTSTOP to apply.
*/
#include <stdlib.h>
#include <cbmem.h>
#include <arch/io.h>
#include <arch/acpi.h>
#include "k8x8xx.h"
/* The 256 bytes of NVRAM for S3 storage, 256B aligned */
#define K8T890_NVRAM_IO_BASE 0xf00
#define K8T890_MULTIPLE_FN_EN 0x4f
/* AMD K8 LDT0, LDT1, LDT2 Link Control Registers */
static u8 ldtreg[3] = {0x86, 0xa6, 0xc6};
#if IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
#define K8X8XX_HT_CFG_BASE 0xc0
#else
#define K8X8XX_HT_CFG_BASE 0x60
#endif
/* This functions sets KT890 link frequency and width to same values as
* it has been setup on K8 side, by AMD NB init.
* This will not work for K8T800_OLD, which has a slightly different
* register arrangement (device 3188)
*/
u8 k8t890_early_setup_ht(void)
{
u8 awidth, afreq, cldtfreq;
u8 cldtwidth_in, cldtwidth_out, vldtwidth_in, vldtwidth_out, ldtnr, width;
u16 vldtcaps;
#if !IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
u8 reg;
/* hack, enable NVRAM in chipset */
pci_write_config8(PCI_DEV(0, 0x0, 0), K8T890_MULTIPLE_FN_EN, 0x01);
/*
* NVRAM I/O base at K8T890_NVRAM_IO_BASE
*/
pci_write_config8(PCI_DEV(0, 0x0, 2), 0xa2, (K8T890_NVRAM_IO_BASE >> 8));
reg = pci_read_config8(PCI_DEV(0, 0x0, 2), 0xa1);
reg |= 0x1;
pci_write_config8(PCI_DEV(0, 0x0, 2), 0xa1, reg);
#endif
/* check if connected non coherent, initcomplete (find the SB on K8 side) */
ldtnr = 0;
if (0x7 == pci_read_config8(PCI_DEV(0, 0x18, 0), 0x98)) {
ldtnr = 0;
} else if (0x7 == pci_read_config8(PCI_DEV(0, 0x18, 0), 0xb8)) {
ldtnr = 1;
} else if (0x7 == pci_read_config8(PCI_DEV(0, 0x18, 0), 0xd8)) {
ldtnr = 2;
}
#if IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8M800)
printk(BIOS_DEBUG, "K8M800 found at LDT ");
#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800)
printk(BIOS_DEBUG, "K8T800 found at LDT ");
#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
printk(BIOS_DEBUG, "K8T800_OLD found at LDT ");
pci_write_config8(PCI_DEV(0, 0x0, 0), 0x64, 0x00);
pci_write_config8(PCI_DEV(0, 0x0, 0), 0xdd, 0x50);
#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800PRO)
printk(BIOS_DEBUG, "K8T800 Pro found at LDT ");
#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8M890)
printk(BIOS_DEBUG, "K8M890 found at LDT ");
/* K8M890 fix HT delay */
pci_write_config8(PCI_DEV(0, 0x0, 2), 0xab, 0x22);
#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T890)
printk(BIOS_DEBUG, "K8T890 found at LDT ");
#endif
printk(BIOS_DEBUG, "%02x", ldtnr);
/* get the maximum widths for both sides */
cldtwidth_in = pci_read_config8(PCI_DEV(0, 0x18, 0), ldtreg[ldtnr]) & 0x7;
cldtwidth_out = (pci_read_config8(PCI_DEV(0, 0x18, 0), ldtreg[ldtnr]) >> 4) & 0x7;
vldtwidth_in = pci_read_config8(PCI_DEV(0, 0x0, 0), K8X8XX_HT_CFG_BASE + 0x6) & 0x7;
vldtwidth_out = (pci_read_config8(PCI_DEV(0, 0x0, 0), K8X8XX_HT_CFG_BASE + 0x6) >> 4) & 0x7;
width = MIN(MIN(MIN(cldtwidth_out, cldtwidth_in), vldtwidth_out), vldtwidth_in);
printk(BIOS_DEBUG, " Agreed on width: %02x", width);
awidth = pci_read_config8(PCI_DEV(0, 0x0, 0), K8X8XX_HT_CFG_BASE + 0x7);
/* Update the desired HT LNK to match AMD NB max from VIA NB is 0x1 */
width = (width == 0x01) ? 0x11 : 0x00;
pci_write_config8(PCI_DEV(0, 0x0, 0), K8X8XX_HT_CFG_BASE + 0x7, width);
/* Get programmed HT freq at base 0x89 */
cldtfreq = pci_read_config8(PCI_DEV(0, 0x18, 0), ldtreg[ldtnr] + 3) & 0xf;
printk(BIOS_DEBUG, " CPU programmed to HT freq: %02x", cldtfreq);
vldtcaps = pci_read_config16(PCI_DEV(0, 0, 0), K8X8XX_HT_CFG_BASE + 0xe);
printk(BIOS_DEBUG, " VIA HT caps: %04x", vldtcaps);
if (!(vldtcaps & (1 << cldtfreq ))) {
die("Chipset does not support desired HT frequency\n");
}
afreq = pci_read_config8(PCI_DEV(0, 0x0, 0), K8X8XX_HT_CFG_BASE + 0xd);
pci_write_config8(PCI_DEV(0, 0x0, 0), K8X8XX_HT_CFG_BASE + 0xd, cldtfreq);
printk(BIOS_DEBUG, "\n");
/* no reset needed */
if ((width == awidth) && (afreq == cldtfreq)) {
return 0;
}
return 1;
}
int s3_save_nvram_early(u32 dword, int size, int nvram_pos)
{
printk(BIOS_DEBUG, "Writing %x of size %d to nvram pos: %d\n", dword, size, nvram_pos);
switch (size) {
case 1:
outb((dword & 0xff), K8T890_NVRAM_IO_BASE+nvram_pos);
nvram_pos +=1;
break;
case 2:
outw((dword & 0xffff), K8T890_NVRAM_IO_BASE+nvram_pos);
nvram_pos +=2;
break;
default:
outl(dword, K8T890_NVRAM_IO_BASE+nvram_pos);
nvram_pos +=4;
break;
}
return nvram_pos;
}
int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos)
{
switch (size) {
case 1:
*old_dword &= ~0xff;
*old_dword |= inb(K8T890_NVRAM_IO_BASE+nvram_pos);
nvram_pos +=1;
break;
case 2:
*old_dword &= ~0xffff;
*old_dword |= inw(K8T890_NVRAM_IO_BASE+nvram_pos);
nvram_pos +=2;
break;
default:
*old_dword = inl(K8T890_NVRAM_IO_BASE+nvram_pos);
nvram_pos +=4;
break;
}
printk(BIOS_DEBUG, "Loading %x of size %d to nvram pos:%d\n", * old_dword, size, nvram_pos-size);
return nvram_pos;
}
uintptr_t restore_top_of_low_cacheable(void)
{
if (acpi_get_sleep_type() != 3)
return 0;
return inl(K8T890_NVRAM_IO_BASE+K8T890_NVRAM_TOP_OF_RAM);
}

View File

@ -1,65 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@gmail.com>
*
* 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 <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <console/console.h>
#include "k8x8xx.h"
static void error_enable(struct device *dev)
{
printk(BIOS_DEBUG, " K8x8xx: Enabling NB error reporting: ");
/*
* bit0 - Enable V-link parity error reporting in 0x50 bit0 (RWC)
* bit6 - Parity Error/SERR# Report Through V-Link to SB
* bit7 - Parity Error/SERR# Report Through NMI
*/
pci_write_config8(dev, 0x58, 0x81);
printk(BIOS_DEBUG, "Done\n");
/* TODO: enable AGP errors reporting on K8M890 */
printk(BIOS_DEBUG, " VIA_X_1 device dump:\n");
dump_south(dev);
}
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static const struct device_operations error_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.enable = error_enable,
.ops_pci = &lops_pci,
};
static const unsigned short error_ids[] = {
PCI_DEVICE_ID_VIA_K8T800_ERR,
PCI_DEVICE_ID_VIA_K8M800_ERR,
PCI_DEVICE_ID_VIA_K8T890CE_1,
PCI_DEVICE_ID_VIA_K8T890CF_1,
PCI_DEVICE_ID_VIA_K8M890CE_1,
0
};
static const struct pci_driver northbridge_driver_t800 __pci_driver = {
.ops = &error_ops,
.vendor = PCI_VENDOR_ID_VIA,
.devices= error_ids,
};

View File

@ -1,149 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@gmail.com>
*
* 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 <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <device/pci_ids.h>
#include <console/console.h>
#include "k8x8xx.h"
static void host_old_enable(struct device *dev)
{
int agp3;
/* some HT tweaking */
pci_write_config8(dev, 0x50, 0x03);
pci_write_config8(dev, 0x55, 0x2c);
/* AGP setup */
pci_write_config8(dev, 0xac, 0x06);
pci_write_config8(dev, 0xad, 0x08);
pci_write_config8(dev, 0xfd, 0x02);
pci_write_config8(dev, 0x85, 0xb0);
pci_write_config8(dev, 0x87, 0x07);
pci_write_config8(dev, 0xfd, 0x06); // this is required for the following write to work
pci_write_config8(dev, 0xaf, 0x88);
pci_write_config8(dev, 0xfd, 0x04); // select AGP 3.0
agp3 = pci_read_config8(dev, 0x84) & 0x08;
pci_write_config8(dev, 0xb1, agp3 ? 0x00 : 0x9B);
pci_write_config8(dev, 0xb3, agp3 ? 0x00 : 0x9B);
pci_write_config8(dev, 0xb0, 0x40);
pci_write_config8(dev, 0xb2, 0x11);
pci_write_config8(dev, 0xed, 0x40);
}
static void host_old_init(struct device *dev)
{
k8x8xx_vt8237r_cfg(dev, NULL);
}
static void host_enable(struct device *dev)
{
/* Multiple function control */
pci_write_config8(dev, K8T890_MULTIPLE_FN_EN, 0x01);
printk(BIOS_DEBUG, " VIA_X_0 device dump:\n");
dump_south(dev);
}
static void host_init(struct device *dev)
{
u8 reg;
/* AGP Capability Header Control */
reg = pci_read_config8(dev, 0x4d);
reg |= 0x20; /* GART access enabled by either D0F0 Rx90[8] or D1F0 Rx90[8] */
pci_write_config8(dev, 0x4d, reg);
/* GD Output Stagger Delay */
reg = pci_read_config8(dev, 0x42);
reg |= 0x10; /* AD[31:16] with 1ns */
pci_write_config8(dev, 0x42, reg);
/* AGP Control */
reg = pci_read_config8(dev, 0xbc);
reg |= 0x20; /* AGP Read Snoop DRAM Post-Write Buffer */
pci_write_config8(dev, 0xbc, reg);
}
static const struct device_operations host_ops_old = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.enable = host_old_enable,
.init = host_old_init,
.ops_pci = 0,
};
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static const struct device_operations host_ops_t = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.enable = host_enable,
.ops_pci = &lops_pci,
};
static const struct device_operations host_ops_m = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.enable = host_enable,
.init = host_init,
.ops_pci = &lops_pci,
};
static const struct pci_driver northbridge_driver_t800_old __pci_driver = {
.ops = &host_ops_old,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T800_AGP,
};
static const struct pci_driver northbridge_driver_t800 __pci_driver = {
.ops = &host_ops_t,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T800_HT_AGP_CTR,
};
static const struct pci_driver northbridge_driver_m800 __pci_driver = {
.ops = &host_ops_m,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8M800_HT_AGP_CTR,
};
static const struct pci_driver northbridge_driver_t890 __pci_driver = {
.ops = &host_ops_t,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T890CE_0,
};
static const struct pci_driver northbridge_driver_t890cf __pci_driver = {
.ops = &host_ops_t,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T890CF_0,
};
static const struct pci_driver northbridge_driver_m890 __pci_driver = {
.ops = &host_ops_m,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8M890CE_0,
};

View File

@ -1,160 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@gmail.com>
*
* 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 <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <device/pci_ids.h>
#include <console/console.h>
#include <cbmem.h>
#include <arch/io.h>
#include "k8x8xx.h"
/* this may be later merged */
/* This fine tunes the HT link settings, which were loaded by ROM strap. */
static void host_ctrl_enable_k8t8xx(struct device *dev)
{
/*
* Bit 4 is reserved but set by AW. Set PCI to HT outstanding
* requests to 3.
*/
pci_write_config8(dev, 0xa0, 0x13);
/*
* NVRAM I/O base at K8T890_NVRAM_IO_BASE
* Some bits are set and reserved.
*/
pci_write_config8(dev, 0xa2, (K8T890_NVRAM_IO_BASE >> 8));
/* enable NB NVRAM and enable non-posted PCI writes. */
pci_write_config8(dev, 0xa1, 0x8f);
/* Arbitration control, some bits are reserved. */
pci_write_config8(dev, 0xa5, 0x3c);
/* Arbitration control 2 */
pci_write_config8(dev, 0xa6, 0x80);
/* this will be possibly removed, when I figure out
* if the ROM SIP is good, second reason is that the
* unknown bits are AGP related, which are dummy on K8T890
*/
writeback(dev, 0xa0, 0x13); /* Bit4 is reserved! */
writeback(dev, 0xa1, 0x8e); /* Some bits are reserved. */
writeback(dev, 0xa2, 0x0e); /* I/O NVRAM base 0xe00-0xeff disabled. */
writeback(dev, 0xa3, 0x31);
writeback(dev, 0xa4, 0x30);
writeback(dev, 0xa5, 0x3c); /* Some bits reserved. */
writeback(dev, 0xa6, 0x80); /* Some bits reserved. */
writeback(dev, 0xa7, 0x86); /* Some bits reserved. */
writeback(dev, 0xa8, 0x7f); /* Some bits reserved. */
writeback(dev, 0xa9, 0xcf); /* Some bits reserved. */
writeback(dev, 0xaa, 0x44);
writeback(dev, 0xab, 0x22);
writeback(dev, 0xac, 0x35); /* Maybe bit0 is read-only? */
writeback(dev, 0xae, 0x22);
writeback(dev, 0xaf, 0x40);
/* b0 is missing. */
writeback(dev, 0xb1, 0x13);
writeback(dev, 0xb4, 0x02); /* Some bits are reserved. */
writeback(dev, 0xc0, 0x20);
writeback(dev, 0xc1, 0xaa);
writeback(dev, 0xc2, 0xaa);
writeback(dev, 0xc3, 0x02);
writeback(dev, 0xc4, 0x50);
writeback(dev, 0xc5, 0x50);
printk(BIOS_DEBUG, " VIA_X_2 device dump:\n");
dump_south(dev);
}
/* This fine tunes the HT link settings, which were loaded by ROM strap. */
static void host_ctrl_enable_k8m8xx(struct device *dev) {
/*
* Set PCI to HT outstanding requests to 03.
* Bit 4 32 AGP ADS Read Outstanding Request Number
*/
pci_write_config8(dev, 0xa0, 0x13);
/*
* NVRAM I/O base at K8T890_NVRAM_IO_BASE
*/
pci_write_config8(dev, 0xa2, (K8T890_NVRAM_IO_BASE >> 8));
/* Enable NVRAM and enable non-posted PCI writes. */
pci_write_config8(dev, 0xa1, 0x8f);
/* Arbitration control */
pci_write_config8(dev, 0xa5, 0x3c);
/* Arbitration control 2, Enable C2NOW delay to PSTATECTL */
pci_write_config8(dev, 0xa6, 0x83);
}
void backup_top_of_low_cacheable(uintptr_t ramtop)
{
outl((u32) ramtop, K8T890_NVRAM_IO_BASE+K8T890_NVRAM_TOP_OF_RAM);
}
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static const struct device_operations host_ctrl_ops_t = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.enable = host_ctrl_enable_k8t8xx,
.ops_pci = &lops_pci,
};
static const struct device_operations host_ctrl_ops_m = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.enable = host_ctrl_enable_k8m8xx,
.ops_pci = &lops_pci,
};
static const struct pci_driver northbridge_driver_t800 __pci_driver = {
.ops = &host_ctrl_ops_t,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T800_HOST_CTR,
};
static const struct pci_driver northbridge_driver_m800 __pci_driver = {
.ops = &host_ctrl_ops_m,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8M800_HOST_CTR,
};
static const struct pci_driver northbridge_driver_t890 __pci_driver = {
.ops = &host_ctrl_ops_t,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T890CE_2,
};
static const struct pci_driver northbridge_driver_m890 __pci_driver = {
.ops = &host_ctrl_ops_m,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8M890CE_2,
};

View File

@ -1,56 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
*
* 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 SOUTHBRIDGE_VIA_K8T890_K8T890_H
#define SOUTHBRIDGE_VIA_K8T890_K8T890_H
/* Static resources for K8T890. */
#define K8T890_APIC_ID 0x3
/*
* Please check the datasheet and traf_ctrl_enable before change!
* It can't be changed to an arbitrary address.
*/
#define K8T890_APIC_BASE 0xfecc0000
/* The 256 bytes of NVRAM for S3 storage, 256B aligned */
#define K8T890_NVRAM_IO_BASE 0xf00
#define K8T890_NVRAM_TOP_OF_RAM 0xfc
#define K8T890_MMCONFIG_MBAR 0x61
#define K8T890_MULTIPLE_FN_EN 0x4f
/* the FB size in MB (min is 8MB max is 512MB) */
#define K8M890_FBSIZEMB 64
#ifdef __PRE_RAM__
u8 k8t890_early_setup_ht(void);
int s3_save_nvram_early(u32 dword, int size, int nvram_pos);
int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos);
#define k8x8xx_early_setup_ht() k8t890_early_setup_ht()
#else
#include <device/device.h>
#if 0
extern void writeback(struct device *dev, u16 where, u8 what);
extern void dump_south(struct device *dev);
#endif
#endif
#include <southbridge/via/vt8237r/vt8237r.h>
int k8m890_host_fb_size_get(void);
//void k8m890_host_fb_direct_set(uint32_t fb_address);
#endif

View File

@ -1,42 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 Alexandru Gagniuc <mr.nuke.me@gmail.com>
*
* 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, either version 2 of the License, or
* (at your option) any later version.
*
* 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 SOUTHBRIDGE_VIA_K8T890_K8X8XX_H
#define SOUTHBRIDGE_VIA_K8T890_K8X8XX_H
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
#ifndef __PRE_RAM__
#include <device/device.h>
#endif
#include "k8t890.h"
#ifndef __PRE_RAM__
struct k8x8xx_vt8237_mirrored_regs {
u16 low_top_address;
u8 rom_shadow_ctrl_pg_c,
rom_shadow_ctrl_pg_d,
rom_shadow_ctrl_pg_e_memhole_smi_decoding,
rom_shadow_ctrl_pg_f_memhole,
smm_apic_decoding,
shadow_mem_ctrl;
};
void k8x8xx_vt8237_mirrored_regs_fill(struct k8x8xx_vt8237_mirrored_regs *regs);
void k8x8xx_vt8237r_cfg(struct device *, struct device *);
#endif
#endif /* SOUTHBRIDGE_VIA_K8T890_K8X8XX_H */

View File

@ -1,162 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
*
* 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/pciexp.h>
#include <device/pci_ids.h>
#include <delay.h>
#include "k8t890.h"
/*
* Note:
* The pcie bridges are similar to the VX800 ones documented at
* http://linux.via.com.tw/
*/
static void pcie_common_init(struct device *dev)
{
u8 reg;
int i, up;
/* Disable downstream read cycle retry,
* otherwise the bus scan will hang if no device is plugged in. */
reg = pci_read_config8(dev, 0xa3);
pci_write_config8(dev, 0xa3, reg & ~0x01);
/* Use PHY negotiation for lane config */
reg = pci_read_config8(dev, 0xc1);
pci_write_config8(dev, 0xc1, reg & ~0x1f);
/* Award has 0xb, VIA recommends 0xd, default 0x8.
* bit4: receive polarity change control
* bits3:2: squelch window select 64~175mv
* bit1: Number of non-idle bits detected before exiting idle state
* 0: 10 bits, 1: 2 bits
* bit0: Number of idle bits detected before entering idle state
* 0: 10 bits, 1: 2 bits
*/
pci_write_config8(dev, 0xe1, 0xb);
/* Set replay timer limit. */
pci_write_config8(dev, 0xb1, 0xf0);
/* Enable link. */
reg = pci_read_config8(dev, 0x50);
pci_write_config8(dev, 0x50, reg & ~0x10);
/* Wait up to 100ms for link to come up */
up = 0;
for (i = 0; i < 1000; i++) {
if (pci_read_config16(dev, 0x52) & (1<<13)) {
up = 1;
break;
}
udelay(100);
}
printk(BIOS_SPEW, "%s PCIe link ", dev_path(dev));
if (up)
printk(BIOS_SPEW, "up after %d us\n", i*100);
else
printk(BIOS_SPEW, "timeout\n");
dump_south(dev);
}
static void peg_init(struct device *dev)
{
u8 reg;
printk(BIOS_DEBUG, "Configuring PCIe PEG\n");
dump_south(dev);
/* Disable link. */
reg = pci_read_config8(dev, 0x50);
pci_write_config8(dev, 0x50, reg | 0x10);
/*
* pci_write_config8(dev, 0xe2, 0x0);
* pci_write_config8(dev, 0xe3, 0x92);
*/
/* Bit0 = 1 SDP (Start DLLP) always at Lane0. */
reg = pci_read_config8(dev, 0xb8);
pci_write_config8(dev, 0xb8, reg | 0x1);
/*
* Downstream wait and Upstream Checking Malformed TLP through
* "Byte Enable Rule" And "Over 4K Boundary Rule".
*/
reg = pci_read_config8(dev, 0xa4);
pci_write_config8(dev, 0xa4, reg | 0x30);
pcie_common_init(dev);
}
static void pcie_init(struct device *dev)
{
u8 reg;
printk(BIOS_DEBUG, "Configuring PCIe PEXs\n");
dump_south(dev);
/* Disable link. */
reg = pci_read_config8(dev, 0x50);
pci_write_config8(dev, 0x50, reg | 0x10);
pcie_common_init(dev);
}
static const struct device_operations peg_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.enable = peg_init,
.scan_bus = pciexp_scan_bridge,
.reset_bus = pci_bus_reset,
.ops_pci = 0,
};
static const struct device_operations pcie_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.enable = pcie_init,
.scan_bus = pciexp_scan_bridge,
.reset_bus = pci_bus_reset,
.ops_pci = 0,
};
static const struct pci_driver northbridge_driver __pci_driver = {
.ops = &peg_ops,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T890CE_PEG,
};
static const unsigned short pci_device_ids[] = {
PCI_DEVICE_ID_VIA_K8T890CE_PEX0,
PCI_DEVICE_ID_VIA_K8T890CE_PEX1,
PCI_DEVICE_ID_VIA_K8T890CE_PEX2,
PCI_DEVICE_ID_VIA_K8T890CE_PEX3,
0,
};
static const struct pci_driver pex_driver __pci_driver = {
.ops = &pcie_ops,
.vendor = PCI_VENDOR_ID_VIA,
.devices = pci_device_ids,
};

View File

@ -1,101 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Tyan Computer
* (Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer)
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
/* This file constructs the ROM strap table for K8T890 and K8M890 */
.section ".romstrap", "a", @progbits
.globl __romstrap_start
.globl __romstrap_end
__romstrap_start:
/*
* Below are some Dev0 Func2 HT control registers values,
* depending on strap pin, one of below lines is used.
*/
#if IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8M800) || \
IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800) || \
IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
tblpointer:
.long 0x50220000, 0X619707C2
.long 0x50220000, 0X619707C2
.long 0x50220000, 0X619707C2
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8M890)
tblpointer:
.long 0x504400FF, 0x61970FC2 //;200M
.long 0x504400FF, 0x61970FC2 //;400M
.long 0x504400FF, 0x61970FC2 //;600M
.long 0x504400FF, 0x61970FC2 //;800M
.long 0x504400FF, 0x61970FC2 //;1000M
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T890)
tblpointer:
.long 0x504400AA, 0x61970FC2 //;200M
.long 0x504400AA, 0x61970FC2 //;400M
.long 0x504400AA, 0x61970FC2 //;600M
.long 0x504400AA, 0x61970FC2 //;800M
.long 0x504400AA, 0x61970FC2 //;1000M
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
.long 0x0
#endif
/*
* The pointer to above table should be at 0xffffd,
* the table itself MUST be aligned to 128B it seems!
*/
.long tblpointer - 0xFFF00000
__romstrap_end:
.previous

View File

@ -1,25 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 AMD
* (Written by Yinghai Lu <yinghai.lu@amd.com> for AMD)
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
/* Modified for K8T890 ROM strap by Rudolf Marek <r.marek@assembler.cz>. */
SECTIONS {
. = (0xffffffff - 0x2c) - (__romstrap_end - __romstrap_start) + 1;
.romstrap (.): {
KEEP(*(.romstrap))
}
}

View File

@ -1,195 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
*
* 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 <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <console/console.h>
#include <arch/acpi.h>
#include <arch/acpigen.h>
#include <cpu/amd/powernow.h>
#include <lib.h>
#include "k8t890.h"
static void mmconfig_set_resources(struct device *dev)
{
struct resource *resource;
u8 reg;
resource = find_resource(dev, K8T890_MMCONFIG_MBAR);
if (resource) {
report_resource_stored(dev, resource, "<mmconfig>");
/* Remember this resource has been stored. */
resource->flags |= IORESOURCE_STORED;
pci_write_config8(dev, K8T890_MMCONFIG_MBAR,
(resource->base >> 28));
reg = pci_read_config8(dev, 0x60);
reg |= 0x3;
/* Enable MMCONFIG decoding. */
pci_write_config8(dev, 0x60, reg);
}
pci_dev_set_resources(dev);
}
static void apic_mmconfig_read_resources(struct device *dev)
{
struct resource *res;
pci_dev_read_resources(dev);
res = new_resource(dev, 0x40);
/* NB APIC fixed to this address. */
res->base = K8T890_APIC_BASE;
res->size = 256;
res->limit = res->base + res->size - 1;
res->align = 8;
res->gran = 8;
res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_RESERVE |
IORESOURCE_STORED | IORESOURCE_ASSIGNED;
/* Add an MMCONFIG resource. */
res = new_resource(dev, K8T890_MMCONFIG_MBAR);
res->size = 256 * 1024 * 1024;
res->align = log2(res->size);
res->gran = log2(res->size);
res->limit = 0xffffffff; /* 4G */
res->flags = IORESOURCE_MEM | IORESOURCE_RESERVE;
}
static void traf_ctrl_enable_generic(struct device *dev)
{
volatile u32 *apic;
u32 data;
/* no device2 redirect, enable just one device behind
* bridge device 2 and device 3).
*/
pci_write_config8(dev, 0x60, 0x08);
/* Will enable MMCONFIG later. */
pci_write_config8(dev, 0x64, 0x23);
/* No extended RCRB Base Address. */
pci_write_config8(dev, 0x62, 0x00);
/* Offset80 ->95 bit 4 in 1 in Award. */
/* Enable APIC, to K8T890_APIC_BASE. */
pci_write_config8(dev, 0x41, 0x00);
pci_write_config8(dev, 0x40, 0x8c);
/* BT_INTR enable, APIC Nonshare Mode Enable. */
pci_write_config8(dev, 0x42, 0x5);
apic = (u32 *)K8T890_APIC_BASE;
/* Set APIC to FSB transported messages. */
apic[0] = 3;
data = apic[4];
apic[4] = (data & 0xFFFFFE) | 1;
/* Set APIC ID. */
apic[0] = 0;
data = apic[4];
apic[4] = (data & 0xF0FFFF) | (K8T890_APIC_ID << 24);
}
static void traf_ctrl_enable_k8m890(struct device *dev)
{
traf_ctrl_enable_generic(dev);
}
static void traf_ctrl_enable_k8t890(struct device *dev)
{
u8 reg;
traf_ctrl_enable_generic(dev);
/* Enable D3F1-D3F3 */
reg = pci_read_config8(dev, 0x60);
pci_write_config8(dev, 0x60, 0x80 | reg);
}
#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
static void southbridge_acpi_fill_ssdt_generator(struct device *dev) {
amd_generate_powernow(0, 0, 0);
acpigen_write_mainboard_resources("\\_SB.PCI0.MBRS", "_CRS");
}
#endif
static const struct device_operations traf_ctrl_ops_m = {
.read_resources = apic_mmconfig_read_resources,
.set_resources = mmconfig_set_resources,
.enable_resources = pci_dev_enable_resources,
.enable = traf_ctrl_enable_k8m890,
#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
.write_acpi_tables = acpi_write_hpet,
.acpi_fill_ssdt_generator = southbridge_acpi_fill_ssdt_generator,
#endif
.ops_pci = 0,
};
static const struct device_operations traf_ctrl_ops_t = {
.read_resources = apic_mmconfig_read_resources,
.set_resources = mmconfig_set_resources,
.enable_resources = pci_dev_enable_resources,
.enable = traf_ctrl_enable_k8t890,
#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
.write_acpi_tables = acpi_write_hpet,
#endif
.ops_pci = 0,
};
/* K8X800 chipsets have no APIC; no 800 PCI ids here */
unsigned long acpi_fill_mcfg(unsigned long current)
{
struct device *dev;
struct resource *res;
dev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_K8T890CE_5, 0);
if (!dev)
dev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_K8T890CF_5, 0);
if (!dev)
dev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_K8M890CE_5, 0);
if (!dev)
return current;
res = find_resource(dev, K8T890_MMCONFIG_MBAR);
if (res) {
current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)
current, res->base, 0x0, 0x0, 0xff);
}
return current;
}
static const struct pci_driver northbridge_driver_t __pci_driver = {
.ops = &traf_ctrl_ops_t,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T890CE_5,
};
static const struct pci_driver northbridge_driver_tcf __pci_driver = {
.ops = &traf_ctrl_ops_t,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8T890CF_5,
};
static const struct pci_driver northbridge_driver_m __pci_driver = {
.ops = &traf_ctrl_ops_m,
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_K8M890CE_5,
};

View File

@ -319,21 +319,11 @@ static void vt8237r_init(struct device *dev)
*/
pci_write_config8(dev, 0x48, 0x0c);
#else
#if IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800) || \
IS_ENABLED(CONFIG_SOUTHBRIDGE_VIA_SUBTYPE_K8T800_OLD)
/* It seems that when we pair with the K8T800, we need to disable
* the A2 mask
*/
pci_write_config8(dev, 0x48, 0x0c);
#else
/*
* Set Read Pass Write Control Enable
* (force A2 from APIC FSB to low).
*/
pci_write_config8(dev, 0x48, 0x8c);
#endif
#endif
southbridge_init_common(dev);