nvram_storage.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * Copyright (c) 2017 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief NVRAM storage
  9. */
  10. #include <errno.h>
  11. #include <sys/__assert.h>
  12. #include <stdbool.h>
  13. #include <kernel.h>
  14. #include <device.h>
  15. #include <init.h>
  16. #include <drivers/flash.h>
  17. #include <string.h>
  18. #include <board_cfg.h>
  19. #include "nvram_storage.h"
  20. #define LOG_LEVEL 2
  21. #include <logging/log.h>
  22. LOG_MODULE_REGISTER(nvram_stor);
  23. #ifdef CONFIG_NVRAM_STORAGE_RAMSIM
  24. #define NVRAM_MEM_SIZE (CONFIG_NVRAM_FACTORY_REGION_SIZE + \
  25. CONFIG_NVRAM_USER_REGION_SIZE)
  26. #define NVRAM_MEM_OFFS CONFIG_NVRAM_FACTORY_REGION_BASE_ADDR
  27. static uint8_t nvram_mem_buf[NVRAM_MEM_SIZE];
  28. #endif
  29. #if defined(CONFIG_BOARD_NANDBOOT) || defined(CONFIG_BOARD_EMMCBOOT)
  30. #define NV_NAND_PAGE_SIZE 2048
  31. #define NV_NAND_SECTOR_SIZE 512
  32. #define NV_CACHE_SECT_NUM (NV_NAND_PAGE_SIZE/NV_NAND_SECTOR_SIZE)
  33. #define NV_CACEH_NUM_ITEM 2
  34. struct nv_nand_cache_item {
  35. u16_t cache_valid:1;
  36. u16_t write_valid:1;
  37. u16_t reserved:14;
  38. u16_t seq_index;
  39. u32_t cache_start_sector;
  40. u8_t cache_data[NV_NAND_PAGE_SIZE];
  41. };
  42. static struct nv_nand_cache_item __act_s2_notsave nv_nand_cache[NV_CACEH_NUM_ITEM];
  43. static u16_t g_seq_index;
  44. static void _nv_nand_cache_init(void)
  45. {
  46. int i;
  47. for(i = 0; i < NV_CACEH_NUM_ITEM; i++) {
  48. nv_nand_cache[i].cache_valid = 0;
  49. nv_nand_cache[i].write_valid = 0;
  50. }
  51. }
  52. static int _nv_flush_cache(struct device *dev, struct nv_nand_cache_item *item)
  53. {
  54. int err;
  55. if(item->write_valid && item->cache_valid){
  56. item->write_valid = 0;
  57. LOG_DBG("nand flush startsec 0x%x, buf %p\n", item->cache_start_sector, item->cache_data);
  58. err = flash_write(dev, (item->cache_start_sector<<9), item->cache_data, NV_CACHE_SECT_NUM<<9);
  59. if (err < 0) {
  60. LOG_ERR("nand write error %d, offsec 0x%x, buf %p\n",
  61. err, item->cache_start_sector, item->cache_data);
  62. return -EIO;
  63. }
  64. }
  65. return 0;
  66. }
  67. static int _nv_update_cache(struct device *dev, struct nv_nand_cache_item *item, u32_t sec_off)
  68. {
  69. int err;
  70. u32_t page_off = sec_off/NV_CACHE_SECT_NUM;
  71. item->cache_start_sector = page_off * NV_CACHE_SECT_NUM;
  72. item->cache_valid = 1;
  73. item->write_valid = 0;
  74. item->seq_index = g_seq_index++;
  75. LOG_DBG("nand update start_sec 0x%x, buf %p, sec_off=0x%x,0x%x\n",
  76. item->cache_start_sector, item->cache_data, sec_off, sec_off*NV_NAND_SECTOR_SIZE);
  77. err = flash_read(dev, (item->cache_start_sector<<9), item->cache_data, NV_CACHE_SECT_NUM<<9);
  78. if (err < 0) {
  79. LOG_ERR("nand read error %d, offsec 0x%x, buf %p\n",
  80. err, item->cache_start_sector, item->cache_data);
  81. return -EIO;
  82. }
  83. return 0;
  84. }
  85. static struct nv_nand_cache_item * _nv_find_cache_item(u32_t sec_off)
  86. {
  87. for (int i = 0; i < NV_CACEH_NUM_ITEM; i++) {
  88. if (nv_nand_cache[i].cache_valid && (nv_nand_cache[i].cache_start_sector <= sec_off)
  89. && (sec_off < nv_nand_cache[i].cache_start_sector+NV_CACHE_SECT_NUM)) {
  90. return &nv_nand_cache[i];
  91. }
  92. }
  93. //LOG_INF("sect_off 0x%x not in cache\n", sec_off);
  94. return NULL;
  95. }
  96. /*
  97. if have invaid ,use invalid, else use same
  98. */
  99. static struct nv_nand_cache_item * _nv_new_cache_item(struct device *dev, u32_t sec_off)
  100. {
  101. int i;
  102. struct nv_nand_cache_item *invalid, *valid, *new_item;
  103. valid = invalid = NULL;
  104. for(i = 0; i < NV_CACEH_NUM_ITEM; i++) {
  105. if(nv_nand_cache[i].cache_valid){
  106. if(valid == NULL){
  107. valid = &nv_nand_cache[i];
  108. }else{
  109. if(valid->seq_index > nv_nand_cache[i].seq_index)
  110. valid = &nv_nand_cache[i];
  111. }
  112. }else{
  113. invalid = &nv_nand_cache[i];
  114. break;
  115. }
  116. }
  117. if(invalid){
  118. new_item = invalid;
  119. }else{
  120. new_item = valid;
  121. }
  122. //LOG_INF("new item sect_off 0x%x, 0x%x is_write=%d\n", sec_off, sec_off*NV_NAND_SECTOR_SIZE, is_write);
  123. _nv_flush_cache(dev, new_item);
  124. _nv_update_cache(dev, new_item, sec_off);
  125. return new_item;
  126. }
  127. void nvram_storage_flush(struct device *dev)
  128. {
  129. int i;
  130. for(i = 0; i < NV_CACEH_NUM_ITEM; i++)
  131. _nv_flush_cache(dev, &nv_nand_cache[i]);
  132. }
  133. /*brwe = 0 (read), 1(write), 2(erase)*/
  134. static void _nand_storage_read_write(struct device *dev, uint32_t addr,
  135. uint8_t *buf, int32_t size, int brwe)
  136. {
  137. int32_t wsize, len;
  138. uint32_t sector_off, addr_in_sec,cache_sec_index;
  139. static struct nv_nand_cache_item * item;
  140. wsize = size;
  141. sector_off = addr / NV_NAND_SECTOR_SIZE;
  142. addr_in_sec = addr - (sector_off*NV_NAND_SECTOR_SIZE);
  143. //LOG_INF("sect_off 0x%x, size 0x%x iswrite %d\n", sector_off, size, brwe);
  144. while(wsize > 0) {
  145. item = _nv_find_cache_item(sector_off);
  146. if(item == NULL)
  147. item = _nv_new_cache_item(dev, sector_off);
  148. cache_sec_index = sector_off -item->cache_start_sector;
  149. if(addr_in_sec){//not sector algin
  150. len = NV_NAND_SECTOR_SIZE - addr_in_sec;
  151. if(len > wsize)
  152. len = wsize;
  153. if(brwe == 1)
  154. memcpy(&item->cache_data[cache_sec_index*NV_NAND_SECTOR_SIZE+addr_in_sec],buf, len);
  155. else if(brwe == 0)
  156. memcpy(buf, &item->cache_data[cache_sec_index*NV_NAND_SECTOR_SIZE+addr_in_sec], len);
  157. else
  158. memset(&item->cache_data[cache_sec_index*NV_NAND_SECTOR_SIZE+addr_in_sec], 0xff, len);
  159. buf += len;
  160. wsize -= len;
  161. cache_sec_index++;
  162. addr_in_sec = 0; // next align
  163. }
  164. for( ; wsize && (cache_sec_index < NV_CACHE_SECT_NUM); cache_sec_index++){
  165. if(wsize < NV_NAND_SECTOR_SIZE)
  166. len = wsize;
  167. else
  168. len = NV_NAND_SECTOR_SIZE;
  169. if(brwe == 1)
  170. memcpy(&item->cache_data[cache_sec_index*NV_NAND_SECTOR_SIZE],buf, len);
  171. else if(brwe == 0)
  172. memcpy(buf, &item->cache_data[cache_sec_index*NV_NAND_SECTOR_SIZE], len);
  173. else
  174. memset(&item->cache_data[cache_sec_index*NV_NAND_SECTOR_SIZE], 0xff, len);
  175. buf += len;
  176. wsize -= len;
  177. }
  178. if(brwe)
  179. item->write_valid = 1; //dirty
  180. sector_off = item->cache_start_sector + NV_CACHE_SECT_NUM;
  181. }
  182. }
  183. static int _nand_storage_write(struct device *dev, uint32_t addr,
  184. uint8_t *buf, int32_t size)
  185. {
  186. _nand_storage_read_write(dev, addr, buf, size, 1);
  187. //LOG_INF("nand write end 0x%x len 0x%x", addr, size);
  188. return 0;
  189. }
  190. static int _nand_storage_read(struct device *dev, uint32_t addr,
  191. void *buf, int32_t size)
  192. {
  193. _nand_storage_read_write(dev, addr, buf, size, 0);
  194. //LOG_INF("nand read end 0x%x len 0x%x", addr, size);
  195. return 0;
  196. }
  197. static int _nand_storage_erase(struct device *dev, uint32_t addr,
  198. int32_t size)
  199. {
  200. uint8_t buf[1]; // not use;
  201. _nand_storage_read_write(dev, addr, buf, size, 2);
  202. //LOG_INF("nand erase end 0x%x len 0x%x", addr, size);
  203. return 0;
  204. }
  205. #endif
  206. #define NVRAM_STORAGE_READ_SEGMENT_SIZE 256
  207. #define NVRAM_STORAGE_WRITE_SEGMENT_SIZE 32
  208. int nvram_storage_write(struct device *dev, uint32_t addr,
  209. const void *buf, int32_t size)
  210. {
  211. LOG_INF("write addr 0x%x len 0x%x", addr, size);
  212. #ifdef CONFIG_NVRAM_STORAGE_RAMSIM
  213. memcpy(nvram_mem_buf + addr - NVRAM_MEM_OFFS, buf, len);
  214. return 0;
  215. #else
  216. #if defined(CONFIG_BOARD_NANDBOOT) || defined(CONFIG_BOARD_EMMCBOOT)
  217. _nand_storage_write(dev, addr, (uint8_t *)buf, size);
  218. #else
  219. int err;
  220. int wlen = NVRAM_STORAGE_WRITE_SEGMENT_SIZE;
  221. while (size > 0) {
  222. if (size < NVRAM_STORAGE_WRITE_SEGMENT_SIZE)
  223. wlen = size;
  224. err = flash_write(dev, addr, buf, wlen);
  225. if (err < 0) {
  226. LOG_ERR("write error %d, addr 0x%x, buf %p, size %d",
  227. err, addr, buf, size);
  228. return -EIO;
  229. }
  230. addr += wlen;
  231. buf = (void*)((uint8_t *)buf + wlen);
  232. size -= wlen;
  233. }
  234. #endif
  235. return 0;
  236. #endif
  237. }
  238. int nvram_storage_read(struct device *dev, uint32_t addr,
  239. void *buf, int32_t size)
  240. {
  241. LOG_DBG("read addr 0x%x len 0x%x", addr, size);
  242. #ifdef CONFIG_NVRAM_STORAGE_RAMSIM
  243. memcpy(buf, nvram_mem_buf + addr - NVRAM_MEM_OFFS, size);
  244. return 0;
  245. #else
  246. #if defined(CONFIG_BOARD_NANDBOOT) || defined(CONFIG_BOARD_EMMCBOOT)
  247. _nand_storage_read(dev, addr, (uint8_t *)buf, size);
  248. #else
  249. int err;
  250. int rlen = NVRAM_STORAGE_READ_SEGMENT_SIZE;
  251. while (size > 0) {
  252. if (size < NVRAM_STORAGE_READ_SEGMENT_SIZE)
  253. rlen = size;
  254. err = flash_read(dev, addr, buf, rlen);
  255. if (err < 0) {
  256. LOG_ERR("read error %d, addr 0x%x, buf %p, size %d", err, addr, buf, size);
  257. return -EIO;
  258. }
  259. addr += rlen;
  260. buf = (void*)((uint8_t *)buf + rlen);
  261. size -= rlen;
  262. }
  263. #endif
  264. return 0;
  265. #endif
  266. }
  267. int nvram_storage_erase(struct device *dev, uint32_t addr,
  268. int32_t size)
  269. {
  270. LOG_INF("erase addr 0x%x size 0x%x", addr, size);
  271. #ifdef CONFIG_NVRAM_STORAGE_RAMSIM
  272. memset(nvram_mem_buf + addr - NVRAM_MEM_OFFS, 0xff, size);
  273. return 0;
  274. #else
  275. #if defined(CONFIG_BOARD_NANDBOOT) || defined(CONFIG_BOARD_EMMCBOOT)
  276. return _nand_storage_erase(dev, addr, size);
  277. #else
  278. return flash_erase(dev, (off_t)addr, (size_t)size);
  279. #endif
  280. #endif
  281. }
  282. struct device *nvram_storage_init(void)
  283. {
  284. struct device *dev;
  285. printk("init nvram storage\n");
  286. #ifdef CONFIG_NVRAM_STORAGE_RAMSIM
  287. LOG_INF("init simulated nvram storage: addr 0x%x size 0x%x",
  288. NVRAM_MEM_OFFS, NVRAM_MEM_SIZE);
  289. memset(nvram_mem_buf, 0xff, NVRAM_MEM_SIZE);
  290. /* dummy device pointer */
  291. dev = (struct device *)-1;
  292. #else
  293. #if defined(CONFIG_BOARD_NANDBOOT)
  294. #define FLASH_DEV_NAME "spinand"
  295. _nv_nand_cache_init();
  296. #elif defined(CONFIG_BOARD_EMMCBOOT)
  297. #define FLASH_DEV_NAME CONFIG_SD_NAME
  298. _nv_nand_cache_init();
  299. #else
  300. #define FLASH_DEV_NAME CONFIG_SPI_FLASH_NAME
  301. #endif
  302. dev = (struct device *)device_get_binding(FLASH_DEV_NAME);
  303. if (!dev) {
  304. LOG_ERR("cannot found device \'%s\'\n",
  305. FLASH_DEV_NAME);
  306. return NULL;
  307. }
  308. #endif
  309. return dev;
  310. }