mrccache.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. * From coreboot src/southbridge/intel/bd82x6x/mrccache.c
  3. *
  4. * Copyright (C) 2014 Google Inc.
  5. * Copyright (C) 2015 Bin Meng <bmeng.cn@gmail.com>
  6. *
  7. * SPDX-License-Identifier: GPL-2.0
  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. DECLARE_GLOBAL_DATA_PTR;
  18. static struct mrc_data_container *next_mrc_block(
  19. struct mrc_data_container *cache)
  20. {
  21. /* MRC data blocks are aligned within the region */
  22. u32 mrc_size = sizeof(*cache) + cache->data_size;
  23. u8 *region_ptr = (u8 *)cache;
  24. if (mrc_size & (MRC_DATA_ALIGN - 1UL)) {
  25. mrc_size &= ~(MRC_DATA_ALIGN - 1UL);
  26. mrc_size += MRC_DATA_ALIGN;
  27. }
  28. region_ptr += mrc_size;
  29. return (struct mrc_data_container *)region_ptr;
  30. }
  31. static int is_mrc_cache(struct mrc_data_container *cache)
  32. {
  33. return cache && (cache->signature == MRC_DATA_SIGNATURE);
  34. }
  35. struct mrc_data_container *mrccache_find_current(struct mrc_region *entry)
  36. {
  37. struct mrc_data_container *cache, *next;
  38. ulong base_addr, end_addr;
  39. uint id;
  40. base_addr = entry->base + entry->offset;
  41. end_addr = base_addr + entry->length;
  42. cache = NULL;
  43. /* Search for the last filled entry in the region */
  44. for (id = 0, next = (struct mrc_data_container *)base_addr;
  45. is_mrc_cache(next);
  46. id++) {
  47. cache = next;
  48. next = next_mrc_block(next);
  49. if ((ulong)next >= end_addr)
  50. break;
  51. }
  52. if (id-- == 0) {
  53. debug("%s: No valid MRC cache found.\n", __func__);
  54. return NULL;
  55. }
  56. /* Verify checksum */
  57. if (cache->checksum != compute_ip_checksum(cache->data,
  58. cache->data_size)) {
  59. printf("%s: MRC cache checksum mismatch\n", __func__);
  60. return NULL;
  61. }
  62. debug("%s: picked entry %u from cache block\n", __func__, id);
  63. return cache;
  64. }
  65. /**
  66. * find_next_mrc_cache() - get next cache entry
  67. *
  68. * @entry: MRC cache flash area
  69. * @cache: Entry to start from
  70. *
  71. * @return next cache entry if found, NULL if we got to the end
  72. */
  73. static struct mrc_data_container *find_next_mrc_cache(struct mrc_region *entry,
  74. struct mrc_data_container *cache)
  75. {
  76. ulong base_addr, end_addr;
  77. base_addr = entry->base + entry->offset;
  78. end_addr = base_addr + entry->length;
  79. cache = next_mrc_block(cache);
  80. if ((ulong)cache >= end_addr) {
  81. /* Crossed the boundary */
  82. cache = NULL;
  83. debug("%s: no available entries found\n", __func__);
  84. } else {
  85. debug("%s: picked next entry from cache block at %p\n",
  86. __func__, cache);
  87. }
  88. return cache;
  89. }
  90. int mrccache_update(struct udevice *sf, struct mrc_region *entry,
  91. struct mrc_data_container *cur)
  92. {
  93. struct mrc_data_container *cache;
  94. ulong offset;
  95. ulong base_addr;
  96. int ret;
  97. if (!is_mrc_cache(cur))
  98. return -EINVAL;
  99. /* Find the last used block */
  100. base_addr = entry->base + entry->offset;
  101. debug("Updating MRC cache data\n");
  102. cache = mrccache_find_current(entry);
  103. if (cache && (cache->data_size == cur->data_size) &&
  104. (!memcmp(cache, cur, cache->data_size + sizeof(*cur)))) {
  105. debug("MRC data in flash is up to date. No update\n");
  106. return -EEXIST;
  107. }
  108. /* Move to the next block, which will be the first unused block */
  109. if (cache)
  110. cache = find_next_mrc_cache(entry, cache);
  111. /*
  112. * If we have got to the end, erase the entire mrc-cache area and start
  113. * again at block 0.
  114. */
  115. if (!cache) {
  116. debug("Erasing the MRC cache region of %x bytes at %x\n",
  117. entry->length, entry->offset);
  118. ret = spi_flash_erase_dm(sf, entry->offset, entry->length);
  119. if (ret) {
  120. debug("Failed to erase flash region\n");
  121. return ret;
  122. }
  123. cache = (struct mrc_data_container *)base_addr;
  124. }
  125. /* Write the data out */
  126. offset = (ulong)cache - base_addr + entry->offset;
  127. debug("Write MRC cache update to flash at %lx\n", offset);
  128. ret = spi_flash_write_dm(sf, offset, cur->data_size + sizeof(*cur),
  129. cur);
  130. if (ret) {
  131. debug("Failed to write to SPI flash\n");
  132. return ret;
  133. }
  134. return 0;
  135. }
  136. int mrccache_reserve(void)
  137. {
  138. struct mrc_data_container *cache;
  139. u16 checksum;
  140. if (!gd->arch.mrc_output_len)
  141. return 0;
  142. /* adjust stack pointer to store pure cache data plus the header */
  143. gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE);
  144. cache = (struct mrc_data_container *)gd->start_addr_sp;
  145. cache->signature = MRC_DATA_SIGNATURE;
  146. cache->data_size = gd->arch.mrc_output_len;
  147. checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size);
  148. debug("Saving %d bytes for MRC output data, checksum %04x\n",
  149. cache->data_size, checksum);
  150. cache->checksum = checksum;
  151. cache->reserved = 0;
  152. memcpy(cache->data, gd->arch.mrc_output, cache->data_size);
  153. /* gd->arch.mrc_output now points to the container */
  154. gd->arch.mrc_output = (char *)cache;
  155. gd->start_addr_sp &= ~0xf;
  156. return 0;
  157. }
  158. int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
  159. {
  160. const void *blob = gd->fdt_blob;
  161. int node, mrc_node;
  162. u32 reg[2];
  163. int ret;
  164. /* Find the flash chip within the SPI controller node */
  165. node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
  166. if (node < 0) {
  167. debug("%s: Cannot find SPI flash\n", __func__);
  168. return -ENOENT;
  169. }
  170. if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2))
  171. return -EINVAL;
  172. entry->base = reg[0];
  173. /* Find the place where we put the MRC cache */
  174. mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache");
  175. if (mrc_node < 0)
  176. return -EPERM;
  177. if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2))
  178. return -EINVAL;
  179. entry->offset = reg[0];
  180. entry->length = reg[1];
  181. if (devp) {
  182. ret = uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node,
  183. devp);
  184. debug("ret = %d\n", ret);
  185. if (ret)
  186. return ret;
  187. }
  188. return 0;
  189. }
  190. int mrccache_save(void)
  191. {
  192. struct mrc_data_container *data;
  193. struct mrc_region entry;
  194. struct udevice *sf;
  195. int ret;
  196. if (!gd->arch.mrc_output_len)
  197. return 0;
  198. debug("Saving %d bytes of MRC output data to SPI flash\n",
  199. gd->arch.mrc_output_len);
  200. ret = mrccache_get_region(&sf, &entry);
  201. if (ret)
  202. goto err_entry;
  203. data = (struct mrc_data_container *)gd->arch.mrc_output;
  204. ret = mrccache_update(sf, &entry, data);
  205. if (!ret) {
  206. debug("Saved MRC data with checksum %04x\n", data->checksum);
  207. } else if (ret == -EEXIST) {
  208. debug("MRC data is the same as last time, skipping save\n");
  209. ret = 0;
  210. }
  211. err_entry:
  212. if (ret)
  213. debug("%s: Failed: %d\n", __func__, ret);
  214. return ret;
  215. }