]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/jse/flash.c
arm: mx5: clock: add support for changing CPU clock via cmdline
[karo-tx-uboot.git] / board / jse / flash.c
1 /*
2  * (C) Copyright 2000-2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 /*
9  * Modified 4/5/2001
10  * Wait for completion of each sector erase command issued
11  * 4/5/2001
12  * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
13  */
14
15 #include <common.h>
16 #include <asm/ppc4xx.h>
17 #include <asm/processor.h>
18
19 #if CONFIG_SYS_MAX_FLASH_BANKS != 1
20 #error "CONFIG_SYS_MAX_FLASH_BANKS must be 1"
21 #endif
22 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];    /* info for FLASH chips */
23
24 /*-----------------------------------------------------------------------
25  * Functions
26  */
27 static ulong flash_get_size (vu_long * addr, flash_info_t * info);
28 static int write_word (flash_info_t * info, ulong dest, ulong data);
29 static void flash_get_offsets (ulong base, flash_info_t * info);
30
31 #define ADDR0           0x5555
32 #define ADDR1           0x2aaa
33 #define FLASH_WORD_SIZE unsigned char
34
35 /*-----------------------------------------------------------------------
36  */
37
38 unsigned long flash_init (void)
39 {
40         unsigned long size_b0;
41
42         /* Init: no FLASHes known */
43         flash_info[0].flash_id = FLASH_UNKNOWN;
44
45         /* Static FLASH Bank configuration here - FIXME XXX */
46
47         size_b0 = flash_get_size ((vu_long *) FLASH_BASE0_PRELIM, &flash_info[0]);
48
49         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
50                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
51                         size_b0, size_b0 << 20);
52         }
53
54         /* Only one bank */
55         /* Setup offsets */
56         flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);
57
58         /* Monitor protection ON by default */
59         (void) flash_protect (FLAG_PROTECT_SET,
60                               FLASH_BASE0_PRELIM,
61                               FLASH_BASE0_PRELIM + monitor_flash_len - 1,
62                               &flash_info[0]);
63         flash_info[0].size = size_b0;
64
65         return size_b0;
66 }
67
68
69 /*-----------------------------------------------------------------------
70  */
71 /*
72  * This implementation assumes that the flash chips are uniform sector
73  * devices. This is true for all likely JSE devices.
74  */
75 static void flash_get_offsets (ulong base, flash_info_t * info)
76 {
77         unsigned idx;
78         unsigned long sector_size = info->size / info->sector_count;
79
80         for (idx = 0; idx < info->sector_count; idx += 1) {
81                 info->start[idx] = base + (idx * sector_size);
82         }
83 }
84
85 /*-----------------------------------------------------------------------
86  */
87 void flash_print_info (flash_info_t * info)
88 {
89         int i;
90         int k;
91         int size;
92         int erased;
93         volatile unsigned long *flash;
94
95         if (info->flash_id == FLASH_UNKNOWN) {
96                 printf ("missing or unknown FLASH type\n");
97                 return;
98         }
99
100         switch (info->flash_id & FLASH_VENDMASK) {
101         case FLASH_MAN_AMD:
102                 printf ("AMD ");
103                 break;
104         case FLASH_MAN_FUJ:
105                 printf ("FUJITSU ");
106                 break;
107         case FLASH_MAN_SST:
108                 printf ("SST ");
109                 break;
110         case FLASH_MAN_STM:
111                 printf ("ST Micro ");
112                 break;
113         default:
114                 printf ("Unknown Vendor ");
115                 break;
116         }
117
118           /* (Reduced table of only parts expected in JSE boards.) */
119         switch (info->flash_id) {
120         case FLASH_MAN_AMD | FLASH_AM040:
121                 printf ("AM29F040 (512 Kbit, uniform sector size)\n");
122                 break;
123         case FLASH_MAN_STM | FLASH_AM040:
124                 printf ("MM29W040W (512 Kbit, uniform sector size)\n");
125                 break;
126         default:
127                 printf ("Unknown Chip Type\n");
128                 break;
129         }
130
131         printf ("  Size: %ld KB in %d Sectors\n",
132                 info->size >> 10, info->sector_count);
133
134         printf ("  Sector Start Addresses:");
135         for (i = 0; i < info->sector_count; ++i) {
136                 /*
137                  * Check if whole sector is erased
138                  */
139                 if (i != (info->sector_count - 1))
140                         size = info->start[i + 1] - info->start[i];
141                 else
142                         size = info->start[0] + info->size - info->start[i];
143                 erased = 1;
144                 flash = (volatile unsigned long *) info->start[i];
145                 size = size >> 2;       /* divide by 4 for longword access */
146                 for (k = 0; k < size; k++) {
147                         if (*flash++ != 0xffffffff) {
148                                 erased = 0;
149                                 break;
150                         }
151                 }
152
153                 if ((i % 5) == 0)
154                         printf ("\n   ");
155                 printf (" %08lX%s%s",
156                         info->start[i],
157                         erased ? " E" : "  ", info->protect[i] ? "RO " : "   "
158                 );
159         }
160         printf ("\n");
161         return;
162 }
163
164 /*-----------------------------------------------------------------------
165  */
166
167
168 /*-----------------------------------------------------------------------
169  */
170
171 /*
172  * The following code cannot be run from FLASH!
173  */
174 static ulong flash_get_size (vu_long * addr, flash_info_t * info)
175 {
176         short i;
177         FLASH_WORD_SIZE value;
178         ulong base = (ulong) addr;
179         volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) addr;
180
181         /* Write auto select command: read Manufacturer ID */
182         addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
183         addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
184         addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00900090;
185
186         value = addr2[0];
187
188         switch (value) {
189         case (FLASH_WORD_SIZE) AMD_MANUFACT:
190                 info->flash_id = FLASH_MAN_AMD;
191                 break;
192         case (FLASH_WORD_SIZE) FUJ_MANUFACT:
193                 info->flash_id = FLASH_MAN_FUJ;
194                 break;
195         case (FLASH_WORD_SIZE) SST_MANUFACT:
196                 info->flash_id = FLASH_MAN_SST;
197                 break;
198         case (FLASH_WORD_SIZE)STM_MANUFACT:
199                 info->flash_id = FLASH_MAN_STM;
200                 break;
201         default:
202                 info->flash_id = FLASH_UNKNOWN;
203                 info->sector_count = 0;
204                 info->size = 0;
205                 printf("Unknown flash manufacturer code: 0x%x\n", value);
206                 return (0);     /* no or unknown flash  */
207         }
208
209         value = addr2[1];       /* device ID            */
210
211         switch (value) {
212         case (FLASH_WORD_SIZE) AMD_ID_F040B:
213                 info->flash_id += FLASH_AM040;
214                 info->sector_count = 8;
215                 info->size = 0x0080000; /* => 512 ko */
216                 break;
217         case (FLASH_WORD_SIZE) AMD_ID_LV040B:
218                 info->flash_id += FLASH_AM040;
219                 info->sector_count = 8;
220                 info->size = 0x0080000; /* => 512 ko */
221                 break;
222         case (FLASH_WORD_SIZE)STM_ID_M29W040B: /* most likele JSE chip */
223                 info->flash_id += FLASH_AM040;
224                 info->sector_count = 8;
225                 info->size = 0x0080000; /* => 512 ko */
226                 break;
227         default:
228                 info->flash_id = FLASH_UNKNOWN;
229                 return (0);     /* => no or unknown flash */
230
231         }
232
233           /* Calculate the sector offsets (Use JSE Optimized code). */
234         flash_get_offsets(base, info);
235
236         /* check for protected sectors */
237         for (i = 0; i < info->sector_count; i++) {
238                 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
239                 /* D0 = 1 if protected */
240                 addr2 = (volatile FLASH_WORD_SIZE *) (info->start[i]);
241                 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
242                         info->protect[i] = 0;
243                 else
244                         info->protect[i] = addr2[2] & 1;
245         }
246
247         /*
248          * Prevent writes to uninitialized FLASH.
249          */
250         if (info->flash_id != FLASH_UNKNOWN) {
251                 addr2 = (FLASH_WORD_SIZE *) info->start[0];
252                 *addr2 = (FLASH_WORD_SIZE) 0x00F000F0;  /* reset bank */
253         }
254
255         return (info->size);
256 }
257
258 int wait_for_DQ7 (flash_info_t * info, int sect)
259 {
260         ulong start, now, last;
261         volatile FLASH_WORD_SIZE *addr =
262                 (FLASH_WORD_SIZE *) (info->start[sect]);
263
264         start = get_timer (0);
265         last = start;
266         while ((addr[0] & (FLASH_WORD_SIZE) 0x00800080) !=
267                (FLASH_WORD_SIZE) 0x00800080) {
268                 if ((now = get_timer (start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
269                         printf ("Timeout\n");
270                         return -1;
271                 }
272                 /* show that we're waiting */
273                 if ((now - last) > 1000) {      /* every second */
274                         putc ('.');
275                         last = now;
276                 }
277         }
278         return 0;
279 }
280
281 /*-----------------------------------------------------------------------
282  */
283
284 int flash_erase (flash_info_t * info, int s_first, int s_last)
285 {
286         volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
287         volatile FLASH_WORD_SIZE *addr2;
288         int flag, prot, sect;
289         int i;
290
291         if ((s_first < 0) || (s_first > s_last)) {
292                 if (info->flash_id == FLASH_UNKNOWN) {
293                         printf ("- missing\n");
294                 } else {
295                         printf ("- no sectors to erase\n");
296                 }
297                 return 1;
298         }
299
300         if (info->flash_id == FLASH_UNKNOWN) {
301                 printf ("Can't erase unknown flash type - aborted\n");
302                 return 1;
303         }
304
305         prot = 0;
306         for (sect = s_first; sect <= s_last; ++sect) {
307                 if (info->protect[sect]) {
308                         prot++;
309                 }
310         }
311
312         if (prot) {
313                 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
314         } else {
315                 printf ("\n");
316         }
317
318         /* Disable interrupts which might cause a timeout here */
319         flag = disable_interrupts ();
320
321         /* Start erase on unprotected sectors */
322         for (sect = s_first; sect <= s_last; sect++) {
323                 if (info->protect[sect] == 0) { /* not protected */
324                         addr2 = (FLASH_WORD_SIZE *) (info->start[sect]);
325                         printf ("Erasing sector %p\n", addr2);  /* CLH */
326
327                         if ((info->flash_id & FLASH_VENDMASK) ==
328                             FLASH_MAN_SST) {
329                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
330                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
331                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
332                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
333                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
334                                 addr2[0] = (FLASH_WORD_SIZE) 0x00500050;        /* block erase */
335                                 for (i = 0; i < 50; i++)
336                                         udelay (1000);  /* wait 1 ms */
337                         } else {
338                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
339                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
340                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
341                                 addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
342                                 addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
343                                 addr2[0] = (FLASH_WORD_SIZE) 0x00300030;        /* sector erase */
344                         }
345                         /*
346                          * Wait for each sector to complete, it's more
347                          * reliable.  According to AMD Spec, you must
348                          * issue all erase commands within a specified
349                          * timeout.  This has been seen to fail, especially
350                          * if printf()s are included (for debug)!!
351                          */
352                         wait_for_DQ7 (info, sect);
353                 }
354         }
355
356         /* re-enable interrupts if necessary */
357         if (flag)
358                 enable_interrupts ();
359
360         /* wait at least 80us - let's wait 1 ms */
361         udelay (1000);
362
363         /* reset to read mode */
364         addr = (FLASH_WORD_SIZE *) info->start[0];
365         addr[0] = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
366
367         printf (" done\n");
368         return 0;
369 }
370
371 /*-----------------------------------------------------------------------
372  * Copy memory to flash, returns:
373  * 0 - OK
374  * 1 - write timeout
375  * 2 - Flash not erased
376  */
377
378 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
379 {
380         ulong cp, wp, data;
381         int i, l, rc;
382
383         wp = (addr & ~3);       /* get lower word aligned address */
384
385         /*
386          * handle unaligned start bytes
387          */
388         if ((l = addr - wp) != 0) {
389                 data = 0;
390                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
391                         data = (data << 8) | (*(uchar *) cp);
392                 }
393                 for (; i < 4 && cnt > 0; ++i) {
394                         data = (data << 8) | *src++;
395                         --cnt;
396                         ++cp;
397                 }
398                 for (; cnt == 0 && i < 4; ++i, ++cp) {
399                         data = (data << 8) | (*(uchar *) cp);
400                 }
401
402                 if ((rc = write_word (info, wp, data)) != 0) {
403                         return (rc);
404                 }
405                 wp += 4;
406         }
407
408         /*
409          * handle word aligned part
410          */
411         while (cnt >= 4) {
412                 data = 0;
413                 for (i = 0; i < 4; ++i) {
414                         data = (data << 8) | *src++;
415                 }
416                 if ((rc = write_word (info, wp, data)) != 0) {
417                         return (rc);
418                 }
419                 wp += 4;
420                 cnt -= 4;
421         }
422
423         if (cnt == 0) {
424                 return (0);
425         }
426
427         /*
428          * handle unaligned tail bytes
429          */
430         data = 0;
431         for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
432                 data = (data << 8) | *src++;
433                 --cnt;
434         }
435         for (; i < 4; ++i, ++cp) {
436                 data = (data << 8) | (*(uchar *) cp);
437         }
438
439         return (write_word (info, wp, data));
440 }
441
442 /*-----------------------------------------------------------------------
443  * Write a word to Flash, returns:
444  * 0 - OK
445  * 1 - write timeout
446  * 2 - Flash not erased
447  */
448 static int write_word (flash_info_t * info, ulong dest, ulong data)
449 {
450         volatile FLASH_WORD_SIZE *addr2 =
451                 (FLASH_WORD_SIZE *) (info->start[0]);
452         volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;
453         volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
454         ulong start;
455         int i;
456
457         /* Check if Flash is (sufficiently) erased */
458         if ((*((volatile FLASH_WORD_SIZE *) dest) &
459             (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
460                 return (2);
461         }
462
463         for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) {
464                 int flag;
465
466                 /* Disable interrupts which might cause a timeout here */
467                 flag = disable_interrupts ();
468
469                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
470                 addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
471                 addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0;
472
473                 dest2[i] = data2[i];
474
475                 /* re-enable interrupts if necessary */
476                 if (flag)
477                         enable_interrupts ();
478
479                 /* data polling for D7 */
480                 start = get_timer (0);
481                 while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
482                        (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
483
484                         if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
485                                 return (1);
486                         }
487                 }
488         }
489
490         return (0);
491 }