]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/gen860t/flash.c
Coding Style cleanup: replace leading SPACEs by TABs
[karo-tx-uboot.git] / board / gen860t / flash.c
1 /*
2  * (C) Copyright 2001
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  * Keith Outwater, keith_outwater@mvsi.com
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <mpc8xx.h>
11
12 #if defined(CONFIG_ENV_IS_IN_FLASH)
13 # ifndef  CONFIG_ENV_ADDR
14 #  define CONFIG_ENV_ADDR       (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
15 # endif
16 # ifndef  CONFIG_ENV_SIZE
17 #  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
18 # endif
19 # ifndef  CONFIG_ENV_SECT_SIZE
20 #  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
21 # endif
22 #endif
23
24 /*
25  * Use buffered writes to flash by default - they are about 32x faster than
26  * single byte writes.
27  */
28 #ifndef  CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER
29 #define CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER
30 #endif
31
32 /*
33  * Max time to wait (in mS) for flash device to allocate a write buffer.
34  */
35 #ifndef CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT
36 #define CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT              100
37 #endif
38
39 /*
40  * These functions support a single Intel StrataFlash device (28F128J3A)
41  * in byte mode only!.  The flash routines are very basic and simple
42  * since there isn't really any remapping necessary.
43  */
44
45 /*
46  * Intel SCS (Scalable Command Set) command definitions
47  * (taken from 28F128J3A datasheet)
48  */
49 #define SCS_READ_CMD                            0xff
50 #define SCS_READ_ID_CMD                         0x90
51 #define SCS_QUERY_CMD                           0x98
52 #define SCS_READ_STATUS_CMD                     0x70
53 #define SCS_CLEAR_STATUS_CMD            0x50
54 #define SCS_WRITE_BUF_CMD                       0xe8
55 #define SCS_PROGRAM_CMD                         0x40
56 #define SCS_BLOCK_ERASE_CMD                     0x20
57 #define SCS_BLOCK_ERASE_RESUME_CMD      0xd0
58 #define SCS_PROGRAM_RESUME_CMD          0xd0
59 #define SCS_BLOCK_ERASE_SUSPEND_CMD     0xb0
60 #define SCS_SET_BLOCK_LOCK_CMD          0x60
61 #define SCS_CLR_BLOCK_LOCK_CMD          0x60
62
63 /*
64  * SCS status/extended status register bit definitions
65  */
66 #define  SCS_SR7                                        0x80
67 #define  SCS_XSR7                                       0x80
68
69 /*---------------------------------------------------------------------*/
70 #if 0
71 #define DEBUG_FLASH
72 #endif
73
74 #ifdef DEBUG_FLASH
75 #define PRINTF(fmt,args...) printf(fmt ,##args)
76 #else
77 #define PRINTF(fmt,args...)
78 #endif
79 /*---------------------------------------------------------------------*/
80
81 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
82
83 /*-----------------------------------------------------------------------
84  * Functions
85  */
86 static ulong flash_get_size (vu_char *addr, flash_info_t *info);
87 static int write_data8 (flash_info_t *info, ulong dest, uchar data);
88 static void flash_get_offsets (ulong base, flash_info_t *info);
89
90 /*-----------------------------------------------------------------------
91  * Initialize the flash memory.
92  */
93 unsigned long
94 flash_init (void)
95 {
96         volatile immap_t     *immap  = (immap_t *)CONFIG_SYS_IMMR;
97         volatile memctl8xx_t *memctl = &immap->im_memctl;
98         unsigned long size_b0;
99         int i;
100
101         for (i= 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
102                 flash_info[i].flash_id = FLASH_UNKNOWN;
103         }
104
105         /*
106          * The gen860t board only has one FLASH memory device, so the
107          * FLASH Bank configuration is done statically.
108          */
109         PRINTF("\n## Get flash bank 1 size @ 0x%08x\n", FLASH_BASE0_PRELIM);
110         size_b0 = flash_get_size((vu_char *)FLASH_BASE0_PRELIM, &flash_info[0]);
111         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
112                 printf ("## Unknown FLASH on Bank 0: "
113                                 "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
114                                 flash_info[0].flash_id,size_b0, size_b0 << 20);
115         }
116
117         PRINTF("## Before remap:\n"
118                    "  BR0: 0x%08x    OR0: 0x%08x\n  BR1: 0x%08x    OR1: 0x%08x\n",
119                    memctl->memc_br0, memctl->memc_or0,
120                    memctl->memc_br1, memctl->memc_or1);
121
122         /*
123          * Remap FLASH according to real size
124          */
125         memctl->memc_or0 |= (-size_b0 & 0xFFFF8000);
126         memctl->memc_br0 |= (CONFIG_SYS_FLASH_BASE & BR_BA_MSK);
127
128         PRINTF("## After remap:\n"
129                    "  BR0: 0x%08x    OR0: 0x%08x\n", memctl->memc_br0, memctl->memc_or0);
130
131         /*
132          * Re-do sizing to get full correct info
133          */
134         size_b0 = flash_get_size ((vu_char *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
135         flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
136         flash_info[0].size = size_b0;
137
138 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
139         /*
140          * Monitor protection is ON by default
141          */
142         flash_protect(FLAG_PROTECT_SET,
143                           CONFIG_SYS_MONITOR_BASE,
144                           CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
145                           &flash_info[0]);
146 #endif
147
148 #ifdef  CONFIG_ENV_IS_IN_FLASH
149         /*
150          * Environment protection ON by default
151          */
152         flash_protect(FLAG_PROTECT_SET,
153                           CONFIG_ENV_ADDR,
154                           CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
155                           &flash_info[0]);
156 #endif
157
158         PRINTF("## Final Flash bank size: 0x%08lx\n",size_b0);
159         return (size_b0);
160 }
161
162
163 /*-----------------------------------------------------------------------
164  * Fill in the FLASH offset table
165  */
166 static void
167 flash_get_offsets (ulong base, flash_info_t *info)
168 {
169         int i;
170
171         if (info->flash_id == FLASH_UNKNOWN) {
172                 return;
173         }
174
175         switch (info->flash_id & FLASH_VENDMASK) {
176                 case FLASH_MAN_INTEL:
177                 for (i = 0; i < info->sector_count; i++) {
178                                 info->start[i] = base;
179                                 base += 1024 * 128;
180                 }
181                 return;
182
183                 default:
184                         printf ("Don't know sector offsets for FLASH"
185                                 " type 0x%lx\n", info->flash_id);
186             return;
187         }
188 }
189
190
191 /*-----------------------------------------------------------------------
192  * Display FLASH device info
193  */
194 void
195 flash_print_info (flash_info_t *info)
196 {
197         int i;
198
199         if (info->flash_id == FLASH_UNKNOWN) {
200                 printf ("Missing or unknown FLASH type\n");
201                 return;
202         }
203
204         switch (info->flash_id & FLASH_VENDMASK) {
205         case FLASH_MAN_INTEL:
206                         printf ("Intel ");
207                         break;
208         default:
209                         printf ("Unknown Vendor ");
210                         break;
211         }
212
213         switch (info->flash_id & FLASH_TYPEMASK) {
214         case FLASH_28F128J3A:
215                         printf ("28F128J3A (128Mbit = 128K x 128)\n");
216                         break;
217         default:
218                         printf ("Unknown Chip Type\n");
219                         break;
220         }
221
222         if (info->size >= (1024 * 1024)) {
223                 i = 20;
224         } else {
225                 i = 10;
226         }
227         printf ("  Size: %ld %cB in %d Sectors\n",
228                         info->size >> i,
229                         (i == 20) ? 'M' : 'k',
230                         info->sector_count);
231
232         printf ("  Sector Start Addresses:");
233         for (i=0; i<info->sector_count; ++i) {
234                 if ((i % 5) == 0)
235                         printf ("\n   ");
236                         printf (" %08lX%s",
237                         info->start[i],
238                         info->protect[i] ? " (RO)" : "     "
239                 );
240         }
241         printf ("\n");
242         return;
243 }
244
245
246 /*-----------------------------------------------------------------------
247  * Get size and other information for a FLASH device.
248  * NOTE: The following code cannot be run from FLASH!
249  */
250 static
251 ulong flash_get_size (vu_char *addr, flash_info_t *info)
252 {
253 #define NO_FLASH        0
254
255         vu_char value[2];
256
257         /*
258          * Try to read the manufacturer ID
259          */
260         addr[0] = SCS_READ_CMD;
261         addr[0] = SCS_READ_ID_CMD;
262         value[0] = addr[0];
263         value[1] = addr[2];
264         addr[0] = SCS_READ_CMD;
265
266         PRINTF("Manuf. ID @ 0x%08lx: 0x%02x\n", (ulong)addr, value[0]);
267         switch (value[0]) {
268                 case (INTEL_MANUFACT & 0xff):
269                         info->flash_id = FLASH_MAN_INTEL;
270                         break;
271                 default:
272                         info->flash_id = FLASH_UNKNOWN;
273                         info->sector_count = 0;
274                         info->size = 0;
275                         return (NO_FLASH);
276         }
277
278         /*
279          * Read the device ID
280          */
281         PRINTF("Device ID @ 0x%08lx: 0x%02x\n", (ulong)(&addr[2]), value[1]);
282         switch (value[1]) {
283                 case (INTEL_ID_28F128J3A & 0xff):
284                         info->flash_id += FLASH_28F128J3A;
285                         info->sector_count = 128;
286                         info->size = 16 * 1024 * 1024;
287                         break;
288
289                 default:
290                         info->flash_id = FLASH_UNKNOWN;
291                         return (NO_FLASH);
292         }
293
294         if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
295                 printf ("** ERROR: sector count %d > max (%d) **\n",
296                                 info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
297                                 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
298         }
299         return (info->size);
300 }
301
302
303 /*-----------------------------------------------------------------------
304  * Erase the specified sectors in the specified FLASH device
305  */
306 int
307 flash_erase(flash_info_t *info, int s_first, int s_last)
308 {
309         int flag, prot, sect;
310         ulong start, now, last;
311
312         if ((s_first < 0) || (s_first > s_last)) {
313                 if (info->flash_id == FLASH_UNKNOWN) {
314                         printf ("- missing\n");
315                 } else {
316                         printf ("- no sectors to erase\n");
317                 }
318                 return 1;
319         }
320
321         if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
322                 printf ("Can erase only Intel flash types - aborted\n");
323                 return 1;
324         }
325
326         prot = 0;
327         for (sect=s_first; sect<=s_last; ++sect) {
328                 if (info->protect[sect]) {
329                         prot++;
330                 }
331         }
332
333         if (prot) {
334                 printf ("- Warning: %d protected sectors will not be erased!\n",
335                                 prot);
336         } else {
337                 printf ("\n");
338         }
339
340         start = get_timer (0);
341         last  = start;
342
343         /*
344          * Start erase on unprotected sectors
345          */
346         for (sect = s_first; sect<=s_last; sect++) {
347                 if (info->protect[sect] == 0) { /* not protected */
348                         vu_char *addr = (uchar *)(info->start[sect]);
349                         vu_char status;
350
351                         /*
352                          * Disable interrupts which might cause a timeout
353                          */
354                         flag = disable_interrupts();
355
356                         *addr = SCS_CLEAR_STATUS_CMD;
357                         *addr = SCS_BLOCK_ERASE_CMD;
358                         *addr = SCS_BLOCK_ERASE_RESUME_CMD;
359
360                         /*
361                          * Re-enable interrupts if necessary
362                          */
363                         if (flag)
364                                 enable_interrupts();
365
366                         /*
367                          * Wait at least 80us - let's wait 1 ms
368                          */
369                         udelay (1000);
370
371                         while (((status = *addr) & SCS_SR7) != SCS_SR7) {
372                                 if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
373                                         printf ("Timeout\n");
374                                         *addr = SCS_BLOCK_ERASE_SUSPEND_CMD;
375                                         *addr = SCS_READ_CMD;
376                                         return 1;
377                                 }
378
379                                 /*
380                                  * Show that we're waiting
381                                  */
382                                 if ((now - last) > 1000) {      /* 1 second */
383                                         putc ('.');
384                                         last = now;
385                                 }
386                         }
387                         *addr = SCS_READ_CMD;
388                 }
389         }
390         printf (" done\n");
391         return 0;
392 }
393
394
395 #ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER
396 /*
397  * Allocate a flash buffer, fill it with data and write it to the flash.
398  * 0 - OK
399  * 1 - Timeout on buffer request
400  *
401  * NOTE: After the last call to this function, WSM status needs to be checked!
402  */
403 static int
404 write_flash_buffer8(flash_info_t *info_p, vu_char *src_p, vu_char *dest_p,
405                                     uint count)
406 {
407         vu_char *block_addr_p = NULL;
408         vu_char *start_addr_p = NULL;
409         ulong blocksize = info_p->size / (ulong)info_p->sector_count;
410
411         int i;
412         uint time = get_timer(0);
413
414         PRINTF("%s:%d: src: 0x%p dest: 0x%p  count: %d\n",
415                    __FUNCTION__, __LINE__, src_p, dest_p, count);
416
417         /*
418          * What block are we in? We already know that the source address is
419          * in the flash address range, but we also can't cross a block boundary.
420          * We assume that the block does not cross a boundary (we'll check before
421          * calling this function).
422          */
423         for (i = 0; i < info_p->sector_count; ++i) {
424                 if ( ((ulong)dest_p >= info_p->start[i]) &&
425                     ((ulong)dest_p < (info_p->start[i] + blocksize)) ) {
426                         PRINTF("%s:%d: Dest addr 0x%p is in block %d @ 0x%.8lx\n",
427                                    __FUNCTION__, __LINE__, dest_p, i, info_p->start[i]);
428                         block_addr_p = (vu_char *)info_p->start[i];
429                         break;
430                 }
431         }
432
433         /*
434          * Request a buffer
435          */
436         *block_addr_p = SCS_WRITE_BUF_CMD;
437         while ((*block_addr_p & SCS_XSR7) != SCS_XSR7) {
438                 if (get_timer(time) >  CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT) {
439                         PRINTF("%s:%d: Buffer allocation timeout @ 0x%p (waited %d mS)\n",
440                                    __FUNCTION__, __LINE__, block_addr_p,
441                                    CONFIG_SYS_FLASH_ALLOC_BUFFER_TOUT);
442                         return 1;
443                 }
444                 *block_addr_p = SCS_WRITE_BUF_CMD;
445         }
446
447         /*
448          * Fill the buffer with data
449          */
450         start_addr_p = dest_p;
451         *block_addr_p = count - 1; /* flash device wants count - 1 */
452         PRINTF("%s:%d: Fill buffer at block addr 0x%p\n",
453                    __FUNCTION__, __LINE__, block_addr_p);
454         for (i = 0; i < count; i++) {
455                 *start_addr_p++ = *src_p++;
456         }
457
458         /*
459          * Flush buffer to flash
460          */
461         *block_addr_p = SCS_PROGRAM_RESUME_CMD;
462 #if 1
463         time = get_timer(0);
464         while ((*block_addr_p & SCS_SR7) != SCS_SR7) {
465                 if (get_timer(time) >  CONFIG_SYS_FLASH_WRITE_TOUT) {
466                         PRINTF("%s:%d: Write timeout @ 0x%p (waited %d mS)\n",
467                                    __FUNCTION__, __LINE__, block_addr_p, CONFIG_SYS_FLASH_WRITE_TOUT);
468                         return 1;
469                 }
470         }
471
472 #endif
473         return 0;
474 }
475 #endif
476
477
478 /*-----------------------------------------------------------------------
479  * Copy memory to flash, returns:
480  * 0 - OK
481  * 1 - write timeout
482  * 2 - Flash not erased
483  * 4 - Flash not identified
484  */
485 int
486 write_buff(flash_info_t *info_p, uchar *src_p, ulong addr, ulong count)
487 {
488         int rc = 0;
489 #ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER
490 #define FLASH_WRITE_BUF_SIZE    0x00000020      /* 32 bytes */
491         int i;
492         uint bufs;
493         ulong buf_count;
494         vu_char *sp;
495         vu_char *dp;
496 #else
497         ulong wp;
498 #endif
499
500         PRINTF("\n%s:%d: src: 0x%.8lx dest: 0x%.8lx size: %d (0x%.8lx)\n",
501                    __FUNCTION__, __LINE__, (ulong)src_p, addr, (uint)count, count);
502
503         if (info_p->flash_id == FLASH_UNKNOWN) {
504                 return 4;
505         }
506
507 #ifdef CONFIG_SYS_GEN860T_FLASH_USE_WRITE_BUFFER
508         sp = src_p;
509         dp = (uchar *)addr;
510
511         /*
512          * For maximum performance, we want to align the start address to
513          * the beginning of a write buffer boundary (i.e. A4-A0 of the
514          * start address = 0). See how many bytes are required to get to a
515          * write-buffer-aligned address.  If that number is non-zero, do
516          * non buffered writes of the non-aligned data.  By doing non-buffered
517          * writes, we avoid the problem of crossing a block (sector) boundary
518          * with buffered writes.
519          */
520         buf_count = FLASH_WRITE_BUF_SIZE - (addr & (FLASH_WRITE_BUF_SIZE - 1));
521         if (buf_count == FLASH_WRITE_BUF_SIZE) { /* already on a boundary */
522                 buf_count = 0;
523         }
524         if (buf_count > count) { /* not a full buffers worth of data to write */
525                 buf_count = count;
526         }
527         count -= buf_count;
528
529         PRINTF("%s:%d: Write buffer alignment count = %ld\n",
530                    __FUNCTION__, __LINE__, buf_count);
531         while (buf_count-- >= 1) {
532                 if ((rc = write_data8(info_p, (ulong)dp++, *sp++)) != 0)  {
533                         return (rc);
534                 }
535         }
536
537         PRINTF("%s:%d: count = %ld\n", __FUNCTION__, __LINE__, count);
538         if (count == 0) { /* all done */
539                 PRINTF("%s:%d: Less than 1 buffer (%d) worth of bytes\n",
540                            __FUNCTION__, __LINE__, FLASH_WRITE_BUF_SIZE);
541                 return (rc);
542         }
543
544         /*
545          * Now that we are write buffer aligned, write full or partial buffers.
546          * The fact that we are write buffer aligned automatically avoids
547          * crossing a block address during a write buffer operation.
548          */
549         bufs = count / FLASH_WRITE_BUF_SIZE;
550         PRINTF("%s:%d: %d (0x%x) buffers to write\n", __FUNCTION__, __LINE__,
551                    bufs, bufs);
552         while (bufs >= 1) {
553                 rc = write_flash_buffer8(info_p, sp, dp, FLASH_WRITE_BUF_SIZE);
554                 if (rc != 0) {
555                         PRINTF("%s:%d: ** Error writing buf %d\n",
556                                    __FUNCTION__, __LINE__, bufs);
557                         return (rc);
558                 }
559                 bufs--;
560                 sp += FLASH_WRITE_BUF_SIZE;
561                 dp += FLASH_WRITE_BUF_SIZE;
562         }
563
564         /*
565          * Do the leftovers
566          */
567         i = count % FLASH_WRITE_BUF_SIZE;
568         PRINTF("%s:%d: %d (0x%x) leftover bytes\n", __FUNCTION__, __LINE__, i, i);
569         if (i > 0) {
570                 rc = write_flash_buffer8(info_p, sp, dp, i);
571         }
572
573         sp = (vu_char*)info_p->start[0];
574         *sp = SCS_READ_CMD;
575         return (rc);
576
577 #else
578         wp = addr;
579         while (count-- >= 1) {
580                 if((rc = write_data8(info_p, wp++, *src_p++)) != 0)
581                         return (rc);
582         }
583         return 0;
584 #endif
585 }
586
587
588 /*-----------------------------------------------------------------------
589  * Write a byte to Flash, returns:
590  * 0 - OK
591  * 1 - write timeout
592  * 2 - Flash not erased
593  */
594 static int
595 write_data8 (flash_info_t *info, ulong dest, uchar data)
596 {
597         vu_char *addr = (vu_char *)dest;
598         vu_char status;
599         ulong start;
600         int flag;
601
602         /* Check if Flash is (sufficiently) erased */
603         if ((*addr & data) != data) {
604                 return (2);
605         }
606         /* Disable interrupts which might cause a timeout here */
607         flag = disable_interrupts();
608
609         *addr = SCS_PROGRAM_CMD;
610         *addr = data;
611
612         /* re-enable interrupts if necessary */
613         if (flag)
614                 enable_interrupts();
615
616         start = get_timer (0);
617
618         while (((status = *addr) & SCS_SR7) != SCS_SR7) {
619                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
620                         *addr = SCS_READ_CMD;
621                         return (1);
622                 }
623         }
624         *addr = SCS_READ_CMD;
625         return (0);
626 }
627
628 /* vim: set ts=4 sw=4 tw=78: */