northbridge/intel/pineview: Add remaining boilerplate code for northbridge

This patch does *not* include native raminit

Change-Id: I3fb8146ef7fe2ad27c167ecd2fb0fd629f051cc1
Signed-off-by: Damien Zammit <damien@zamaudio.com>
Reviewed-on: https://review.coreboot.org/12430
Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Tested-by: build bot (Jenkins)
This commit is contained in:
Damien Zammit 2015-11-14 00:59:21 +11:00 committed by Stefan Reinauer
parent 1a38374535
commit f7060f1d0f
11 changed files with 933 additions and 63 deletions

View File

@ -25,8 +25,7 @@ config NORTHBRIDGE_SPECIFIC_OPTIONS # dummy
select MMCONF_SUPPORT_DEFAULT select MMCONF_SUPPORT_DEFAULT
select HAVE_DEBUG_RAM_SETUP select HAVE_DEBUG_RAM_SETUP
select LAPIC_MONOTONIC_TIMER select LAPIC_MONOTONIC_TIMER
select VGA select LATE_CBMEM_INIT
select PER_DEVICE_ACPI_TABLES
config BOOTBLOCK_NORTHBRIDGE_INIT config BOOTBLOCK_NORTHBRIDGE_INIT
string string

View File

@ -17,8 +17,10 @@
ifeq ($(CONFIG_NORTHBRIDGE_INTEL_PINEVIEW),y) ifeq ($(CONFIG_NORTHBRIDGE_INTEL_PINEVIEW),y)
ramstage-y += ram_calc.c ramstage-y += ram_calc.c
ramstage-y += northbridge.c
ramstage-y += acpi.c ramstage-y += acpi.c
romstage-y += ram_calc.c romstage-y += ram_calc.c
romstage-y += early_init.c
endif endif

View File

@ -24,42 +24,14 @@
unsigned long acpi_fill_mcfg(unsigned long current) unsigned long acpi_fill_mcfg(unsigned long current)
{ {
device_t dev; u32 length = 0;
u32 pciexbar = 0; u32 pciexbar = 0;
u32 pciexbar_reg;
u32 reg32;
int max_buses; int max_buses;
const struct {
u16 num_buses;
u32 addr_mask;
} busmask[] = {
{256, 0xff000000},
{128, 0xf8000000},
{64, 0xfc000000},
{0, 0},
};
dev = dev_find_slot(0, PCI_DEVFN(0,0)); if (!decode_pciebar(&pciexbar, &length))
if (!dev)
return current; return current;
pciexbar_reg = pci_read_config32(dev, PCIEXBAR); max_buses = length >> 20;
// MMCFG not supported or not enabled.
if (!(pciexbar_reg & (1 << 0))) {
printk(BIOS_WARNING, "WARNING: MMCONF not set\n");
return current;
}
reg32 = (pciexbar_reg >> 1) & 3;
pciexbar = pciexbar_reg & busmask[reg32].addr_mask;
max_buses = busmask[reg32].num_buses;
if (!pciexbar) {
printk(BIOS_WARNING, "WARNING: pciexbar invalid\n");
return current;
}
current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current,
pciexbar, 0x0, 0x0, max_buses - 1); pciexbar, 0x0, 0x0, max_buses - 1);

View File

@ -0,0 +1,235 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <arch/ioapic.h>
Name(_HID,EISAID("PNP0A08")) // PCIe
Name(_CID,EISAID("PNP0A03")) // PCI
Name(_ADR, 0)
Name(_BBN, 0)
Device (MCHC)
{
Name(_ADR, 0x00000000) /* 0:0.0 */
OperationRegion(MCHP, PCI_Config, 0x00, 0x100)
Field (MCHP, DWordAcc, NoLock, Preserve)
{
Offset (0x40), /* EPBAR */
EPEN, 1, /* Enable */
, 11,
EPBR, 24, /* EPBAR */
Offset (0x48), /* MCHBAR */
MHEN, 1, /* Enable */
, 13,
MHBR, 22, /* MCHBAR */
Offset (0x60), /* PCIec BAR */
PXEN, 1, /* Enable */
PXSZ, 2, /* BAR size */
, 23,
PXBR, 10, /* PCIec BAR */
Offset (0x68), /* DMIBAR */
DMEN, 1, /* Enable */
, 11, /*
DMBR, 20, /* DMIBAR */
// ...
Offset (0x90), /* PAM0 */
, 4,
PM0H, 2,
, 2,
Offset (0x91), /* PAM1 */
PM1L, 2,
, 2,
PM1H, 2,
, 2,
Offset (0x92), /* PAM2 */
PM2L, 2,
, 2,
PM2H, 2,
, 2,
Offset (0x93), /* PAM3 */
PM3L, 2,
, 2,
PM3H, 2,
, 2,
Offset (0x94), /* PAM4 */
PM4L, 2,
, 2,
PM4H, 2,
, 2,
Offset (0x95), /* PAM5 */
PM5L, 2,
, 2,
PM5H, 2,
, 2,
Offset (0x96), /* PAM6 */
PM6L, 2,
, 2,
PM6H, 2,
, 2,
Offset (0xa0), /* Top of Memory */
TOM, 8,
Offset (0xb0), /* Top of Low Used Memory */
, 4,
TLUD, 12,
}
}
/* Current Resource Settings */
Name (MCRS, ResourceTemplate()
{
/* Bus Numbers */
WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
0x0000, 0x0000, 0x00ff, 0x0000, 0x0100,,, PB00)
/* IO Region 0 */
DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,, PI00)
/* PCI Config Space */
Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008)
/* IO Region 1 */
DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, 0x0d00, 0xffff, 0x0000, 0xf300,,, PI01)
/* VGA memory (0xa0000-0xbffff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000a0000, 0x000bffff, 0x00000000,
0x00020000,,, ASEG)
/* OPROM reserved (0xc0000-0xc3fff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000c0000, 0x000c3fff, 0x00000000,
0x00004000,,, OPR0)
/* OPROM reserved (0xc4000-0xc7fff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000c4000, 0x000c7fff, 0x00000000,
0x00004000,,, OPR1)
/* OPROM reserved (0xc8000-0xcbfff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000c8000, 0x000cbfff, 0x00000000,
0x00004000,,, OPR2)
/* OPROM reserved (0xcc000-0xcffff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000cc000, 0x000cffff, 0x00000000,
0x00004000,,, OPR3)
/* OPROM reserved (0xd0000-0xd3fff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000d0000, 0x000d3fff, 0x00000000,
0x00004000,,, OPR4)
/* OPROM reserved (0xd4000-0xd7fff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000d4000, 0x000d7fff, 0x00000000,
0x00004000,,, OPR5)
/* OPROM reserved (0xd8000-0xdbfff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000d8000, 0x000dbfff, 0x00000000,
0x00004000,,, OPR6)
/* OPROM reserved (0xdc000-0xdffff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000dc000, 0x000dffff, 0x00000000,
0x00004000,,, OPR7)
/* BIOS Extension (0xe0000-0xe3fff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000e0000, 0x000e3fff, 0x00000000,
0x00004000,,, ESG0)
/* BIOS Extension (0xe4000-0xe7fff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000e4000, 0x000e7fff, 0x00000000,
0x00004000,,, ESG1)
/* BIOS Extension (0xe8000-0xebfff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000e8000, 0x000ebfff, 0x00000000,
0x00004000,,, ESG2)
/* BIOS Extension (0xec000-0xeffff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000ec000, 0x000effff, 0x00000000,
0x00004000,,, ESG3)
/* System BIOS (0xf0000-0xfffff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x000f0000, 0x000fffff, 0x00000000,
0x00010000,,, FSEG)
/* PCI Memory Region (Top of memory-0xfebfffff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0x00000000, 0xfebfffff, 0x00000000,
IO_APIC_ADDR,,, PM01)
/* TPM Area (0xfed40000-0xfed44fff) */
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, 0xfed40000, 0xfed44fff, 0x00000000,
0x00005000,,, TPMR)
})
Method (_CRS, 0, Serialized)
{
/* Find PCI resource area in MCRS */
CreateDwordField(MCRS, ^PM01._MIN, PMIN)
CreateDwordField(MCRS, ^PM01._MAX, PMAX)
CreateDwordField(MCRS, ^PM01._LEN, PLEN)
/* Fix up PCI memory region:
* Enter actual TOLUD. The TOLUD register contains bits 27-31 of
* the top of memory address.
*/
ShiftLeft (^MCHC.TLUD, 27, PMIN)
Add(Subtract(PMAX, PMIN), 1, PLEN)
Return (MCRS)
}
/* IRQ assignment is mainboard specific. Get it from mainboard ACPI code */
#include "acpi/pineview_pci_irqs.asl"

View File

@ -0,0 +1,41 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
Device (PEGP)
{
Name (_ADR, 0x00010000)
// PCI Interrupt Routing.
Method (_PRT)
{
If (PICM) {
Return (Package() {
Package() { 0x0000ffff, 0, 0, 16 },
Package() { 0x0000ffff, 1, 0, 17 },
Package() { 0x0000ffff, 2, 0, 18 },
Package() { 0x0000ffff, 3, 0, 19 }
})
} Else {
Return (Package() {
Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKB, 0 },
Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKC, 0 },
Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }
})
}
}
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "hostbridge.asl"
#include "../iomap.h"
#include <southbridge/intel/i82801gx/i82801gx.h>
/* PCI Device Resource Consumption */
Device (PDRC)
{
Name (_HID, EISAID("PNP0C02"))
Name (_UID, 1)
/* This does not seem to work correctly yet - set values statically for
* now.
*/
Name (PDRS, ResourceTemplate() {
Memory32Fixed(ReadWrite, 0xfed1c000, 0x00004000) /* RCBA */
Memory32Fixed(ReadWrite, DEFAULT_MCHBAR, 0x00004000)
Memory32Fixed(ReadWrite, DEFAULT_DMIBAR, 0x00001000)
Memory32Fixed(ReadWrite, DEFAULT_EPBAR, 0x00001000)
Memory32Fixed(ReadWrite, DEFAULT_PCIEXBAR, 0x04000000)
Memory32Fixed(ReadWrite, 0xfed20000, 0x00020000) /* Misc ICH */
Memory32Fixed(ReadWrite, 0xfed40000, 0x00005000) /* Misc ICH */
Memory32Fixed(ReadWrite, 0xfed45000, 0x0004b000) /* Misc ICH */
})
/* Current Resource Settings */
Method (_CRS, 0, Serialized)
{
Return(PDRS)
}
}
// PCIe graphics port 0:1.0
#include "peg.asl"

View File

@ -0,0 +1,8 @@
#include <drivers/intel/gma/i915.h>
struct northbridge_intel_pineview_config {
u32 gpu_hotplug;
u32 gpu_backlight;
int gpu_lvds_use_spread_spectrum_clock;
struct i915_gpu_controller_info gfx;
};

View File

@ -0,0 +1,166 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2015 Damien Zammit <damien@zamaudio.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdint.h>
#include <stdlib.h>
#include <console/console.h>
#include <arch/io.h>
#include <device/pci_def.h>
#include <cbmem.h>
#include <halt.h>
#include <string.h>
#include <northbridge/intel/pineview/pineview.h>
#define LPC PCI_DEV(0, 0x1f, 0)
#define D0F0 PCI_DEV(0, 0, 0)
static void pineview_setup_bars(void)
{
u8 reg8;
u16 reg16;
u32 reg32;
/* Setting up Southbridge. In the northbridge code. */
printk(BIOS_DEBUG, "Setting up static southbridge registers...");
pci_write_config32(LPC, RCBA, (uintptr_t)DEFAULT_RCBA | 1);
pci_write_config32(LPC, PMBASE, DEFAULT_PMBASE | 1);
pci_write_config8(LPC, 0x44 /* ACPI_CNTL */ , 0x80); /* Enable ACPI */
pci_write_config32(LPC, GPIOBASE, DEFAULT_GPIOBASE | 1);
pci_write_config8(LPC, 0x4c /* GC */ , 0x10); /* Enable GPIOs */
pci_write_config32(LPC, 0x88, 0x007c0291);
pci_write_config32(PCI_DEV(0, 0x1e, 0), 0x1b, 0x20);
printk(BIOS_DEBUG, " done.\n");
printk(BIOS_DEBUG, "Disabling Watchdog reboot...");
RCBA32(GCS) = RCBA32(GCS) | (1 << 5); /* No reset */
outw((1 << 11), DEFAULT_PMBASE | 0x60 | 0x08); /* halt timer */
printk(BIOS_DEBUG, " done.\n");
/* Enable upper 128bytes of CMOS */
RCBA32(0x3400) = (1 << 2);
printk(BIOS_DEBUG, "Setting up static northbridge registers...");
pci_write_config8(D0F0, 0x8, 0x69);
/* Set up all hardcoded northbridge BARs */
pci_write_config32(D0F0, EPBAR, DEFAULT_EPBAR | 1);
pci_write_config32(D0F0, MCHBAR, (uintptr_t)DEFAULT_MCHBAR | 1);
pci_write_config32(D0F0, DMIBAR, (uintptr_t)DEFAULT_DMIBAR | 1);
pci_write_config32(D0F0, PMIOBAR, (uintptr_t)0x400 | 1);
reg32 = MCHBAR32(0x30);
MCHBAR32(0x30) = 0x21800;
DMIBAR32(0x2c) = 0x86000040;
pci_write_config8(D0F0, DEVEN, 0x09);
pci_write_config32(PCI_DEV(0, 0x1e, 0), 0x18, 0x00020200);
pci_write_config32(PCI_DEV(0, 0x1e, 0), 0x18, 0x00000000);
reg8 = pci_read_config8(D0F0, 0xe5); // 0x10
reg16 = pci_read_config16(PCI_DEV(0, 0x02, 0), 0x0); // 0x8086
reg16 = pci_read_config16(D0F0, GGC);
pci_write_config16(D0F0, GGC, 0x130);
reg16 = pci_read_config16(D0F0, GGC);
pci_write_config16(D0F0, GGC, 0x130);
MCHBAR8(0xb08) = 0x20;
reg8 = pci_read_config8(D0F0, 0xe6); // 0x11
reg16 = MCHBAR16(0xc8c);
MCHBAR16(0xc8c) = reg16 | 0x0200;
reg8 = MCHBAR8(0xc8c);
MCHBAR8(0xc8c) = reg8;
MCHBAR8(0xc8c) = 0x12;
pci_write_config8(PCI_DEV(0, 0x02, 0), 0x62, 0x02);
pci_write_config16(PCI_DEV(0, 0x02, 0), 0xe8, 0x8000);
MCHBAR32(0x3004) = 0x48000000;
MCHBAR32(0x3008) = 0xfffffe00;
MCHBAR32(0xb08) = 0x06028220;
MCHBAR32(0xff4) = 0xc6db8b5f;
MCHBAR16(0xff8) = 0x024f;
// PLL Voltage controlled oscillator
//MCHBAR8(0xc38) = 0x04;
pci_write_config16(PCI_DEV(0, 0x02, 0), 0xcc, 0x014d);
reg32 = MCHBAR32(0x40);
MCHBAR32(0x40) = 0x0;
reg32 = MCHBAR32(0x40);
MCHBAR32(0x40) = 0x8;
pci_write_config8(LPC, 0x8, 0x1d);
pci_write_config8(LPC, 0x8, 0x0);
RCBA32(0x3410) = 0x00020465;
RCBA32(0x88) = 0x0011d000;
RCBA32(0x1fc) = 0x60f;
RCBA32(0x1f4) = 0x86000040;
RCBA32(0x214) = 0x10030509;
RCBA32(0x218) = 0x00020504;
RCBA32(0x220) = 0xc5;
RCBA32(0x3430) = 0x1;
RCBA32(0x2027) = 0x38f6a70d;
RCBA16(0x3e08) = 0x0080;
RCBA16(0x3e48) = 0x0080;
RCBA32(0x3e0e) = 0x00000080;
RCBA32(0x3e4e) = 0x00000080;
RCBA32(0x2034) = 0xb24577cc;
RCBA32(0x1c) = 0x03128010;
RCBA32(0x2010) = 0x400;
RCBA32(0x3400) = 0x4;
RCBA32(0x2080) = 0x18006007;
RCBA32(0x20a0) = 0x18006007;
RCBA32(0x20c0) = 0x18006007;
RCBA32(0x20e0) = 0x18006007;
pci_write_config32(PCI_DEV(0, 0x1d, 0), 0xca, 0x1);
pci_write_config32(PCI_DEV(0, 0x1d, 1), 0xca, 0x1);
pci_write_config32(PCI_DEV(0, 0x1d, 2), 0xca, 0x1);
pci_write_config32(PCI_DEV(0, 0x1d, 3), 0xca, 0x1);
RCBA32(0x3100) = 0x42210;
RCBA32(0x3108) = 0x10004321;
RCBA32(0x310c) = 0x00214321;
RCBA32(0x3110) = 0x1;
RCBA32(0x3140) = 0x01460132;
RCBA32(0x3142) = 0x02370146;
RCBA32(0x3144) = 0x32010237;
RCBA32(0x3146) = 0x01463201;
RCBA32(0x3148) = 0x146;
/* Set C0000-FFFFF to access RAM on both reads and writes */
pci_write_config8(D0F0, PAM0, 0x30);
pci_write_config8(D0F0, PAM1, 0x33);
pci_write_config8(D0F0, PAM2, 0x33);
pci_write_config8(D0F0, PAM3, 0x33);
pci_write_config8(D0F0, PAM4, 0x33);
pci_write_config8(D0F0, PAM5, 0x33);
pci_write_config8(D0F0, PAM6, 0x33);
pci_write_config32(D0F0, SKPAD, SKPAD_NORMAL_BOOT_MAGIC);
printk(BIOS_DEBUG, " done.\n");
}
void pineview_early_initialization(void)
{
/* Print some chipset specific information */
printk(BIOS_DEBUG, "Intel Pineview northbridge\n");
/* Setup all BARs required for early PCIe and raminit */
pineview_setup_bars();
/* Change port80 to LPC */
RCBA32(GCS) &= (~0x04);
RCBA32(0x2010) |= (1 << 10);
}

View File

@ -0,0 +1,230 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2007-2009 coresystems GmbH
* Copyright (C) 2015 Damien Zammit <damien@zamaudio.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <console/console.h>
#include <arch/io.h>
#include <stdint.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/hypertransport.h>
#include <stdlib.h>
#include <string.h>
#include <cpu/cpu.h>
#include <boot/tables.h>
#include <arch/acpi.h>
#include <cbmem.h>
#include <northbridge/intel/pineview/pineview.h>
/* Reserve segments A and B:
*
* 0xa0000 - 0xbffff: legacy VGA
*/
static const int legacy_hole_base_k = 0xa0000 / 1024;
static const int legacy_hole_size_k = 128;
static void mch_domain_read_resources(device_t dev)
{
u64 tom, touud;
u32 tomk, tolud, uma_sizek = 0, usable_tomk;
u32 pcie_config_base, pcie_config_size;
pci_domain_read_resources(dev);
/* Top of Upper Usable DRAM, including remap */
touud = pci_read_config16(dev, 0xa2);
touud <<= 20;
/* Top of Lower Usable DRAM */
tolud = pci_read_config16(dev, 0xb0) & 0xfff0;
tolud <<= 16;
/* Top of Memory - does not account for any UMA */
tom = pci_read_config16(dev, 0xa0) & 0x1ff;
tom <<= 27;
printk(BIOS_DEBUG, "TOUUD 0x%llx TOLUD 0x%08x TOM 0x%llx\n",
touud, tolud, tom);
tomk = tolud >> 10;
/* Graphics memory comes next */
const u16 ggc = pci_read_config16(dev, GGC);
/* Graphics memory */
const u32 gms_sizek = decode_igd_memory_size((ggc >> 4) & 0xf);
printk(BIOS_DEBUG, "%uM UMA", gms_sizek >> 10);
tomk -= gms_sizek;
/* GTT Graphics Stolen Memory Size (GGMS) */
const u32 gsm_sizek = decode_igd_gtt_size((ggc >> 8) & 0xf);
printk(BIOS_DEBUG, " and %uM GTT\n", gsm_sizek >> 10);
tomk -= gsm_sizek;
uma_sizek = gms_sizek + gsm_sizek;
usable_tomk = ALIGN_DOWN(tomk, 64 << 10);
if (tomk - usable_tomk > (16 << 10))
usable_tomk = tomk;
printk(BIOS_INFO, "Available memory below 4GB: %uM\n", usable_tomk >> 10);
/* Report the memory regions */
ram_resource(dev, 3, 0, legacy_hole_base_k);
ram_resource(dev, 4, legacy_hole_base_k + legacy_hole_size_k,
(usable_tomk - (legacy_hole_base_k + legacy_hole_size_k)));
mmio_resource(dev, 5, legacy_hole_base_k,
(0xc0000 >> 10) - legacy_hole_base_k);
/*
* If >= 4GB installed then memory from TOLUD to 4GB
* is remapped above TOM, TOUUD will account for both
*/
touud >>= 10; /* Convert to KB */
if (touud > 4096 * 1024) {
ram_resource(dev, 6, 4096 * 1024, touud - (4096 * 1024));
printk(BIOS_INFO, "Available memory above 4GB: %lluM\n",
(touud >> 10) - 4096);
}
printk(BIOS_DEBUG, "Adding UMA memory area base=0x%llx "
"size=0x%llx\n", ((u64)tomk) << 10, ((u64)uma_sizek) << 10);
/* Don't use uma_resource() as our UMA touches the PCI hole. */
fixed_mem_resource(dev, 7, tomk, uma_sizek, IORESOURCE_RESERVE);
if (decode_pciebar(&pcie_config_base, &pcie_config_size)) {
printk(BIOS_DEBUG, "Adding PCIe config bar base=0x%08x "
"size=0x%x\n", pcie_config_base, pcie_config_size);
fixed_mem_resource(dev, 8, pcie_config_base >> 10,
pcie_config_size >> 10, IORESOURCE_RESERVE);
}
set_top_of_ram(tomk << 10);
}
static void mch_domain_set_resources(device_t dev)
{
struct resource *resource;
int i;
for (i = 3; i < 9; ++i) {
/* Report read resources. */
resource = probe_resource(dev, i);
if (resource)
report_resource_stored(dev, resource, "");
}
assign_resources(dev->link_list);
}
static void mch_domain_init(device_t dev)
{
u32 reg32;
/* Enable SERR */
reg32 = pci_read_config32(dev, PCI_COMMAND);
reg32 |= PCI_COMMAND_SERR;
pci_write_config32(dev, PCI_COMMAND, reg32);
}
static struct device_operations pci_domain_ops = {
.read_resources = mch_domain_read_resources,
.set_resources = mch_domain_set_resources,
.enable_resources = NULL,
.init = mch_domain_init,
.scan_bus = pci_domain_scan_bus,
.ops_pci_bus = pci_bus_default_ops,
};
static void cpu_bus_init(device_t dev)
{
initialize_cpus(dev->link_list);
}
static struct device_operations cpu_bus_ops = {
.read_resources = DEVICE_NOOP,
.set_resources = DEVICE_NOOP,
.enable_resources = DEVICE_NOOP,
.init = cpu_bus_init,
.scan_bus = 0,
};
static void enable_dev(device_t dev)
{
/* Set the operations if it is a special bus type */
if (dev->path.type == DEVICE_PATH_DOMAIN) {
dev->ops = &pci_domain_ops;
#if CONFIG_HAVE_ACPI_RESUME
switch (pci_read_config32(dev_find_slot(0, PCI_DEVFN(0, 0)), /*D0F0_SKPD*/0xdc)) {
case SKPAD_NORMAL_BOOT_MAGIC:
printk(BIOS_DEBUG, "Normal boot.\n");
acpi_slp_type=0;
break;
case SKPAD_ACPI_S3_MAGIC:
printk(BIOS_DEBUG, "S3 Resume.\n");
acpi_slp_type=3;
break;
default:
printk(BIOS_DEBUG, "Unknown boot method, assuming normal.\n");
acpi_slp_type=0;
break;
}
#endif
} else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
dev->ops = &cpu_bus_ops;
}
}
static void pineview_init(void *const chip_info)
{
int dev, fn;
struct device *const d0f0 = dev_find_slot(0, 0);
const struct {
u8 fn;
u8 bitbase;
} intfunc[] = {
{0, 0},
{0, 1}, /* PEG */
{1, 3}, /* IGD */
{3, 6}, /* ME */
};
/* Hide internal functions based on devicetree info. */
for (dev = 3; dev > 0; --dev) {
for (fn = intfunc[dev].fn; fn >= 0; --fn) {
const struct device *const d =
dev_find_slot(0, PCI_DEVFN(dev, fn));
if (!d || d->enabled) continue;
const u32 deven = pci_read_config32(d0f0, DEVEN);
pci_write_config32(d0f0, DEVEN, deven
& ~(1 << (intfunc[dev].bitbase + fn)));
}
}
const u32 deven = pci_read_config32(d0f0, DEVEN);
if (!(deven & (0xf << 6)))
pci_write_config32(d0f0, DEVEN, deven & ~(1 << 14));
}
struct chip_operations northbridge_intel_pineview_ops = {
CHIP_NAME("Intel Pineview Northbridge")
.enable_dev = enable_dev,
.init = pineview_init,
};

View File

@ -20,6 +20,16 @@
#include <northbridge/intel/pineview/iomap.h> #include <northbridge/intel/pineview/iomap.h>
#include <southbridge/intel/i82801gx/i82801gx.h> #include <southbridge/intel/i82801gx/i82801gx.h>
#define BOOT_PATH_NORMAL 0
#define BOOT_PATH_RESET 1
#define BOOT_PATH_RESUME 2
#define SYSINFO_DIMM_NOT_POPULATED 0x00
#define SYSINFO_DIMM_X16SS 0x01
#define SYSINFO_DIMM_X16DS 0x02
#define SYSINFO_DIMM_X8DS 0x05
#define SYSINFO_DIMM_X8DDS 0x06
/* Device 0:0.0 PCI configuration space (Host Bridge) */ /* Device 0:0.0 PCI configuration space (Host Bridge) */
#define EPBAR 0x40 #define EPBAR 0x40
@ -58,7 +68,7 @@
#define TOUUD 0xa2 #define TOUUD 0xa2
#define GBSM 0xa4 #define GBSM 0xa4
#define BGSM 0xa8 #define BGSM 0xa8
#define TSEGMB 0xac #define TSEG 0xac
#define TOLUD 0xb0 /* Top of Low Used Memory */ #define TOLUD 0xb0 /* Top of Low Used Memory */
#define ERRSTS 0xc8 #define ERRSTS 0xc8
#define ERRCMD 0xca #define ERRCMD 0xca
@ -77,7 +87,6 @@
#define BCTRL1 0x3e /* 16bit */ #define BCTRL1 0x3e /* 16bit */
#define PEGSTS 0x214 /* 32bit */ #define PEGSTS 0x214 /* 32bit */
/* Device 0:2.0 PCI configuration space (Graphics Device) */ /* Device 0:2.0 PCI configuration space (Graphics Device) */
#define GMADR 0x18 #define GMADR 0x18
@ -85,6 +94,7 @@
#define BSM 0x5c #define BSM 0x5c
#define GCFC 0xf0 /* Graphics Clock Frequency & Gating Control */ #define GCFC 0xf0 /* Graphics Clock Frequency & Gating Control */
#define GPIO32(x) *((volatile u32 *)(DEFAULT_GPIOBASE + x))
/* /*
* MCHBAR * MCHBAR
@ -110,7 +120,126 @@
#define DMIBAR16(x) *((volatile u16 *)(DEFAULT_DMIBAR + x)) #define DMIBAR16(x) *((volatile u16 *)(DEFAULT_DMIBAR + x))
#define DMIBAR32(x) *((volatile u32 *)(DEFAULT_DMIBAR + x)) #define DMIBAR32(x) *((volatile u32 *)(DEFAULT_DMIBAR + x))
enum fsb_clk {
FSB_CLOCK_667MHz = 0,
FSB_CLOCK_800MHz = 1,
};
enum mem_clk {
MEM_CLOCK_667MHz = 0,
MEM_CLOCK_800MHz = 1,
};
enum ddr {
DDR2 = 2,
DDR3 = 3,
};
enum chip_width { /* as in DDR3 spd */
CHIP_WIDTH_x4 = 0,
CHIP_WIDTH_x8 = 1,
CHIP_WIDTH_x16 = 2,
CHIP_WIDTH_x32 = 3,
};
enum chip_cap { /* as in DDR3 spd */
CHIP_CAP_256M = 0,
CHIP_CAP_512M = 1,
CHIP_CAP_1G = 2,
CHIP_CAP_2G = 3,
CHIP_CAP_4G = 4,
CHIP_CAP_8G = 5,
CHIP_CAP_16G = 6,
};
struct timings {
unsigned int CAS;
enum fsb_clk fsb_clock;
enum mem_clk mem_clock;
unsigned int tRAS;
unsigned int tRP;
unsigned int tRCD;
unsigned int tWR;
unsigned int tRFC;
unsigned int tWTR;
unsigned int tRRD;
unsigned int tRTP;
};
struct dimminfo {
unsigned int card_type; /* 0x0: unpopulated,
0xa - 0xf: raw card type A - F */
u8 type;
enum chip_width width;
enum chip_cap chip_capacity;
unsigned int page_size; /* of whole DIMM in Bytes (4096 or 8192) */
unsigned int sides;
unsigned int banks;
unsigned int ranks;
unsigned int rows;
unsigned int cols;
unsigned int cas_latencies;
unsigned int tAAmin;
unsigned int tCKmin;
unsigned int tWR;
unsigned int tRP;
unsigned int tRCD;
unsigned int tRAS;
unsigned int rank_capacity_mb; /* per rank in Mega Bytes */
u8 spd_data[256];
};
struct pllparam {
u8 kcoarse[2][72];
u8 pi[2][72];
u8 dben[2][72];
u8 dbsel[2][72];
u8 clkdelay[2][72];
};
struct sysinfo {
u8 maxpi;
u8 pioffset;
u8 pi[8];
u16 coarsectrl;
u16 coarsedelay;
u16 mediumphase;
u16 readptrdelay;
int txt_enabled;
int cores;
int boot_path;
int max_ddr2_mhz;
int max_ddr3_mt;
int max_fsb_mhz;
int max_render_mhz;
int enable_igd;
int enable_peg;
u16 ggc;
int dimm_config[2];
int dimms_per_ch;
int spd_type;
int channel_capacity[2];
struct timings selected_timings;
struct dimminfo dimms[4];
u8 spd_map[4];
u8 nodll;
u8 async;
u8 dt0mode;
u8 mvco4x; /* 0 (8x) or 1 (4x) */
};
void pineview_early_initialization(void);
u32 decode_igd_memory_size(const u32 gms);
u32 decode_igd_gtt_size(const u32 gsm);
u8 decode_pciebar(u32 *const base, u32 *const len);
/* provided by mainboard code */ /* provided by mainboard code */
void setup_ich7_gpios(void); void setup_ich7_gpios(void);
struct acpi_rsdp;
unsigned long northbridge_write_acpi_tables(unsigned long start, struct acpi_rsdp *rsdp);
#endif /* NORTHBRIDGE_INTEL_PINEVIEW_H */ #endif /* NORTHBRIDGE_INTEL_PINEVIEW_H */

View File

@ -14,45 +14,83 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
/* Use simple device model for this file even in ramstage */
#define __SIMPLE_DEVICE__ #define __SIMPLE_DEVICE__
#include <arch/io.h> #include <arch/io.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <console/console.h>
#include <cbmem.h> #include <cbmem.h>
#include <northbridge/intel/pineview/pineview.h> #include <northbridge/intel/pineview/pineview.h>
static void *find_ramtop(void) u8 decode_pciebar(u32 *const base, u32 *const len)
{ {
uint32_t tom; *base = 0;
*len = 0;
const pci_devfn_t dev = PCI_DEV(0,0,0);
u32 pciexbar = 0;
u32 pciexbar_reg;
u32 reg32;
int max_buses;
const struct {
u16 num_buses;
u32 addr_mask;
} busmask[] = {
{256, 0xf0000000},
{128, 0xf8000000},
{64, 0xfc000000},
{0, 0},
};
if (pci_read_config8(PCI_DEV(0, 0x0, 0), DEVEN) & (DEVEN_D2F0 | DEVEN_D2F1)) { if (!dev)
/* IGD enabled, get top of Memory from BSM register */ return 0;
tom = pci_read_config32(PCI_DEV(0,2,0), BSM);
} else
tom = (pci_read_config8(PCI_DEV(0,0,0), TOLUD) & 0xf7) << 24;
/* if TSEG enabled subtract size */ pciexbar_reg = pci_read_config32(dev, PCIEXBAR);
switch(pci_read_config8(PCI_DEV(0, 0, 0), ESMRAM) & 0x07) {
case 0x01: // MMCFG not supported or not enabled.
/* 1MB TSEG */ if (!(pciexbar_reg & (1 << 0))) {
tom -= 0x100000; printk(BIOS_WARNING, "WARNING: MMCONF not set\n");
break; return 0;
case 0x03:
/* 2MB TSEG */
tom -= 0x200000;
break;
case 0x05:
/* 8MB TSEG */
tom -= 0x800000;
break;
default:
/* TSEG either disabled or invalid */
break;
}
return (void *)tom;
} }
void *cbmem_top(void) reg32 = (pciexbar_reg >> 1) & 3;
pciexbar = pciexbar_reg & busmask[reg32].addr_mask;
max_buses = busmask[reg32].num_buses;
if (!pciexbar) {
printk(BIOS_WARNING, "WARNING: pciexbar invalid\n");
return 0;
}
*base = pciexbar;
*len = max_buses << 20;
return 1;
}
/** Decodes used Graphics Mode Select (GMS) to kilobytes. */
u32 decode_igd_memory_size(const u32 gms)
{ {
return find_ramtop(); const u32 gmssize[] = {
0, 1, 4, 8, 16, 32, 48, 64, 128, 256
};
if (gms > 9) {
printk(BIOS_DEBUG, "Bad Graphics Mode Select (GMS) value.\n");
return 0;
}
return gmssize[gms] << 10;
}
/** Decodes used Graphics Stolen Memory (GSM) to kilobytes. */
u32 decode_igd_gtt_size(const u32 gsm)
{
const u8 gsmsize[] = {
0, 1, 0, 0,
};
if (gsm > 3) {
printk(BIOS_DEBUG, "Bad Graphics Stolen Memory (GSM) value.\n");
return 0;
}
return (u32)(gsmsize[gsm] << 10);
} }