blob: 0514719344819a45adebb7c7db2e64f676308a25 [file] [log] [blame]
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2012 secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <arch/io.h>
#include <device/pci_def.h>
#include <console/console.h>
#include <northbridge/intel/gm45/gm45.h>
#include "i82801ix.h"
/* VC1 Port Arbitration Table */
static const u8 vc1_pat[] = {
0x0f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00,
0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f,
0x00, 0x00, 0x00, 0x00,
0x00, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00,
0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f,
0x00, 0x00, 0x00, 0x00,
0x00, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
void i82801ix_dmi_setup(void)
{
int i;
u32 reg32;
RCBA32(RCBA_V1CAP) = (RCBA32(RCBA_V1CAP) & ~(0x7f<<16)) | (0x12<<16);
RCBA32(0x0088) = 0x00109000;
RCBA16(0x01fc) = 0x060b;
RCBA32(0x01f4) = 0x86000040;
RCBA8 (0x0220) = 0x45;
RCBA32(0x2024) &= ~(1 << 7);
/* VC1 setup for isochronous transfers: */
/* Set VC1 virtual channel id to 1. */
RCBA32(RCBA_V1CTL) = (RCBA32(RCBA_V1CTL) & ~(0x7 << 24)) | (0x1 << 24);
/* Enable TC7 traffic on VC1. */
RCBA32(RCBA_V1CTL) = (RCBA32(RCBA_V1CTL) & ~(0x7f << 1)) | (1 << 7);
/* Disable TC7-TC1 traffic on VC0. */
RCBA32(RCBA_V0CTL) &= ~(0x7f << 1);
/* TC7-TC1 traffic on PCIe root ports will be disabled in pci driver. */
/* Set table type to time-based WRR. */
RCBA32(RCBA_V1CTL) = (RCBA32(RCBA_V1CTL) & ~(0x7 << 17)) | (0x4 << 17);
/* Program port arbitration table. */
for (i = 0; i < sizeof(vc1_pat); ++i)
RCBA8(RCBA_PAT + i) = vc1_pat[i];
/* Load port arbitration table. */
RCBA32(RCBA_V1CTL) |= (1 << 16);
/* Enable VC1. */
RCBA32(RCBA_V1CTL) |= (1 << 31);
/* Setup RCRB: */
/* Set component id to 2 for southbridge, northbridge has id 1. */
RCBA8(RCBA_ESD + 2) = 2;
/* Set target port number and target component id of the northbridge. */
RCBA8(RCBA_ULD + 3) = 1;
RCBA8(RCBA_ULD + 2) = 1;
/* Set target rcrb base address, i.e. DMIBAR. */
RCBA32(RCBA_ULBA) = DEFAULT_DMIBAR;
/* Enable ASPM. */
if (LPC_IS_MOBILE(PCI_DEV(0, 0x1f, 0))) {
reg32 = RCBA32(RCBA_DMC);
/* Enable mobile specific power saving (set this first). */
reg32 = (reg32 & ~(3 << 10)) | (1 << 10);
RCBA32(RCBA_DMC) = reg32;
/* Enable DMI power savings. */
reg32 |= (1 << 19);
RCBA32(RCBA_DMC) = reg32;
/* Advertise L0s and L1. */
RCBA32(RCBA_LCAP) |= (3 << 10);
/* Enable L0s and L1. */
RCBA32(RCBA_LCTL) |= (3 << 0);
} else {
/* Enable DMI power savings. */
RCBA32(RCBA_DMC) |= (1 << 19);
/* Advertise L0s only. */
RCBA32(RCBA_LCAP) = (RCBA32(RCBA_LCAP) & ~(3<<10)) | (1<<10);
/* Enable L0s only. */
RCBA32(RCBA_LCTL) = (RCBA32(RCBA_LCTL) & ~(3<< 0)) | (1<< 0);
}
}
/* Should be called after VC1 has been enabled on both sides. */
void i82801ix_dmi_poll_vc1(void)
{
int timeout;
timeout = 0x7ffff;
printk(BIOS_DEBUG, "ICH9 waits for VC1 negotiation... ");
while ((RCBA32(RCBA_V1STS) & (1 << 1)) && --timeout) {}
if (!timeout)
printk(BIOS_DEBUG, "timeout!\n");
else
printk(BIOS_DEBUG, "done.\n");
/* Check for x2 DMI link. */
if (((RCBA16(RCBA_LSTS) >> 4) & 0x3f) == 2) {
printk(BIOS_DEBUG, "x2 DMI link detected.\n");
RCBA32(0x2024) = (RCBA32(0x2024) & ~(7 << 21)) | (3 << 21);
RCBA16(0x20c4) |= (1 << 15);
RCBA16(0x20e4) |= (1 << 15);
/* TODO: Maybe we have to save and
restore these settings across S3. */
}
timeout = 0x7ffff;
printk(BIOS_DEBUG, "ICH9 waits for port arbitration table update... ");
while ((RCBA32(RCBA_V1STS) & (1 << 0)) && --timeout) {}
if (!timeout)
printk(BIOS_DEBUG, "timeout!\n");
else
printk(BIOS_DEBUG, "done.\n");
}