dm: core: Require users of devres to include the header
[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 /**
122  * mrccache_update() - update the MRC cache with a new record
123  *
124  * This writes a new record to the end of the MRC cache region. If the new
125  * record is the same as the latest record then the write is skipped
126  *
127  * @sf:         SPI flash to write to
128  * @entry:      Position and size of MRC cache in SPI flash
129  * @cur:        Record to write
130  * @return 0 if updated, -EEXIST if the record is the same as the latest
131  * record, -EINVAL if the record is not valid, other error if SPI write failed
132  */
133 static int mrccache_update(struct udevice *sf, struct mrc_region *entry,
134                            struct mrc_data_container *cur)
135 {
136         struct mrc_data_container *cache;
137         ulong offset;
138         ulong base_addr;
139         int ret;
140
141         if (!is_mrc_cache(cur)) {
142                 debug("%s: Cache data not valid\n", __func__);
143                 return -EINVAL;
144         }
145
146         /* Find the last used block */
147         base_addr = entry->base + entry->offset;
148         debug("Updating MRC cache data\n");
149         cache = mrccache_find_current(entry);
150         if (cache && (cache->data_size == cur->data_size) &&
151             (!memcmp(cache, cur, cache->data_size + sizeof(*cur)))) {
152                 debug("MRC data in flash is up to date. No update\n");
153                 return -EEXIST;
154         }
155
156         /* Move to the next block, which will be the first unused block */
157         if (cache)
158                 cache = find_next_mrc_cache(entry, cache, cur->data_size);
159
160         /*
161          * If we have got to the end, erase the entire mrc-cache area and start
162          * again at block 0.
163          */
164         if (!cache) {
165                 debug("Erasing the MRC cache region of %x bytes at %x\n",
166                       entry->length, entry->offset);
167
168                 ret = spi_flash_erase_dm(sf, entry->offset, entry->length);
169                 if (ret) {
170                         debug("Failed to erase flash region\n");
171                         return ret;
172                 }
173                 cache = (struct mrc_data_container *)base_addr;
174         }
175
176         /* Write the data out */
177         offset = (ulong)cache - base_addr + entry->offset;
178         debug("Write MRC cache update to flash at %lx\n", offset);
179         ret = spi_flash_write_dm(sf, offset, cur->data_size + sizeof(*cur),
180                                  cur);
181         if (ret) {
182                 debug("Failed to write to SPI flash\n");
183                 return log_msg_ret("Cannot update mrccache", ret);
184         }
185
186         return 0;
187 }
188
189 static void mrccache_setup(struct mrc_output *mrc, void *data)
190 {
191         struct mrc_data_container *cache = data;
192         u16 checksum;
193
194         cache->signature = MRC_DATA_SIGNATURE;
195         cache->data_size = mrc->len;
196         checksum = compute_ip_checksum(mrc->buf, cache->data_size);
197         debug("Saving %d bytes for MRC output data, checksum %04x\n",
198               cache->data_size, checksum);
199         cache->checksum = checksum;
200         cache->reserved = 0;
201         memcpy(cache->data, mrc->buf, cache->data_size);
202
203         mrc->cache = cache;
204 }
205
206 int mrccache_reserve(void)
207 {
208         int i;
209
210         for (i = 0; i < MRC_TYPE_COUNT; i++) {
211                 struct mrc_output *mrc = &gd->arch.mrc[i];
212
213                 if (!mrc->len)
214                         continue;
215
216                 /* adjust stack pointer to store pure cache data plus header */
217                 gd->start_addr_sp -= (mrc->len + MRC_DATA_HEADER_SIZE);
218                 mrccache_setup(mrc, (void *)gd->start_addr_sp);
219
220                 gd->start_addr_sp &= ~0xf;
221         }
222
223         return 0;
224 }
225
226 int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
227                         struct mrc_region *entry)
228 {
229         struct udevice *dev;
230         ofnode mrc_node;
231         ulong map_base;
232         uint map_size;
233         uint offset;
234         u32 reg[2];
235         int ret;
236
237         /*
238          * Find the flash chip within the SPI controller node. Avoid probing
239          * the device here since it may put it into a strange state where the
240          * memory map cannot be read.
241          */
242         ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
243         if (ret)
244                 return log_msg_ret("Cannot find SPI flash\n", ret);
245         ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
246         if (!ret) {
247                 entry->base = map_base;
248         } else {
249                 ret = dev_read_u32_array(dev, "memory-map", reg, 2);
250                 if (ret)
251                         return log_msg_ret("Cannot find memory map\n", ret);
252                 entry->base = reg[0];
253         }
254
255         /* Find the place where we put the MRC cache */
256         mrc_node = dev_read_subnode(dev, type == MRC_TYPE_NORMAL ?
257                                     "rw-mrc-cache" : "rw-var-mrc-cache");
258         if (!ofnode_valid(mrc_node))
259                 return log_msg_ret("Cannot find node", -EPERM);
260
261         ret = ofnode_read_u32_array(mrc_node, "reg", reg, 2);
262         if (ret)
263                 return log_msg_ret("Cannot find address", ret);
264         entry->offset = reg[0];
265         entry->length = reg[1];
266
267         if (devp)
268                 *devp = dev;
269         debug("MRC cache type %d in '%s', offset %x, len %x, base %x\n",
270               type, dev->name, entry->offset, entry->length, entry->base);
271
272         return 0;
273 }
274
275 static int mrccache_save_type(enum mrc_type_t type)
276 {
277         struct mrc_data_container *cache;
278         struct mrc_output *mrc;
279         struct mrc_region entry;
280         struct udevice *sf;
281         int ret;
282
283         mrc = &gd->arch.mrc[type];
284         if (!mrc->len)
285                 return 0;
286         log_debug("Saving %#x bytes of MRC output data type %d to SPI flash\n",
287                   mrc->len, type);
288         ret = mrccache_get_region(type, &sf, &entry);
289         if (ret)
290                 return log_msg_ret("Cannot get region", ret);
291         ret = device_probe(sf);
292         if (ret)
293                 return log_msg_ret("Cannot probe device", ret);
294         cache = mrc->cache;
295
296         ret = mrccache_update(sf, &entry, cache);
297         if (!ret)
298                 debug("Saved MRC data with checksum %04x\n", cache->checksum);
299         else if (ret == -EEXIST)
300                 debug("MRC data is the same as last time, skipping save\n");
301
302         return 0;
303 }
304
305 int mrccache_save(void)
306 {
307         int i;
308
309         for (i = 0; i < MRC_TYPE_COUNT; i++) {
310                 int ret;
311
312                 ret = mrccache_save_type(i);
313                 if (ret)
314                         return ret;
315         }
316
317         return 0;
318 }
319
320 int mrccache_spl_save(void)
321 {
322         int i;
323
324         for (i = 0; i < MRC_TYPE_COUNT; i++) {
325                 struct mrc_output *mrc = &gd->arch.mrc[i];
326                 void *data;
327                 int size;
328
329                 size = mrc->len + MRC_DATA_HEADER_SIZE;
330                 data = malloc(size);
331                 if (!data)
332                         return log_msg_ret("Allocate MRC cache block", -ENOMEM);
333                 mrccache_setup(mrc, data);
334         }
335
336         return mrccache_save();
337 }