blob: 2ed9c9ad639ffbf56fa4318f39d8d789febe4690 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
2 * (C) Copyright 2002
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Marius Groeger <mgroeger@sysgo.de>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25#include <common.h>
26
27#define FLASH_BANK_SIZE 0x1000000
28#define MAIN_SECT_SIZE 0x20000
29
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020030flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
wdenkc6097192002-11-03 00:24:07 +000031
32
33/*-----------------------------------------------------------------------
34 */
35
36ulong flash_init (void)
37{
38 int i, j;
39 ulong size = 0;
40
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020041 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
wdenkc6097192002-11-03 00:24:07 +000042 ulong flashbase = 0;
43
44 flash_info[i].flash_id =
45 (INTEL_MANUFACT & FLASH_VENDMASK) |
46 (INTEL_ID_28F128J3 & FLASH_TYPEMASK);
47 flash_info[i].size = FLASH_BANK_SIZE;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020048 flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
49 memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
wdenkc6097192002-11-03 00:24:07 +000050 if (i == 0)
51 flashbase = PHYS_FLASH_1;
52 else
wdenk5f535fe2003-09-18 09:21:33 +000053 panic ("configured too many flash banks!\n");
wdenkc6097192002-11-03 00:24:07 +000054 for (j = 0; j < flash_info[i].sector_count; j++) {
55 flash_info[i].start[j] = flashbase + j * MAIN_SECT_SIZE;
56 }
57 size += flash_info[i].size;
58 }
59
60 /* Protect monitor and environment sectors
61 */
62 flash_protect ( FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020063 CONFIG_SYS_FLASH_BASE,
64 CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
wdenkc6097192002-11-03 00:24:07 +000065 &flash_info[0]);
66
67 flash_protect ( FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD0e8d1582008-09-10 22:48:06 +020068 CONFIG_ENV_ADDR,
69 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
wdenkc6097192002-11-03 00:24:07 +000070
71 return size;
72}
73
74/*-----------------------------------------------------------------------
75 */
76void flash_print_info (flash_info_t * info)
77{
78 int i;
79
80 switch (info->flash_id & FLASH_VENDMASK) {
81 case (INTEL_MANUFACT & FLASH_VENDMASK):
82 printf ("Intel: ");
83 break;
84 default:
85 printf ("Unknown Vendor ");
86 break;
87 }
88
89 switch (info->flash_id & FLASH_TYPEMASK) {
90 case (INTEL_ID_28F128J3 & FLASH_TYPEMASK):
91 printf ("28F128J3 (128Mbit)\n");
92 break;
93 default:
94 printf ("Unknown Chip Type\n");
95 goto Done;
96 break;
97 }
98
99 printf (" Size: %ld MB in %d Sectors\n",
100 info->size >> 20, info->sector_count);
101
102 printf (" Sector Start Addresses:");
103 for (i = 0; i < info->sector_count; i++) {
104 if ((i % 5) == 0) {
105 printf ("\n ");
106 }
107 printf (" %08lX%s", info->start[i],
108 info->protect[i] ? " (RO)" : " ");
109 }
110 printf ("\n");
111
wdenke86e5a02004-10-17 21:12:06 +0000112Done: ;
wdenkc6097192002-11-03 00:24:07 +0000113}
114
115/*-----------------------------------------------------------------------
116 */
117
118int flash_erase (flash_info_t * info, int s_first, int s_last)
119{
120 int flag, prot, sect;
121 int rc = ERR_OK;
Graeme Russa60d1e52011-07-15 23:31:37 +0000122 ulong start;
wdenkc6097192002-11-03 00:24:07 +0000123
124 if (info->flash_id == FLASH_UNKNOWN)
125 return ERR_UNKNOWN_FLASH_TYPE;
126
127 if ((s_first < 0) || (s_first > s_last)) {
128 return ERR_INVAL;
129 }
130
131 if ((info->flash_id & FLASH_VENDMASK) !=
132 (INTEL_MANUFACT & FLASH_VENDMASK)) {
133 return ERR_UNKNOWN_FLASH_VENDOR;
134 }
135
136 prot = 0;
137 for (sect = s_first; sect <= s_last; ++sect) {
138 if (info->protect[sect]) {
139 prot++;
140 }
141 }
142 if (prot)
143 return ERR_PROTECTED;
144
145 /*
146 * Disable interrupts which might cause a timeout
147 * here. Remember that our exception vectors are
148 * at address 0 in the flash, and we don't want a
149 * (ticker) exception to happen while the flash
150 * chip is in programming mode.
151 */
152 flag = disable_interrupts ();
153
154 /* Start erase on unprotected sectors */
155 for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
156
157 printf ("Erasing sector %2d ... ", sect);
158
159 /* arm simple, non interrupt dependent timer */
Graeme Russa60d1e52011-07-15 23:31:37 +0000160 start = get_timer(0);
wdenkc6097192002-11-03 00:24:07 +0000161
162 if (info->protect[sect] == 0) { /* not protected */
163 vu_short *addr = (vu_short *) (info->start[sect]);
164
165 *addr = 0x20; /* erase setup */
166 *addr = 0xD0; /* erase confirm */
167
168 while ((*addr & 0x80) != 0x80) {
Graeme Russa60d1e52011-07-15 23:31:37 +0000169 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenkc6097192002-11-03 00:24:07 +0000170 *addr = 0xB0; /* suspend erase */
171 *addr = 0xFF; /* reset to read mode */
172 rc = ERR_TIMOUT;
173 goto outahere;
174 }
175 }
176
177 /* clear status register command */
178 *addr = 0x50;
179 /* reset to read mode */
180 *addr = 0xFF;
181 }
182 printf ("ok.\n");
183 }
184 if (ctrlc ())
185 printf ("User Interrupt!\n");
186
187 outahere:
188
189 /* allow flash to settle - wait 10 ms */
190 udelay_masked (10000);
191
192 if (flag)
193 enable_interrupts ();
194
195 return rc;
196}
197
198/*-----------------------------------------------------------------------
199 * Copy memory to flash
200 */
201
202static int write_word (flash_info_t * info, ulong dest, ushort data)
203{
204 vu_short *addr = (vu_short *) dest, val;
205 int rc = ERR_OK;
206 int flag;
Graeme Russa60d1e52011-07-15 23:31:37 +0000207 ulong start;
wdenkc6097192002-11-03 00:24:07 +0000208
209 /* Check if Flash is (sufficiently) erased
210 */
211 if ((*addr & data) != data)
212 return ERR_NOT_ERASED;
213
214 /*
215 * Disable interrupts which might cause a timeout
216 * here. Remember that our exception vectors are
217 * at address 0 in the flash, and we don't want a
218 * (ticker) exception to happen while the flash
219 * chip is in programming mode.
220 */
221 flag = disable_interrupts ();
222
223 /* clear status register command */
224 *addr = 0x50;
225
226 /* program set-up command */
227 *addr = 0x40;
228
229 /* latch address/data */
230 *addr = data;
231
232 /* arm simple, non interrupt dependent timer */
Graeme Russa60d1e52011-07-15 23:31:37 +0000233 start = get_timer(0);
wdenkc6097192002-11-03 00:24:07 +0000234
235 /* wait while polling the status register */
236 while (((val = *addr) & 0x80) != 0x80) {
Graeme Russa60d1e52011-07-15 23:31:37 +0000237 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkc6097192002-11-03 00:24:07 +0000238 rc = ERR_TIMOUT;
239 /* suspend program command */
240 *addr = 0xB0;
241 goto outahere;
242 }
243 }
244
245 if (val & 0x1A) { /* check for error */
246 printf ("\nFlash write error %02x at address %08lx\n",
247 (int) val, (unsigned long) dest);
248 if (val & (1 << 3)) {
249 printf ("Voltage range error.\n");
250 rc = ERR_PROG_ERROR;
251 goto outahere;
252 }
253 if (val & (1 << 1)) {
254 printf ("Device protect error.\n");
255 rc = ERR_PROTECTED;
256 goto outahere;
257 }
258 if (val & (1 << 4)) {
259 printf ("Programming error.\n");
260 rc = ERR_PROG_ERROR;
261 goto outahere;
262 }
263 rc = ERR_PROG_ERROR;
264 goto outahere;
265 }
266
267 outahere:
268 /* read array command */
269 *addr = 0xFF;
270
271 if (flag)
272 enable_interrupts ();
273
274 return rc;
275}
276
277/*-----------------------------------------------------------------------
278 * Copy memory to flash.
279 */
280
281int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
282{
283 ulong cp, wp;
284 ushort data;
285 int l;
286 int i, rc;
287
288 wp = (addr & ~1); /* get lower word aligned address */
289
290 /*
291 * handle unaligned start bytes
292 */
293 if ((l = addr - wp) != 0) {
294 data = 0;
295 for (i = 0, cp = wp; i < l; ++i, ++cp) {
296 data = (data >> 8) | (*(uchar *) cp << 8);
297 }
298 for (; i < 2 && cnt > 0; ++i) {
299 data = (data >> 8) | (*src++ << 8);
300 --cnt;
301 ++cp;
302 }
303 for (; cnt == 0 && i < 2; ++i, ++cp) {
304 data = (data >> 8) | (*(uchar *) cp << 8);
305 }
306
307 if ((rc = write_word (info, wp, data)) != 0) {
308 return (rc);
309 }
310 wp += 2;
311 }
312
313 /*
314 * handle word aligned part
315 */
316 while (cnt >= 2) {
317 data = *((vu_short *) src);
318 if ((rc = write_word (info, wp, data)) != 0) {
319 return (rc);
320 }
321 src += 2;
322 wp += 2;
323 cnt -= 2;
324 }
325
326 if (cnt == 0) {
327 return ERR_OK;
328 }
329
330 /*
331 * handle unaligned tail bytes
332 */
333 data = 0;
334 for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
335 data = (data >> 8) | (*src++ << 8);
336 --cnt;
337 }
338 for (; i < 2; ++i, ++cp) {
339 data = (data >> 8) | (*(uchar *) cp << 8);
340 }
341
342 return write_word (info, wp, data);
343}