10949d249e529b5e8c2d715a4c4ea5c1713e2ea5
[oweals/u-boot.git] / arch / x86 / lib / mrccache.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * From coreboot src/southbridge/intel/bd82x6x/mrccache.c
4  *
5  * Copyright (C) 2014 Google Inc.
6  * Copyright (C) 2015 Bin Meng <bmeng.cn@gmail.com>
7  */
8
9 #include <common.h>
10 #include <dm.h>
11 #include <errno.h>
12 #include <fdtdec.h>
13 #include <net.h>
14 #include <spi.h>
15 #include <spi_flash.h>
16 #include <asm/mrccache.h>
17 #include <dm/device-internal.h>
18 #include <dm/uclass-internal.h>
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 static uint mrc_block_size(uint data_size)
23 {
24         uint mrc_size = sizeof(struct mrc_data_container) + data_size;
25
26         return ALIGN(mrc_size, MRC_DATA_ALIGN);
27 }
28
29 static struct mrc_data_container *next_mrc_block(
30         struct mrc_data_container *cache)
31 {
32         /* MRC data blocks are aligned within the region */
33         u8 *region_ptr = (u8 *)cache;
34
35         region_ptr += mrc_block_size(cache->data_size);
36
37         return (struct mrc_data_container *)region_ptr;
38 }
39
40 static int is_mrc_cache(struct mrc_data_container *cache)
41 {
42         return cache && (cache->signature == MRC_DATA_SIGNATURE);
43 }
44
45 struct mrc_data_container *mrccache_find_current(struct mrc_region *entry)
46 {
47         struct mrc_data_container *cache, *next;
48         ulong base_addr, end_addr;
49         uint id;
50
51         base_addr = entry->base + entry->offset;
52         end_addr = base_addr + entry->length;
53         cache = NULL;
54
55         /* Search for the last filled entry in the region */
56         for (id = 0, next = (struct mrc_data_container *)base_addr;
57              is_mrc_cache(next);
58              id++) {
59                 cache = next;
60                 next = next_mrc_block(next);
61                 if ((ulong)next >= end_addr)
62                         break;
63         }
64
65         if (id-- == 0) {
66                 debug("%s: No valid MRC cache found.\n", __func__);
67                 return NULL;
68         }
69
70         /* Verify checksum */
71         if (cache->checksum != compute_ip_checksum(cache->data,
72                                                    cache->data_size)) {
73                 printf("%s: MRC cache checksum mismatch\n", __func__);
74                 return NULL;
75         }
76
77         debug("%s: picked entry %u from cache block\n", __func__, id);
78
79         return cache;
80 }
81
82 /**
83  * find_next_mrc_cache() - get next cache entry
84  *
85  * This moves to the next cache entry in the region, making sure it has enough
86  * space to hold data of size @data_size.
87  *
88  * @entry:      MRC cache flash area
89  * @cache:      Entry to start from
90  * @data_size:  Required data size of the new entry. Note that we assume that
91  *      all cache entries are the same size
92  *
93  * @return next cache entry if found, NULL if we got to the end
94  */
95 static struct mrc_data_container *find_next_mrc_cache(struct mrc_region *entry,
96                 struct mrc_data_container *prev, int data_size)
97 {
98         struct mrc_data_container *cache;
99         ulong base_addr, end_addr;
100
101         base_addr = entry->base + entry->offset;
102         end_addr = base_addr + entry->length;
103
104         /*
105          * We assume that all cache entries are the same size, but let's use
106          * data_size here for clarity.
107          */
108         cache = next_mrc_block(prev);
109         if ((ulong)cache + mrc_block_size(data_size) > end_addr) {
110                 /* Crossed the boundary */
111                 cache = NULL;
112                 debug("%s: no available entries found\n", __func__);
113         } else {
114                 debug("%s: picked next entry from cache block at %p\n",
115                       __func__, cache);
116         }
117
118         return cache;
119 }
120
121 int mrccache_update(struct udevice *sf, struct mrc_region *entry,
122                     struct mrc_data_container *cur)
123 {
124         struct mrc_data_container *cache;
125         ulong offset;
126         ulong base_addr;
127         int ret;
128
129         if (!is_mrc_cache(cur)) {
130                 debug("%s: Cache data not valid\n", __func__);
131                 return -EINVAL;
132         }
133
134         /* Find the last used block */
135         base_addr = entry->base + entry->offset;
136         debug("Updating MRC cache data\n");
137         cache = mrccache_find_current(entry);
138         if (cache && (cache->data_size == cur->data_size) &&
139             (!memcmp(cache, cur, cache->data_size + sizeof(*cur)))) {
140                 debug("MRC data in flash is up to date. No update\n");
141                 return -EEXIST;
142         }
143
144         /* Move to the next block, which will be the first unused block */
145         if (cache)
146                 cache = find_next_mrc_cache(entry, cache, cur->data_size);
147
148         /*
149          * If we have got to the end, erase the entire mrc-cache area and start
150          * again at block 0.
151          */
152         if (!cache) {
153                 debug("Erasing the MRC cache region of %x bytes at %x\n",
154                       entry->length, entry->offset);
155
156                 ret = spi_flash_erase_dm(sf, entry->offset, entry->length);
157                 if (ret) {
158                         debug("Failed to erase flash region\n");
159                         return ret;
160                 }
161                 cache = (struct mrc_data_container *)base_addr;
162         }
163
164         /* Write the data out */
165         offset = (ulong)cache - base_addr + entry->offset;
166         debug("Write MRC cache update to flash at %lx\n", offset);
167         ret = spi_flash_write_dm(sf, offset, cur->data_size + sizeof(*cur),
168                                  cur);
169         if (ret) {
170                 debug("Failed to write to SPI flash\n");
171                 return log_msg_ret("Cannot update mrccache", ret);
172         }
173
174         return 0;
175 }
176
177 static void mrccache_setup(struct mrc_output *mrc, void *data)
178 {
179         struct mrc_data_container *cache = data;
180         u16 checksum;
181
182         cache->signature = MRC_DATA_SIGNATURE;
183         cache->data_size = mrc->len;
184         checksum = compute_ip_checksum(mrc->buf, cache->data_size);
185         debug("Saving %d bytes for MRC output data, checksum %04x\n",
186               cache->data_size, checksum);
187         cache->checksum = checksum;
188         cache->reserved = 0;
189         memcpy(cache->data, mrc->buf, cache->data_size);
190
191         mrc->cache = cache;
192 }
193
194 int mrccache_reserve(void)
195 {
196         int i;
197
198         for (i = 0; i < MRC_TYPE_COUNT; i++) {
199                 struct mrc_output *mrc = &gd->arch.mrc[i];
200
201                 if (!mrc->len)
202                         continue;
203
204                 /* adjust stack pointer to store pure cache data plus header */
205                 gd->start_addr_sp -= (mrc->len + MRC_DATA_HEADER_SIZE);
206                 mrccache_setup(mrc, (void *)gd->start_addr_sp);
207
208                 gd->start_addr_sp &= ~0xf;
209         }
210
211         return 0;
212 }
213
214 int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
215                         struct mrc_region *entry)
216 {
217         struct udevice *dev;
218         ofnode mrc_node;
219         ulong map_base;
220         uint map_size;
221         uint offset;
222         u32 reg[2];
223         int ret;
224
225         /*
226          * Find the flash chip within the SPI controller node. Avoid probing
227          * the device here since it may put it into a strange state where the
228          * memory map cannot be read.
229          */
230         ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
231         if (ret)
232                 return log_msg_ret("Cannot find SPI flash\n", ret);
233         ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
234         if (!ret) {
235                 entry->base = map_base;
236         } else {
237                 ret = dev_read_u32_array(dev, "memory-map", reg, 2);
238                 if (ret)
239                         return log_msg_ret("Cannot find memory map\n", ret);
240                 entry->base = reg[0];
241         }
242
243         /* Find the place where we put the MRC cache */
244         mrc_node = dev_read_subnode(dev, type == MRC_TYPE_NORMAL ?
245                                     "rw-mrc-cache" : "rw-var-mrc-cache");
246         if (!ofnode_valid(mrc_node))
247                 return log_msg_ret("Cannot find node", -EPERM);
248
249         ret = ofnode_read_u32_array(mrc_node, "reg", reg, 2);
250         if (ret)
251                 return log_msg_ret("Cannot find address", ret);
252         entry->offset = reg[0];
253         entry->length = reg[1];
254
255         if (devp)
256                 *devp = dev;
257         debug("MRC cache type %d in '%s', offset %x, len %x, base %x\n",
258               type, dev->name, entry->offset, entry->length, entry->base);
259
260         return 0;
261 }
262
263 static int mrccache_save_type(enum mrc_type_t type)
264 {
265         struct mrc_data_container *cache;
266         struct mrc_output *mrc;
267         struct mrc_region entry;
268         struct udevice *sf;
269         int ret;
270
271         mrc = &gd->arch.mrc[type];
272         if (!mrc->len)
273                 return 0;
274         log_debug("Saving %#x bytes of MRC output data type %d to SPI flash\n",
275                   mrc->len, type);
276         ret = mrccache_get_region(type, &sf, &entry);
277         if (ret)
278                 return log_msg_ret("Cannot get region", ret);
279         ret = device_probe(sf);
280         if (ret)
281                 return log_msg_ret("Cannot probe device", ret);
282         cache = mrc->cache;
283
284         ret = mrccache_update(sf, &entry, cache);
285         if (!ret)
286                 debug("Saved MRC data with checksum %04x\n", cache->checksum);
287         else if (ret == -EEXIST)
288                 debug("MRC data is the same as last time, skipping save\n");
289
290         return 0;
291 }
292
293 int mrccache_save(void)
294 {
295         int i;
296
297         for (i = 0; i < MRC_TYPE_COUNT; i++) {
298                 int ret;
299
300                 ret = mrccache_save_type(i);
301                 if (ret)
302                         return ret;
303         }
304
305         return 0;
306 }
307
308 int mrccache_spl_save(void)
309 {
310         int i;
311
312         for (i = 0; i < MRC_TYPE_COUNT; i++) {
313                 struct mrc_output *mrc = &gd->arch.mrc[i];
314                 void *data;
315                 int size;
316
317                 size = mrc->len + MRC_DATA_HEADER_SIZE;
318                 data = malloc(size);
319                 if (!data)
320                         return log_msg_ret("Allocate MRC cache block", -ENOMEM);
321                 mrccache_setup(mrc, data);
322         }
323
324         return mrccache_save();
325 }