示例#1
0
/**
 * 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);
}
示例#2
0
/*
 * 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" : "");
    }
}
示例#3
0
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));
}
示例#4
0
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);
}
示例#5
0
/**
 * 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;
}
示例#6
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);
}