/** * sandybridge_init_iommu() - Set up IOMMU so that azalia can be used * * It is not obvious where these values come from. They may be undocumented. */ static void sandybridge_init_iommu(struct udevice *dev) { u32 capid0_a; dm_pci_read_config32(dev, 0xe4, &capid0_a); if (capid0_a & (1 << 23)) { log_debug("capid0_a not needed\n"); return; } /* setup BARs */ writel(IOMMU_BASE1 >> 32, MCHBAR_REG(0x5404)); writel(IOMMU_BASE1 | 1, MCHBAR_REG(0x5400)); writel(IOMMU_BASE2 >> 32, MCHBAR_REG(0x5414)); writel(IOMMU_BASE2 | 1, MCHBAR_REG(0x5410)); /* lock policies */ writel(0x80000000, IOMMU_BASE1 + 0xff0); /* Enable azalia sound */ writel(0x20000000, IOMMU_BASE2 + 0xff0); writel(0xa0000000, IOMMU_BASE2 + 0xff0); }
/* * Dump in the log memory controller configuration as read from the memory * controller registers. */ static void report_memory_config(void) { u32 addr_decoder_common, addr_decode_ch[2]; int i; addr_decoder_common = readl(MCHBAR_REG(0x5000)); addr_decode_ch[0] = readl(MCHBAR_REG(0x5004)); addr_decode_ch[1] = readl(MCHBAR_REG(0x5008)); debug("memcfg DDR3 clock %d MHz\n", (readl(MCHBAR_REG(0x5e04)) * 13333 * 2 + 50) / 100); debug("memcfg channel assignment: A: %d, B % d, C % d\n", addr_decoder_common & 3, (addr_decoder_common >> 2) & 3, (addr_decoder_common >> 4) & 3); for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) { u32 ch_conf = addr_decode_ch[i]; debug("memcfg channel[%d] config (%8.8x):\n", i, ch_conf); debug(" ECC %s\n", ecc_decoder[(ch_conf >> 24) & 3]); debug(" enhanced interleave mode %s\n", ((ch_conf >> 22) & 1) ? "on" : "off"); debug(" rank interleave %s\n", ((ch_conf >> 21) & 1) ? "on" : "off"); debug(" DIMMA %d MB width x%d %s rank%s\n", ((ch_conf >> 0) & 0xff) * 256, ((ch_conf >> 19) & 1) ? 16 : 8, ((ch_conf >> 17) & 1) ? "dual" : "single", ((ch_conf >> 16) & 1) ? "" : ", selected"); debug(" DIMMB %d MB width x%d %s rank%s\n", ((ch_conf >> 8) & 0xff) * 256, ((ch_conf >> 20) & 1) ? 16 : 8, ((ch_conf >> 18) & 1) ? "dual" : "single", ((ch_conf >> 16) & 1) ? ", selected" : ""); } }
static void northbridge_init(struct udevice *dev, int rev) { u32 bridge_type; add_fixed_resources(dev, 6); northbridge_dmi_init(dev, rev); bridge_type = readl(MCHBAR_REG(0x5f10)); bridge_type &= ~0xff; if ((rev & BASE_REV_MASK) == BASE_REV_IVB) { /* Enable Power Aware Interrupt Routing - fixed priority */ clrsetbits_8(MCHBAR_REG(0x5418), 0xf, 0x4); /* 30h for IvyBridge */ bridge_type |= 0x30; } else { /* 20h for Sandybridge */ bridge_type |= 0x20; } writel(bridge_type, MCHBAR_REG(0x5f10)); /* * Set bit 0 of BIOS_RESET_CPL to indicate to the CPU * that BIOS has initialized memory and power management */ setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 1); debug("Set BIOS_RESET_CPL\n"); /* Configure turbo power limits 1ms after reset complete bit */ mdelay(1); set_power_limits(28); /* * CPUs with configurable TDP also need power limits set * in MCHBAR. Use same values from MSR_PKG_POWER_LIMIT. */ if (cpu_config_tdp_levels()) { msr_t msr = msr_read(MSR_PKG_POWER_LIMIT); writel(msr.lo, MCHBAR_REG(0x59A0)); writel(msr.hi, MCHBAR_REG(0x59A4)); } /* Set here before graphics PM init */ writel(0x00100001, MCHBAR_REG(0x5500)); }
static void post_system_agent_init(struct udevice *dev, struct udevice *me_dev, struct pei_data *pei_data) { uint16_t done; /* * Send ME init done for SandyBridge here. This is done inside the * SystemAgent binary on IvyBridge */ dm_pci_read_config16(dev, PCI_DEVICE_ID, &done); done &= BASE_REV_MASK; if (BASE_REV_SNB == done) intel_early_me_init_done(dev, me_dev, ME_INIT_STATUS_SUCCESS); else intel_me_status(me_dev); /* If PCIe init is skipped, set the PEG clock gating */ if (!pei_data->pcie_init) setbits_le32(MCHBAR_REG(0x7010), 1); }
/** * Find the PEI executable in the ROM and execute it. * * @param pei_data: configuration data for UEFI PEI reference code */ int sdram_initialise(struct pei_data *pei_data) { unsigned version; const char *data; uint16_t done; int ret; report_platform_info(); /* Wait for ME to be ready */ ret = intel_early_me_init(); if (ret) return ret; ret = intel_early_me_uma_size(); if (ret < 0) return ret; debug("Starting UEFI PEI System Agent\n"); /* * Do not pass MRC data in for recovery mode boot, * Always pass it in for S3 resume. */ if (!recovery_mode_enabled() || pei_data->boot_mode == PEI_BOOT_RESUME) { ret = prepare_mrc_cache(pei_data); if (ret) debug("prepare_mrc_cache failed: %d\n", ret); } /* If MRC data is not found we cannot continue S3 resume. */ if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) { debug("Giving up in sdram_initialize: No MRC data\n"); reset_cpu(0); } /* Pass console handler in pei_data */ pei_data->tx_byte = console_tx_byte; debug("PEI data at %p, size %x:\n", pei_data, sizeof(*pei_data)); data = (char *)CONFIG_X86_MRC_ADDR; if (data) { int rv; int (*func)(struct pei_data *); debug("Calling MRC at %p\n", data); post_code(POST_PRE_MRC); func = (int (*)(struct pei_data *))data; rv = func(pei_data); post_code(POST_MRC); if (rv) { switch (rv) { case -1: printf("PEI version mismatch.\n"); break; case -2: printf("Invalid memory frequency.\n"); break; default: printf("MRC returned %x.\n", rv); } printf("Nonzero MRC return value.\n"); return -EFAULT; } } else { printf("UEFI PEI System Agent not found.\n"); return -ENOSYS; } #if CONFIG_USBDEBUG /* mrc.bin reconfigures USB, so reinit it to have debug */ early_usbdebug_init(); #endif version = readl(MCHBAR_REG(0x5034)); debug("System Agent Version %d.%d.%d Build %d\n", version >> 24 , (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); debug("MCR output data length %#x at %p\n", pei_data->mrc_output_len, pei_data->mrc_output); /* * Send ME init done for SandyBridge here. This is done inside the * SystemAgent binary on IvyBridge */ done = x86_pci_read_config32(PCH_DEV, PCI_DEVICE_ID); done &= BASE_REV_MASK; if (BASE_REV_SNB == done) intel_early_me_init_done(ME_INIT_STATUS_SUCCESS); else intel_early_me_status(); post_system_agent_init(pei_data); report_memory_config(); /* S3 resume: don't save scrambler seed or MRC data */ if (pei_data->boot_mode != PEI_BOOT_RESUME) { /* * This will be copied to SDRAM in reserve_arch(), then written * to SPI flash in sdram_save_mrc_data() */ gd->arch.mrc_output = (char *)pei_data->mrc_output; gd->arch.mrc_output_len = pei_data->mrc_output_len; ret = write_seeds_to_cmos(pei_data); if (ret) debug("Failed to write seeds to CMOS: %d\n", ret); } return 0; }
static void post_system_agent_init(struct pei_data *pei_data) { /* If PCIe init is skipped, set the PEG clock gating */ if (!pei_data->pcie_init) setbits_le32(MCHBAR_REG(0x7010), 1); }