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