1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2010 DENX Software Engineering 4 * Wolfgang Denk <wd@denx.de> 5 * 6 * (C) Copyright 2005-2009 Samsung Electronics 7 * Kyungmin Park <kyungmin.park@samsung.com> 8 */ 9 10 #include <common.h> 11 #include <command.h> 12 #include <environment.h> 13 #include <linux/stddef.h> 14 #include <malloc.h> 15 #include <search.h> 16 #include <errno.h> 17 #include <onenand_uboot.h> 18 19 #include <linux/compat.h> 20 #include <linux/mtd/mtd.h> 21 #include <linux/mtd/onenand.h> 22 23 #define ONENAND_MAX_ENV_SIZE CONFIG_ENV_SIZE 24 #define ONENAND_ENV_SIZE(mtd) (ONENAND_MAX_ENV_SIZE - ENV_HEADER_SIZE) 25 26 DECLARE_GLOBAL_DATA_PTR; 27 28 static int env_onenand_load(void) 29 { 30 struct mtd_info *mtd = &onenand_mtd; 31 #ifdef CONFIG_ENV_ADDR_FLEX 32 struct onenand_chip *this = &onenand_chip; 33 #endif 34 int rc; 35 size_t retlen; 36 #ifdef ENV_IS_EMBEDDED 37 char *buf = (char *)&environment; 38 #else 39 loff_t env_addr = CONFIG_ENV_ADDR; 40 char onenand_env[ONENAND_MAX_ENV_SIZE]; 41 char *buf = (char *)&onenand_env[0]; 42 #endif /* ENV_IS_EMBEDDED */ 43 44 #ifndef ENV_IS_EMBEDDED 45 # ifdef CONFIG_ENV_ADDR_FLEX 46 if (FLEXONENAND(this)) 47 env_addr = CONFIG_ENV_ADDR_FLEX; 48 # endif 49 /* Check OneNAND exist */ 50 if (mtd->writesize) 51 /* Ignore read fail */ 52 mtd_read(mtd, env_addr, ONENAND_MAX_ENV_SIZE, 53 &retlen, (u_char *)buf); 54 else 55 mtd->writesize = MAX_ONENAND_PAGESIZE; 56 #endif /* !ENV_IS_EMBEDDED */ 57 58 rc = env_import(buf, 1); 59 if (!rc) 60 gd->env_valid = ENV_VALID; 61 62 return rc; 63 } 64 65 static int env_onenand_save(void) 66 { 67 env_t env_new; 68 int ret; 69 struct mtd_info *mtd = &onenand_mtd; 70 #ifdef CONFIG_ENV_ADDR_FLEX 71 struct onenand_chip *this = &onenand_chip; 72 #endif 73 loff_t env_addr = CONFIG_ENV_ADDR; 74 size_t retlen; 75 struct erase_info instr = { 76 .callback = NULL, 77 }; 78 79 ret = env_export(&env_new); 80 if (ret) 81 return ret; 82 83 instr.len = CONFIG_ENV_SIZE; 84 #ifdef CONFIG_ENV_ADDR_FLEX 85 if (FLEXONENAND(this)) { 86 env_addr = CONFIG_ENV_ADDR_FLEX; 87 instr.len = CONFIG_ENV_SIZE_FLEX; 88 instr.len <<= onenand_mtd.eraseregions[0].numblocks == 1 ? 89 1 : 0; 90 } 91 #endif 92 instr.addr = env_addr; 93 instr.mtd = mtd; 94 if (mtd_erase(mtd, &instr)) { 95 printf("OneNAND: erase failed at 0x%08llx\n", env_addr); 96 return 1; 97 } 98 99 if (mtd_write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen, 100 (u_char *)&env_new)) { 101 printf("OneNAND: write failed at 0x%llx\n", instr.addr); 102 return 2; 103 } 104 105 return 0; 106 } 107 108 U_BOOT_ENV_LOCATION(onenand) = { 109 .location = ENVL_ONENAND, 110 ENV_NAME("OneNAND") 111 .load = env_onenand_load, 112 .save = env_save_ptr(env_onenand_save), 113 }; 114