and though bugs are the bane of my existence, rest assured the wretched thing will get the best of care here

...
 
Commits (2)
......@@ -18,8 +18,6 @@ romstage-y += romstage.c
romstage-y += early_init.c
romstage-y += report_platform.c
smm-y += finalize.c
# We don't ship that, but booting without it is bound to fail
cbfs-files-$(CONFIG_HAVE_MRC) += mrc.bin
mrc.bin-file := $(call strip_quotes,$(CONFIG_MRC_FILE))
......
......@@ -4,6 +4,14 @@
#define NORTHBRIDGE_INTEL_HASWELL_CHIP_H
#include <drivers/intel/gma/gma.h>
#include <types.h>
struct peg_config {
bool is_onboard;
uint8_t power_limit_scale;
uint8_t power_limit_value;
uint16_t phys_slot_number;
};
/*
* Digital Port Hotplug Enable:
......@@ -20,6 +28,8 @@ struct northbridge_intel_haswell_config {
/* IGD panel configuration */
struct i915_gpu_panel_config panel_cfg;
struct peg_config peg_cfg[3];
bool gpu_ddi_e_connected;
bool ec_present;
......
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/pci_ops.h>
#include "haswell.h"
void intel_northbridge_haswell_finalize_smm(void)
{
pci_or_config16(HOST_BRIDGE, GGC, 1 << 0);
pci_or_config32(HOST_BRIDGE, DPR, 1 << 0);
pci_or_config32(HOST_BRIDGE, MESEG_LIMIT, 1 << 10);
pci_or_config32(HOST_BRIDGE, REMAPBASE, 1 << 0);
pci_or_config32(HOST_BRIDGE, REMAPLIMIT, 1 << 0);
pci_or_config32(HOST_BRIDGE, TOM, 1 << 0);
pci_or_config32(HOST_BRIDGE, TOUUD, 1 << 0);
pci_or_config32(HOST_BRIDGE, BDSM, 1 << 0);
pci_or_config32(HOST_BRIDGE, BGSM, 1 << 0);
pci_or_config32(HOST_BRIDGE, TSEG, 1 << 0);
pci_or_config32(HOST_BRIDGE, TOLUD, 1 << 0);
/* Memory Controller Lockdown */
MCHBAR32(MC_LOCK) |= 0x8f;
MCHBAR32_OR(MMIO_PAVP_MSG, 1 << 0); /* PAVP */
MCHBAR32_OR(PCU_DDR_PTM_CTL, 1 << 5); /* DDR PTM */
MCHBAR32_OR(DMIVCLIM, 1 << 31);
MCHBAR32_OR(CRDTLCK, 1 << 0);
MCHBAR32_OR(MCARBLCK, 1 << 0);
MCHBAR32_OR(REQLIM, 1 << 31);
MCHBAR32_OR(UMAGFXCTL, 1 << 0); /* UMA GFX */
MCHBAR32_OR(VTDTRKLCK, 1 << 0); /* VTDTRK */
/* Read+write the following */
MCHBAR32(VDMBDFBARKVM) = MCHBAR32(VDMBDFBARKVM);
MCHBAR32(VDMBDFBARPAVP) = MCHBAR32(VDMBDFBARPAVP);
MCHBAR32(HDAUDRID) = MCHBAR32(HDAUDRID);
}
......@@ -20,12 +20,33 @@
/* Device 0:1.0 PCI configuration space (PCIe Graphics) */
#define PEG_CAP 0xa2
#define PEG_DCAP 0xa4
#define PEG_LCAP 0xac
#define PEG_DSTS 0xaa
#define PEG_SLOTCAP 0xb4
#define PEG_DCAP2 0xc4 /* 32bit */
#define PEG_LCTL2 0xd0
#define PEG_VC0RCTL 0x114
#define PEG_ESD 0x144 /* 32bit */
#define PEG_LE1D 0x150 /* 32bit */
#define PEG_LE1A 0x158 /* 64bit */
#define PEG_UESTS 0x1c4
#define PEG_UESEV 0x1cc
#define PEG_CESTS 0x1d0
#define PEG_L0SLAT 0x22c
#define PEG_AFE_PM_TMR 0xc28
/* Device 0:2.0 PCI configuration space (Graphics Device) */
#define MSAC 0x62 /* Multi Size Aperture Control */
......@@ -75,8 +96,6 @@
#ifndef __ASSEMBLER__
void intel_northbridge_haswell_finalize_smm(void);
void mb_late_romstage_setup(void); /* optional */
void haswell_early_initialization(void);
......
......@@ -546,11 +546,44 @@ static void northbridge_init(struct device *dev)
set_power_limits(28);
}
static void northbridge_final(struct device *dev)
{
pci_or_config16(dev, GGC, 1 << 0);
pci_or_config32(dev, DPR, 1 << 0);
pci_or_config32(dev, MESEG_LIMIT, 1 << 10);
pci_or_config32(dev, REMAPBASE, 1 << 0);
pci_or_config32(dev, REMAPLIMIT, 1 << 0);
pci_or_config32(dev, TOM, 1 << 0);
pci_or_config32(dev, TOUUD, 1 << 0);
pci_or_config32(dev, BDSM, 1 << 0);
pci_or_config32(dev, BGSM, 1 << 0);
pci_or_config32(dev, TSEG, 1 << 0);
pci_or_config32(dev, TOLUD, 1 << 0);
/* Memory Controller Lockdown */
MCHBAR32(MC_LOCK) |= 0x8f;
MCHBAR32_OR(MMIO_PAVP_MSG, 1 << 0); /* PAVP */
MCHBAR32_OR(PCU_DDR_PTM_CTL, 1 << 5); /* DDR PTM */
MCHBAR32_OR(DMIVCLIM, 1 << 31);
MCHBAR32_OR(CRDTLCK, 1 << 0);
MCHBAR32_OR(MCARBLCK, 1 << 0);
MCHBAR32_OR(REQLIM, 1 << 31);
MCHBAR32_OR(UMAGFXCTL, 1 << 0); /* UMA GFX */
MCHBAR32_OR(VTDTRKLCK, 1 << 0); /* VTDTRK */
/* Read+write the following */
MCHBAR32(VDMBDFBARKVM) = MCHBAR32(VDMBDFBARKVM);
MCHBAR32(VDMBDFBARPAVP) = MCHBAR32(VDMBDFBARPAVP);
MCHBAR32(HDAUDRID) = MCHBAR32(HDAUDRID);
}
static struct device_operations mc_ops = {
.read_resources = mc_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = northbridge_init,
.final = northbridge_final,
.acpi_fill_ssdt = generate_cpu_entries,
.ops_pci = &pci_dev_ops_pci,
};
......
......@@ -5,7 +5,12 @@
#include <device/pci.h>
#include <device/pciexp.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <assert.h>
#include <types.h>
#include "chip.h"
#include "haswell.h"
#if CONFIG(HAVE_ACPI_TABLES)
static const char *pcie_acpi_name(const struct device *dev)
......@@ -41,12 +46,101 @@ static const char *pcie_acpi_name(const struct device *dev)
}
#endif
static void peg_enable(struct device *dev)
{
const struct northbridge_intel_haswell_config *config = config_of(dev);
const uint8_t func = PCI_FUNC(PCI_BDF(dev));
assert(func < ARRAY_SIZE(config->peg_cfg));
const bool slot_implemented = !config->peg_cfg[func].is_onboard;
if (slot_implemented) {
/* Default is 1, but register is R/WO and needs to be written to once */
pci_or_config16(dev, PEG_CAP, 1 << 8);
} else {
pci_and_config16(dev, PEG_CAP, ~(1 << 8));
}
/* Note: this register is write-once */
uint32_t slotcap = pci_read_config32(dev, PEG_SLOTCAP);
/* Physical slot number (zero for ports connected to onboard devices) */
slotcap &= ~(0x1fff << 19);
if (slot_implemented) {
uint16_t slot_number = config->peg_cfg[func].phys_slot_number & 0x1fff;
if (slot_number == 0) {
/* Slot number must be non-zero and unique */
slot_number = func + 1;
}
slotcap |= slot_number << 19;
}
/* Default to 1.0 watt scale */
slotcap &= ~(3 << 15);
slotcap |= (config->peg_cfg[func].power_limit_scale & 3) << 15;
uint8_t power_limit_value = config->peg_cfg[func].power_limit_value;
if (power_limit_value == 0) {
/* Default to 75 watts */
power_limit_value = 75;
}
slotcap &= ~(0xff << 7);
slotcap |= power_limit_value << 7;
pci_write_config32(dev, PEG_SLOTCAP, slotcap);
/* Clear errors */
pci_write_config16(dev, PCI_STATUS, 0xffff);
pci_write_config16(dev, PCI_SEC_STATUS, 0xffff);
pci_write_config16(dev, PEG_DSTS, 0xffff);
pci_write_config32(dev, PEG_UESTS, 0xffffffff);
pci_write_config32(dev, PEG_CESTS, 0xffffffff);
pci_write_config32(dev, 0x1f0, 0xffffffff);
pci_or_config32(dev, PEG_VC0RCTL, 0x7f << 1);
/* Advertise OBFF support using WAKE# signaling only */
pci_or_config32(dev, PEG_DCAP2, 1 << 19);
pci_or_config32(dev, PEG_UESEV, 1 << 14);
/* Select -3.5 dB de-emphasis */
pci_or_config32(dev, PEG_LCTL2, 1 << 6);
pci_or_config32(dev, PEG_L0SLAT, 1 << 31);
pci_update_config32(dev, 0x250, ~(7 << 20), 2 << 20);
pci_or_config32(dev, 0x238, 1 << 29);
pci_or_config32(dev, 0x1f8, 1 << 16);
pci_update_config32(dev, PEG_AFE_PM_TMR, ~0x1f, 0x13);
/* Lock DCAP */
pci_update_config32(dev, PEG_DCAP, ~0, 0);
if (func == 0)
pci_or_config32(dev, 0xcd0, 1 << 11);
/* Enable support for L0s and L1 */
pci_or_config32(dev, PEG_LCAP, 3 << 10);
pci_and_config32(dev, 0x200, ~(3 << 26));
/* Other fields in this register must not be changed while writing this */
pci_or_config16(dev, 0x258, 1 << 2);
}
static struct device_operations device_ops = {
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_bus_enable_resources,
.scan_bus = pciexp_scan_bridge,
.reset_bus = pci_bus_reset,
.enable = peg_enable,
.init = pci_dev_init,
.ops_pci = &pci_dev_ops_pci,
#if CONFIG(HAVE_ACPI_TABLES)
......
......@@ -273,7 +273,6 @@ static void southbridge_smi_apmc(void)
}
intel_pch_finalize_smm();
intel_northbridge_haswell_finalize_smm();
intel_cpu_haswell_finalize_smm();
chipset_finalized = 1;
......