From f7060f1d0f72bab5b349846bc97784895643cf50 Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Sat, 14 Nov 2015 00:59:21 +1100 Subject: northbridge/intel/pineview: Add remaining boilerplate code for northbridge This patch does *not* include native raminit Change-Id: I3fb8146ef7fe2ad27c167ecd2fb0fd629f051cc1 Signed-off-by: Damien Zammit Reviewed-on: https://review.coreboot.org/12430 Reviewed-by: Alexandru Gagniuc Tested-by: build bot (Jenkins) --- src/northbridge/intel/pineview/Kconfig | 3 +- src/northbridge/intel/pineview/Makefile.inc | 2 + src/northbridge/intel/pineview/acpi.c | 34 +-- src/northbridge/intel/pineview/acpi/hostbridge.asl | 235 +++++++++++++++++++++ src/northbridge/intel/pineview/acpi/peg.asl | 41 ++++ src/northbridge/intel/pineview/acpi/pineview.asl | 50 +++++ src/northbridge/intel/pineview/chip.h | 8 + src/northbridge/intel/pineview/early_init.c | 166 +++++++++++++++ src/northbridge/intel/pineview/northbridge.c | 230 ++++++++++++++++++++ src/northbridge/intel/pineview/pineview.h | 133 +++++++++++- src/northbridge/intel/pineview/ram_calc.c | 98 ++++++--- 11 files changed, 935 insertions(+), 65 deletions(-) create mode 100644 src/northbridge/intel/pineview/acpi/hostbridge.asl create mode 100644 src/northbridge/intel/pineview/acpi/peg.asl create mode 100644 src/northbridge/intel/pineview/acpi/pineview.asl create mode 100644 src/northbridge/intel/pineview/chip.h create mode 100644 src/northbridge/intel/pineview/early_init.c create mode 100644 src/northbridge/intel/pineview/northbridge.c (limited to 'src/northbridge') diff --git a/src/northbridge/intel/pineview/Kconfig b/src/northbridge/intel/pineview/Kconfig index 6253b84ab7..767bb81043 100644 --- a/src/northbridge/intel/pineview/Kconfig +++ b/src/northbridge/intel/pineview/Kconfig @@ -25,8 +25,7 @@ config NORTHBRIDGE_SPECIFIC_OPTIONS # dummy select MMCONF_SUPPORT_DEFAULT select HAVE_DEBUG_RAM_SETUP select LAPIC_MONOTONIC_TIMER - select VGA - select PER_DEVICE_ACPI_TABLES + select LATE_CBMEM_INIT config BOOTBLOCK_NORTHBRIDGE_INIT string diff --git a/src/northbridge/intel/pineview/Makefile.inc b/src/northbridge/intel/pineview/Makefile.inc index 9330b1787b..07a6a8022c 100644 --- a/src/northbridge/intel/pineview/Makefile.inc +++ b/src/northbridge/intel/pineview/Makefile.inc @@ -17,8 +17,10 @@ ifeq ($(CONFIG_NORTHBRIDGE_INTEL_PINEVIEW),y) ramstage-y += ram_calc.c +ramstage-y += northbridge.c ramstage-y += acpi.c romstage-y += ram_calc.c +romstage-y += early_init.c endif diff --git a/src/northbridge/intel/pineview/acpi.c b/src/northbridge/intel/pineview/acpi.c index f29d235b20..9dd8e311be 100644 --- a/src/northbridge/intel/pineview/acpi.c +++ b/src/northbridge/intel/pineview/acpi.c @@ -24,42 +24,14 @@ unsigned long acpi_fill_mcfg(unsigned long current) { - device_t dev; + u32 length = 0; u32 pciexbar = 0; - u32 pciexbar_reg; - u32 reg32; 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 (!dev) + if (!decode_pciebar(&pciexbar, &length)) return current; - pciexbar_reg = pci_read_config32(dev, PCIEXBAR); - - // 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; - } - + max_buses = length >> 20; current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, pciexbar, 0x0, 0x0, max_buses - 1); diff --git a/src/northbridge/intel/pineview/acpi/hostbridge.asl b/src/northbridge/intel/pineview/acpi/hostbridge.asl new file mode 100644 index 0000000000..d759514bbf --- /dev/null +++ b/src/northbridge/intel/pineview/acpi/hostbridge.asl @@ -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 + +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" diff --git a/src/northbridge/intel/pineview/acpi/peg.asl b/src/northbridge/intel/pineview/acpi/peg.asl new file mode 100644 index 0000000000..227ca27004 --- /dev/null +++ b/src/northbridge/intel/pineview/acpi/peg.asl @@ -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 } + }) + } + + } +} diff --git a/src/northbridge/intel/pineview/acpi/pineview.asl b/src/northbridge/intel/pineview/acpi/pineview.asl new file mode 100644 index 0000000000..d32a906835 --- /dev/null +++ b/src/northbridge/intel/pineview/acpi/pineview.asl @@ -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 + +/* 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" diff --git a/src/northbridge/intel/pineview/chip.h b/src/northbridge/intel/pineview/chip.h new file mode 100644 index 0000000000..a620857157 --- /dev/null +++ b/src/northbridge/intel/pineview/chip.h @@ -0,0 +1,8 @@ +#include + +struct northbridge_intel_pineview_config { + u32 gpu_hotplug; + u32 gpu_backlight; + int gpu_lvds_use_spread_spectrum_clock; + struct i915_gpu_controller_info gfx; +}; diff --git a/src/northbridge/intel/pineview/early_init.c b/src/northbridge/intel/pineview/early_init.c new file mode 100644 index 0000000000..dcbdbb13ba --- /dev/null +++ b/src/northbridge/intel/pineview/early_init.c @@ -0,0 +1,166 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Damien Zammit + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/src/northbridge/intel/pineview/northbridge.c b/src/northbridge/intel/pineview/northbridge.c new file mode 100644 index 0000000000..21f133dfb2 --- /dev/null +++ b/src/northbridge/intel/pineview/northbridge.c @@ -0,0 +1,230 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2015 Damien Zammit + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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, +}; diff --git a/src/northbridge/intel/pineview/pineview.h b/src/northbridge/intel/pineview/pineview.h index 4b3b0b189c..d8073402a5 100644 --- a/src/northbridge/intel/pineview/pineview.h +++ b/src/northbridge/intel/pineview/pineview.h @@ -20,6 +20,16 @@ #include #include +#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) */ #define EPBAR 0x40 @@ -58,7 +68,7 @@ #define TOUUD 0xa2 #define GBSM 0xa4 #define BGSM 0xa8 -#define TSEGMB 0xac +#define TSEG 0xac #define TOLUD 0xb0 /* Top of Low Used Memory */ #define ERRSTS 0xc8 #define ERRCMD 0xca @@ -77,7 +87,6 @@ #define BCTRL1 0x3e /* 16bit */ #define PEGSTS 0x214 /* 32bit */ - /* Device 0:2.0 PCI configuration space (Graphics Device) */ #define GMADR 0x18 @@ -85,6 +94,7 @@ #define BSM 0x5c #define GCFC 0xf0 /* Graphics Clock Frequency & Gating Control */ +#define GPIO32(x) *((volatile u32 *)(DEFAULT_GPIOBASE + x)) /* * MCHBAR @@ -110,7 +120,126 @@ #define DMIBAR16(x) *((volatile u16 *)(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 */ 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 */ diff --git a/src/northbridge/intel/pineview/ram_calc.c b/src/northbridge/intel/pineview/ram_calc.c index e9f8eedb43..c273071182 100644 --- a/src/northbridge/intel/pineview/ram_calc.c +++ b/src/northbridge/intel/pineview/ram_calc.c @@ -14,45 +14,83 @@ * GNU General Public License for more details. */ -/* Use simple device model for this file even in ramstage */ #define __SIMPLE_DEVICE__ #include +#include +#include +#include #include #include -static void *find_ramtop(void) +u8 decode_pciebar(u32 *const base, u32 *const len) { - uint32_t tom; - - if (pci_read_config8(PCI_DEV(0, 0x0, 0), DEVEN) & (DEVEN_D2F0 | DEVEN_D2F1)) { - /* IGD enabled, get top of Memory from BSM register */ - 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 */ - switch(pci_read_config8(PCI_DEV(0, 0, 0), ESMRAM) & 0x07) { - case 0x01: - /* 1MB TSEG */ - tom -= 0x100000; - break; - case 0x03: - /* 2MB TSEG */ - tom -= 0x200000; - break; - case 0x05: - /* 8MB TSEG */ - tom -= 0x800000; - break; - default: - /* TSEG either disabled or invalid */ - break; + *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 (!dev) + return 0; + + pciexbar_reg = pci_read_config32(dev, PCIEXBAR); + + // MMCFG not supported or not enabled. + if (!(pciexbar_reg & (1 << 0))) { + printk(BIOS_WARNING, "WARNING: MMCONF not set\n"); + return 0; + } + + 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) +{ + 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 (void *)tom; + return gmssize[gms] << 10; } -void *cbmem_top(void) +/** Decodes used Graphics Stolen Memory (GSM) to kilobytes. */ +u32 decode_igd_gtt_size(const u32 gsm) { - return find_ramtop(); + 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); } -- cgit v1.2.3