]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/evb4510/flash.c
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[karo-tx-uboot.git] / board / evb4510 / flash.c
1 /*
2  *
3  * Copyright (c) 2004   Cucy Systems (http://www.cucy.com)
4  * Curt Brune <curt@cucy.com>
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 #include <asm/hardware.h>
27 #include <flash.h>
28
29 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
30
31 typedef enum {
32         FLASH_DEV_U9_512KB = 0,
33         FLASH_DEV_U7_2MB = 1
34 } FLASH_DEV;
35
36 #define FLASH_DQ7               (0x80)
37 #define FLASH_DQ5               (0x20)
38
39 #define PROG_ADDR               (0xAAA)
40 #define SETUP_ADDR              (0xAAA)
41 #define ID_ADDR                 (0xAAA)
42 #define UNLOCK_ADDR1            (0xAAA)
43 #define UNLOCK_ADDR2            (0x555)
44
45 #define UNLOCK_CMD1             (0xAA)
46 #define UNLOCK_CMD2             (0x55)
47 #define ERASE_SUSPEND_CMD       (0xB0)
48 #define ERASE_RESUME_CMD        (0x30)
49 #define RESET_CMD               (0xF0)
50 #define ID_CMD                  (0x90)
51 #define SELECT_CMD              (0x90)
52 #define CHIPERASE_CMD           (0x10)
53 #define BYPASS_CMD              (0x20)
54 #define SECERASE_CMD            (0x30)
55 #define PROG_CMD                (0xa0)
56 #define SETUP_CMD               (0x80)
57
58 #if 0
59 #define WRITE_UNLOCK(addr) { \
60         PUT__U8( addr + UNLOCK_ADDR1, UNLOCK_CMD1); \
61         PUT__U8( addr + UNLOCK_ADDR2, UNLOCK_CMD2); \
62 }
63
64 /* auto select command */
65 #define CMD_ID(addr) WRITE_UNLOCK(addr); { \
66         PUT__U8( addr + ID_ADDR, ID_CMD); \
67 }
68
69 #define CMD_RESET(addr) WRITE_UNLOCK(addr); { \
70         PUT__U8( addr + ID_ADDR, RESET_CMD); \
71 }
72
73 #define CMD_ERASE_SEC(base, addr) WRITE_UNLOCK(base); \
74         PUT__U8( base + SETUP_ADDR, SETUP_CMD); \
75         WRITE_UNLOCK(base); \
76         PUT__U8( addr, SECERASE_CMD);
77
78 #define CMD_ERASE_CHIP(base) WRITE_UNLOCK(base); \
79         PUT__U8( base + SETUP_ADDR, SETUP_CMD); \
80         WRITE_UNLOCK(base); \
81         PUT__U8( base + SETUP_ADDR, CHIPERASE_CMD);
82
83 /* prepare for bypass programming */
84 #define CMD_UNLOCK_BYPASS(addr) WRITE_UNLOCK(addr); { \
85         PUT__U8( addr + ID_ADDR, 0x20); \
86 }
87
88 /* terminate bypass programming */
89 #define CMD_BYPASS_RESET(addr) { \
90         PUT__U8(addr, 0x90); \
91         PUT__U8(addr, 0x00); \
92 }
93 #endif
94
95 inline static void FLASH_CMD_UNLOCK (FLASH_DEV dev, u32 base)
96 {
97         switch (dev) {
98         case FLASH_DEV_U7_2MB:
99                 PUT__U8 (base + 0xAAA, 0xAA);
100                 PUT__U8 (base + 0x555, 0x55);
101                 break;
102         case FLASH_DEV_U9_512KB:
103                 PUT__U8 (base + 0x555, 0xAA);
104                 PUT__U8 (base + 0x2AA, 0x55);
105                 break;
106         }
107 }
108
109 inline static void FLASH_CMD_SELECT (FLASH_DEV dev, u32 base)
110 {
111         switch (dev) {
112         case FLASH_DEV_U7_2MB:
113                 FLASH_CMD_UNLOCK (dev, base);
114                 PUT__U8 (base + 0xAAA, SELECT_CMD);
115                 break;
116         case FLASH_DEV_U9_512KB:
117                 FLASH_CMD_UNLOCK (dev, base);
118                 PUT__U8 (base + 0x555, SELECT_CMD);
119                 break;
120         }
121 }
122
123 inline static void FLASH_CMD_RESET (FLASH_DEV dev, u32 base)
124 {
125         switch (dev) {
126         case FLASH_DEV_U7_2MB:
127                 FLASH_CMD_UNLOCK (dev, base);
128                 PUT__U8 (base + 0xAAA, RESET_CMD);
129                 break;
130         case FLASH_DEV_U9_512KB:
131                 FLASH_CMD_UNLOCK (dev, base);
132                 PUT__U8 (base + 0x555, RESET_CMD);
133                 break;
134         }
135 }
136
137 inline static void FLASH_CMD_ERASE_SEC (FLASH_DEV dev, u32 base, u32 addr)
138 {
139         switch (dev) {
140         case FLASH_DEV_U7_2MB:
141                 FLASH_CMD_UNLOCK (dev, base);
142                 PUT__U8 (base + 0xAAA, SETUP_CMD);
143                 FLASH_CMD_UNLOCK (dev, base);
144                 PUT__U8 (addr, SECERASE_CMD);
145                 break;
146         case FLASH_DEV_U9_512KB:
147                 FLASH_CMD_UNLOCK (dev, base);
148                 PUT__U8 (base + 0x555, SETUP_CMD);
149                 FLASH_CMD_UNLOCK (dev, base);
150                 PUT__U8 (addr, SECERASE_CMD);
151                 break;
152         }
153 }
154
155 inline static void FLASH_CMD_ERASE_CHIP (FLASH_DEV dev, u32 base)
156 {
157         switch (dev) {
158         case FLASH_DEV_U7_2MB:
159                 FLASH_CMD_UNLOCK (dev, base);
160                 PUT__U8 (base + 0xAAA, SETUP_CMD);
161                 FLASH_CMD_UNLOCK (dev, base);
162                 PUT__U8 (base, CHIPERASE_CMD);
163                 break;
164         case FLASH_DEV_U9_512KB:
165                 FLASH_CMD_UNLOCK (dev, base);
166                 PUT__U8 (base + 0x555, SETUP_CMD);
167                 FLASH_CMD_UNLOCK (dev, base);
168                 PUT__U8 (base, CHIPERASE_CMD);
169                 break;
170         }
171 }
172
173 inline static void FLASH_CMD_UNLOCK_BYPASS (FLASH_DEV dev, u32 base)
174 {
175         switch (dev) {
176         case FLASH_DEV_U7_2MB:
177                 FLASH_CMD_UNLOCK (dev, base);
178                 PUT__U8 (base + 0xAAA, BYPASS_CMD);
179                 break;
180         case FLASH_DEV_U9_512KB:
181                 FLASH_CMD_UNLOCK (dev, base);
182                 PUT__U8 (base + 0x555, BYPASS_CMD);
183                 break;
184         }
185 }
186
187 inline static void FLASH_CMD_BYPASS_RESET (FLASH_DEV dev, u32 base)
188 {
189         PUT__U8 (base, SELECT_CMD);
190         PUT__U8 (base, 0x0);
191 }
192
193 /* poll for flash command completion */
194 static u16 _flash_poll (FLASH_DEV dev, u32 addr, u16 data, ulong timeOut)
195 {
196         u32 done = 0;
197         ulong t0;
198
199         u16 error = 0;
200         volatile u16 flashData;
201
202         data = data & 0xFF;
203         t0 = get_timer (0);
204         while (get_timer (t0) < timeOut) {
205                 /*      for( i = 0; i < POLL_LOOPS; i++) { */
206                 /*  Read the Data */
207                 flashData = GET__U8 (addr);
208
209                 /*  FLASH_DQ7 = Data? */
210                 if ((flashData & FLASH_DQ7) == (data & FLASH_DQ7)) {
211                         done = 1;
212                         break;
213                 }
214
215                 /*  Check Timeout (FLASH_DQ5==1) */
216                 if (flashData & FLASH_DQ5) {
217                         /*  Read the Data */
218                         flashData = GET__U8 (addr);
219
220                         /*  FLASH_DQ7 = Data? */
221                         if (!((flashData & FLASH_DQ7) == (data & FLASH_DQ7))) {
222                                 printf ("_flash_poll(): FLASH_DQ7 & flashData not equal to write value\n");
223                                 error = ERR_PROG_ERROR;
224                         }
225                         FLASH_CMD_RESET (dev, addr);
226                         done = 1;
227                         break;
228                 }
229                 /*  spin delay */
230                 udelay (10);
231         }
232
233
234         /*  error update */
235         if (!done) {
236                 printf ("_flash_poll(): Timeout\n");
237                 error = ERR_TIMOUT;
238         }
239
240         /*  Check the data */
241         if (!error) {
242                 /*  Read the Data */
243                 flashData = GET__U8 (addr);
244                 if (flashData != data) {
245                         error = ERR_PROG_ERROR;
246                         printf ("_flash_poll(): flashData(0x%04x) not equal to data(0x%04x)\n",
247                                 flashData, data);
248                 }
249         }
250
251         return error;
252 }
253
254 /*-----------------------------------------------------------------------
255  */
256 static int _flash_check_protection (flash_info_t * info, int s_first, int s_last)
257 {
258         int sect, prot = 0;
259
260         for (sect = s_first; sect <= s_last; sect++)
261                 if (info->protect[sect]) {
262                         printf ("  Flash sector %d protected.\n", sect);
263                         prot++;
264                 }
265         return prot;
266 }
267
268 static int _detectFlash (FLASH_DEV dev, u32 base, u8 venId, u8 devId)
269 {
270
271         u32 baseAddr = base | CACHE_DISABLE_MASK;
272         u8 vendorId, deviceId;
273
274         /*      printf(__FUNCTION__"(): detecting flash @ 0x%08x\n", base); */
275
276         /* Send auto select command and read manufacturer info */
277         FLASH_CMD_SELECT (dev, baseAddr);
278         vendorId = GET__U8 (baseAddr);
279         FLASH_CMD_RESET (dev, baseAddr);
280
281         /* Send auto select command and read device info */
282         FLASH_CMD_SELECT (dev, baseAddr);
283
284         if (dev == FLASH_DEV_U7_2MB) {
285                 deviceId = GET__U8 (baseAddr + 2);
286         } else if (dev == FLASH_DEV_U9_512KB) {
287                 deviceId = GET__U8 (baseAddr + 1);
288         } else {
289                 return 0;
290         }
291
292         FLASH_CMD_RESET (dev, baseAddr);
293
294         /* printf (__FUNCTION__"(): found vendorId 0x%04x, deviceId 0x%04x\n",
295                 vendorId, deviceId);
296          */
297
298         return (vendorId == venId) && (deviceId == devId);
299
300 }
301
302 /******************************************************************************
303  *
304  * Public u-boot interface functions below
305  *
306  *****************************************************************************/
307
308 /***************************************************************************
309  *
310  * Flash initialization
311  *
312  * This board has two banks of flash, but the base addresses depend on
313  * how the board is jumpered.
314  *
315  * The two flash types are:
316  *
317  *   AMD Am29LV160DB (2MB) sectors layout 16KB, 2x8KB, 32KB, 31x64KB
318  *
319  *   AMD Am29LV040B  (512KB)  sectors: 8x64KB
320  *****************************************************************************/
321
322 unsigned long flash_init (void)
323 {
324         flash_info_t *info;
325         u16 i;
326         u32 flashtest;
327         s16 amd160 = -1;
328         u32 amd160base = 0;
329
330 #if CONFIG_SYS_MAX_FLASH_BANKS == 2
331         s16 amd040 = -1;
332         u32 amd040base = 0;
333 #endif
334
335         /* configure PHYS_FLASH_1 */
336         if (_detectFlash (FLASH_DEV_U7_2MB, PHYS_FLASH_1, 0x1, 0x49)) {
337                 amd160 = 0;
338                 amd160base = PHYS_FLASH_1;
339 #if CONFIG_SYS_MAX_FLASH_BANKS == 1
340         }
341 #else
342                 if (_detectFlash
343                     (FLASH_DEV_U9_512KB, PHYS_FLASH_2, 0x1, 0x4F)) {
344                         amd040 = 1;
345                         amd040base = PHYS_FLASH_2;
346                 } else {
347                         printf (__FUNCTION__
348                                 "(): Unable to detect PHYS_FLASH_2: 0x%08x\n",
349                                 PHYS_FLASH_2);
350                 }
351         } else if (_detectFlash (FLASH_DEV_U9_512KB, PHYS_FLASH_1, 0x1, 0x4F)) {
352                 amd040 = 0;
353                 amd040base = PHYS_FLASH_1;
354                 if (_detectFlash (FLASH_DEV_U7_2MB, PHYS_FLASH_2, 0x1, 0x49)) {
355                         amd160 = 1;
356                         amd160base = PHYS_FLASH_2;
357                 } else {
358                         printf (__FUNCTION__
359                                 "(): Unable to detect PHYS_FLASH_2: 0x%08x\n",
360                                 PHYS_FLASH_2);
361                 }
362         }
363 #endif
364         else {
365                 printf ("flash_init(): Unable to detect PHYS_FLASH_1: 0x%08x\n",
366                         PHYS_FLASH_1);
367         }
368
369         /* Configure AMD Am29LV160DB (2MB) */
370         info = &flash_info[amd160];
371         info->flash_id = FLASH_DEV_U7_2MB;
372         info->sector_count = 35;
373         info->size = 2 * 1024 * 1024;   /* 2MB */
374         /* 1*16K Boot Block
375            2*8K Parameter Block
376            1*32K Small Main Block */
377         info->start[0] = amd160base;
378         info->start[1] = amd160base + 0x4000;
379         info->start[2] = amd160base + 0x6000;
380         info->start[3] = amd160base + 0x8000;
381         for (i = 1; i < info->sector_count; i++)
382                 info->start[3 + i] = amd160base + i * (64 * 1024);
383
384         for (i = 0; i < info->sector_count; i++) {
385                 /* Write auto select command sequence and query sector protection */
386                 FLASH_CMD_SELECT (info->flash_id,
387                                   info->start[i] | CACHE_DISABLE_MASK);
388                 flashtest =
389                         GET__U8 (((info->start[i] + 4) | CACHE_DISABLE_MASK));
390                 FLASH_CMD_RESET (info->flash_id,
391                                  amd160base | CACHE_DISABLE_MASK);
392                 info->protect[i] = (flashtest & 0x0001);
393         }
394
395         /*
396          * protect monitor and environment sectors in 2MB flash
397          */
398         flash_protect (FLAG_PROTECT_SET,
399                        amd160base, amd160base + monitor_flash_len - 1, info);
400
401         flash_protect (FLAG_PROTECT_SET,
402                        CONFIG_ENV_ADDR, CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, info);
403
404 #if CONFIG_SYS_MAX_FLASH_BANKS == 2
405         /* Configure AMD Am29LV040B (512KB) */
406         info = &flash_info[amd040];
407         info->flash_id = FLASH_DEV_U9_512KB;
408         info->sector_count = 8;
409         info->size = 512 * 1024;        /* 512KB, 8 x 64KB */
410         for (i = 0; i < info->sector_count; i++) {
411                 info->start[i] = amd040base + i * (64 * 1024);
412                 /* Write auto select command sequence and query sector protection */
413                 FLASH_CMD_SELECT (info->flash_id,
414                                   info->start[i] | CACHE_DISABLE_MASK);
415                 flashtest =
416                         GET__U8 (((info->start[i] + 2) | CACHE_DISABLE_MASK));
417                 FLASH_CMD_RESET (info->flash_id,
418                                  amd040base | CACHE_DISABLE_MASK);
419                 info->protect[i] = (flashtest & 0x0001);
420         }
421 #endif
422
423         return flash_info[0].size
424 #if CONFIG_SYS_MAX_FLASH_BANKS == 2
425                 + flash_info[1].size
426 #endif
427                 ;
428 }
429
430 void flash_print_info (flash_info_t * info)
431 {
432         int i;
433
434         if (info->flash_id == FLASH_DEV_U7_2MB) {
435                 printf ("AMD Am29LV160DB (2MB) 16KB,2x8KB,32KB,31x64KB\n");
436         } else if (info->flash_id == FLASH_DEV_U9_512KB) {
437                 printf ("AMD Am29LV040B  (512KB) 8x64KB\n");
438         } else {
439                 printf ("Unknown flash_id ...\n");
440                 return;
441         }
442
443         printf ("  Size: %ld KB in %d Sectors\n",
444                 info->size >> 10, info->sector_count);
445         printf ("  Sector Start Addresses:");
446         for (i = 0; i < info->sector_count; i++) {
447                 if ((i % 4) == 0)
448                         printf ("\n   ");
449                 printf (" S%02d @ 0x%08lX%s", i,
450                         info->start[i], info->protect[i] ? " !" : "  ");
451         }
452         printf ("\n");
453 }
454
455 int flash_erase (flash_info_t * info, int s_first, int s_last)
456 {
457         u16 i, error = 0;
458
459         printf ("\n");
460
461         /* check flash protection bits */
462         if (_flash_check_protection (info, s_first, s_last)) {
463                 printf ("  Flash erase aborted due to protected sectors\n");
464                 return ERR_PROTECTED;
465         }
466
467         if ((s_first < info->sector_count) && (s_first <= s_last)) {
468                 for (i = s_first; i <= s_last && !error; i++) {
469                         printf ("  Erasing Sector %d @ 0x%08lx ... ", i,
470                                 info->start[i]);
471                         /* bypass the cache to access the flash memory */
472                         FLASH_CMD_ERASE_SEC (info->flash_id,
473                                              (info->
474                                               start[0] | CACHE_DISABLE_MASK),
475                                              (info->
476                                               start[i] | CACHE_DISABLE_MASK));
477                         /* look for sector to become 0xFF after erase */
478                         error = _flash_poll (info->flash_id,
479                                              info->
480                                              start[i] | CACHE_DISABLE_MASK,
481                                              0xFF, CONFIG_SYS_FLASH_ERASE_TOUT);
482                         FLASH_CMD_RESET (info->flash_id,
483                                          (info->
484                                           start[0] | CACHE_DISABLE_MASK));
485                         printf ("done\n");
486                         if (error) {
487                                 break;
488                         }
489                 }
490         } else
491                 error = ERR_INVAL;
492
493         return error;
494 }
495
496 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
497 {
498         u16 error = 0, i;
499         u32 n;
500         u8 *bp, *bps;
501
502         /*  Write Setup */
503         /* bypass the cache to access the flash memory */
504         FLASH_CMD_UNLOCK_BYPASS (info->flash_id,
505                                  (info->start[0] | CACHE_DISABLE_MASK));
506
507         /*  Write the Data to Flash */
508
509         bp = (u8 *) (addr | CACHE_DISABLE_MASK);
510         bps = (u8 *) src;
511
512         for (n = 0; n < cnt && !error; n++, bp++, bps++) {
513
514                 if (!(n % (cnt / 15))) {
515                         printf (".");
516                 }
517
518                 /*  write the flash command for flash memory */
519                 *bp = 0xA0;
520
521                 /*  Write the data */
522                 *bp = *bps;
523
524                 /*  Check if the write is done */
525                 for (i = 0; i < 0xff; i++);
526                 error = _flash_poll (info->flash_id, (u32) bp, *bps,
527                                      CONFIG_SYS_FLASH_WRITE_TOUT);
528                 if (error) {
529                         return error;
530                 }
531         }
532
533         /*  Reset the Flash Mode to read */
534         FLASH_CMD_BYPASS_RESET (info->flash_id, info->start[0]);
535
536         printf (" ");
537
538         return error;
539 }