Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2016 Google, Inc * * From coreboot src/soc/intel/broadwell/romstage/raminit.c */ #define LOG_CATEGORY UCLASS_RAM #include <dm.h> #include <init.h> #include <log.h> #include <pci.h> #include <syscon.h> #include <asm/cpu.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/lpc_common.h> #include <asm/mrccache.h> #include <asm/mrc_common.h> #include <asm/mtrr.h> #include <asm/pci.h> #include <asm/arch/iomap.h> #include <asm/arch/me.h> #include <asm/arch/pch.h> #include <asm/arch/pei_data.h> #include <asm/arch/pm.h> phys_addr_t board_get_usable_ram_top(phys_size_t total_size) { return mrc_common_board_get_usable_ram_top(total_size); } int dram_init_banksize(void) { mrc_common_dram_init_banksize(); return 0; } static unsigned long get_top_of_ram(struct udevice *dev) { /* * Base of DPR is top of usable DRAM below 4GiB. The register has * 1 MiB alignment and reports the TOP of the range, the base * must be calculated from the size in MiB in bits 11:4. */ u32 dpr, tom; dm_pci_read_config32(dev, DPR, &dpr); tom = dpr & ~((1 << 20) - 1); debug("dpt %08x tom %08x\n", dpr, tom); /* Subtract DMA Protected Range size if enabled */ if (dpr & DPR_EPM) tom -= (dpr & DPR_SIZE_MASK) << 16; return (unsigned long)tom; } /** * sdram_find() - Find available memory * * This is a bit complicated since on x86 there are system memory holes all * over the place. We create a list of available memory blocks * * @dev: Northbridge device */ static int sdram_find(struct udevice *dev) { struct memory_info *info = &gd->arch.meminfo; ulong top_of_ram; top_of_ram = get_top_of_ram(dev); mrc_add_memory_area(info, 0, top_of_ram); /* Add MTRRs for memory */ mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30); return 0; } static int prepare_mrc_cache(struct pei_data *pei_data) { struct mrc_data_container *mrc_cache; struct mrc_region entry; int ret; ret = mrccache_get_region(MRC_TYPE_NORMAL, NULL, &entry); if (ret) return ret; mrc_cache = mrccache_find_current(&entry); if (!mrc_cache) return -ENOENT; pei_data->saved_data = mrc_cache->data; pei_data->saved_data_size = mrc_cache->data_size; debug("%s: at %p, size %x checksum %04x\n", __func__, pei_data->saved_data, pei_data->saved_data_size, mrc_cache->checksum); return 0; } int dram_init(void) { struct pei_data _pei_data __aligned(8); struct pei_data *pei_data = &_pei_data; struct udevice *dev, *me_dev, *pch_dev; struct chipset_power_state ps; const void *spd_data; int ret, size; memset(pei_data, '\0', sizeof(struct pei_data)); /* Print ME state before MRC */ ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev); if (ret) { debug("Cannot get ME (err=%d)\n", ret); return ret; } intel_me_status(me_dev); /* Save ME HSIO version */ ret = uclass_first_device_err(UCLASS_PCH, &pch_dev); if (ret) { debug("Cannot get PCH (err=%d)\n", ret); return ret; } power_state_get(pch_dev, &ps); intel_me_hsio_version(me_dev, &ps.hsio_version, &ps.hsio_checksum); broadwell_fill_pei_data(pei_data); mainboard_fill_pei_data(pei_data); ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev); if (ret) { debug("Cannot get Northbridge (err=%d)\n", ret); return ret; } size = 256; ret = mrc_locate_spd(dev, size, &spd_data); if (ret) { debug("Cannot locate SPD (err=%d)\n", ret); return ret; } memcpy(pei_data->spd_data[0][0], spd_data, size); memcpy(pei_data->spd_data[1][0], spd_data, size); ret = prepare_mrc_cache(pei_data); if (ret) debug("prepare_mrc_cache failed: %d\n", ret); debug("PEI version %#x\n", pei_data->pei_version); ret = mrc_common_init(dev, pei_data, true); if (ret) { debug("mrc_common_init() failed(err=%d)\n", ret); return ret; } debug("Memory init done\n"); ret = sdram_find(dev); if (ret) { debug("sdram_find() failed (err=%d)\n", ret); return ret; } gd->ram_size = gd->arch.meminfo.total_32bit_memory; debug("RAM size %llx\n", (unsigned long long)gd->ram_size); debug("MRC output data length %#x at %p\n", pei_data->data_to_save_size, pei_data->data_to_save); /* S3 resume: don't save scrambler seed or MRC data */ if (pei_data->boot_mode != SLEEP_STATE_S3) { struct mrc_output *mrc = &gd->arch.mrc[MRC_TYPE_NORMAL]; /* * This will be copied to SDRAM in reserve_arch(), then written * to SPI flash in mrccache_save() */ mrc->buf = (char *)pei_data->data_to_save; mrc->len = pei_data->data_to_save_size; } gd->arch.pei_meminfo = pei_data->meminfo; return 0; } /* Use this hook to save our SDRAM parameters */ int misc_init_r(void) { int ret; ret = mrccache_save(); if (ret) printf("Unable to save MRC data: %d\n", ret); else debug("Saved MRC cache data\n"); return 0; } static const struct udevice_id broadwell_syscon_ids[] = { { .compatible = "intel,me", .data = X86_SYSCON_ME }, { } }; U_BOOT_DRIVER(syscon_intel_me) = { .name = "intel_me_syscon", .id = UCLASS_SYSCON, .of_match = broadwell_syscon_ids, }; |