Merge branch 'mpc8349ads'
[platform/kernel/u-boot.git] / common / env_nand.c
1 /*
2  * (C) Copyright 2004
3  * Jian Zhang, Texas Instruments, jzhang@ti.com.
4
5  * (C) Copyright 2000-2004
6  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7  *
8  * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
9  * Andreas Heppel <aheppel@sysgo.de>
10
11  * See file CREDITS for list of people who contributed to this
12  * project.
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License as
16  * published by the Free Software Foundation; either version 2 of
17  * the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27  * MA 02111-1307 USA
28  */
29
30 /* #define DEBUG */
31
32 #include <common.h>
33
34 #if defined(CFG_ENV_IS_IN_NAND) /* Environment is in Nand Flash */
35
36 #include <command.h>
37 #include <environment.h>
38 #include <linux/stddef.h>
39 #include <linux/mtd/nand.h>
40
41 #if ((CONFIG_COMMANDS&(CFG_CMD_ENV|CFG_CMD_NAND)) == (CFG_CMD_ENV|CFG_CMD_NAND))
42 #define CMD_SAVEENV
43 #endif
44
45 #if defined(CFG_ENV_SIZE_REDUND)
46 #error CFG_ENV_SIZE_REDUND  not supported yet
47 #endif
48
49 #if defined(CFG_ENV_ADDR_REDUND)
50 #error CFG_ENV_ADDR_REDUND and CFG_ENV_IS_IN_NAND not supported yet
51 #endif
52
53
54 #ifdef CONFIG_INFERNO
55 #error CONFIG_INFERNO not supported yet
56 #endif
57
58 /* references to names in cmd_nand.c */
59 #define NANDRW_READ             0x01
60 #define NANDRW_WRITE    0x00
61 #define NANDRW_JFFS2    0x02
62 extern struct nand_chip nand_dev_desc[];
63 int nand_rw (struct nand_chip* nand, int cmd,
64             size_t start, size_t len,
65             size_t * retlen, u_char * buf);
66 int nand_erase(struct nand_chip* nand, size_t ofs,
67                                 size_t len, int clean);
68
69 /* references to names in env_common.c */
70 extern uchar default_environment[];
71 extern int default_environment_size;
72
73 char * env_name_spec = "NAND";
74
75
76 #ifdef ENV_IS_EMBEDDED
77 extern uchar environment[];
78 env_t *env_ptr = (env_t *)(&environment[0]);
79 #else /* ! ENV_IS_EMBEDDED */
80 env_t *env_ptr = 0;
81 #endif /* ENV_IS_EMBEDDED */
82
83
84 /* local functions */
85 static void use_default(void);
86
87
88 uchar env_get_char_spec (int index)
89 {
90         DECLARE_GLOBAL_DATA_PTR;
91
92         return ( *((uchar *)(gd->env_addr + index)) );
93 }
94
95
96 /* this is called before nand_init()
97  * so we can't read Nand to validate env data.
98  * Mark it OK for now. env_relocate() in env_common.c
99  * will call our relocate function which will does
100  * the real validation.
101  */
102 int env_init(void)
103 {
104         DECLARE_GLOBAL_DATA_PTR;
105
106         gd->env_addr  = (ulong)&default_environment[0];
107         gd->env_valid = 1;
108
109         return (0);
110 }
111
112 #ifdef CMD_SAVEENV
113 int saveenv(void)
114 {
115         int     total, ret = 0;
116         puts ("Erasing Nand...");
117         if (nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SIZE, 0))
118                 return 1;
119
120         puts ("Writing to Nand... ");
121         ret = nand_rw(nand_dev_desc + 0,
122                                   NANDRW_WRITE | NANDRW_JFFS2, CFG_ENV_OFFSET, CFG_ENV_SIZE,
123                               &total, (u_char*)env_ptr);
124         if (ret || total != CFG_ENV_SIZE)
125                 return 1;
126
127         puts ("done\n");
128         return ret;
129 }
130 #endif /* CMD_SAVEENV */
131
132
133 void env_relocate_spec (void)
134 {
135 #if !defined(ENV_IS_EMBEDDED)
136         int ret, total;
137
138         ret = nand_rw(nand_dev_desc + 0,
139                                   NANDRW_READ | NANDRW_JFFS2, CFG_ENV_OFFSET, CFG_ENV_SIZE,
140                               &total, (u_char*)env_ptr);
141         if (ret || total != CFG_ENV_SIZE)
142                 return use_default();
143
144         if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)
145                 return use_default();
146 #endif /* ! ENV_IS_EMBEDDED */
147
148 }
149
150 static void use_default()
151 {
152         DECLARE_GLOBAL_DATA_PTR;
153
154         puts ("*** Warning - bad CRC or NAND, using default environment\n\n");
155
156         if (default_environment_size > CFG_ENV_SIZE){
157                 puts ("*** Error - default environment is too large\n\n");
158                 return;
159         }
160
161         memset (env_ptr, 0, sizeof(env_t));
162         memcpy (env_ptr->data,
163                         default_environment,
164                         default_environment_size);
165         env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE);
166         gd->env_valid = 1;
167
168 }
169
170 #endif /* CFG_ENV_IS_IN_NAND */