From 43a1f780ff6809f758092136b0b38c6917c27340 Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Wed, 19 Aug 2015 15:16:59 +1000 Subject: northbridge/intel/x4x: Intel 4-series northbridge support Boots to console on Gigabyte GA-G41M-ES2L Ram initialization *not* included in this patch VGA native init works on analog connector Change-Id: I5262f73fd03d5e5c12e9f11d027bdfbbf0ddde82 Signed-off-by: Damien Zammit Reviewed-on: https://review.coreboot.org/11305 Tested-by: build bot (Jenkins) Reviewed-by: Alexandru Gagniuc --- src/northbridge/intel/x4x/Kconfig | 39 ++++ src/northbridge/intel/x4x/Makefile.inc | 27 +++ src/northbridge/intel/x4x/acpi.c | 57 +++++ src/northbridge/intel/x4x/acpi/hostbridge.asl | 234 +++++++++++++++++++ src/northbridge/intel/x4x/acpi/peg.asl | 42 ++++ src/northbridge/intel/x4x/acpi/x4x.asl | 49 ++++ src/northbridge/intel/x4x/bootblock.c | 32 +++ src/northbridge/intel/x4x/chip.h | 26 +++ src/northbridge/intel/x4x/early_init.c | 58 +++++ src/northbridge/intel/x4x/gma.c | 286 +++++++++++++++++++++++ src/northbridge/intel/x4x/iomap.h | 28 +++ src/northbridge/intel/x4x/northbridge.c | 234 +++++++++++++++++++ src/northbridge/intel/x4x/ram_calc.c | 88 +++++++ src/northbridge/intel/x4x/x4x.h | 320 ++++++++++++++++++++++++++ 14 files changed, 1520 insertions(+) create mode 100644 src/northbridge/intel/x4x/Kconfig create mode 100644 src/northbridge/intel/x4x/Makefile.inc create mode 100644 src/northbridge/intel/x4x/acpi.c create mode 100644 src/northbridge/intel/x4x/acpi/hostbridge.asl create mode 100644 src/northbridge/intel/x4x/acpi/peg.asl create mode 100644 src/northbridge/intel/x4x/acpi/x4x.asl create mode 100644 src/northbridge/intel/x4x/bootblock.c create mode 100644 src/northbridge/intel/x4x/chip.h create mode 100644 src/northbridge/intel/x4x/early_init.c create mode 100644 src/northbridge/intel/x4x/gma.c create mode 100644 src/northbridge/intel/x4x/iomap.h create mode 100644 src/northbridge/intel/x4x/northbridge.c create mode 100644 src/northbridge/intel/x4x/ram_calc.c create mode 100644 src/northbridge/intel/x4x/x4x.h (limited to 'src/northbridge') diff --git a/src/northbridge/intel/x4x/Kconfig b/src/northbridge/intel/x4x/Kconfig new file mode 100644 index 0000000000..c330fd50d5 --- /dev/null +++ b/src/northbridge/intel/x4x/Kconfig @@ -0,0 +1,39 @@ +## +## 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. +## + +config NORTHBRIDGE_INTEL_X4X + bool + +if NORTHBRIDGE_INTEL_X4X + +config NORTHBRIDGE_SPECIFIC_OPTIONS # dummy + def_bool y + select HAVE_DEBUG_RAM_SETUP + select MMCONF_SUPPORT + select MMCONF_SUPPORT_DEFAULT + select VGA + select INTEL_GMA_ACPI + select LATE_CBMEM_INIT + +config BOOTBLOCK_NORTHBRIDGE_INIT + string + default "northbridge/intel/x4x/bootblock.c" + +config VGA_BIOS_ID + string + default "8086,2e32" + +endif diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc new file mode 100644 index 0000000000..8d1247e3a9 --- /dev/null +++ b/src/northbridge/intel/x4x/Makefile.inc @@ -0,0 +1,27 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2012 secunet Security Networks AG +# 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. +# + +ifeq ($(CONFIG_NORTHBRIDGE_INTEL_X4X),y) + +romstage-y += early_init.c +romstage-y += ram_calc.c + +ramstage-y += acpi.c +ramstage-y += ram_calc.c +ramstage-y += gma.c +ramstage-y += northbridge.c + +endif diff --git a/src/northbridge/intel/x4x/acpi.c b/src/northbridge/intel/x4x/acpi.c new file mode 100644 index 0000000000..386096c172 --- /dev/null +++ b/src/northbridge/intel/x4x/acpi.c @@ -0,0 +1,57 @@ +/* + * 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 "x4x.h" + +unsigned long acpi_fill_mcfg(unsigned long current) +{ + device_t dev; + u32 pciexbar = 0; + u32 length = 0; + + dev = dev_find_slot(0, PCI_DEVFN(0,0)); + if (!decode_pciebar(&pciexbar, &length)) + return current; + + current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, + pciexbar, 0x0, 0x0, (length >> 20) - 1); + + return current; +} + +unsigned long northbridge_write_acpi_tables(device_t device, + unsigned long start, + struct acpi_rsdp *rsdp) +{ + unsigned long current; + current = acpi_align_current(start); + + printk(BIOS_DEBUG, "current = %lx\n", current); + + return current; +} diff --git a/src/northbridge/intel/x4x/acpi/hostbridge.asl b/src/northbridge/intel/x4x/acpi/hostbridge.asl new file mode 100644 index 0000000000..530fdfafd9 --- /dev/null +++ b/src/northbridge/intel/x4x/acpi/hostbridge.asl @@ -0,0 +1,234 @@ +/* + * 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 + +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), // PCIe BAR + PXEN, 1, // Enable + PXSZ, 2, // BAR size + , 23, // + PXBR, 10, // PCIe BAR + + Offset (0x68), // DMIBAR + DMEN, 1, // Enable + , 11, // + DMBR, 24, // 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 Used Memory + TOM, 8, + + Offset (0xb0), // Top of Low Used Memory + , 4, + TLUD, 12, + } + +} + +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) +}) + +// Current Resource Settings + +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 20-31 of + // the top of memory address. + ShiftLeft (^MCHC.TLUD, 20, PMIN) + Add(Subtract(PMAX, PMIN), 1, PLEN) + + Return (MCRS) +} + +/* IRQ assignment is mainboard specific. Get it from mainboard ACPI code */ +#include "acpi/x4x_pci_irqs.asl" diff --git a/src/northbridge/intel/x4x/acpi/peg.asl b/src/northbridge/intel/x4x/acpi/peg.asl new file mode 100644 index 0000000000..f2314c24d0 --- /dev/null +++ b/src/northbridge/intel/x4x/acpi/peg.asl @@ -0,0 +1,42 @@ +/* + * 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. + */ + +Device (PEGP) +{ + Name (_ADR, 0x00010000) + + // PCI Interrupt Routing. + Method (_PRT) + { + If (PICM) { + Return (Package() { + Package() { 0x0001ffff, 0, 0, 16 }, + Package() { 0x0001ffff, 1, 0, 17 }, + Package() { 0x0001ffff, 2, 0, 18 }, + Package() { 0x0001ffff, 3, 0, 19 }, + }) + } Else { + Return (Package() { + Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 }, + Package() { 0x0001ffff, 1, \_SB.PCI0.LPCB.LNKB, 0 }, + Package() { 0x0001ffff, 2, \_SB.PCI0.LPCB.LNKC, 0 }, + Package() { 0x0001ffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }, + }) + } + + } +} diff --git a/src/northbridge/intel/x4x/acpi/x4x.asl b/src/northbridge/intel/x4x/acpi/x4x.asl new file mode 100644 index 0000000000..7724d8ee0f --- /dev/null +++ b/src/northbridge/intel/x4x/acpi/x4x.asl @@ -0,0 +1,49 @@ +/* + * 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 "hostbridge.asl" +#include "../iomap.h" + +/* PCI Device Resource Consumption */ +Device (PDRC) +{ + Name (_HID, EISAID("PNP0C02")) + Name (_UID, 1) + + 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" + +// Integrated graphics 0:2.0 +#include diff --git a/src/northbridge/intel/x4x/bootblock.c b/src/northbridge/intel/x4x/bootblock.c new file mode 100644 index 0000000000..0a8946c5ec --- /dev/null +++ b/src/northbridge/intel/x4x/bootblock.c @@ -0,0 +1,32 @@ +/* + * 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 + +#define D0F0_PCIEXBAR_LO 0x60 +#define TPMBASE 0xfed40000 +#define TPM32(x) *((volatile u32 *)(TPMBASE + x)) + +static void bootblock_northbridge_init(void) +{ + uint32_t reg32; + + /* Disable LaGrande Technology (LT) */ + reg32 = TPM32(0); + + reg32 = CONFIG_MMCONF_BASE_ADDRESS | 16 | 1; + pci_io_write_config32(PCI_DEV(0,0,0), D0F0_PCIEXBAR_LO, reg32); +} diff --git a/src/northbridge/intel/x4x/chip.h b/src/northbridge/intel/x4x/chip.h new file mode 100644 index 0000000000..1fb54ccf86 --- /dev/null +++ b/src/northbridge/intel/x4x/chip.h @@ -0,0 +1,26 @@ +/* + * 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. + */ + +#ifndef NORTHBRIDGE_INTEL_X4X_CHIP_H +#define NORTHBRIDGE_INTEL_X4X_CHIP_H + +#include + +struct northbridge_intel_x4x_config { + struct i915_gpu_controller_info gfx; +}; + +#endif diff --git a/src/northbridge/intel/x4x/early_init.c b/src/northbridge/intel/x4x/early_init.c new file mode 100644 index 0000000000..1d43e0aca5 --- /dev/null +++ b/src/northbridge/intel/x4x/early_init.c @@ -0,0 +1,58 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 secunet Security Networks AG + * 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 "x4x.h" + +void x4x_early_init(void) +{ + u16 reg16; + + const device_t d0f0 = PCI_DEV(0, 0, 0); + + /* Setup MCHBAR. */ + pci_write_config32(d0f0, D0F0_MCHBAR_LO, (uintptr_t)DEFAULT_MCHBAR | 1); + + /* Setup DMIBAR. */ + pci_write_config32(d0f0, D0F0_DMIBAR_LO, (uintptr_t)DEFAULT_DMIBAR | 1); + + /* Setup EPBAR. */ + pci_write_config32(d0f0, D0F0_EPBAR_LO, DEFAULT_EPBAR | 1); + + /* Setup PMBASE */ + pci_write_config32(d0f0, D0F0_PMBASE, DEFAULT_PMBASE | 1); + + /* Setup HECIBAR */ + pci_write_config32(PCI_DEV(0,3,0), 0x10, DEFAULT_HECIBAR); + reg16 = pci_read_config16(PCI_DEV(0,3,0), 0x4); + pci_write_config16(PCI_DEV(0,3,0), 0x4, reg16 | 0x6); + + /* Set C0000-FFFFF to access RAM on both reads and writes */ + pci_write_config8(d0f0, D0F0_PAM(0), 0x30); + pci_write_config8(d0f0, D0F0_PAM(1), 0x33); + pci_write_config8(d0f0, D0F0_PAM(2), 0x33); + pci_write_config8(d0f0, D0F0_PAM(3), 0x33); + pci_write_config8(d0f0, D0F0_PAM(4), 0x33); + pci_write_config8(d0f0, D0F0_PAM(5), 0x33); + pci_write_config8(d0f0, D0F0_PAM(6), 0x33); + + /* Enable internal GFX */ + pci_write_config16(d0f0, D0F0_GGC, 0x0170); + + reg16 = pci_read_config16(d0f0, D0F0_DEVEN); + pci_write_config16(d0f0, D0F0_DEVEN, reg16 | 0x8); +} diff --git a/src/northbridge/intel/x4x/gma.c b/src/northbridge/intel/x4x/gma.c new file mode 100644 index 0000000000..7891229392 --- /dev/null +++ b/src/northbridge/intel/x4x/gma.c @@ -0,0 +1,286 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 Chromium OS Authors + * Copyright (C) 2013 Vladimir Serbinenko + * 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 "drivers/intel/gma/i915_reg.h" +#include "chip.h" +#include "x4x.h" +#include +#include +#include +#include + +static struct resource *gtt_res = NULL; + +void gtt_write(u32 reg, u32 data) +{ + write32(res2mmio(gtt_res, reg, 0), data); +} + +static void intel_gma_init(const struct northbridge_intel_x4x_config *info, + u8 *mmio, u32 physbase, u16 piobase, u32 lfb) +{ + + int i; + u32 hactive, vactive; + vga_gr_write(0x18, 0); + + /* Setup GTT. */ + for (i = 0; i < 0x2000; i++) + { + outl((i << 2) | 1, piobase); + outl(physbase + (i << 12) + 1, piobase + 4); + } + + write32(mmio + VGA0, 0x31108); + write32(mmio + VGA1, 0x31406); + + write32(mmio + ADPA, ADPA_DAC_ENABLE + | ADPA_PIPE_A_SELECT + | ADPA_CRT_HOTPLUG_MONITOR_COLOR + | ADPA_CRT_HOTPLUG_ENABLE + | ADPA_USE_VGA_HVPOLARITY + | ADPA_VSYNC_CNTL_ENABLE + | ADPA_HSYNC_CNTL_ENABLE + | ADPA_DPMS_ON + ); + + write32(mmio + 0x7041c, 0x0); + write32(mmio + DPLL_MD(0), 0x3); + write32(mmio + DPLL_MD(1), 0x3); + + vga_misc_write(0x67); + + const u8 cr[] = { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, + 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, + 0xff + }; + vga_cr_write(0x11, 0); + + for (i = 0; i <= 0x18; i++) + vga_cr_write(i, cr[i]); + + /* Disable screen memory to prevent garbage from appearing. */ + vga_sr_write(1, vga_sr_read(1) | 0x20); + + hactive = 640; + vactive = 400; + + vga_textmode_init(); + + mdelay(1); + write32(mmio + FP0(0), 0x31108); + write32(mmio + DPLL(0), + DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL + | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 + | 0x10601 + ); + mdelay(1); + write32(mmio + DPLL(0), + DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL + | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 + | 0x10601 + ); + + write32(mmio + ADPA, ADPA_DAC_ENABLE + | ADPA_PIPE_A_SELECT + | ADPA_CRT_HOTPLUG_MONITOR_COLOR + | ADPA_CRT_HOTPLUG_ENABLE + | ADPA_USE_VGA_HVPOLARITY + | ADPA_VSYNC_CNTL_ENABLE + | ADPA_HSYNC_CNTL_ENABLE + | ADPA_DPMS_ON + ); + + write32(mmio + HTOTAL(0), + ((hactive - 1) << 16) + | (hactive - 1)); + write32(mmio + HBLANK(0), + ((hactive - 1) << 16) + | (hactive - 1)); + write32(mmio + HSYNC(0), + ((hactive - 1) << 16) + | (hactive - 1)); + + write32(mmio + VTOTAL(0), ((vactive - 1) << 16) + | (vactive - 1)); + write32(mmio + VBLANK(0), ((vactive - 1) << 16) + | (vactive - 1)); + write32(mmio + VSYNC(0), + ((vactive - 1) << 16) + | (vactive - 1)); + + write32(mmio + PIPECONF(0), PIPECONF_DISABLE); + + write32(mmio + PF_WIN_POS(0), 0); + + write32(mmio + PIPESRC(0), (639 << 16) | 399); + write32(mmio + PF_CTL(0),PF_ENABLE | PF_FILTER_MED_3x3); + write32(mmio + PF_WIN_SZ(0), vactive | (hactive << 16)); + write32(mmio + PFIT_CONTROL, 0xa0000000); + + mdelay(1); + + write32(mmio + 0x000f000c, 0x00002040); + mdelay(1); + write32(mmio + 0x000f000c, 0x00002050); + write32(mmio + 0x00060100, 0x00044000); + mdelay(1); + write32(mmio + PIPECONF(0), PIPECONF_ENABLE | PIPECONF_BPP_6 | PIPECONF_DITHER_EN); + + write32(mmio + VGACNTRL, 0x0); + write32(mmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888); + mdelay(1); + + write32(mmio + ADPA, ADPA_DAC_ENABLE + | ADPA_PIPE_A_SELECT + | ADPA_CRT_HOTPLUG_MONITOR_COLOR + | ADPA_CRT_HOTPLUG_ENABLE + | ADPA_USE_VGA_HVPOLARITY + | ADPA_VSYNC_CNTL_ENABLE + | ADPA_HSYNC_CNTL_ENABLE + | ADPA_DPMS_ON + ); + + write32(mmio + PP_CONTROL, PANEL_POWER_ON); + + /* Enable screen memory. */ + vga_sr_write(1, vga_sr_read(1) & ~0x20); + + /* Clear interrupts. */ + write32(mmio + DEIIR, 0xffffffff); + write32(mmio + SDEIIR, 0xffffffff); +} + +static void gma_func0_init(struct device *dev) +{ + u32 reg32; + + /* IGD needs to be Bus Master */ + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; + pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Init graphics power management */ + gtt_res = find_resource(dev, PCI_BASE_ADDRESS_0); + + struct northbridge_intel_x4x_config *conf = dev->chip_info; + + if (!IS_ENABLED(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT)) { + /* PCI Init, will run VBIOS */ + pci_dev_init(dev); + } else { + u32 physbase; + struct resource *lfb_res; + struct resource *pio_res; + + lfb_res = find_resource(dev, PCI_BASE_ADDRESS_2); + pio_res = find_resource(dev, PCI_BASE_ADDRESS_4); + + physbase = pci_read_config32(dev, 0x5c) & ~0xf; + + if (gtt_res && gtt_res->base && physbase && pio_res && pio_res->base + && lfb_res && lfb_res->base) { + printk(BIOS_SPEW, "Initializing VGA without OPROM. MMIO 0x%llx\n", + gtt_res->base); + intel_gma_init(conf, res2mmio(gtt_res, 0, 0), physbase, + pio_res->base, lfb_res->base); + } + + /* Linux relies on VBT for panel info. */ + generate_fake_intel_oprom(&conf->gfx, dev, "$VBT EAGLELAKE "); + } + + /* Post VBIOS init */ + /* Enable Backlight */ + gtt_write(BLC_PWM_CTL2, (1 << 31)); + if (conf->gfx.backlight == 0) + gtt_write(BLC_PWM_CTL, 0x06100610); + else + gtt_write(BLC_PWM_CTL, conf->gfx.backlight); +} + +static void gma_set_subsystem(device_t dev, unsigned vendor, unsigned device) +{ + if (!vendor || !device) { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + pci_read_config32(dev, PCI_VENDOR_ID)); + } else { + pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, + ((device & 0xffff) << 16) | (vendor & + 0xffff)); + } +} + +const struct i915_gpu_controller_info * +intel_gma_get_controller_info(void) +{ + device_t dev = dev_find_slot(0, PCI_DEVFN(0x2,0)); + if (!dev) { + return NULL; + } + struct northbridge_intel_x4x_config *chip = dev->chip_info; + return &chip->gfx; +} + +static void gma_ssdt(device_t device) +{ + const struct i915_gpu_controller_info *gfx = intel_gma_get_controller_info(); + if (!gfx) { + return; + } + + drivers_intel_gma_displays_ssdt_generate(gfx); +} + +static struct pci_operations gma_pci_ops = { + .set_subsystem = gma_set_subsystem, +}; + +static struct device_operations gma_func0_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .enable_resources = pci_dev_enable_resources, + .acpi_fill_ssdt_generator = gma_ssdt, + .init = gma_func0_init, + .scan_bus = 0, + .enable = 0, + .ops_pci = &gma_pci_ops, +}; + +static const unsigned short pci_device_ids[] = +{ + 0x2e32, 0 +}; + +static const struct pci_driver gma __pci_driver = { + .ops = &gma_func0_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; diff --git a/src/northbridge/intel/x4x/iomap.h b/src/northbridge/intel/x4x/iomap.h new file mode 100644 index 0000000000..34153c1b4a --- /dev/null +++ b/src/northbridge/intel/x4x/iomap.h @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#ifndef X4X_IOMAP_H +#define X4X_IOMAP_H + +/* 4 KB per PCIe device */ +#define DEFAULT_PCIEXBAR CONFIG_MMCONF_BASE_ADDRESS + +#define DEFAULT_MCHBAR 0xfed14000 /* 16 KB */ +#define DEFAULT_DMIBAR 0xfed18000 /* 4 KB */ +#define DEFAULT_EPBAR 0xfed19000 /* 4 KB */ +#define DEFAULT_HECIBAR 0xfed10000 + +#endif /* X4X_IOMAP_H */ diff --git a/src/northbridge/intel/x4x/northbridge.c b/src/northbridge/intel/x4x/northbridge.c new file mode 100644 index 0000000000..c5a89682a7 --- /dev/null +++ b/src/northbridge/intel/x4x/northbridge.c @@ -0,0 +1,234 @@ +/* + * 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, tsegk, tolud, usable_tomk; + u32 pcie_config_base, pcie_config_size; + u32 uma_sizek = 0; + + /* 1024KiB TSEG */ + tsegk = 1 << 10; + + pci_domain_read_resources(dev); + + /* Top of Upper Usable DRAM, including remap */ + touud = pci_read_config16(dev, D0F0_TOUUD); + touud <<= 20; + + /* Top of Lower Usable DRAM */ + tolud = pci_read_config16(dev, D0F0_TOLUD) & 0xfff0; + tolud <<= 16; + + /* Top of Memory - does not account for any UMA */ + tom = pci_read_config16(dev, D0F0_TOM) & 0x01ff; + tom <<= 26; + + 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, D0F0_GGC); + printk(BIOS_DEBUG, "IGD decoded, subtracting "); + + /* Graphics memory */ + const u32 gms_sizek = decode_igd_memory_size((ggc >> 4) & 0xf); + printk(BIOS_DEBUG, "%uM UMA", gms_sizek >> 10); + + /* 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); + + uma_sizek = gms_sizek + gsm_sizek + tsegk; + usable_tomk = tomk - uma_sizek; + + 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))); + + /* + * 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, 5, 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%08x " + "size=0x%08x\n", usable_tomk << 10, uma_sizek << 10); + fixed_mem_resource(dev, 6, usable_tomk, uma_sizek, IORESOURCE_RESERVE); + + /* Some strange hole, reserve it */ + //fixed_mem_resource(dev, 7, usable_tomk - (0x02000000 >> 10), 0x02000000 >> 10, 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, 7, pcie_config_base >> 10, + pcie_config_size >> 10, IORESOURCE_RESERVE); + } +} + +static void mch_domain_set_resources(device_t dev) +{ + struct resource *resource; + int i; + + for (i = 3; i < 8; ++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, + .write_acpi_tables = northbridge_write_acpi_tables, + .acpi_fill_ssdt_generator = generate_cpu_entries, +}; + + +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 x4x_init(void *const chip_info) +{ + int dev, fn, bit_base; + + struct device *const d0f0 = dev_find_slot(0, 0); + + /* Hide internal functions based on devicetree info. */ + for (dev = 3; dev > 0; --dev) { + switch (dev) { + case 3: /* ME */ + fn = 3; + bit_base = 6; + break; + case 2: /* IGD */ + fn = 1; + bit_base = 3; + break; + case 1: /* PEG */ + fn = 0; + bit_base = 1; + break; + } + for (; 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, D0F0_DEVEN); + pci_write_config32(d0f0, D0F0_DEVEN, + deven & ~(1 << (bit_base + fn))); + } + } + + const u32 deven = pci_read_config32(d0f0, D0F0_DEVEN); + if (!(deven & (0xf << 6))) + pci_write_config32(d0f0, D0F0_DEVEN, deven & ~(1 << 14)); +} + +struct chip_operations northbridge_intel_x4x_ops = { + CHIP_NAME("Intel 4-Series Northbridge") + .enable_dev = enable_dev, + .init = x4x_init, +}; diff --git a/src/northbridge/intel/x4x/ram_calc.c b/src/northbridge/intel/x4x/ram_calc.c new file mode 100644 index 0000000000..f11b19a9f1 --- /dev/null +++ b/src/northbridge/intel/x4x/ram_calc.c @@ -0,0 +1,88 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 secunet Security Networks AG + * 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. + */ + +#define __SIMPLE_DEVICE__ + +#include +#include +#include +#include +#include +#include + +/** Decodes used Graphics Mode Select (GMS) to kilobytes. */ +u32 decode_igd_memory_size(const u32 gms) +{ + static const u16 ggc2uma[] = { 0, 0, 0, 0, 0, + 32, 48, 64, 128, 256, 96, 160, 224, 352 }; + + if (gms > ARRAY_SIZE(ggc2uma)) + die("Bad Graphics Mode Select (GMS) setting.\n"); + + return ggc2uma[gms] << 10; +} + +/** Decodes used GTT Graphics Memory Size (GGMS) to kilobytes. */ +u32 decode_igd_gtt_size(const u32 gsm) +{ + static const u8 ggc2gtt[] = { 0, 1, 0, 2, 0, 0, 0, 0, 0, 2, 3, 4}; + + if (gsm > ARRAY_SIZE(ggc2gtt)) + die("Bad GTT Graphics Memory Size (GGMS) setting.\n"); + + return ggc2gtt[gsm] << 10; +} + +u8 decode_pciebar(u32 *const base, u32 *const len) +{ + *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}, + }; + + pciexbar_reg = pci_read_config32(dev, D0F0_PCIEXBAR_LO); + + if (!(pciexbar_reg & 1)) { + 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; +} diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h new file mode 100644 index 0000000000..89ca9313b9 --- /dev/null +++ b/src/northbridge/intel/x4x/x4x.h @@ -0,0 +1,320 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2008 coresystems GmbH + * 2012 secunet Security Networks AG + * 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. + */ + +#ifndef __NORTHBRIDGE_INTEL_X4X_H__ +#define __NORTHBRIDGE_INTEL_X4X_H__ + +#include +#include + +/* + * D0:F0 + */ +#define D0F0_EPBAR_LO 0x40 +#define D0F0_EPBAR_HI 0x44 +#define D0F0_MCHBAR_LO 0x48 +#define D0F0_MCHBAR_HI 0x4c +#define D0F0_GGC 0x52 +#define D0F0_DEVEN 0x54 +#define D0F0_PCIEXBAR_LO 0x60 +#define D0F0_PCIEXBAR_HI 0x64 +#define D0F0_DMIBAR_LO 0x68 +#define D0F0_DMIBAR_HI 0x6c +#define D0F0_PMBASE 0x78 +#define D0F0_PAM(x) (0x90+(x)) /* 0-6*/ +#define D0F0_REMAPBASE 0x98 +#define D0F0_REMAPLIMIT 0x9a +#define D0F0_SMRAM 0x9d +#define D0F0_ESMRAMC 0x9e +#define D0F0_TOM 0xa0 +#define D0F0_TOUUD 0xa2 +#define D0F0_TOLUD 0xb0 +#define D0F0_GBSM 0xa4 +#define D0F0_BGSM 0xa8 +#define D0F0_TSEG 0xac +#define D0F0_SKPD 0xdc /* Scratchpad Data */ +#define D0F0_CAPID0 0xe0 + +/* + * D1:F0 PEG + */ +#define PEG_CAP 0xa2 +#define SLOTCAP 0xb4 +#define PEGLC 0xec +#define D1F0_VCCAP 0x104 +#define D1F0_VC0RCTL 0x114 + +/* + * Graphics frequencies + */ +#define GCFGC_PCIDEV PCI_DEV(0, 2, 0) +#define GCFGC_OFFSET 0xf0 +#define GCFGC_CR_SHIFT 0 +#define GCFGC_CR_MASK (0xf << GCFGC_CR_SHIFT) +#define GCFGC_CS_SHIFT 8 +#define GCFGC_CS_MASK (0xf << GCFGC_CS_SHIFT) +#define GCFGC_CD_SHIFT 12 +#define GCFGC_CD_MASK (0x1 << GCFGC_CD_SHIFT) +#define GCFGC_UPDATE_SHIFT 5 +#define GCFGC_UPDATE (0x1 << GCFGC_UPDATE_SHIFT) + +/* + * MCHBAR + */ + +#define MCHBAR8(x) *((volatile u8 *)(DEFAULT_MCHBAR + x)) +#define MCHBAR16(x) *((volatile u16 *)(DEFAULT_MCHBAR + x)) +#define MCHBAR32(x) *((volatile u32 *)(DEFAULT_MCHBAR + x)) + +#define PMSTS_MCHBAR 0x0f14 /* Self refresh channel status */ +#define PMSTS_WARM_RESET (1 << 1) +#define PMSTS_BOTH_SELFREFRESH (1 << 0) + +#define CLKCFG_MCHBAR 0x0c00 +#define CLKCFG_FSBCLK_SHIFT 0 +#define CLKCFG_FSBCLK_MASK (7 << CLKCFG_FSBCLK_SHIFT) +#define CLKCFG_MEMCLK_SHIFT 4 +#define CLKCFG_MEMCLK_MASK (7 << CLKCFG_MEMCLK_SHIFT) +#define CLKCFG_UPDATE (1 << 12) + +#define SSKPD_MCHBAR 0x0c1c +#define SSKPD_CLK_SHIFT 0 +#define SSKPD_CLK_MASK (7 << SSKPD_CLK_SHIFT) + +/* + * DMIBAR + */ + +#define DMIBAR8(x) *((volatile u8 *)(DEFAULT_DMIBAR + x)) +#define DMIBAR16(x) *((volatile u16 *)(DEFAULT_DMIBAR + x)) +#define DMIBAR32(x) *((volatile u32 *)(DEFAULT_DMIBAR + x)) + +#define DMIVC0RCTL 0x14 +#define DMIVC1RCTL 0x20 +#define DMIVC1RSTS 0x26 +#define DMIESD 0x44 +#define DMILE1D 0x50 +#define DMILE1A 0x58 +#define DMILE2D 0x60 +#define DMILE2A 0x68 + +/* + * EPBAR + */ + +#define EPBAR8(x) *((volatile u8 *)(DEFAULT_EPBAR + x)) +#define EPBAR16(x) *((volatile u16 *)(DEFAULT_EPBAR + x)) +#define EPBAR32(x) *((volatile u32 *)(DEFAULT_EPBAR + x)) + +#define EPESD 0x44 +#define EPLE1D 0x50 +#define EPLE1A 0x58 +#define EPLE2D 0x60 + +#define NOP_CMD 0x2 +#define PRECHARGE_CMD 0x4 +#define MRS_CMD 0x6 +#define EMRS_CMD 0x8 +#define EMRS1_CMD (EMRS_CMD | 0x10) +#define EMRS2_CMD (EMRS_CMD | 0x20) +#define EMRS3_CMD (EMRS_CMD | 0x30) +#define ZQCAL_CMD 0xa +#define CBR_CMD 0xc +#define NORMALOP_CMD 0xe + +#define TOTAL_CHANNELS 2 +#define TOTAL_DIMMS 4 + +#define DIMM_IS_POPULATED(dimms, idx) (dimms[idx].card_type != 0) +#define IF_DIMM_POPULATED(dimms, idx) if (dimms[idx].card_type != 0) +#define ONLY_DIMMA_IS_POPULATED(dimms, ch) ( \ + (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \ + !DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3))) +#define ONLY_DIMMB_IS_POPULATED(dimms, ch) ( \ + (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3) && \ + !DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2))) +#define BOTH_DIMMS_ARE_POPULATED(dimms, ch) ( \ + (DIMM_IS_POPULATED(dimms, (ch == 0) ? 0 : 2) && \ + (DIMM_IS_POPULATED(dimms, (ch == 0) ? 1 : 3)))) +#define FOR_EACH_DIMM(idx) \ + for (idx = 0; idx < TOTAL_DIMMS; ++idx) +#define FOR_EACH_POPULATED_DIMM(dimms, idx) \ + FOR_EACH_DIMM(idx) IF_DIMM_POPULATED(dimms, idx) +#define CHANNEL_IS_POPULATED(dimms, idx) ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0)) +#define CHANNEL_IS_CARDF(dimms, idx) ((dimms[idx<<1].card_type == 0xf) || (dimms[(idx<<1) + 1].card_type == 0xf)) +#define IF_CHANNEL_POPULATED(dimms, idx) if ((dimms[idx<<1].card_type != 0) || (dimms[(idx<<1) + 1].card_type != 0)) +#define FOR_EACH_CHANNEL(idx) \ + for (idx = 0; idx < TOTAL_CHANNELS; ++idx) +#define FOR_EACH_POPULATED_CHANNEL(dimms, idx) \ + FOR_EACH_CHANNEL(idx) IF_CHANNEL_POPULATED(dimms, idx) + +#define RANKS_PER_CHANNEL 4 +#define RANK_IS_POPULATED(dimms, ch, r) \ + ((dimms[ch<<1].card_type && ((r) < dimms[ch<<1].ranks)) || \ + (dimms[(ch<<1) + 1].card_type && ((r) >= 2) && ((r) < (dimms[(ch<<1) + 1].ranks + 2)))) +#define IF_RANK_POPULATED(dimms, ch, r) \ + if ((dimms[ch<<1].card_type && ((r) < dimms[ch<<1].ranks)) || \ + (dimms[(ch<<1) + 1].card_type && ((r) >= 2) && ((r) < (dimms[(ch<<1) + 1].ranks + 2)))) +#define FOR_EACH_RANK_IN_CHANNEL(r) \ + for (r = 0; r < RANKS_PER_CHANNEL; ++r) +#define FOR_EACH_POPULATED_RANK_IN_CHANNEL(dimms, ch, r) \ + FOR_EACH_RANK_IN_CHANNEL(r) IF_RANK_POPULATED(dimms, ch, r) +#define FOR_EACH_RANK(ch, r) \ + FOR_EACH_CHANNEL(ch) FOR_EACH_RANK_IN_CHANNEL(r) +#define FOR_EACH_POPULATED_RANK(dimms, ch, r) \ + FOR_EACH_RANK(ch, r) IF_RANK_POPULATED(dimms, ch, r) + +#define DDR3_MAX_CAS 18 + +enum fsb_clock { + FSB_CLOCK_800MHz = 0, + FSB_CLOCK_1066MHz = 1, + FSB_CLOCK_1333MHz = 2, +}; + +enum mem_clock { + MEM_CLOCK_400MHz = 0, + MEM_CLOCK_533MHz = 1, + MEM_CLOCK_667MHz = 2, + MEM_CLOCK_800MHz = 3, + MEM_CLOCK_1066MHz = 4, + MEM_CLOCK_1333MHz = 5, +}; + +enum ddr { + DDR2 = 2, + DDR3 = 3, +}; + +enum ddrxspd { + DDR2SPD = 0x8, + DDR3SPD = 0xb, +}; + +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_clock fsb_clk; + enum mem_clock mem_clk; + 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 */ + 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]; +}; + +/* The setup is up to two DIMMs per channel */ +struct sysinfo { + int txt_enabled; + int cores; + int boot_path; + int max_ddr2_mhz; + int max_ddr3_mt; + enum fsb_clock max_fsb; + 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]; +}; + +enum ddr2_signals { + CLKSET0 = 0, + CTRL0, + CLKSET1, + CMD, + CTRL1, + CTRL2, + CTRL3, + DQS1, + DQS2, + DQS3, + DQS4, + DQS5, + DQS6, + DQS7, + DQS8, + DQ1, + DQ2, + DQ3, + DQ4, + DQ5, + DQ6, + DQ7, + DQ8 +}; + +void x4x_early_init(void); +u32 decode_igd_memory_size(u32 gms); +u32 decode_igd_gtt_size(u32 gsm); +u8 decode_pciebar(u32 *const base, u32 *const len); +void sdram_initialize(int boot_path, const u8 *spd_map); +void raminit_ddr2(struct sysinfo *); + +struct acpi_rsdp; +unsigned long northbridge_write_acpi_tables(device_t device, unsigned long start, struct acpi_rsdp *rsdp); + +#endif /* __NORTHBRIDGE_INTEL_X4X_H__ */ -- cgit v1.2.3