sb/amd/sb700: Drop support

Relocatable ramstage, postcar stage and C_ENVIRONMENT_BOOTBLOCK are
now mandatory features, which platforms using this code lack.

Change-Id: Iffa4f54b2d1b43b6710447e69061c6ed433bff1d
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/36967
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Arthur Heymans
2019-11-19 17:23:12 +01:00
committed by Kyösti Mälkki
parent ecebee0561
commit 24284270c7
27 changed files with 1 additions and 4711 deletions

View File

@@ -30,10 +30,6 @@
#include <southbridge/amd/common/reset.h>
#if CONFIG(SOUTHBRIDGE_AMD_SB700)
#include <southbridge/amd/sb700/sb700.h>
#endif
#if CONFIG(SOUTHBRIDGE_AMD_SB800)
#include <southbridge/amd/sb800/sb800.h>
#endif
@@ -1045,7 +1041,7 @@ void cpuSetAMDMSR(uint8_t node_id)
}
}
#if CONFIG(SOUTHBRIDGE_AMD_SB700) || CONFIG(SOUTHBRIDGE_AMD_SB800)
#if CONFIG(SOUTHBRIDGE_AMD_SB800)
if (revision & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) {
/* Set up message triggered C1E */
msr = rdmsr(MSR_INTPEND);

View File

@@ -1,68 +0,0 @@
##
## This file is part of the coreboot project.
##
## Copyright (C) 2010 Advanced Micro Devices, Inc.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; version 2 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
config SOUTHBRIDGE_AMD_SB700
bool
if SOUTHBRIDGE_AMD_SB700
config SOUTHBRIDGE_SPECIFIC_OPTIONS # dummy
def_bool y
select IOAPIC
select HAVE_USBDEBUG_OPTIONS
select SMBUS_HAS_AUX_CHANNELS
select HAVE_POWER_STATE_AFTER_FAILURE
select HAVE_POWER_STATE_PREVIOUS_AFTER_FAILURE
config SOUTHBRIDGE_AMD_SB700_33MHZ_SPI
bool "Enable high speed SPI clock"
default n
help
When set, the SPI clock will run at 33MHz instead
of the compatibility mode 16.5MHz. Note that not
all ROMs are capable of 33MHz operation, so you
will need to verify this option is appropriate for
the ROM you are using.
# Set for southbridge SP5100 which also uses SB700 driver
config SOUTHBRIDGE_AMD_SUBTYPE_SP5100
bool
default n
config BOOTBLOCK_SOUTHBRIDGE_INIT
string
default "southbridge/amd/sb700/bootblock.c"
config SOUTHBRIDGE_AMD_SB700_SKIP_ISA_DMA_INIT
bool
default n
config SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA
bool
default n
config SOUTHBRIDGE_AMD_SB700_SATA_PORT_COUNT_BITFIELD
hex
default 0xf
config EHCI_BAR
hex
default 0xfef00000
config HPET_MIN_TICKS
hex
default 0x14
endif # SOUTHBRIDGE_AMD_SB700

View File

@@ -1,27 +0,0 @@
ifeq ($(CONFIG_SOUTHBRIDGE_AMD_SB700),y)
ramstage-y += sb700.c
ramstage-y += usb.c
ramstage-y += lpc.c
ramstage-y += smbus.c
ramstage-y += sm.c
ramstage-y += ide.c
ramstage-y += sata.c
ramstage-y += hda.c
ramstage-y += pci.c
ramstage-$(CONFIG_HAVE_ACPI_TABLES) += fadt.c
romstage-y += reset.c
ramstage-y += reset.c
ramstage-y += spi.c
bootblock-y += enable_usbdebug.c
romstage-y += enable_usbdebug.c
ramstage-y += enable_usbdebug.c
romstage-y += early_setup.c
romstage-y += smbus.c
romstage-y += ramtop.c
ramstage-y += ramtop.c
endif

View File

@@ -1,230 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
* Copyright (C) 2010 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/* Some timing tables */
Name(UDTT, Package(){ /* Udma timing table */
120, 90, 60, 45, 30, 20, 15, 0 /* UDMA modes 0 -> 6 */
})
Name(MDTT, Package(){ /* MWDma timing table */
480, 150, 120, 0 /* Legacy DMA modes 0 -> 2 */
})
Name(POTT, Package(){ /* Pio timing table */
600, 390, 270, 180, 120, 0 /* PIO modes 0 -> 4 */
})
/* Some timing register value tables */
Name(MDRT, Package(){ /* MWDma timing register table */
0x77, 0x21, 0x20, 0xFF /* Legacy DMA modes 0 -> 2 */
})
Name(PORT, Package(){
0x99, 0x47, 0x34, 0x22, 0x20, 0x99 /* PIO modes 0 -> 4 */
})
OperationRegion(ICRG, PCI_Config, 0x40, 0x20) /* ide control registers */
Field(ICRG, AnyAcc, NoLock, Preserve)
{
PPTS, 8, /* Primary PIO Slave Timing */
PPTM, 8, /* Primary PIO Master Timing */
OFFSET(0x04), PMTS, 8, /* Primary MWDMA Slave Timing */
PMTM, 8, /* Primary MWDMA Master Timing */
OFFSET(0x08), PPCR, 8, /* Primary PIO Control */
OFFSET(0x0A), PPMM, 4, /* Primary PIO master Mode */
PPSM, 4, /* Primary PIO slave Mode */
OFFSET(0x14), PDCR, 2, /* Primary UDMA Control */
OFFSET(0x16), PDMM, 4, /* Primary UltraDMA Mode */
PDSM, 4, /* Primary UltraDMA Mode */
}
Method(GTTM, 1) /* get total time*/
{
Store(And(Arg0, 0x0F), Local0) /* Recovery Width */
Increment(Local0)
Store(ShiftRight(Arg0, 4), Local1) /* Command Width */
Increment(Local1)
Return(Multiply(30, Add(Local0, Local1)))
}
Device(PRID)
{
Name (_ADR, Zero)
Method(_GTM, 0, Serialized)
{
NAME(OTBF, Buffer(20) { /* out buffer */
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
})
CreateDwordField(OTBF, 0, PSD0) /* PIO spd0 */
CreateDwordField(OTBF, 4, DSD0) /* DMA spd0 */
CreateDwordField(OTBF, 8, PSD1) /* PIO spd1 */
CreateDwordField(OTBF, 12, DSD1) /* DMA spd1 */
CreateDwordField(OTBF, 16, BFFG) /* buffer flags */
/* Just return if the channel is disabled */
If(And(PPCR, 0x01)) { /* primary PIO control */
Return(OTBF)
}
/* Always tell them independent timing available and IOChannelReady used on both drives */
Or(BFFG, 0x1A, BFFG)
Store(GTTM(PPTM), PSD0) /* save total time of primary PIO master timming to PIO spd0 */
Store(GTTM(PPTS), PSD1) /* save total time of primary PIO slave Timing to PIO spd1 */
If(And(PDCR, 0x01)) { /* It's under UDMA mode */
Or(BFFG, 0x01, BFFG)
Store(DerefOf(Index(UDTT, PDMM)), DSD0)
}
Else {
Store(GTTM(PMTM), DSD0) /* Primary MWDMA Master Timing, DmaSpd0 */
}
If(And(PDCR, 0x02)) { /* It's under UDMA mode */
Or(BFFG, 0x04, BFFG)
Store(DerefOf(Index(UDTT, PDSM)), DSD1)
}
Else {
Store(GTTM(PMTS), DSD1) /* Primary MWDMA Slave Timing, DmaSpd0 */
}
Return(OTBF) /* out buffer */
} /* End Method(_GTM) */
Method(_STM, 3, Serialized)
{
NAME(INBF, Buffer(20) { /* in buffer */
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00
})
CreateDwordField(INBF, 0, PSD0) /* PIO spd0 */
CreateDwordField(INBF, 4, DSD0) /* PIO spd0 */
CreateDwordField(INBF, 8, PSD1) /* PIO spd1 */
CreateDwordField(INBF, 12, DSD1) /* DMA spd1 */
CreateDwordField(INBF, 16, BFFG) /*buffer flag */
Store(Match(POTT, MLE, PSD0, MTR, 0, 0), Local0)
Divide(Local0, 5, PPMM,) /* Primary PIO master Mode */
Store(Match(POTT, MLE, PSD1, MTR, 0, 0), Local1)
Divide(Local1, 5, PPSM,) /* Primary PIO slave Mode */
Store(DerefOf(Index(PORT, Local0)), PPTM) /* Primary PIO Master Timing */
Store(DerefOf(Index(PORT, Local1)), PPTS) /* Primary PIO Slave Timing */
If(And(BFFG, 0x01)) { /* Drive 0 is under UDMA mode */
Store(Match(UDTT, MLE, DSD0, MTR, 0, 0), Local0)
Divide(Local0, 7, PDMM,)
Or(PDCR, 0x01, PDCR)
}
Else {
If(LNotEqual(DSD0, 0xFFFFFFFF)) {
Store(Match(MDTT, MLE, DSD0, MTR, 0, 0), Local0)
Store(DerefOf(Index(MDRT, Local0)), PMTM)
}
}
If(And(BFFG, 0x04)) { /* Drive 1 is under UDMA mode */
Store(Match(UDTT, MLE, DSD1, MTR, 0, 0), Local0)
Divide(Local0, 7, PDSM,)
Or(PDCR, 0x02, PDCR)
}
Else {
If(LNotEqual(DSD1, 0xFFFFFFFF)) {
Store(Match(MDTT, MLE, DSD1, MTR, 0, 0), Local0)
Store(DerefOf(Index(MDRT, Local0)), PMTS)
}
}
/* Return(INBF) */
} /*End Method(_STM) */
Device(MST)
{
Name(_ADR, 0)
Method(_GTF, 0, Serialized) {
Name(CMBF, Buffer(21) {
0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5
})
CreateByteField(CMBF, 1, POMD)
CreateByteField(CMBF, 8, DMMD)
CreateByteField(CMBF, 5, CMDA)
CreateByteField(CMBF, 12, CMDB)
CreateByteField(CMBF, 19, CMDC)
Store(0xA0, CMDA)
Store(0xA0, CMDB)
Store(0xA0, CMDC)
Or(PPMM, 0x08, POMD)
If(And(PDCR, 0x01)) {
Or(PDMM, 0x40, DMMD)
}
Else {
Store(Match
(MDTT, MLE, GTTM(PMTM),
MTR, 0, 0), Local0)
If(LLess(Local0, 3)) {
Or(0x20, Local0, DMMD)
}
}
Return(CMBF)
}
} /* End Device(MST) */
Device(SLAV)
{
Name(_ADR, 1)
Method(_GTF, 0, Serialized) {
Name(CMBF, Buffer(21) {
0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5
})
CreateByteField(CMBF, 1, POMD)
CreateByteField(CMBF, 8, DMMD)
CreateByteField(CMBF, 5, CMDA)
CreateByteField(CMBF, 12, CMDB)
CreateByteField(CMBF, 19, CMDC)
Store(0xB0, CMDA)
Store(0xB0, CMDB)
Store(0xB0, CMDC)
Or(PPSM, 0x08, POMD)
If(And(PDCR, 0x02)) {
Or(PDSM, 0x40, DMMD)
}
Else {
Store(Match
(MDTT, MLE, GTTM(PMTS),
MTR, 0, 0), Local0)
If(LLess(Local0, 3)) {
Or(0x20, Local0, DMMD)
}
}
Return(CMBF)
}
} /* End Device(SLAV) */
}

View File

@@ -1,129 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
*
* 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.
*/
Name(STTM, Buffer(20) {
0x78, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
0x78, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00
})
/* Start by clearing the PhyRdyChg bits */
Method(_INI) {
\_GPE._L1F()
}
Device(PMRY)
{
Name(_ADR, 0)
Method(_GTM, 0x0, NotSerialized) {
Return(STTM)
}
Method(_STM, 0x3, NotSerialized) {}
Device(PMST) {
Name(_ADR, 0)
Method(_STA,0) {
if (LGreater(P0IS,0)) {
return (0x0F) /* sata is visible */
} else {
return (0x00) /* sata is missing */
}
}
}/* end of PMST */
Device(PSLA)
{
Name(_ADR, 1)
Method(_STA,0) {
if (LGreater(P1IS,0)) {
return (0x0F) /* sata is visible */
} else {
return (0x00) /* sata is missing */
}
}
} /* end of PSLA */
} /* end of PMRY */
Device(SEDY)
{
Name(_ADR, 1) /* IDE Scondary Channel */
Method(_GTM, 0x0, NotSerialized) {
Return(STTM)
}
Method(_STM, 0x3, NotSerialized) {}
Device(SMST)
{
Name(_ADR, 0)
Method(_STA,0) {
if (LGreater(P2IS,0)) {
return (0x0F) /* sata is visible */
} else {
return (0x00) /* sata is missing */
}
}
} /* end of SMST */
Device(SSLA)
{
Name(_ADR, 1)
Method(_STA,0) {
if (LGreater(P3IS,0)) {
return (0x0F) /* sata is visible */
} else {
return (0x00) /* sata is missing */
}
}
} /* end of SSLA */
} /* end of SEDY */
/* SATA Hot Plug Support */
Scope(\_GPE) {
Method(_L1F,0x0,NotSerialized) {
if (\_SB.P0PR) {
if (LGreater(\_SB.P0IS,0)) {
sleep(32)
}
Notify(\_SB.PCI0.SAT0.PMRY.PMST, 0x01) /* NOTIFY_DEVICE_CHECK */
store(one, \_SB.P0PR)
}
if (\_SB.P1PR) {
if (LGreater(\_SB.P1IS,0)) {
sleep(32)
}
Notify(\_SB.PCI0.SAT0.PMRY.PSLA, 0x01) /* NOTIFY_DEVICE_CHECK */
store(one, \_SB.P1PR)
}
if (\_SB.P2PR) {
if (LGreater(\_SB.P2IS,0)) {
sleep(32)
}
Notify(\_SB.PCI0.SAT0.SEDY.SMST, 0x01) /* NOTIFY_DEVICE_CHECK */
store(one, \_SB.P2PR)
}
if (\_SB.P3PR) {
if (LGreater(\_SB.P3IS,0)) {
sleep(32)
}
Notify(\_SB.PCI0.SAT0.SEDY.SSLA, 0x01) /* NOTIFY_DEVICE_CHECK */
store(one, \_SB.P3PR)
}
}
}

View File

@@ -1,129 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
* Copyright (C) 2010 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdint.h>
#include <device/pci_ops.h>
#define IO_MEM_PORT_DECODE_ENABLE_5 0x48
#define IO_MEM_PORT_DECODE_ENABLE_6 0x4a
#define SPI_BASE_ADDRESS 0xa0
#define SPI_CONTROL_1 0xc
#define TEMPORARY_SPI_BASE_ADDRESS 0xfec10000
/*
* 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 SB700 power-on default is to map 512K ROM space.
*
* Details: AMD SB700/710/750 BIOS Developer's Guide (BDG), Rev. 1.00,
* PN 43366_sb7xx_bdg_pub_1.00, June 2009, section 3.1, page 14.
*/
static void sb700_enable_rom(void)
{
u8 reg8;
u32 dword;
pci_devfn_t dev;
dev = PCI_DEV(0, 0x14, 3);
reg8 = pci_io_read_config8(dev, IO_MEM_PORT_DECODE_ENABLE_5);
if (CONFIG(SPI_FLASH))
/* Disable decode of variable LPC ROM address ranges 1 and 2. */
reg8 &= ~((1 << 3) | (1 << 4));
else
/* Decode variable LPC ROM address ranges 1 and 2. */
reg8 |= (1 << 3) | (1 << 4);
pci_io_write_config8(dev, IO_MEM_PORT_DECODE_ENABLE_5, 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
* 0xff80(0000): 8MB
*/
pci_io_write_config16(dev, 0x6c, 0x10000 - (CONFIG_COREBOOT_ROMSIZE_KB >> 6));
/* Enable LPC ROM range end at 0xffff(ffff). */
pci_io_write_config16(dev, 0x6e, 0xffff);
/* SB700 LPC Bridge 0x48.
* Turn on all LPC IO Port decode enables
*/
pci_io_write_config32(dev, 0x44, 0xffffffff);
/* SB700 LPC Bridge 0x48.
* BIT0: Port Enable for SuperIO 0x2E-0x2F
* BIT1: Port Enable for SuperIO 0x4E-0x4F
* BIT6: Port Enable for RTC IO 0x70-0x73
*/
reg8 = pci_io_read_config8(dev, IO_MEM_PORT_DECODE_ENABLE_5);
reg8 |= (1 << 0) | (1 << 1) | (1 << 6);
pci_io_write_config8(dev, IO_MEM_PORT_DECODE_ENABLE_5, reg8);
/* SB700 LPC Bridge 0x4a.
* BIT5: Port Enable for Port 0x80
*/
reg8 = pci_io_read_config8(dev, IO_MEM_PORT_DECODE_ENABLE_6);
reg8 |= (1 << 5);
pci_io_write_config8(dev, IO_MEM_PORT_DECODE_ENABLE_6, reg8);
}
static void sb700_configure_rom(void)
{
pci_devfn_t dev;
uint32_t dword;
dev = PCI_DEV(0, 0x14, 3);
if (CONFIG(SOUTHBRIDGE_AMD_SB700_33MHZ_SPI)) {
uint32_t prev_spi_cfg;
volatile uint32_t *spi_mmio;
/* Temporarily set up SPI access to change SPI speed */
prev_spi_cfg = dword = pci_io_read_config32(dev, SPI_BASE_ADDRESS);
dword &= ~(0x7ffffff << 5); /* SPI_BaseAddr */
dword |= TEMPORARY_SPI_BASE_ADDRESS & (0x7ffffff << 5);
dword |= (0x1 << 1); /* SpiRomEnable = 1 */
pci_io_write_config32(dev, SPI_BASE_ADDRESS, dword);
spi_mmio = (void *)(TEMPORARY_SPI_BASE_ADDRESS + SPI_CONTROL_1);
dword = *spi_mmio;
dword &= ~(0x3 << 12); /* NormSpeed = 0x1 */
dword |= (0x1 << 12);
*spi_mmio = dword;
/* Restore previous SPI access */
pci_io_write_config32(dev, SPI_BASE_ADDRESS, prev_spi_cfg);
}
}
static void bootblock_southbridge_init(void)
{
sb700_enable_rom();
sb700_configure_rom();
}

View File

@@ -1,24 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef SB700_CHIP_H
#define SB700_CHIP_H
struct southbridge_amd_sb700_config
{
u32 boot_switch_sata_ide : 1;
};
#endif /* SB700_CHIP_H */

View File

@@ -1,854 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2015 - 2016 Raptor Engineering, LLC
*
* 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 _SB700_EARLY_SETUP_C_
#define _SB700_EARLY_SETUP_C_
#include <stdint.h>
#include <option.h>
#include <arch/io.h>
#include <device/pci_ops.h>
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <device/pci.h>
#include "sb700.h"
#include "smbus.h"
u32 get_sbdn(u32 bus);
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);
}
static void sb700_acpi_init(void)
{
u16 word;
pmio_write(0x20, ACPI_PM_EVT_BLK & 0xFF);
pmio_write(0x21, ACPI_PM_EVT_BLK >> 8);
pmio_write(0x22, ACPI_PM1_CNT_BLK & 0xFF);
pmio_write(0x23, ACPI_PM1_CNT_BLK >> 8);
pmio_write(0x24, ACPI_PM_TMR_BLK & 0xFF);
pmio_write(0x25, ACPI_PM_TMR_BLK >> 8);
pmio_write(0x28, ACPI_GPE0_BLK & 0xFF);
pmio_write(0x29, ACPI_GPE0_BLK >> 8);
/* CpuControl is in \_PR.CP00, 6 bytes */
pmio_write(0x26, ACPI_CPU_CONTROL & 0xFF);
pmio_write(0x27, ACPI_CPU_CONTROL >> 8);
pmio_write(0x2A, 0); /* AcpiSmiCmdLo */
pmio_write(0x2B, 0); /* AcpiSmiCmdHi */
pmio_write(0x2C, ACPI_PMA_CNT_BLK & 0xFF);
pmio_write(0x2D, ACPI_PMA_CNT_BLK >> 8);
pmio_write(0x0E, 1<<3 | 0<<2); /* AcpiDecodeEnable, When set, SB uses
* the contents of the PM registers at
* index 20-2B to decode ACPI I/O address.
* AcpiSmiEn & SmiCmdEn*/
pmio_write(0x10, 1<<1 | 1<<3| 1<<5); /* RTC_En_En, TMR_En_En, GBL_EN_EN */
word = inl(ACPI_PM1_CNT_BLK);
word |= 1;
outl(word, ACPI_PM1_CNT_BLK); /* set SCI_EN */
}
/* RPR 2.28: Get SB ASIC Revision. */
static u8 set_sb700_revision(void)
{
pci_devfn_t dev;
u8 rev_id, enable_14Mhz, byte;
u8 rev = 0;
/* if (rev != 0) return rev; */
dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0);
if (dev == PCI_DEV_INVALID) {
die("SMBUS controller not found\n");
/* NOT REACHED */
}
rev_id = pci_read_config8(dev, 0x08);
if (rev_id == 0x39) {
enable_14Mhz = (pmio_read(0x53) >> 6) & 1;
if (enable_14Mhz == 0x0)
rev = 0x11; /* A11 */
else if (enable_14Mhz == 0x1) {
/* This happens, if does, only once. So later if we need to get
* the revision ID, we don't have to make such a big function.
* We just get reg 0x8 in smbus dev. 0x39 is A11, 0x3A is A12. */
rev = 0x12;
byte = pci_read_config8(dev, 0x40);
byte |= 1 << 0;
pci_write_config8(dev, 0x40, byte);
pci_write_config8(dev, 0x08, 0x3A); /* Change 0x39 to 0x3A. */
byte &= ~(1 << 0);
pci_write_config8(dev, 0x40, byte);
}
} else if (rev_id == 0x3A) { /* A12 will be 0x3A after BIOS is initialized */
rev = 0x12;
} else if (rev_id == 0x3C) {
rev = 0x14;
} else if (rev_id == 0x3D) {
rev = 0x15;
} else
die("It is not SB700 or SB710\n");
return rev;
}
/***************************************
* Legacy devices are mapped to LPC space.
* Serial port 0
* KBC Port
* ACPI Micro-controller port
* This function does not change port 0x80 decoding.
* Console output through any port besides 0x3f8 is unsupported.
* If you use FWH ROMs, you have to setup IDSEL.
***************************************/
void sb7xx_51xx_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);
#if CONFIG(SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
post_code(0x66);
dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */
reg8 = pci_read_config8(dev, 0xBB);
reg8 |= 1 << 2 | 1 << 3 | 1 << 6 | 1 << 7;
reg8 &= ~(1 << 1);
pci_write_config8(dev, 0xBB, reg8);
#endif
dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */
/* Decode port 0x3f8-0x3ff (Serial 0) */
// XXX Serial port decode on LPC is hardcoded to 0x3f8
reg8 = pci_read_config8(dev, 0x44);
reg8 |= 1 << 6;
#if CONFIG(SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
#if CONFIG_TTYS0_BASE == 0x2f8
reg8 |= 1 << 7;
#endif
#endif
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);
/* Enable PrefetchEnSPIFromHost to speed up SPI flash read (does not affect LPC) */
reg8 = pci_read_config8(dev, 0xbb);
reg8 |= 1 << 0;
pci_write_config8(dev, 0xbb, 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);
}
void sb7xx_51xx_enable_wideio(u8 wio_index, u16 base)
{
/* TODO: Now assume wio_index=0 */
pci_devfn_t dev;
u8 reg8;
dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */
pci_write_config32(dev, 0x64, base);
reg8 = pci_read_config8(dev, 0x48);
reg8 |= 1 << 2;
pci_write_config8(dev, 0x48, reg8);
}
void sb7xx_51xx_disable_wideio(u8 wio_index)
{
/* TODO: Now assume wio_index=0 */
pci_devfn_t dev;
u8 reg8;
dev = pci_locate_device(PCI_ID(0x1002, 0x439d), 0); /* LPC Controller */
pci_write_config32(dev, 0x64, 0);
reg8 = pci_read_config8(dev, 0x48);
reg8 &= ~(1 << 2);
pci_write_config8(dev, 0x48, reg8);
}
/* what is its usage? */
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;
}
/*
* RPR 2.4 C-state and VID/FID change for the K8 platform.
*/
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); /* TODO: if the HT Link is 200 MHz, it is 0x0A. It doesn't often happen. */
pmio_write(0x8a, 0x90);
pmio_write(0x88, 0x10);
byte = pmio_read(0x7c);
byte |= 0x03;
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(0x42);
byte &= ~0x04;
pmio_write(0x42, byte);
pmio_write(0x89, 0x10);
/* Toggle the LDT_STOP# during FID/VID Change, this bit is documented
only in SB600!
While here, enable C states too
*/
pmio_write(0x67, 0x6);
}
void sb7xx_51xx_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, 0x439D), 0);
byte = pci_read_config8(dev, 0x4A);
byte &= ~(1 << 5); /* disable lpc port 80 */
pci_write_config8(dev, 0x4A, byte);
}
void sb7xx_51xx_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, 0x439d), 0);
byte = pci_read_config8(dev, 0x4a);
byte |= 1 << 5; /* enable port 80 */
pci_write_config8(dev, 0x4a, byte);
}
/* sbDevicesPorInitTable */
static void sb700_devices_por_init(void)
{
pci_devfn_t dev;
u8 byte;
uint32_t dword;
uint8_t nvram;
uint8_t sata_ahci_mode;
sata_ahci_mode = 0;
if (get_option(&nvram, "sata_ahci_mode") == CB_SUCCESS)
sata_ahci_mode = !!nvram;
printk(BIOS_INFO, "sb700_devices_por_init()\n");
/* SMBus Device, BDF:0-20-0 */
printk(BIOS_INFO, "sb700_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 A%x\n",
set_sb700_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. */
/* 4.3:Enables the SB700 to send transactions upstream over A-Link Express interface. */
axcfg_reg(0x04, 1 << 2, 1 << 2);
axindxc_reg(0x21, 0xff, 0);
/* 2.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, 0x90, SMBUS_IO_BASE | 1);
/* enable smbus controller interface */
byte = pci_read_config8(dev, 0xd2);
byte |= (1 << 0);
pci_write_config8(dev, 0xd2, byte);
/* set auxiliary smbus iobase and enable controller */
pci_write_config32(dev, 0x58, SMBUS_AUX_IO_BASE | 1);
if (inb(SMBUS_IO_BASE) == 0xff)
printk(BIOS_INFO, "%s: Primary SMBUS controller I/O not found\n", __func__);
if (inb(SMBUS_AUX_IO_BASE) == 0xff) {
printk(BIOS_INFO, "%s: Secondary SMBUS controller I/O not found\n", __func__);
}
else {
if (CONFIG(SOUTHBRIDGE_AMD_SUBTYPE_SP5100)) {
/* Disable legacy sensor support / reset ASF Slave state machine per RPR 2.27 step 3 */
outb(0x40, SMBUS_AUX_IO_BASE + SMBSLVMISC);
}
}
/* KB2RstEnable */
pci_write_config8(dev, 0x40, 0x44);
/* 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); */
/* Enable DMA verify bugfix */
byte = pci_read_config8(dev, 0x67);
byte |= 0x1 << 1;
pci_write_config8(dev, 0x67, byte);
/* Disabling Legacy USB Fast SMI# */
byte = pci_read_config8(dev, 0x62);
byte |= 0x24;
pci_write_config8(dev, 0x62, byte);
/* Configure HPET Counter CLK period */
byte = pci_read_config8(dev, 0x43);
byte &= 0xF7; /* Unhide HPET regs */
pci_write_config8(dev, 0x43, byte);
pci_write_config32(dev, 0x34, 0x0429b17e); /* Counter CLK period */
byte |= 0x08; /* Hide HPET regs */
pci_write_config8(dev, 0x43, byte);
/* Features Enable */
pci_write_config32(dev, 0x64, 0x829E79BF); /* 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);
if (CONFIG(SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) {
printk(BIOS_DEBUG, "%s: Disabling ISA DMA support\n", __func__);
/* Disable LPC ISA DMA Capability */
byte = pci_read_config8(dev, 0x78);
byte &= ~(1 << 0);
pci_write_config8(dev, 0x78, byte);
}
/* 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, "sb700_devices_por_init(): IDE Device, BDF:0-20-1\n");
dev = pci_locate_device(PCI_ID(0x1002, 0x439C), 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, "sb700_devices_por_init(): LPC Device, BDF:0-20-3\n");
dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0);
if (!CONFIG(SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) {
/* DMA enable */
pci_write_config8(dev, 0x40, 0x04);
}
/* IO Port Decode Enable */
pci_write_config8(dev, 0x44, 0xFF);
pci_write_config8(dev, 0x45, 0xFF);
pci_write_config8(dev, 0x46, 0xC3);
pci_write_config8(dev, 0x47, 0xFF);
// TODO: This has already been done(?)
/* IO/Mem Port Decode Enable, I don't know why CIM disable some ports.
* Disable LPC TimeOut counter, enable SuperIO Configuration Port (2e/2f),
* Alternate Super I/O Configuration Port (4e/4f), Wide Generic IO Port (64/65). */
byte = pci_read_config8(dev, 0x48);
byte |= (1 << 1) | (1 << 0); /* enable Super IO config port 2e-2h, 4e-4f */
byte |= 1 << 6; /* enable for RTC I/O range */
pci_write_config8(dev, 0x48, byte);
pci_write_config8(dev, 0x49, 0xFF);
/* Enable 0x480-0x4bf, 0x4700-0x470B */
byte = pci_read_config8(dev, 0x4A);
byte |= ((1 << 1) + (1 << 6)); /*0x42, save the configuration for port 0x80. */
pci_write_config8(dev, 0x4A, byte);
/* 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,
*/
printk(BIOS_INFO, "sb700_devices_por_init(): P2P Bridge, BDF:0-20-4\n");
dev = pci_locate_device(PCI_ID(0x1002, 0x4384), 0);
/* 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);
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);
if (!sata_ahci_mode){
#if CONFIG(SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
/* SP5100 default SATA mode is RAID5 MODE */
dev = pci_locate_device(PCI_ID(0x1002, 0x4392), 0);
if (dev != PCI_DEV_INVALID) {
/* Set SATA Operation Mode, Set to IDE mode */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 0);
pci_write_config8(dev, 0x40, byte);
dword = 0x01018f00;
pci_write_config32(dev, 0x8, dword);
/* set SATA Device ID writable */
dword = pci_read_config32(dev, 0x40);
dword &= ~(1 << 24);
pci_write_config32(dev, 0x40, dword);
/* set Device ID consistent with IDE emulation mode configuration */
pci_write_config32(dev, 0x0, 0x43901002);
}
#endif
}
/* rpr v2.13 4.17 Reset CPU on Sync Flood */
abcfg_reg(0x10050, 1 << 2, 1 << 2);
/* SATA Device, BDF:0-17-0, Non-Raid-5 SATA controller */
printk(BIOS_INFO, "sb700_devices_por_init(): SATA Device, BDF:0-17-0\n");
dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0);
if (sata_ahci_mode) {
/* Switch to AHCI mode (AMD inbox) */
dword = pci_read_config32(dev, 0x40);
dword |= (0x1 << 24); /* Lock Flash Device ID = 1 */
pci_write_config32(dev, 0x40, dword);
/* Deactivate Sub-Class Code write protection */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 0);
pci_write_config8(dev, 0x40, byte);
dword = pci_read_config32(dev, 0x08);
dword &= ~(0xff << 16); /* Sub-Class Code = 0x6 */
dword |= (0x6 << 16);
dword &= ~(0xff << 8); /* Operating Mode Selection = 0x1 */
dword |= (0x1 << 8);
pci_write_config32(dev, 0x08, dword);
}
/* PHY Global Control */
pci_write_config16(dev, 0x86, 0x2C00);
}
/* 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 sb700_pmio_por_init(void)
{
u8 byte;
uint8_t enable_c_states;
enable_c_states = 0;
#if CONFIG(HAVE_ACPI_TABLES)
if (get_option(&byte, "cpu_c_states") == CB_SUCCESS)
enable_c_states = !!byte;
#endif
printk(BIOS_INFO, "sb700_pmio_por_init()\n");
/* K8KbRstEn, KB_RST# control for K8 system. */
byte = pmio_read(0x66);
byte |= 0x20;
pmio_write(0x66, byte);
if (CONFIG(SOUTHBRIDGE_AMD_SUBTYPE_SP5100)) {
/* RPR 2.11 Sx State Settings */
byte = pmio_read(0x65);
byte &= ~(1 << 7); /* SpecialFunc = 0 */
pmio_write(0x65, byte);
byte = pmio_read(0x68);
byte |= 1 << 2; /* MaskApicEn = 1 */
pmio_write(0x68, byte);
} else {
/* RPR2.31 PM_TURN_OFF_MSG during ASF Shutdown. */
if (get_sb700_revision(pci_locate_device(PCI_ID(0x1002, 0x4385), 0)) <= 0x12) {
byte = pmio_read(0x65);
byte &= ~(1 << 7);
pmio_write(0x65, byte);
byte = pmio_read(0x75);
byte &= 0xc0;
byte |= 0x05;
pmio_write(0x75, byte);
byte = pmio_read(0x52);
byte &= 0xc0;
byte |= 0x08;
pmio_write(0x52, byte);
} else {
byte = pmio_read(0xD7);
byte |= 1 << 0;
pmio_write(0xD7, byte);
byte = pmio_read(0x65);
byte |= 1 << 7;
pmio_write(0x65, byte);
byte = pmio_read(0x75);
byte &= 0xc0;
byte |= 0x01;
pmio_write(0x75, byte);
byte = pmio_read(0x52);
byte &= 0xc0;
byte |= 0x02;
pmio_write(0x52, 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.15: Enabling Spread Spectrum */
byte = pmio_read(0x42);
byte |= 1 << 7;
pmio_write(0x42, byte);
/* TODO: Check if it is necessary. IDE reset */
byte = pmio_read(0xB2);
byte |= 1 << 0;
pmio_write(0xB2, byte);
/* Set up IOAPIC and BM_STS monitoring */
byte = pmio_read(0x61);
if (enable_c_states)
byte |= 0x4;
else
byte &= ~0x04;
pmio_write(0x61, byte);
/* NOTE: Enabling automatic C1e state switch caused failures when initializing processors */
/* Enable precision HPET clock and automatic C state switch */
byte = pmio_read(0xbb);
byte |= 0xc0;
pmio_write(0xbb, byte);
#if CONFIG(SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
/* RPR 2.26 Alter CPU reset timing */
byte = pmio_read(0xb2);
byte |= 0x1 << 2; /* Enable CPU reset timing option */
pmio_write(0xb2, byte);
/* Work around system clock drift issues */
byte = pmio_read(0xd4);
byte |= 0x1 << 6; /* Enable alternate 14MHz clock source */
byte |= 0x1 << 7; /* Disable 25MHz oscillator buffer */
pmio_write(0xd4, byte);
#endif
}
/*
* Add any south bridge setting.
*/
static void sb700_pci_cfg(void)
{
pci_devfn_t dev;
u8 byte;
uint8_t acpi_s1_supported = 1;
/* SMBus Device, BDF:0-20-0 */
dev = pci_locate_device(PCI_ID(0x1002, 0x4385), 0);
/* Enable watchdog timer decode */
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);
/* IDE Device, BDF:0-20-1 */
dev = pci_locate_device(PCI_ID(0x1002, 0x439C), 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 */
/* The code below is ported from old chipset. It is not
* mentioned in RPR. But I keep them. The registers and the
* comments are compatible. */
dev = pci_locate_device(PCI_ID(0x1002, 0x439D), 0);
if (!CONFIG(SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) {
/* Enabling LPC DMA function. */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 2);
pci_write_config8(dev, 0x40, byte);
}
/* Disabling LPC TimeOut. 0x48[7] clear. */
byte = pci_read_config8(dev, 0x48);
byte &= 0x7f;
pci_write_config8(dev, 0x48, byte);
/* 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-17-0, Non-Raid-5 SATA controller */
dev = pci_locate_device(PCI_ID(0x1002, 0x4390), 0);
if (dev == PCI_DEV_INVALID)
dev = pci_locate_device(PCI_ID(0x1002, 0x4391), 0);
if (dev == PCI_DEV_INVALID)
dev = pci_locate_device(PCI_ID(0x1002, 0x4394), 0);
/* rpr7.12 SATA MSI and D3 Power State Capability. */
byte = pci_read_config8(dev, 0x40);
byte |= 1 << 0;
pci_write_config8(dev, 0x40, byte);
if (acpi_s1_supported)
pci_write_config8(dev, 0x34, 0x70); /* Hide D3 power state and MSI capabilities */
else
pci_write_config8(dev, 0x61, 0x70); /* Hide MSI capability */
byte &= ~(1 << 0);
pci_write_config8(dev, 0x40, byte);
}
/*
*/
static void sb700_por_init(void)
{
/* sbDevicesPorInitTable + sbK8PorInitTable */
sb700_devices_por_init();
/* sbPmioPorInitTable + sbK8PmioPorInitTable */
sb700_pmio_por_init();
}
uint16_t sb7xx_51xx_decode_last_reset(void) {
uint16_t reset_status = 0;
reset_status |= pmio_read(0x44);
reset_status |= (pmio_read(0x45) << 8);
printk(BIOS_INFO, "sb700 reset flags: %04x\n", reset_status);
if (reset_status & (0x1 << 10))
printk(BIOS_WARNING, "WARNING: Last reset was caused by fatal error / sync flood!\n");
return reset_status;
}
/*
* It should be called during early POST after memory detection and BIOS shadowing but before PCI bus enumeration.
*/
void sb7xx_51xx_before_pci_init(void)
{
sb700_pci_cfg();
}
/*
* This function should be called after enable_sb700_smbus().
*/
void sb7xx_51xx_early_setup(void)
{
printk(BIOS_INFO, "sb700_early_setup()\n");
sb700_por_init();
sb700_acpi_init();
}
int s3_save_nvram_early(u32 dword, int size, int nvram_pos)
{
int i;
printk(BIOS_DEBUG, "Writing %x of size %d to nvram pos: %d\n", dword, size, nvram_pos);
for (i = 0; i < size; i++) {
outb(nvram_pos, BIOSRAM_INDEX);
outb((dword >> (8 * i)) & 0xff, BIOSRAM_DATA);
nvram_pos++;
}
return nvram_pos;
}
int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos)
{
u32 data = *old_dword;
int i;
for (i = 0; i < size; i++) {
outb(nvram_pos, BIOSRAM_INDEX);
data &= ~(0xff << (i * 8));
data |= inb(BIOSRAM_DATA) << (i *8);
nvram_pos++;
}
*old_dword = data;
printk(BIOS_DEBUG, "Loading %x of size %d to nvram pos:%d\n", *old_dword, size,
nvram_pos-size);
return nvram_pos;
}
void set_lpc_sticky_ctl(bool enable)
{
uint8_t byte;
byte = pmio_read(0xbb);
if (enable)
byte |= 0x20;
else
byte &= ~0x20;
pmio_write(0xbb, byte);
}
#endif

View File

@@ -1,47 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
*
* 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 <device/mmio.h>
#include <device/pci_ehci.h>
#include <device/pci_def.h>
#include "sb700.h"
#define DEBUGPORT_MISC_CONTROL 0x80
pci_devfn_t pci_ehci_dbg_dev(unsigned int hcd_idx)
{
if (hcd_idx == 2)
return PCI_DEV(0, 0x13, 2);
else
return PCI_DEV(0, 0x12, 2);
}
void pci_ehci_dbg_set_port(pci_devfn_t dev, unsigned int port)
{
u8 *base_regs = pci_ehci_base_regs(dev);
u32 reg32;
/* Write the port number to DEBUGPORT_MISC_CONTROL[31:28]. */
reg32 = read32(base_regs + DEBUGPORT_MISC_CONTROL);
reg32 &= ~(0xf << 28);
reg32 |= (port << 28);
reg32 |= (1 << 27); /* Enable Debug Port port number remapping. */
write32(base_regs + DEBUGPORT_MISC_CONTROL, reg32);
}

View File

@@ -1,162 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Raptor Engineering
*
* 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.
*/
/*
* ACPI - create the Fixed ACPI Description Tables (FADT)
*/
#include <string.h>
#include <console/console.h>
#include <arch/acpi.h>
#include <device/device.h>
#include <cpu/amd/powernow.h>
#include <version.h>
#include "sb700.h"
void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt)
{
acpi_header_t *header = &(fadt->header);
printk(BIOS_DEBUG, "pm_base: 0x%04x\n", SB700_ACPI_IO_BASE);
/* Prepare the header */
memset((void *)fadt, 0, sizeof(acpi_fadt_t));
memcpy(header->signature, "FACP", 4);
header->length = sizeof(acpi_fadt_t);
header->revision = get_acpi_table_revision(FADT);
memcpy(header->oem_id, OEM_ID, 6);
memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
memcpy(header->asl_compiler_id, ASLC, 4);
header->asl_compiler_revision = asl_revision;
fadt->firmware_ctrl = (u32) facs;
fadt->dsdt = (u32) dsdt;
/* 3=Workstation,4=Enterprise Server, 7=Performance Server */
fadt->preferred_pm_profile = 0x03;
fadt->sci_int = 9;
/* disable system management mode by setting to 0: */
fadt->smi_cmd = 0;
fadt->acpi_enable = 0xf0;
fadt->acpi_disable = 0xf1;
fadt->s4bios_req = 0x0;
fadt->pstate_cnt = 0xe2;
fadt->pm1a_evt_blk = ACPI_PM_EVT_BLK;
fadt->pm1b_evt_blk = 0x0000;
fadt->pm1a_cnt_blk = ACPI_PM1_CNT_BLK;
fadt->pm1b_cnt_blk = 0x0000;
fadt->pm2_cnt_blk = ACPI_PMA_CNT_BLK;
fadt->pm_tmr_blk = ACPI_PM_TMR_BLK;
fadt->gpe0_blk = ACPI_GPE0_BLK;
fadt->gpe1_blk = 0x0000; /* we don't have gpe1 block, do we? */
fadt->pm1_evt_len = 4;
fadt->pm1_cnt_len = 2;
fadt->pm2_cnt_len = 1;
fadt->pm_tmr_len = 4;
fadt->gpe0_blk_len = 8;
fadt->gpe1_blk_len = 0;
fadt->gpe1_base = 0;
fadt->cst_cnt = 0xe3;
fadt->p_lvl2_lat = 101;
fadt->p_lvl3_lat = 1001;
fadt->flush_size = 0;
fadt->flush_stride = 0;
fadt->duty_offset = 1;
fadt->duty_width = 3;
fadt->day_alrm = 0; /* 0x7d these have to be */
fadt->mon_alrm = 0; /* 0x7e added to cmos.layout */
fadt->century = 0; /* 0x7f to make rtc alarm work */
fadt->iapc_boot_arch = 0x3; /* See table 5-11 */
fadt->flags = 0x0001c1a5;/* 0x25; */
fadt->res2 = 0;
fadt->reset_reg.space_id = 1;
fadt->reset_reg.bit_width = 8;
fadt->reset_reg.bit_offset = 0;
fadt->reset_reg.access_size = 0;
fadt->reset_reg.addrl = 0xcf9;
fadt->reset_reg.addrh = 0x0;
fadt->reset_value = 6;
fadt->x_firmware_ctl_l = (u32) facs;
fadt->x_firmware_ctl_h = 0;
fadt->x_dsdt_l = (u32) dsdt;
fadt->x_dsdt_h = 0;
fadt->x_pm1a_evt_blk.space_id = 1;
fadt->x_pm1a_evt_blk.bit_width = 32;
fadt->x_pm1a_evt_blk.bit_offset = 0;
fadt->x_pm1a_evt_blk.access_size = 0;
fadt->x_pm1a_evt_blk.addrl = ACPI_PM_EVT_BLK;
fadt->x_pm1a_evt_blk.addrh = 0x0;
fadt->x_pm1b_evt_blk.space_id = 1;
fadt->x_pm1b_evt_blk.bit_width = 4;
fadt->x_pm1b_evt_blk.bit_offset = 0;
fadt->x_pm1b_evt_blk.access_size = 0;
fadt->x_pm1b_evt_blk.addrl = 0x0;
fadt->x_pm1b_evt_blk.addrh = 0x0;
fadt->x_pm1a_cnt_blk.space_id = 1;
fadt->x_pm1a_cnt_blk.bit_width = 16;
fadt->x_pm1a_cnt_blk.bit_offset = 0;
fadt->x_pm1a_cnt_blk.access_size = 0;
fadt->x_pm1a_cnt_blk.addrl = ACPI_PM1_CNT_BLK;
fadt->x_pm1a_cnt_blk.addrh = 0x0;
fadt->x_pm1b_cnt_blk.space_id = 1;
fadt->x_pm1b_cnt_blk.bit_width = 2;
fadt->x_pm1b_cnt_blk.bit_offset = 0;
fadt->x_pm1b_cnt_blk.access_size = 0;
fadt->x_pm1b_cnt_blk.addrl = 0x0;
fadt->x_pm1b_cnt_blk.addrh = 0x0;
fadt->x_pm2_cnt_blk.space_id = 1;
fadt->x_pm2_cnt_blk.bit_width = 8;
fadt->x_pm2_cnt_blk.bit_offset = 0;
fadt->x_pm2_cnt_blk.access_size = 0;
fadt->x_pm2_cnt_blk.addrl = ACPI_PMA_CNT_BLK;
fadt->x_pm2_cnt_blk.addrh = 0x0;
fadt->x_pm_tmr_blk.space_id = 1;
fadt->x_pm_tmr_blk.bit_width = 32;
fadt->x_pm_tmr_blk.bit_offset = 0;
fadt->x_pm_tmr_blk.access_size = 0;
fadt->x_pm_tmr_blk.addrl = ACPI_PM_TMR_BLK;
fadt->x_pm_tmr_blk.addrh = 0x0;
fadt->x_gpe0_blk.space_id = 1;
fadt->x_gpe0_blk.bit_width = 64;
fadt->x_gpe0_blk.bit_offset = 0;
fadt->x_gpe0_blk.access_size = 0;
fadt->x_gpe0_blk.addrl = ACPI_GPE0_BLK;
fadt->x_gpe0_blk.addrh = 0x0;
fadt->x_gpe1_blk.space_id = 1;
fadt->x_gpe1_blk.bit_width = 0;
fadt->x_gpe1_blk.bit_offset = 0;
fadt->x_gpe1_blk.access_size = 0;
fadt->x_gpe1_blk.addrl = 0;
fadt->x_gpe1_blk.addrh = 0x0;
if (CONFIG(CPU_AMD_MODEL_10XXX))
amd_powernow_update_fadt(fadt);
header->checksum = acpi_checksum((void *)fadt, sizeof(acpi_fadt_t));
}

View File

@@ -1,226 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <device/mmio.h>
#include <delay.h>
#include "sb700.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;
}
/**
* 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;
/* 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, "%x(th) codec viddid: %08x\n", addr, dword);
}
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[3], no ac97 in sb700. */
byte = pm_ioread(0x59);
byte |= 1 << 3;
pm_iowrite(0x59, byte);
/* Find the SMBus */
sm_dev = dev_find_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SB700_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,
.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_SB700_HDA,
};

View File

@@ -1,87 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
* Copyright (C) 2010 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <option.h>
#include <types.h>
#include "sb700.h"
#include "chip.h"
static void ide_init(struct device *dev)
{
struct southbridge_amd_sb700_config *conf;
/* Enable ide devices so the linux ide driver will work */
u32 dword;
u8 byte;
uint8_t nvram;
uint8_t sata_ahci_mode;
sata_ahci_mode = 0;
if (get_option(&nvram, "sata_ahci_mode") == CB_SUCCESS)
sata_ahci_mode = !!nvram;
conf = dev->chip_info;
/* RPR9.1 disable MSI */
/* TODO: For A14, it should set as 1. I doubt it. */
dword = pci_read_config32(dev, 0x70);
dword &= ~(1 << 16);
pci_write_config32(dev, 0x70, dword);
if (!sata_ahci_mode) {
/* 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);
/* set ide as primary, if you want to boot from IDE, you'd better set it
* in $vendor/$mainboard/devicetree.cb */
if (conf->boot_switch_sata_ide == 1) {
struct device *sm_dev = pcidev_on_root(0x14, 0);
byte = pci_read_config8(sm_dev, 0xad);
byte |= 1 << 4;
pci_write_config8(sm_dev, 0xad, byte);
}
}
}
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,
.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_SB700_IDE,
};

View File

@@ -1,292 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
*
* 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 <pc80/isa-dma.h>
#include <arch/ioapic.h>
#include <cpu/amd/powernow.h>
#include "sb700.h"
static void lpc_init(struct device *dev)
{
u8 byte;
u32 dword;
struct device *sm_dev;
printk(BIOS_SPEW, "%s\n", __func__);
/* Enable the LPC Controller */
sm_dev = pcidev_on_root(0x14, 0);
dword = pci_read_config32(sm_dev, 0x64);
dword |= 1 << 20;
pci_write_config32(sm_dev, 0x64, dword);
/* Initialize isa dma */
#if CONFIG(SOUTHBRIDGE_AMD_SB700_SKIP_ISA_DMA_INIT)
printk(BIOS_DEBUG, "Skipping isa_dma_init() to avoid getting stuck.\n");
#else
isa_dma_init();
#endif
if (!CONFIG(SOUTHBRIDGE_AMD_SB700_DISABLE_ISA_DMA)) {
/* Enable DMA transaction on the LPC bus */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 2);
pci_write_config8(dev, 0x40, byte);
}
/* Disable the timeout mechanism on LPC */
byte = pci_read_config8(dev, 0x48);
byte &= ~(1 << 7);
pci_write_config8(dev, 0x48, byte);
/* Disable LPC MSI Capability */
byte = pci_read_config8(dev, 0x78);
byte &= ~(1 << 1);
#if CONFIG(SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
/* Disable FlowContrl, Always service the request from Host
* whenever there is a request from Host pending
*/
byte &= ~(1 << 0);
#endif
pci_write_config8(dev, 0x78, byte);
cmos_check_update_date();
setup_i8259(); /* Initialize i8259 pic */
setup_i8254(); /* Initialize i8254 timers */
}
static void sb700_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);
}
static void sb700_lpc_set_resources(struct device *dev)
{
struct resource *res;
pci_dev_set_resources(dev);
/* Special case. SPI Base Address. The SpiRomEnable should be set. */
res = find_resource(dev, 0xA0);
pci_write_config32(dev, 0xA0, res->base | 1 << 1);
}
/**
* @brief Enable resources for children devices
*
* @param dev the device whose children's resources are to be enabled
*
*/
static void sb700_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)))
continue;
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, "sb700 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:
/* only 3 var ; compact them ? */
if (var_num >= 3)
continue;
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 3:
pci_write_config16(dev, 0x90, reg_var[2]);
/* fall through */
case 2:
pci_write_config16(dev, 0x66, reg_var[1]);
/* fall through */
case 1:
pci_write_config16(dev, 0x64, reg_var[0]);
break;
}
pci_write_config8(dev, 0x74, wiosize);
}
static void sb700_lpc_enable_resources(struct device *dev)
{
pci_dev_enable_resources(dev);
sb700_lpc_enable_childrens_resources(dev);
}
#if CONFIG(HAVE_ACPI_TABLES)
static void southbridge_acpi_fill_ssdt_generator(struct device *device) {
amd_generate_powernow(ACPI_CPU_CONTROL, 6, 1);
}
static const char *lpc_acpi_name(const struct device *dev)
{
if (dev->path.type != DEVICE_PATH_PCI)
return NULL;
switch (dev->path.pci.devfn) {
case PCI_DEVFN(0x14, 3):
return "LPC";
}
return NULL;
}
#endif
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations lpc_ops = {
.read_resources = sb700_lpc_read_resources,
.set_resources = sb700_lpc_set_resources,
.enable_resources = sb700_lpc_enable_resources,
#if CONFIG(HAVE_ACPI_TABLES)
.acpi_name = lpc_acpi_name,
.write_acpi_tables = acpi_write_hpet,
.acpi_fill_ssdt_generator = southbridge_acpi_fill_ssdt_generator,
#endif
.init = lpc_init,
.scan_bus = scan_static_bus,
.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_SB700_LPC,
};

View File

@@ -1,123 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include "sb700.h"
static void pci_init(struct device *dev)
{
u32 dword;
u16 word;
u8 byte;
/* RPR 5.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);
/* RPR5.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 5.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 5.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 5.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 5.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 5.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 5.8 Adjusts the GNT# de-assertion time */
word = pci_read_config16(dev, 0x64);
word |= 1 << 12;
pci_write_config16(dev, 0x64, word);
/* RPR 5.9 Fast Back to Back transactions support */
byte = pci_read_config8(dev, 0x48);
byte |= 1 << 2;
/* pci_write_config8(dev, 0x48, byte); */
/* RPR 5.10 Enable Lock Operation */
/* byte = pci_read_config8(dev, 0x48); */
byte |= 1 << 3;
pci_write_config8(dev, 0x48, byte);
/* RPR 5.11 Enable additional optional PCI clock */
word = pci_read_config16(dev, 0x64);
word |= 1 << 8;
pci_write_config16(dev, 0x64, word);
/* RPR 5.12 Enable One-Prefetch-Channel Mode */
dword = pci_read_config32(dev, 0x64);
dword |= 1 << 20;
pci_write_config32(dev, 0x64, dword);
/* RPR 5.13 Disable PCIB MSI Capability */
byte = pci_read_config8(dev, 0x40);
byte &= ~(1 << 3);
pci_write_config8(dev, 0x40, byte);
/* rpr5.14 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,
.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_SB700_PCI,
};

View File

@@ -1,50 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <arch/io.h> /*inb, outb*/
#include "pmio.h"
static void pmio_write_index(u16 port_base, u8 reg, u8 value)
{
outb(reg, port_base);
outb(value, port_base + 1);
}
static u8 pmio_read_index(u16 port_base, u8 reg)
{
outb(reg, port_base);
return inb(port_base + 1);
}
void pm_iowrite(u8 reg, u8 value)
{
pmio_write_index(PM_INDEX, reg, value);
}
u8 pm_ioread(u8 reg)
{
return pmio_read_index(PM_INDEX, reg);
}
void pm2_iowrite(u8 reg, u8 value)
{
pmio_write_index(PM2_INDEX, reg, value);
}
u8 pm2_ioread(u8 reg)
{
return pmio_read_index(PM2_INDEX, reg);
}

View File

@@ -1,30 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _PMIO_H_
#define _PMIO_H_
#define PM_INDEX 0xCD6
#define PM_DATA 0xCD7
#define PM2_INDEX 0xCD0
#define PM2_DATA 0xCD1
void pm_iowrite(u8 reg, u8 value);
u8 pm_ioread(u8 reg);
void pm2_iowrite(u8 reg, u8 value);
u8 pm2_ioread(u8 reg);
#endif

View File

@@ -1,51 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdint.h>
#include <arch/io.h>
#include <arch/acpi.h>
#include <cbmem.h>
#include "sb700.h"
int acpi_get_sleep_type(void)
{
u16 tmp;
tmp = inw(ACPI_PM1_CNT_BLK);
return ((tmp & (7 << 10)) >> 10);
}
void backup_top_of_low_cacheable(uintptr_t ramtop)
{
u32 dword = (u32) ramtop;
int nvram_pos = 0xfc, i;
for (i = 0; i < 4; i++) {
outb(nvram_pos, BIOSRAM_INDEX);
outb((dword >> (8 * i)) & 0xff, BIOSRAM_DATA);
nvram_pos++;
}
}
uintptr_t restore_top_of_low_cacheable(void)
{
uint32_t xdata = 0;
int xnvram_pos = 0xfc, xi;
for (xi = 0; xi < 4; xi++) {
outb(xnvram_pos, BIOSRAM_INDEX);
xdata &= ~(0xff << (xi * 8));
xdata |= inb(BIOSRAM_DATA) << (xi *8);
xnvram_pos++;
}
return xdata;
}

View File

@@ -1,66 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 - 2011 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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 <device/pci_ops.h>
#include <reset.h>
#include <southbridge/amd/common/reset.h>
#define HT_INIT_CONTROL 0x6C
#define HTIC_BIOSR_Detect (1<<5)
#if CONFIG_MAX_PHYSICAL_CPUS > 32
#define NODE_PCI(x, fn) ((x < 32)?(PCI_DEV(CONFIG_CBB,(CONFIG_CDB+x),fn)):(PCI_DEV((CONFIG_CBB-1),(CONFIG_CDB+x-32),fn)))
#else
#define NODE_PCI(x, fn) PCI_DEV(CONFIG_CBB,(CONFIG_CDB+x),fn)
#endif
static void set_bios_reset(void)
{
u32 nodes;
u32 htic;
pci_devfn_t dev;
int i;
nodes = ((pci_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), 0x60) >> 4) & 7) + 1;
for (i = 0; i < nodes; i++) {
dev = NODE_PCI(i, 0);
htic = pci_read_config32(dev, HT_INIT_CONTROL);
htic &= ~HTIC_BIOSR_Detect;
pci_write_config32(dev, HT_INIT_CONTROL, htic);
}
}
void do_board_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);
}
void do_soft_reset(void)
{
set_bios_reset();
/* link reset */
outb(0x06, 0x0cf9);
}

View File

@@ -1,555 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
*
* 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 <device/mmio.h>
#include <option.h>
#include <types.h>
#include "sb700.h"
static int sata_drive_detect(int portnum, uint16_t iobar)
{
u8 byte, byte2;
u8 byte_prev, byte2_prev;
int i = 0;
byte_prev = byte2_prev = 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)) {
if ((byte != byte_prev) || (byte2 != byte2_prev))
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 {
if (i == 0)
printk(BIOS_SPEW, "drive detection not yet completed, "
"waiting...\n");
}
mdelay(10);
i++;
byte_prev = byte;
byte2_prev = byte2;
/* Detect stuck SATA controller and attempt reset */
if (i > 1024) {
printk(BIOS_DEBUG, "drive detection not done after %i ms, "
"resetting HBA and retrying init\n", i * 10);
return 2;
}
}
printk(BIOS_SPEW, "drive detection done after %i ms\n", i * 10);
return 0;
}
/* This function can be overloaded in mainboard.c */
void __weak sb7xx_51xx_setup_sata_phys(struct device *dev)
{
/* RPR7.6.1 Program the PHY Global Control to 0x2C00 */
pci_write_config16(dev, 0x86, 0x2c00);
/* RPR7.6.2 SATA GENI PHY ports setting */
pci_write_config32(dev, 0x88, 0x01B48017);
pci_write_config32(dev, 0x8c, 0x01B48019);
pci_write_config32(dev, 0x90, 0x01B48016);
pci_write_config32(dev, 0x94, 0x01B48016);
pci_write_config32(dev, 0x98, 0x01B48016);
pci_write_config32(dev, 0x9c, 0x01B48016);
/* RPR7.6.3 SATA GEN II PHY port setting for port [0~5]. */
pci_write_config16(dev, 0xa0, 0xA09A);
pci_write_config16(dev, 0xa2, 0xA09F);
pci_write_config16(dev, 0xa4, 0xA07A);
pci_write_config16(dev, 0xa6, 0xA07A);
pci_write_config16(dev, 0xa8, 0xA07A);
pci_write_config16(dev, 0xaa, 0xA07A);
}
/* This function can be overloaded in mainboard.c */
void __weak sb7xx_51xx_setup_sata_port_indication(void *sata_bar5)
{
uint32_t dword;
/* RPR7.9 Program Port Indication Registers */
dword = read32(sata_bar5 + 0xf8);
dword &= ~(0x3f << 12); /* Ports 0 and 1 are eSATA */
dword |= (0x3 << 12);
dword &= ~0x3f;
write32(sata_bar5 + 0xf8, dword);
dword = read32(sata_bar5 + 0xfc);
dword |= 0x1 << 20; /* At least one eSATA port is present */
write32(sata_bar5 + 0xfc, dword);
}
static void sata_init(struct device *dev)
{
u8 byte;
u16 word;
u32 dword;
u8 rev_id;
void *sata_bar5;
uint16_t sata_bar0, sata_bar1, sata_bar2, sata_bar3, sata_bar4;
uint16_t ide_bar0, ide_bar1, ide_bar2, ide_bar3;
uint16_t current_bar;
int i, j, ret;
uint8_t nvram;
uint8_t sata_ahci_mode;
uint8_t sata_alpm_enable;
uint8_t port_count;
uint8_t max_port_count;
uint8_t ide_io_enabled;
uint8_t ide_legacy_io_enabled;
sata_ahci_mode = 0;
if (get_option(&nvram, "sata_ahci_mode") == CB_SUCCESS)
sata_ahci_mode = !!nvram;
sata_alpm_enable = 0;
if (get_option(&nvram, "sata_alpm") == CB_SUCCESS)
sata_alpm_enable = !!nvram;
struct device *sm_dev;
/* SATA SMBus Disable */
sm_dev = pcidev_on_root(0x14, 0);
/* WARNING
* Enabling the SATA link latency enhancement (SMBUS 0xAD bit 5)
* causes random persistent drive detection failures until it is cleared,
* with the probabability of detection failure rising exponentially with
* the number of drives attached to the controller!
* This happens on Rev15 H/W.
* Do NOT follow the RPR advice; leave this bit set at all times...
*/
byte = pci_read_config8(sm_dev, 0xad);
/* Disable SATA SMBUS */
byte |= (1 << 1);
/* Enable SATA and power saving */
byte |= (1 << 0);
/* Disable link latency enhancement */
byte |= (1 << 5);
pci_write_config8(sm_dev, 0xad, byte);
/* Take the PHY logic out of reset */
word = pci_read_config16(dev, 0x84);
word |= 0x1 << 2;
word &= ~0x1f8;
pci_write_config16(dev, 0x84, word);
/* get rev_id */
rev_id = pci_read_config8(sm_dev, 0x08) - 0x28;
printk(BIOS_SPEW, "rev_id=%x\n", rev_id);
/* Enable combined mode */
byte = pci_read_config8(sm_dev, 0xad);
byte |= (1 << 3);
pci_write_config8(sm_dev, 0xad, byte);
struct device *ide_dev;
/* IDE Device */
ide_dev = pcidev_on_root(0x14, 1);
/* Disable legacy IDE mode (enable PATA_BAR0/2) */
byte = pci_read_config8(ide_dev, 0x09);
ide_legacy_io_enabled = !(byte & 0x1);
byte |= 0x1;
pci_write_config8(ide_dev, 0x09, byte);
/* Enable IDE I/O access (enable PATA_BAR0/2) */
byte = pci_read_config8(ide_dev, 0x04);
ide_io_enabled = byte & 0x1;
byte |= 0x1;
pci_write_config8(ide_dev, 0x04, byte);
/* RPR 7.2 SATA Initialization */
/* 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 */
ide_bar0 = pci_read_config16(ide_dev, 0x10) & ~0x7;
ide_bar1 = pci_read_config16(ide_dev, 0x14) & ~0x3;
ide_bar2 = pci_read_config16(ide_dev, 0x18) & ~0x7;
ide_bar3 = pci_read_config16(ide_dev, 0x1c) & ~0x3;
printk(BIOS_SPEW, "ide_bar0=%x\n", ide_bar0);
printk(BIOS_SPEW, "ide_bar1=%x\n", ide_bar1);
printk(BIOS_SPEW, "ide_bar2=%x\n", ide_bar2);
printk(BIOS_SPEW, "ide_bar3=%x\n", ide_bar3);
/* Program the Subsystem ID/VID to 0x43801002 */
dword = 0x43801002;
pci_write_config32(dev, 0x2c, dword);
/* 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);
/* Unlock subclass and certain BAR R/O registers */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 0);
pci_write_config8(dev, 0x40, byte);
/* Disable AHCI enhancement (AMD SP5100 RPR page 54) */
dword = pci_read_config32(dev, 0x40);
dword |= (1 << 23);
pci_write_config32(dev, 0x40, dword);
if (sata_ahci_mode) {
/* Force number of ports to 6
* NOTE: This is not documented in the register
* reference guide, but CIMX needs to do this
* to activate all 6 ports when IDE is disabled.
*/
dword = read32(sata_bar5 + 0x00);
dword &= ~0x7;
dword |= 0x5;
write32(sata_bar5 + 0x00, dword);
} else {
/* Set SATA Operation Mode, Set to IDE mode */
byte = pci_read_config8(dev, 0x40);
byte |= (1 << 4);
pci_write_config8(dev, 0x40, byte);
dword = 0x01018f00;
pci_write_config32(dev, 0x8, dword);
}
/* Get maximum number of ports */
max_port_count = read32(sata_bar5 + 0x00) & 0x1f;
max_port_count++;
printk(BIOS_SPEW, "Maximum SATA port count supported by silicon: %d\n", max_port_count);
/* Set number of ports */
dword = CONFIG_SOUTHBRIDGE_AMD_SB700_SATA_PORT_COUNT_BITFIELD;
for (i = max_port_count; i < 32; i++)
dword &= ~(0x1 << i);
write32(sata_bar5 + 0x0c, dword);
/* Disable ALPM if ALPM support not requested */
if (!sata_alpm_enable) {
dword = read32(sata_bar5 + 0xfc);
dword &= ~(0x1 << 11); /* Disable ALPM */
write32(sata_bar5 + 0xfc, dword);
}
/* Enable SATA ports */
byte = pci_read_config8(dev, 0x42);
if (max_port_count <= 6) {
byte |= 0x3f;
for (i = 0; i < max_port_count; i++)
byte &= ~(0x1 << i);
} else {
byte &= ~0x3f;
}
pci_write_config8(dev, 0x42, byte);
if (sata_ahci_mode) {
/* FIXME
* SeaBIOS does not know how to spin
* up the drives and therefore hangs
* in AHCI init if this is enabled...
*/
/* Enable staggered spin-up */
dword = read32(sata_bar5 + 0x00);
#if 0
dword |= 0x1 << 27;
#else
dword &= ~(0x1 << 27);
#endif
write32(sata_bar5 + 0x00, dword);
/* Reset the HBA to avoid stuck drives in SeaBIOS */
dword = read32(sata_bar5 + 0x04);
dword |= 0x1;
write32(sata_bar5 + 0x04, dword);
}
sb7xx_51xx_setup_sata_phys(dev);
sb7xx_51xx_setup_sata_port_indication(sata_bar5);
/* Write protect Sub-Class Code */
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);
/* Set bit 29 and 24 for A12 */
dword = pci_read_config32(dev, 0x40);
if (rev_id < 0x14) /* before A12 */
dword |= (1 << 29);
else
dword &= ~(1 << 29); /* A14 and above */
pci_write_config32(dev, 0x40, dword);
/* set bit 21 for A12 */
dword = pci_read_config32(dev, 0x48);
if (rev_id < 0x14) /* before A12 */
dword |= 1 << 24 | 1 << 21;
else {
dword &= ~(1 << 24 | 1 << 21); /* A14 and above */
dword &= ~0xFF80; /* 15:7 */
dword |= 1 << 15 | 0x7F << 7 | 1 << 6;
}
pci_write_config32(dev, 0x48, dword);
/* Program the watchdog counter to 0x10 */
byte = 0x10;
pci_write_config8(dev, 0x46, byte);
/* Enable the I/O, MM, BusMaster access for SATA */
byte = pci_read_config8(dev, 0x4);
byte |= 7 << 0;
pci_write_config8(dev, 0x4, byte);
#if CONFIG(SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
/* Master Latency Timer */
pci_write_config32(dev, 0xC, 0x00004000);
#endif
/* Determine port count */
port_count = 0;
for (i = 0; i < 32; i++) {
if (CONFIG_SOUTHBRIDGE_AMD_SB700_SATA_PORT_COUNT_BITFIELD & (0x1 << i))
port_count = i;
}
port_count++;
if (port_count > max_port_count)
port_count = max_port_count;
/* Send COMRESET to all ports */
for (i = 0; i < port_count; i++) {
/* Read in Port-N Serial ATA Control Register */
byte = read8(sata_bar5 + 0x12C + 0x80 * i);
/* Set Reset Bit */
byte |= 0x1;
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);
}
/* RPR7.7 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 */
/* Use BAR5+0x328,PATA_BAR0/2 for Primary/Secondary Master emulation */
/* Use BAR5+0x3A8,PATA_BAR0/2 for Primary/Secondary Slave emulation */
for (i = 0; i < port_count; 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 (i < 4)
current_bar = ((i / 2) == 0) ? sata_bar0 : sata_bar2;
else
current_bar = (pci_read_config8(sm_dev, 0xad) & (0x1 << 4))
? ide_bar2 : ide_bar0;
ret = sata_drive_detect(i, current_bar);
if (ret == 0) {
break;
} else if (ret == 2) {
/* Read in Port-N Serial ATA Control Register */
byte = read8(sata_bar5 + 0x12C + 0x80 * i);
/* Set Reset Bit */
byte |= 0x1;
write8((sata_bar5 + 0x12C + 0x80 * i), byte);
/* Wait 1000ms */
mdelay(1000);
/* Clear Reset Bit */
byte &= ~0x01;
write8((sata_bar5 + 0x12C + 0x80 * i), byte);
/* Wait 1ms */
mdelay(1);
}
}
if (sata_ahci_mode)
printk(BIOS_DEBUG, "AHCI device %d is %sready after %i tries\n",
i,
(j == 10) ? "not " : "",
(j == 10) ? j : j + 1);
else
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 {
if (sata_ahci_mode)
printk(BIOS_DEBUG, "No AHCI SATA drive on Slot%i\n", i);
else
printk(BIOS_DEBUG, "No %s %s SATA drive on Slot%i\n",
(i / 2) ? "Secondary" : "Primary",
(i % 2) ? "Slave" : "Master", i);
}
}
/* Restore IDE I/O access */
if (!ide_io_enabled) {
byte = pci_read_config8(ide_dev, 0x04);
byte &= ~0x1;
pci_write_config8(ide_dev, 0x04, byte);
}
/* Re-enable legacy IDE mode */
if (ide_legacy_io_enabled) {
byte = pci_read_config8(ide_dev, 0x09);
byte &= ~0x1;
pci_write_config8(ide_dev, 0x09, byte);
}
/* Below is CIM InitSataLateFar */
if (sata_ahci_mode) {
/* Disable combined mode */
byte = pci_read_config8(sm_dev, 0xad);
byte &= ~(1 << 3);
pci_write_config8(sm_dev, 0xad, byte);
} else {
/* 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);
write32((sata_bar5 + 0x330), 0xFFFFFFFF);
write32((sata_bar5 + 0x3b0), 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,
.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_SB700_SATA,
};
static const struct pci_driver sata1_driver __pci_driver = {
.ops = &sata_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB700_SATA_AHCI,
};
static const struct pci_driver sata2_driver __pci_driver = {
.ops = &sata_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB700_SATA_AHCI_AMD,
};

View File

@@ -1,227 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#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 "sb700.h"
#include "chip.h"
static struct device *find_sm_dev(struct device *dev, u32 devfn)
{
struct device *sm_dev;
sm_dev = pcidev_path_behind(dev->bus, devfn);
if (!sm_dev)
return sm_dev;
if ((sm_dev->vendor != PCI_VENDOR_ID_ATI) ||
((sm_dev->device != PCI_DEVICE_ID_ATI_SB700_SM))) {
u32 id;
id = pci_read_config32(sm_dev, PCI_VENDOR_ID);
if ((id !=
(PCI_VENDOR_ID_ATI | (PCI_DEVICE_ID_ATI_SB700_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 sb7xx_51xx_enable(struct device *dev)
{
struct device *sm_dev = NULL;
struct device *bus_dev = NULL;
int index;
u32 deviceid;
u32 vendorid;
/* struct southbridge_ati_sb700_config *conf; */
/* conf = dev->chip_info; */
int i;
u32 devfn;
printk(BIOS_DEBUG, "sb7xx_51xx_enable()\n");
/*
* 0:11.0 SATA bit 8 of sm_dev 0xac : 1 - enable, default + 32 * 3
* 0:12.0 OHCI0-USB1 bit 0 of sm_dev 0x68
* 0:12.1 OHCI1-USB1 bit 1 of sm_dev 0x68
* 0:12.2 EHCI-USB1 bit 2 of sm_dev 0x68
* 0:13.0 OHCI0-USB2 bit 4 of sm_dev 0x68
* 0:13.1 OHCI1-USB2 bit 5 of sm_dev 0x68
* 0:13.2 EHCI-USB2 bit 6 of sm_dev 0x68
* 0:14.5 OHCI0-USB3 bit 7 of sm_dev 0x68
* 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
*/
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_SB700_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 += (3 << 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 PCI_DEVFN(0x11, 0):
index = 8;
set_sm_enable_bits(sm_dev, 0xac, 1 << index,
(dev->enabled ? 1 : 0) << index);
break;
case PCI_DEVFN(0x12, 0):
case PCI_DEVFN(0x12, 1):
case PCI_DEVFN(0x12, 2):
index = dev->path.pci.devfn & 3;
set_sm_enable_bits(sm_dev, 0x68, 1 << index,
(dev->enabled ? 1 : 0) << index);
break;
case PCI_DEVFN(0x13, 0):
case PCI_DEVFN(0x13, 1):
case PCI_DEVFN(0x13, 2):
index = (dev->path.pci.devfn & 3) + 4;
set_sm_enable_bits(sm_dev, 0x68, 1 << index,
(dev->enabled ? 1 : 0) << index);
break;
case PCI_DEVFN(0x14, 5):
index = 7;
set_sm_enable_bits(sm_dev, 0x68, 1 << index,
(dev->enabled ? 1 : 0) << index);
break;
case PCI_DEVFN(0x14, 0):
break;
case PCI_DEVFN(0x14, 1):
break;
case PCI_DEVFN(0x14, 2):
index = 3;
set_pmio_enable_bits(sm_dev, 0x59, 1 << index,
(dev->enabled ? 1 : 0) << index);
break;
case PCI_DEVFN(0x14, 3):
index = 20;
set_sm_enable_bits(sm_dev, 0x64, 1 << index,
(dev->enabled ? 1 : 0) << index);
break;
case PCI_DEVFN(0x14, 4):
break;
default:
printk(BIOS_DEBUG, "unknown dev: %s deviceid=%4x\n", dev_path(dev),
deviceid);
}
}
#if CONFIG(SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
struct chip_operations southbridge_amd_sb700_ops = {
CHIP_NAME("ATI SP5100")
.enable_dev = sb7xx_51xx_enable,
};
#else
struct chip_operations southbridge_amd_sb700_ops = {
CHIP_NAME("ATI SB700")
.enable_dev = sb7xx_51xx_enable,
};
#endif

View File

@@ -1,83 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
*
* 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 SB700_H
#define SB700_H
#include <types.h>
#include <device/device.h>
/* Power management index/data registers */
#define BIOSRAM_INDEX 0xcd4
#define BIOSRAM_DATA 0xcd5
#define PM_INDEX 0xcd6
#define PM_DATA 0xcd7
#define PM2_INDEX 0xcd0
#define PM2_DATA 0xcd1
#define SB700_ACPI_IO_BASE 0x800
#define ACPI_PM_EVT_BLK (SB700_ACPI_IO_BASE + 0x00) /* 4 bytes */
#define ACPI_PM1_CNT_BLK (SB700_ACPI_IO_BASE + 0x04) /* 2 bytes */
#define ACPI_PMA_CNT_BLK (SB700_ACPI_IO_BASE + 0x16) /* 1 byte */
#define ACPI_PM_TMR_BLK (SB700_ACPI_IO_BASE + 0x20) /* 4 bytes */
#define ACPI_GPE0_BLK (SB700_ACPI_IO_BASE + 0x18) /* 8 bytes */
#define ACPI_CPU_CONTROL (SB700_ACPI_IO_BASE + 0x08) /* 6 bytes */
#define ACPI_CPU_P_LVL2 (ACPI_CPU_CONTROL + 0x4) /* 1 byte */
void pm_iowrite(u8 reg, u8 value);
u8 pm_ioread(u8 reg);
void pm2_iowrite(u8 reg, u8 value);
u8 pm2_ioread(u8 reg);
void set_sm_enable_bits(struct device *sm_dev, u32 reg_pos, u32 mask, u32 val);
#define REV_SB700_A11 0x11
#define REV_SB700_A12 0x12
#define REV_SB700_A14 0x14
#define REV_SB700_A15 0x15
/* This shouldn't be called before set_sb700_revision() is called.
* Once set_sb700_revision() is called, we use get_sb700_revision(),
* the simpler one, to get the sb700 revision ID.
* The id is 0x39 if A11, 0x3A if A12, 0x3C if A14, 0x3D if A15.
* The differentiate is 0x28, isn't it? */
#define get_sb700_revision(sm_dev) (pci_read_config8((sm_dev), 0x08) - 0x28)
void sb7xx_51xx_lpc_port80(void);
void sb7xx_51xx_pci_port80(void);
void sb7xx_51xx_lpc_init(void);
void sb7xx_51xx_enable_wideio(u8 wio_index, u16 base);
void sb7xx_51xx_disable_wideio(u8 wio_index);
void sb7xx_51xx_early_setup(void);
void sb7xx_51xx_before_pci_init(void);
uint16_t sb7xx_51xx_decode_last_reset(void);
/* allow override in mainboard.c */
void sb7xx_51xx_setup_sata_phys(struct device *dev);
void sb7xx_51xx_setup_sata_port_indication(void *sata_bar5);
void sb7xx_51xx_enable(struct device *dev);
void set_lpc_sticky_ctl(bool enable);
int s3_save_nvram_early(u32 dword, int size, int nvram_pos);
int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos);
void enable_fid_change_on_sb(u32 sbbusn, u32 sbdn);
#endif /* SB700_H */

View File

@@ -1,542 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
*
* 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 "sb700.h"
#include "smbus.h"
#define NMI_OFF 0
#define SB_MMIO_CFG_REG 0x9c
#define SB_MMIO_BASE_ADDRESS 0xfeb00000
#define PRIMARY_SMBUS_RESOURCE_NUMBER 0x90
#define AUXILIARY_SMBUS_RESOURCE_NUMBER 0x58
uint8_t amd_sb700_aux_smbus = 0;
enum power_mode {
POWER_MODE_OFF = 0,
POWER_MODE_ON = 1,
POWER_MODE_LAST = 2,
};
static const char *power_mode_names[] = {
[POWER_MODE_OFF] = "off",
[POWER_MODE_ON] = "on",
[POWER_MODE_LAST] = "last",
};
/*
* SB700 enables all USB controllers by default in SMBUS Control.
* SB700 enables SATA by default in SMBUS Control.
*/
static void sm_init(struct device *dev)
{
u8 byte;
u8 byte_old;
u8 rev;
u32 dword;
void *ioapic_base;
uint32_t power_state;
uint32_t enable_legacy_usb;
u32 nmi_option;
printk(BIOS_INFO, "sm_init().\n");
rev = get_sb700_revision(dev);
/* This works in a similar fashion to a memory resource, but without an enable bit */
ioapic_base = (void *)(pci_read_config32(dev, 0x74) & (0xffffffe0));
setup_ioapic(ioapic_base, 0); /* Don't rename IOAPIC ID. */
enable_legacy_usb = 1;
get_option(&enable_legacy_usb, "enable_legacy_usb");
/* 2.10 Interrupt Routing/Filtering */
byte = pci_read_config8(dev, 0x62);
if (enable_legacy_usb)
byte |= 0x3;
else
byte &= ~0x3;
pci_write_config8(dev, 0x62, byte);
byte = pci_read_config8(dev, 0x67);
if (enable_legacy_usb)
byte |= 0x1 << 7;
else
byte &= ~(0x1 << 7);
pci_write_config8(dev, 0x67, byte);
/* Delay back to back interrupts to the CPU. */
dword = pci_read_config16(dev, 0x64);
dword |= 1 << 13;
pci_write_config16(dev, 0x64, dword);
/* rrg:K8 INTR Enable (BIOS should set this bit after PIC initialization) */
/* rpr 2.1 Enabling Legacy Interrupt */
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);
/* Sx State Settings
* Note: These 2 registers need to be set correctly for the S-state
* to work properly. Otherwise the system may hang during resume
* from the S-state.
*/
/*Use 8us clock for delays in the S-state resume timing sequence.*/
byte = pm_ioread(0x65);
byte &= ~(1 << 7);
pm_iowrite(0x65, byte);
/* Delay the APIC interrupt to the CPU until the system has fully resumed from the S-state. */
byte = pm_ioread(0x68);
byte |= 1 << 2;
pm_iowrite(0x68, byte);
/* IRQ0From8254 */
byte = pci_read_config8(dev, 0x41);
byte &= ~(1 << 7);
pci_write_config8(dev, 0x41, byte);
byte = pm_ioread(0x61);
if (CONFIG(CPU_AMD_MODEL_10XXX))
byte &= ~(1 << 1); /* Clear for non-K8 CPUs */
else
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 */
power_state = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
get_option(&power_state, "power_on_after_fail");
if (power_state > 2) {
printk(BIOS_WARNING, "Invalid power_on_after_fail setting, using default\n");
power_state = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
}
byte = pm_ioread(0x74);
byte &= ~0x03;
if (power_state == POWER_MODE_OFF)
byte |= 0x0;
else if (power_state == POWER_MODE_ON)
byte |= 0x1;
else if (power_state == POWER_MODE_LAST)
byte |= 0x2;
byte |= 1 << 2;
pm_iowrite(0x74, byte);
printk(BIOS_INFO, "set power \"%s\" after power fail\n", power_mode_names[power_state]);
byte = pm_ioread(0x68);
byte &= ~(1 << 1);
/* 2.7 */
byte |= 1 << 2;
pm_iowrite(0x68, byte);
/* 2.7 */
byte = pm_ioread(0x65);
byte &= ~(1 << 7);
pm_iowrite(0x65, byte);
/* 2.16 */
byte = pm_ioread(0x55);
byte |= 1 << 5;
pm_iowrite(0x55, byte);
byte = pm_ioread(0xD7);
byte |= 1 << 6 | 1 << 1;
pm_iowrite(0xD7, byte);
/* 2.15 */
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);
}
/*rpr v2.13 2.22 SMBUS PCI Config */
byte = pci_read_config8(dev, 0xE1);
if ((REV_SB700_A11 == rev) || REV_SB700_A12 == rev) {
byte |= 1 << 0;
}
/*Set bit2 to 1, enable Io port 60h read/write SMi trapping and
*Io port 64h write Smi trapping. conflict with ps2 keyboard
*/
//byte |= 1 << 2 | 1 << 3 | 1 << 4;
byte |= 1 << 3 | 1 << 4;
pci_write_config8(dev, 0xE1, byte);
/* 2.5 Enabling Non-Posted Memory Write */
axindxc_reg(0x10, 1 << 9, 1 << 9);
/* 2.11 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);
/* 4.3 Enabling Upstream DMA Access */
axcfg_reg(0x04, 1 << 2, 1 << 2);
/* 4.4 Enabling IDE/PCIB Prefetch for Performance Enhancement */
abcfg_reg(0x10060, 9 << 17, 9 << 17);
abcfg_reg(0x10064, 9 << 17, 9 << 17);
/* 4.5 Enabling OHCI Prefetch for Performance Enhancement, A12 */
abcfg_reg(0x80, 1 << 0, 1<< 0);
/* 4.6 B-Link Client's Credit Variable Settings for the Downstream Arbitration Equation */
/* 4.7 Enabling Additional Address Bits Checking in Downstream */
/* 4.16 IO write and SMI ordering enhancement*/
abcfg_reg(0x9c, 3 << 0, 3 << 0);
if (REV_SB700_A12 == rev) {
abcfg_reg(0x9c, 1 << 8, 1 << 8);
} else if (rev >= REV_SB700_A14) {
abcfg_reg(0x9c, 1 << 8, 0 << 8);
}
if (REV_SB700_A15 == rev) {
abcfg_reg(0x90, 1 << 21, 1 << 21);
abcfg_reg(0x9c, 1 << 5 | 1 << 9 | 1 << 15, 1 << 5 | 1 << 9 | 1 << 15);
}
/* 4.8 Set B-Link Prefetch Mode */
abcfg_reg(0x80, 3 << 17, 3 << 17);
/* 4.9 Enabling Detection of Upstream Interrupts */
abcfg_reg(0x94, 1 << 20 | 0x7FFFF, 1 << 20 | 0x00FEE);
/* 4.10: Enabling Downstream Posted Transactions to Pass Non-Posted
* Transactions for the K8 Platform (for All Revisions) */
abcfg_reg(0x10090, 1 << 8, 1 << 8);
/* Set ACPI Software clock Throttling Period to 244 us*/
byte = pm_ioread(0x68);
byte &= ~(3 << 6);
byte |= (2 << 6); /* 244us */
pm_iowrite(0x68, byte);
if (REV_SB700_A15 == rev) {
u16 word;
/* rpr v2.13 4.18 Enabling Posted Pass Non-Posted Downstream */
axindxc_reg(0x02, 1 << 9, 1 << 9);
abcfg_reg(0x9C, 0x00007CC0, 0x00007CC0);
abcfg_reg(0x1009C, 0x00000030, 0x00000030);
abcfg_reg(0x10090, 0x00001E00, 0x00001E00);
/* rpr v2.13 4.19 Enabling Posted Pass Non-Posted Upstream */
abcfg_reg(0x58, 0x0000F800, 0x0000E800);
/* rpr v2.13 4.20 64 bit Non-Posted Memory Write Support */
axindxc_reg(0x02, 1 << 10, 1 << 10);
/* rpr v2.13 2.38 Unconditional Shutdown */
byte = pci_read_config8(dev, 0x43);
byte &= ~(1 << 3);
pci_write_config8(dev, 0x43, byte);
word = pci_read_config16(dev, 0x38);
word |= 1 << 12;
pci_write_config16(dev, 0x38, word);
byte |= 1 << 3;
pci_write_config8(dev, 0x43, byte);
/* Enable southbridge MMIO decode */
dword = pci_read_config32(dev, SB_MMIO_CFG_REG);
dword &= ~(0xffffff << 8);
dword |= SB_MMIO_BASE_ADDRESS;
dword |= 0x1;
pci_write_config32(dev, SB_MMIO_CFG_REG, dword);
}
byte = pci_read_config8(dev, 0xAE);
if (CONFIG(ENABLE_APIC_EXT_ID))
byte |= 1 << 4;
byte |= 1 << 5; /* ACPI_DISABLE_TIMER_IRQ_ENHANCEMENT_FOR_8254_TIMER */
byte |= 1 << 6; /* Enable arbiter between APIC and PIC interrupts */
pci_write_config8(dev, 0xAE, byte);
/* 4.11:Programming Cycle Delay for AB and BIF Clock Gating */
/* 4.12: Enabling AB and BIF Clock Gating */
abcfg_reg(0x10054, 0xFFFF0000, 0x1040000);
abcfg_reg(0x54, 0xFF << 16, 4 << 16);
abcfg_reg(0x54, 1 << 24, 0 << 24);
abcfg_reg(0x98, 0x0000FF00, 0x00004700);
/* 4.13:Enabling AB Int_Arbiter Enhancement (for All Revisions) */
abcfg_reg(0x10054, 0x0000FFFF, 0x07FF);
/* 4.14:Enabling Requester ID for upstream traffic. */
abcfg_reg(0x98, 1 << 16, 1 << 16);
/* 9.2: Enabling IDE Data Bus DD7 Pull Down Resistor */
byte = pm2_ioread(0xE5);
byte |= 1 << 2;
pm2_iowrite(0xE5, byte);
/* Enable IDE controller. */
byte = pm_ioread(0x59);
byte &= ~(1 << 1);
pm_iowrite(0x59, byte);
/* Enable SCI as irq9. */
outb(0x4, 0xC00);
outb(0x9, 0xC01);
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);
if (!amd_sb700_aux_smbus)
res = find_resource(pbus->dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
else
res = find_resource(pbus->dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
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);
if (!amd_sb700_aux_smbus)
res = find_resource(pbus->dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
else
res = find_resource(pbus->dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
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);
if (!amd_sb700_aux_smbus)
res = find_resource(pbus->dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
else
res = find_resource(pbus->dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
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);
if (!amd_sb700_aux_smbus)
res = find_resource(pbus->dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
else
res = find_resource(pbus->dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
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 sb700_sm_read_resources(struct device *dev)
{
struct resource *res;
/* Get the normal pci resources of this device */
pci_dev_read_resources(dev);
/* 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 | IORESOURCE_RESERVE | IORESOURCE_ASSIGNED;
/* SB MMIO / WDT */
res = new_resource(dev, SB_MMIO_CFG_REG);
res->base = SB_MMIO_BASE_ADDRESS;
res->size = 0x1000;
res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */
res->align = 8;
res->gran = 8;
res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_RESERVE | IORESOURCE_ASSIGNED;
/* HPET */
res = new_resource(dev, 0xB4); /* TODO: test hpet */
res->base = 0xfed00000; /* reset hpet to widely accepted address */
res->size = 0x400;
res->limit = 0xFFFFFFFFUL; /* res->base + res->size -1; */
res->align = 8;
res->gran = 8;
res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_RESERVE | IORESOURCE_ASSIGNED;
/* dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; */
/* primary smbus */
res = new_resource(dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
res->base = SMBUS_IO_BASE;
res->size = 0x10;
res->limit = 0xFFFFUL; /* res->base + res->size -1; */
res->align = 8;
res->gran = 8;
res->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_RESERVE | IORESOURCE_ASSIGNED;
/* auxiliary smbus */
res = new_resource(dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
res->base = SMBUS_AUX_IO_BASE;
res->size = 0x10;
res->limit = 0xFFFFUL; /* res->base + res->size -1; */
res->align = 8;
res->gran = 8;
res->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_RESERVE | IORESOURCE_ASSIGNED;
compact_resources(dev);
}
static void sb700_sm_set_resources(struct device *dev)
{
struct resource *res;
u8 byte;
pci_dev_set_resources(dev);
res = find_resource(dev, 0x74);
pci_write_config32(dev, 0x74, res->base | 1 << 3);
/* TODO: test hpet */
#if 0 //rrg-2.0.3 shows BAR1 not used
/* Make SMBUS BAR1(HPET base at offset 14h) visible */
byte = pci_read_config8(dev, 0x43);
byte &= ~(1 << 3);
pci_write_config8(dev, 0x43, byte);
#endif
res = find_resource(dev, 0xB4);
/* Program HPET BAR Address */
pci_write_config32(dev, 0xB4, res->base);
/* Enable decoding of HPET MMIO, enable HPET MSI */
byte = pci_read_config8(dev, 0x43);
//byte |= (1 << 3); // Make SMBus Bar1 invisible
//byte |= ((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7));
byte |= (1 << 4);
pci_write_config8(dev, 0x43, byte);
/* Enable HPET irq */
byte = pci_read_config8(dev, 0x65);
byte |= (1 << 2);
pci_write_config8(dev, 0x65, byte);
/* TODO: End of test hpet */
res = find_resource(dev, PRIMARY_SMBUS_RESOURCE_NUMBER);
pci_write_config32(dev, PRIMARY_SMBUS_RESOURCE_NUMBER, res->base | 1);
res = find_resource(dev, AUXILIARY_SMBUS_RESOURCE_NUMBER);
pci_write_config32(dev, AUXILIARY_SMBUS_RESOURCE_NUMBER, res->base | 1);
}
static struct pci_operations lops_pci = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations smbus_ops = {
.read_resources = sb700_sm_read_resources,
.set_resources = sb700_sm_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = sm_init,
.scan_bus = scan_smbus,
.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_SB700_SM,
};

View File

@@ -1,231 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _SB700_SMBUS_C_
#define _SB700_SMBUS_C_
#include <arch/io.h>
#include "smbus.h"
extern uint8_t amd_sb700_aux_smbus;
void smbus_switch_to_channel(uint8_t channel_number);
uint8_t smbus_get_current_channel(void);
void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val)
{
u32 tmp;
outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX);
tmp = inl(AB_DATA);
/* rpr 4.2
* For certain revisions of the chip, the ABCFG registers,
* with an address of 0x100NN (where 'N' is any hexadecimal
* number), require an extra programming step.*/
reg_addr & 0x10000 ? outl(0, AB_INDX) : NULL;
tmp &= ~mask;
tmp |= val;
/* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<30 | reg_addr); */
outl((reg_space & 0x3) << 30 | reg_addr, AB_INDX); /* probably we don't have to do it again. */
outl(tmp, AB_DATA);
reg_addr & 0x10000 ? outl(0, AB_INDX) : NULL;
}
/* space = 0: AX_INDXC, AX_DATAC
* space = 1: AX_INDXP, AX_DATAP
*/
void alink_ax_indx(u32 space, u32 axindc, u32 mask, u32 val)
{
u32 tmp;
/* read axindc to tmp */
outl(space << 30 | space << 3 | 0x30, AB_INDX);
outl(axindc, AB_DATA);
outl(space << 30 | space << 3 | 0x34, AB_INDX);
tmp = inl(AB_DATA);
tmp &= ~mask;
tmp |= val;
/* write tmp */
outl(space << 30 | space << 3 | 0x30, AB_INDX);
outl(axindc, AB_DATA);
outl(space << 30 | space << 3 | 0x34, AB_INDX);
outl(tmp, AB_DATA);
}
static 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;
}
void smbus_switch_to_channel(uint8_t channel_number)
{
amd_sb700_aux_smbus = !!channel_number;
}
uint8_t smbus_get_current_channel(void)
{
return amd_sb700_aux_smbus;
}
#endif

View File

@@ -1,70 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
*
* 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 SB700_SMBUS_H
#define SB700_SMBUS_H
#include <stdint.h>
#include "stddef.h"
#define SMBUS_IO_BASE 0xb00
#define SMBUS_AUX_IO_BASE 0xb20
#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 SMBSLVMISC 0xd
#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))
void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val);
void alink_ax_indx(u32 space, u32 axindc, u32 mask, u32 val);
int do_smbus_recv_byte(u32 smbus_io_base, u32 device);
int do_smbus_send_byte(u32 smbus_io_base, u32 device, u8 val);
int do_smbus_read_byte(u32 smbus_io_base, u32 device, u32 address);
int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address, u8 val);
#endif

View File

@@ -1,129 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
* Copyright (C) 2012 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 <device/mmio.h>
#include <console/console.h>
#include <spi-generic.h>
#include <spi_flash.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <types.h>
#define AMD_SB_SPI_TX_LEN 8
static uint32_t get_spi_bar(void)
{
struct device *dev;
dev = pcidev_on_root(0x14, 3);
return pci_read_config32(dev, 0xa0) & ~0x1f;
}
static void reset_internal_fifo_pointer(void)
{
uint32_t spibar = get_spi_bar();
do {
write8((void *)(spibar + 2),
read8((void *)(spibar + 2)) | 0x10);
} while (read8((void *)(spibar + 0xd)) & 0x7);
}
static void execute_command(void)
{
uint32_t spibar = get_spi_bar();
write8((void *)(spibar + 2), read8((void *)(spibar + 2)) | 1);
while ((read8((void *)(spibar + 2)) & 1) &&
(read8((void *)(spibar+3)) & 0x80));
}
static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
size_t bytesout, void *din, size_t bytesin)
{
/* First byte is cmd which cannot be sent through the FIFO. */
u8 cmd = *(u8 *)dout++;
u8 readoffby1;
u8 readwrite;
size_t count;
uint32_t spibar = get_spi_bar();
bytesout--;
/*
* Check if this is a write command attempting to transfer more bytes
* than the controller can handle. Iterations for writes are not
* supported here because each SPI write command needs to be preceded
* and followed by other SPI commands, and this sequence is controlled
* by the SPI chip driver.
*/
if (bytesout > AMD_SB_SPI_TX_LEN) {
printk(BIOS_DEBUG, "FCH SPI: Too much to write. Does your SPI chip driver use"
" spi_crop_chunk()?\n");
return -1;
}
readoffby1 = bytesout ? 0 : 1;
readwrite = (bytesin + readoffby1) << 4 | bytesout;
write8((void *)(spibar + 1), readwrite);
write8((void *)(spibar + 0), cmd);
reset_internal_fifo_pointer();
for (count = 0; count < bytesout; count++, dout++) {
write8((void *)(spibar + 0x0C), *(u8 *)dout);
}
reset_internal_fifo_pointer();
execute_command();
reset_internal_fifo_pointer();
/* Skip the bytes we sent. */
for (count = 0; count < bytesout; count++) {
cmd = read8((void *)(spibar + 0x0C));
}
/* read response bytes */
for (count = 0; count < bytesin; count++, din++) {
*(u8 *)din = read8((void *)(spibar + 0x0C));
}
return 0;
}
static int xfer_vectors(const struct spi_slave *slave,
struct spi_op vectors[], size_t count)
{
return spi_flash_vector_helper(slave, vectors, count, spi_ctrlr_xfer);
}
static const struct spi_ctrlr spi_ctrlr = {
.xfer_vector = xfer_vectors,
.max_xfer_size = AMD_SB_SPI_TX_LEN,
.flags = SPI_CNTRLR_DEDUCT_CMD_LEN,
};
const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
{
.ctrlr = &spi_ctrlr,
.bus_start = 0,
.bus_end = 0,
},
};
const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);

View File

@@ -1,17 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
*
* 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.
*/
int spi_claim_bus(const struct spi_slave *slave);
void spi_release_bus(const struct spi_slave *slave);

View File

@@ -1,257 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2010 Advanced Micro Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#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 <device/mmio.h>
#include <option.h>
#include <types.h>
#include "sb700.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;
/* 6.1 Enable OHCI0-4 and EHCI Controllers */
struct device *sm_dev;
sm_dev = pcidev_on_root(0x14, 0);
byte = pci_read_config8(sm_dev, 0x68);
byte |= 0xFF;
pci_write_config8(sm_dev, 0x68, byte);
/* RPR 6.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 6.3 Support USB device wakeup from the S4/S5 state */
byte = pm_ioread(0x65);
byte &= ~(1 << 0);
pm_iowrite(0x65, byte);
/* RPR 6.5 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);
/* USB_ADVANCED_SLEEP_CONTROL */
byte = pm_ioread(0x95);
byte &= ~(7 << 0);
byte |= 6 << 0; /* Advanced sleep up to 6 uframes */
pm_iowrite(0x95, byte);
/* RPR 6.10 Disable OHCI MSI Capability. */
word = pci_read_config16(dev, 0x40);
word |= (0x3 << 8);
pci_write_config16(dev, 0x40, word);
/* USB-1_OHCI0_Corner Case S3 Wake Up */
dword = pci_read_config32(dev, 0x50);
dword |= (1 << 16);
pci_write_config32(dev, 0x50, dword);
}
static void usb_init2(struct device *dev)
{
uint32_t dword;
void *usb2_bar0;
struct device *sm_dev;
uint8_t rev;
uint8_t ehci_async_data_cache;
uint8_t nvram;
ehci_async_data_cache = 1;
if (get_option(&nvram, "ehci_async_data_cache") == CB_SUCCESS)
ehci_async_data_cache = !!nvram;
sm_dev = pcidev_on_root(0x14, 0);
rev = get_sb700_revision(sm_dev);
/* 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);
/* RPR6.4 Enables the USB PHY auto calibration resister to match 45ohm resistance */
dword = 0x00020F00;
write32(usb2_bar0 + 0xC0, dword);
/* RPR6.9 Sets In/OUT FIFO threshold for best performance */
dword = 0x00400040;
write32(usb2_bar0 + 0xA4, dword);
/* RPR6.11 Disabling EHCI Advance Asynchronous Enhancement */
dword = pci_read_config32(dev, 0x50);
dword |= (1 << 28);
pci_write_config32(dev, 0x50, dword);
/* RPR 6.12 EHCI Advance PHY Power Savings */
/* RPR says it is just for A12. CIMM sets it when it is above A11. */
/* But it makes the linux crash, so we skip it */
dword = pci_read_config32(dev, 0x50);
dword |= 1 << 31;
pci_write_config32(dev, 0x50, dword);
/* RPR6.13 Enabling Fix for EHCI Controller Driver Yellow Sign Issue */
/* RPR says it is just for A12. CIMx sets it when it is above A11. */
dword = pci_read_config32(dev, 0x50);
dword |= (1 << 20);
pci_write_config32(dev, 0x50, dword);
/* RPR6.15 EHCI Async Park Mode */
dword = pci_read_config32(dev, 0x50);
dword |= (1 << 23);
pci_write_config32(dev, 0x50, dword);
/* Each step below causes the linux crashes. Leave them here
* for future debugging. */
u8 byte;
u16 word;
/* RPR6.16 Disable EHCI MSI support */
byte = pci_read_config8(dev, 0x50);
byte |= (1 << 6);
pci_write_config8(dev, 0x50, byte);
/* RPR6.17 Disable the EHCI Dynamic Power Saving feature */
word = read32(usb2_bar0 + 0xBC);
word &= ~(1 << 12);
write16(usb2_bar0 + 0xBC, word);
/* RPR6.19 USB Controller DMA Read Delay Tolerant. */
if (rev >= REV_SB700_A14) {
byte = pci_read_config8(dev, 0x50);
byte |= (1 << 7);
pci_write_config8(dev, 0x50, byte);
}
/* SB700_A15, USB-2_EHCI_PID_ERROR_CHECKING */
if (rev == REV_SB700_A15) {
word = pci_read_config16(dev, 0x50);
word |= (1 << 9);
pci_write_config16(dev, 0x50, word);
}
/* RPR6.20 Async Park Mode. */
/* RPR recommends not to set these bits. */
#if 0
dword = pci_read_config32(dev, 0x50);
dword |= 1 << 23;
if (rev >= REV_SB700_A14) {
dword &= ~(1 << 2);
}
pci_write_config32(dev, 0x50, dword);
#endif
/* RPR6.22 Advance Async Enhancement */
/* RPR6.23 USB Periodic Cache Setting */
dword = pci_read_config32(dev, 0x50);
if (rev == REV_SB700_A12) {
dword |= 1 << 28; /* 6.22 */
dword |= 1 << 27; /* 6.23 */
} else if (rev >= REV_SB700_A14) {
dword |= 1 << 3;
dword &= ~(1 << 28); /* 6.22 */
dword |= 1 << 8;
dword &= ~(1 << 27); /* 6.23 */
}
#if CONFIG(SOUTHBRIDGE_AMD_SUBTYPE_SP5100)
/* SP5100 Erratum 36 */
dword &= ~(1 << 26);
if (!ehci_async_data_cache)
dword |= 1 << 26;
#endif
pci_write_config32(dev, 0x50, dword);
printk(BIOS_DEBUG, "rpr 6.23, final dword=%x\n", dword);
}
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,
.scan_bus = 0,
.ops_pci = &lops_pci,
};
static const struct pci_driver usb_0_driver __pci_driver = {
.ops = &usb_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB700_USB_18_0,
};
static const struct pci_driver usb_1_driver __pci_driver = {
.ops = &usb_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB700_USB_18_1,
};
/* the pci id of usb ctrl 0 and 1 are the same. */
/*
* static const struct pci_driver usb_3_driver __pci_driver = {
* .ops = &usb_ops,
* .vendor = PCI_VENDOR_ID_ATI,
* .device = PCI_DEVICE_ID_ATI_SB700_USB_19_0,
* };
* static const struct pci_driver usb_4_driver __pci_driver = {
* .ops = &usb_ops,
* .vendor = PCI_VENDOR_ID_ATI,
* .device = PCI_DEVICE_ID_ATI_SB700_USB_19_1,
* };
*/
static const struct pci_driver usb_4_driver __pci_driver = {
.ops = &usb_ops,
.vendor = PCI_VENDOR_ID_ATI,
.device = PCI_DEVICE_ID_ATI_SB700_USB_20_5,
};
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,
.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_SB700_USB_18_2,
};
/*
* static const struct pci_driver usb_5_driver __pci_driver = {
* .ops = &usb_ops2,
* .vendor = PCI_VENDOR_ID_ATI,
* .device = PCI_DEVICE_ID_ATI_SB700_USB_19_2,
* };
*/