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