Damien Zammit (damien@zamaudio.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/11305
-gerrit
commit e029105724f1299baf8585c6bbccf16542d2587f Author: Damien Zammit damien@zamaudio.com Date: Wed Aug 19 15:16:59 2015 +1000
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 damien@zamaudio.com --- src/Kconfig | 1 + src/northbridge/intel/x4x/Kconfig | 39 +++ src/northbridge/intel/x4x/Makefile.inc | 29 +++ src/northbridge/intel/x4x/acpi.c | 87 +++++++ src/northbridge/intel/x4x/acpi/hostbridge.asl | 234 +++++++++++++++++ src/northbridge/intel/x4x/acpi/peg.asl | 42 +++ src/northbridge/intel/x4x/acpi/x4x.asl | 46 ++++ src/northbridge/intel/x4x/bootblock.c | 32 +++ src/northbridge/intel/x4x/chip.h | 26 ++ src/northbridge/intel/x4x/debug.h | 28 ++ src/northbridge/intel/x4x/early_init.c | 58 +++++ src/northbridge/intel/x4x/gma.c | 286 ++++++++++++++++++++ src/northbridge/intel/x4x/northbridge.c | 268 +++++++++++++++++++ src/northbridge/intel/x4x/ram_calc.c | 49 ++++ src/northbridge/intel/x4x/x4x.h | 360 ++++++++++++++++++++++++++ 15 files changed, 1585 insertions(+)
diff --git a/src/Kconfig b/src/Kconfig index 8439a00..a491049 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -358,6 +358,7 @@ source "src/mainboard/Kconfig" config CBFS_SIZE hex "Size of CBFS filesystem in ROM" default 0x100000 if HAVE_INTEL_FIRMWARE || \ + NORTHBRIDGE_INTEL_X4X || \ NORTHBRIDGE_INTEL_GM45 || NORTHBRIDGE_INTEL_SANDYBRIDGE_MRC || \ NORTHBRIDGE_INTEL_IVYBRIDGE_MRC || NORTHBRIDGE_INTEL_IVYBRIDGE || \ NORTHBRIDGE_INTEL_SANDYBRIDGE || \ diff --git a/src/northbridge/intel/x4x/Kconfig b/src/northbridge/intel/x4x/Kconfig new file mode 100644 index 0000000..c330fd5 --- /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 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. +## + +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 0000000..34d9b0f --- /dev/null +++ b/src/northbridge/intel/x4x/Makefile.inc @@ -0,0 +1,29 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2012 secunet Security Networks AG +# 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. +# + +ifeq ($(CONFIG_NORTHBRIDGE_INTEL_X4X),y) + +romstage-y += early_init.c +romstage-y += raminit.c +romstage-y += raminit_ddr2.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 0000000..c88c676 --- /dev/null +++ b/src/northbridge/intel/x4x/acpi.c @@ -0,0 +1,87 @@ +/* + * 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 <types.h> +#include <string.h> +#include <console/console.h> +#include <arch/acpi.h> +#include <arch/acpigen.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <cbmem.h> +#include <arch/acpigen.h> +#include <cpu/cpu.h> +#include "x4x.h" + +unsigned long acpi_fill_mcfg(unsigned long current) +{ + device_t dev; + u32 pciexbar = 0; + u32 pciexbar_reg; + int max_buses; + + dev = dev_find_slot(0, PCI_DEVFN(0,0)); + if (!dev) + return current; + + pciexbar_reg = pci_read_config32(dev, D0F0_PCIEXBAR_LO); + + // MMCFG not supported or not enabled. + if (!(pciexbar_reg & (1 << 0))) + return current; + + switch ((pciexbar_reg >> 1) & 3) { + case 0: // 256MB + pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)); + max_buses = 256; + break; + case 1: // 128M + pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)); + max_buses = 128; + break; + case 2: // 64M + pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)); + max_buses = 64; + break; + default: // RSVD + return current; + } + + if (!pciexbar) + return current; + + current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, + pciexbar, 0x0, 0x0, max_buses - 1); + + return current; +} + +#define ALIGN_CURRENT current = (ALIGN(current, 16)) +unsigned long northbridge_write_acpi_tables(device_t device, + unsigned long start, + struct acpi_rsdp *rsdp) +{ + unsigned long current; + current = start; + + ALIGN_CURRENT; + + 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 0000000..530fdfa --- /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 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 <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), // 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 0000000..f2314c2 --- /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 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. + */ + +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 0000000..0b31f4d --- /dev/null +++ b/src/northbridge/intel/x4x/acpi/x4x.asl @@ -0,0 +1,46 @@ +/* + * 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 "hostbridge.asl" +#include "../x4x.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" diff --git a/src/northbridge/intel/x4x/bootblock.c b/src/northbridge/intel/x4x/bootblock.c new file mode 100644 index 0000000..adcaa89 --- /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 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 <arch/io.h> + +#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 | (2 << 1) | 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 0000000..1fb54cc --- /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 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. + */ + +#ifndef NORTHBRIDGE_INTEL_X4X_CHIP_H +#define NORTHBRIDGE_INTEL_X4X_CHIP_H + +#include <drivers/intel/gma/i915.h> + +struct northbridge_intel_x4x_config { + struct i915_gpu_controller_info gfx; +}; + +#endif diff --git a/src/northbridge/intel/x4x/debug.h b/src/northbridge/intel/x4x/debug.h new file mode 100644 index 0000000..c5d3cf4 --- /dev/null +++ b/src/northbridge/intel/x4x/debug.h @@ -0,0 +1,28 @@ +/* + * 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. + */ + +/* Debugging macros. */ +#if 1 +#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x) +#else +#define PRINTK_DEBUG(x...) +#endif + +#if 0 +#define PRINTK_VERBOSE(x...) printk(BIOS_DEBUG, x) +#else +#define PRINTK_VERBOSE(x...) +#endif diff --git a/src/northbridge/intel/x4x/early_init.c b/src/northbridge/intel/x4x/early_init.c new file mode 100644 index 0000000..1d43e0a --- /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 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 <stdint.h> +#include <arch/io.h> +#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 0000000..7891229 --- /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 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 <arch/io.h> +#include <console/console.h> +#include <delay.h> +#include <device/device.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <string.h> +#include <device/pci_ops.h> +#include <cpu/x86/msr.h> +#include <cpu/x86/mtrr.h> +#include <kconfig.h> + +#include "drivers/intel/gma/i915_reg.h" +#include "chip.h" +#include "x4x.h" +#include <drivers/intel/gma/intel_bios.h> +#include <drivers/intel/gma/i915.h> +#include <pc80/vga.h> +#include <pc80/vga_io.h> + +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/northbridge.c b/src/northbridge/intel/x4x/northbridge.c new file mode 100644 index 0000000..716844b --- /dev/null +++ b/src/northbridge/intel/x4x/northbridge.c @@ -0,0 +1,268 @@ +/* + * 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 "chip.h" +#include "x4x.h" +#include "arch/acpi.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 int decode_pcie_bar(u32 *const base, u32 *const len) +{ + *base = 0; + *len = 0; + + const device_t dev = dev_find_slot(0, PCI_DEVFN(0, 0)); + if (!dev) + return 0; + + const u32 pciexbar_reg = pci_read_config32(dev, D0F0_PCIEXBAR_LO); + + if (!(pciexbar_reg & (1 << 0))) + return 0; + + switch ((pciexbar_reg >> 1) & 3) { + case 0: /* 256MB */ + *base = pciexbar_reg & (0x0f << 28); + *len = 256 * 1024 * 1024; + return 1; + case 1: /* 128M */ + *base = pciexbar_reg & (0x1f << 27); + *len = 128 * 1024 * 1024; + return 1; + case 2: /* 64M */ + *base = pciexbar_reg & (0x3f << 26); + *len = 64 * 1024 * 1024; + return 1; + } + + return 0; +} + +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_pcie_bar(&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); + } +} + +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, + .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 0000000..b89240e --- /dev/null +++ b/src/northbridge/intel/x4x/ram_calc.c @@ -0,0 +1,49 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 secunet Security Networks AG + * 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. + */ + +// Use simple device model for this file even in ramstage +#define __SIMPLE_DEVICE__ + +#include <stdint.h> +#include <arch/io.h> +#include <device/pci_def.h> +#include <console/console.h> +#include <cbmem.h> +#include "x4x.h" + +/** Decodes used Graphics Mode Select (GMS) to kilobytes. */ +u32 decode_igd_memory_size(const u32 gms) +{ + 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) +{ + 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; +} diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h new file mode 100644 index 0000000..f8f1bda --- /dev/null +++ b/src/northbridge/intel/x4x/x4x.h @@ -0,0 +1,360 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2008 coresystems GmbH + * 2012 secunet Security Networks AG + * 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. + */ + +#ifndef __NORTHBRIDGE_INTEL_X4X_X4X_H__ +#define __NORTHBRIDGE_INTEL_X4X_X4X_H__ + +#include "southbridge/intel/i82801gx/i82801gx.h" + +#ifndef __ACPI__ + +#include <rules.h> +#include <stdint.h> + +typedef enum { + FSB_CLOCK_800MHz = 0, + FSB_CLOCK_1066MHz = 1, + FSB_CLOCK_1333MHz = 2, +} fsb_clock_t; + +typedef enum { + MEM_CLOCK_400MHz = 0, + MEM_CLOCK_533MHz = 1, + MEM_CLOCK_667MHz = 2, + MEM_CLOCK_800MHz = 3, + MEM_CLOCK_1066MHz = 4, + MEM_CLOCK_1333MHz = 5, +} mem_clock_t; + +typedef enum { + DDR2 = 2, + DDR3 = 3, +} ddr_t; + +typedef enum { /* as in DDR3 spd */ + CHIP_WIDTH_x4 = 0, + CHIP_WIDTH_x8 = 1, + CHIP_WIDTH_x16 = 2, + CHIP_WIDTH_x32 = 3, +} chip_width_t; + +typedef enum { /* 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, +} chip_capacity_t; + +typedef struct { + unsigned int CAS; + fsb_clock_t fsb_clock; + mem_clock_t 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; +} timings_t; + +typedef struct { + unsigned int card_type; /* 0x0: unpopulated, + 0xa - 0xf: raw card type A - F */ + chip_width_t width; + chip_capacity_t 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]; +} dimminfo_t; + +/* The setup is up to two DIMMs per channel */ +typedef struct { + int txt_enabled; + int cores; + int boot_path; + int max_ddr2_mhz; + int max_ddr3_mt; + fsb_clock_t 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]; + timings_t selected_timings; + dimminfo_t dimms[4]; + u8 spd_map[4]; +} sysinfo_t; + +typedef enum { + CLKSET0 = 0, + CTRL0, + CLKSET1, + CMD, + CTRL1, + CTRL2, + CTRL3, + DQS1, + DQS2, + DQS3, + DQS4, + DQS5, + DQS6, + DQS7, + DQS8, + DQ1, + DQ2, + DQ3, + DQ4, + DQ5, + DQ6, + DQ7, + DQ8 +} DDR2_Signals; + +#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 { + VCO_2666 = 4, + VCO_3200 = 0, + VCO_4000 = 1, + VCO_5333 = 2, +}; + +#endif + +/* Offsets of read/write training results in CMOS. + They will be restored upon S3 resumes. */ +#define CMOS_READ_TRAINING 0x80 /* 16 bytes */ +#define CMOS_WRITE_TRAINING 0x90 /* 16 bytes + (could be reduced to 10 bytes) */ + + +#ifndef __ACPI__ +#define DEFAULT_MCHBAR ((u8 *)0xfed14000) +#define DEFAULT_DMIBAR ((u8 *)0xfed18000) +#else +#define DEFAULT_MCHBAR 0xfed14000 +#define DEFAULT_DMIBAR 0xfed18000 +#endif +#define DEFAULT_EPBAR 0xfed19000 +#define DEFAULT_HECIBAR 0xfed10000 + + /* 4 KB per PCIe device */ +#define DEFAULT_PCIEXBAR CONFIG_MMCONF_BASE_ADDRESS + +/* + * 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 + + +#ifndef __ACPI__ +void x4x_early_init(void); +u32 decode_igd_memory_size(u32 gms); +u32 decode_igd_gtt_size(u32 gsm); +void init_igd(const sysinfo_t *const); +void igd_compute_ggc(sysinfo_t *const sysinfo); +int raminit_read_vco_index(void); +void sdram_initialize(int boot_path, const u8 *spd_map); +void raminit_ddr2(sysinfo_t *); + + +#if ENV_RAMSTAGE +#include <device/device.h> + +struct acpi_rsdp; +unsigned long northbridge_write_acpi_tables(device_t device, unsigned long start, struct acpi_rsdp *rsdp); +#endif + + +#endif /* !__ACPI__ */ +#endif