]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/hymod/flash.c
gic: fixed compilation error in GICv2 wait for interrupt macro
[karo-tx-uboot.git] / board / hymod / flash.c
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  *
7  * Hacked for the Hymod board by Murray.Jensen@csiro.au, 20-Oct-00
8  */
9
10 #include <common.h>
11 #include <mpc8260.h>
12 #include <board/hymod/flash.h>
13
14 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];    /* info for FLASH chips */
15
16 /*-----------------------------------------------------------------------
17  * Protection Flags:
18  */
19 #define FLAG_PROTECT_SET        0x01
20 #define FLAG_PROTECT_CLEAR      0x02
21
22 /*-----------------------------------------------------------------------
23  */
24
25 /*
26  * probe for flash bank at address "base" and store info about it
27  * in the flash_info entry "fip". Fatal error if nothing there.
28  */
29 static void
30 bank_probe (flash_info_t *fip, volatile bank_addr_t base)
31 {
32         volatile bank_addr_t addr;
33         bank_word_t word;
34         int i;
35
36         /* reset the flash */
37         *base = BANK_CMD_RST;
38
39         /* put flash into read id mode */
40         *base = BANK_CMD_RD_ID;
41
42         /* check the manufacturer id - must be intel */
43         word = *BANK_REG_MAN_CODE (base);
44         if (word != BANK_FILL_WORD (INTEL_MANUFACT&0xff))
45                 panic ("\nbad manufacturer's code (0x%08lx) at addr 0x%08lx",
46                         (unsigned long)word, (unsigned long)base);
47
48         /* check the device id */
49         word = *BANK_REG_DEV_CODE (base);
50         switch (word) {
51
52         case BANK_FILL_WORD (INTEL_ID_28F320J5&0xff):
53                 fip->flash_id = FLASH_MAN_INTEL | FLASH_28F320J5;
54                 fip->sector_count = 32;
55                 break;
56
57         case BANK_FILL_WORD (INTEL_ID_28F640J5&0xff):
58                 fip->flash_id = FLASH_MAN_INTEL | FLASH_28F640J5;
59                 fip->sector_count = 64;
60                 break;
61
62         case BANK_FILL_WORD (INTEL_ID_28F320J3A&0xff):
63                 fip->flash_id = FLASH_MAN_INTEL | FLASH_28F320J3A;
64                 fip->sector_count = 32;
65                 break;
66
67         case BANK_FILL_WORD (INTEL_ID_28F640J3A&0xff):
68                 fip->flash_id = FLASH_MAN_INTEL | FLASH_28F640J3A;
69                 fip->sector_count = 64;
70                 break;
71
72         case BANK_FILL_WORD (INTEL_ID_28F128J3A&0xff):
73                 fip->flash_id = FLASH_MAN_INTEL | FLASH_28F128J3A;
74                 fip->sector_count = 128;
75                 break;
76
77         default:
78                 panic ("\nbad device code (0x%08lx) at addr 0x%08lx",
79                         (unsigned long)word, (unsigned long)base);
80         }
81
82         if (fip->sector_count >= CONFIG_SYS_MAX_FLASH_SECT)
83                 panic ("\ntoo many sectors (%d) in flash at address 0x%08lx",
84                         fip->sector_count, (unsigned long)base);
85
86         addr = base;
87         for (i = 0; i < fip->sector_count; i++) {
88                 fip->start[i] = (unsigned long)addr;
89                 fip->protect[i] = 0;
90                 addr = BANK_ADDR_NEXT_BLK (addr);
91         }
92
93         fip->size = (bank_size_t)addr - (bank_size_t)base;
94
95         /* reset the flash */
96         *base = BANK_CMD_RST;
97 }
98
99 static void
100 bank_reset (flash_info_t *info, int sect)
101 {
102         volatile bank_addr_t addr = (bank_addr_t)info->start[sect];
103
104 #ifdef FLASH_DEBUG
105         printf ("writing reset cmd to addr 0x%08lx\n", (unsigned long)addr);
106 #endif
107
108         *addr = BANK_CMD_RST;
109 }
110
111 static void
112 bank_erase_init (flash_info_t *info, int sect)
113 {
114         volatile bank_addr_t addr = (bank_addr_t)info->start[sect];
115         int flag;
116
117 #ifdef FLASH_DEBUG
118         printf ("erasing sector %d, addr = 0x%08lx\n",
119                 sect, (unsigned long)addr);
120 #endif
121
122         /* Disable intrs which might cause a timeout here */
123         flag = disable_interrupts ();
124
125 #ifdef FLASH_DEBUG
126         printf ("writing erase cmd to addr 0x%08lx\n", (unsigned long)addr);
127 #endif
128         *addr = BANK_CMD_ERASE1;
129         *addr = BANK_CMD_ERASE2;
130
131         /* re-enable interrupts if necessary */
132         if (flag)
133                 enable_interrupts ();
134 }
135
136 static int
137 bank_erase_poll (flash_info_t *info, int sect)
138 {
139         volatile bank_addr_t addr = (bank_addr_t)info->start[sect];
140         bank_word_t stat = *addr;
141
142 #ifdef FLASH_DEBUG
143         printf ("checking status at addr 0x%08lx [0x%08lx]\n",
144                 (unsigned long)addr, (unsigned long)stat);
145 #endif
146
147         if ((stat & BANK_STAT_RDY) == BANK_STAT_RDY) {
148                 if ((stat & BANK_STAT_ERR) != 0) {
149                         printf ("failed on sector %d [0x%08lx] at "
150                                 "address 0x%08lx\n", sect,
151                                 (unsigned long)stat, (unsigned long)addr);
152                         *addr = BANK_CMD_CLR_STAT;
153                         return (-1);
154                 }
155                 else
156                         return (1);
157         }
158         else
159                 return (0);
160 }
161
162 static int
163 bank_write_word (volatile bank_addr_t addr, bank_word_t value)
164 {
165         bank_word_t stat;
166         ulong start;
167         int flag, retval;
168
169         /* Disable interrupts which might cause a timeout here */
170         flag = disable_interrupts ();
171
172         *addr = BANK_CMD_PROG;
173
174         *addr = value;
175
176         /* re-enable interrupts if necessary */
177         if (flag)
178                 enable_interrupts ();
179
180         retval = 0;
181
182         /* data polling for D7 */
183         start = get_timer (0);
184         do {
185                 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
186                         retval = 1;
187                         goto done;
188                 }
189                 stat = *addr;
190         } while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY);
191
192         if ((stat & BANK_STAT_ERR) != 0) {
193                 printf ("flash program failed [0x%08lx] at address 0x%08lx\n",
194                         (unsigned long)stat, (unsigned long)addr);
195                 *addr = BANK_CMD_CLR_STAT;
196                 retval = 3;
197         }
198
199 done:
200         /* reset to read mode */
201         *addr = BANK_CMD_RST;
202
203         return (retval);
204 }
205
206 /*-----------------------------------------------------------------------
207  */
208
209 unsigned long
210 flash_init (void)
211 {
212         int i;
213
214         /* Init: no FLASHes known */
215         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
216                 flash_info[i].flash_id = FLASH_UNKNOWN;
217         }
218
219         bank_probe (&flash_info[0], (bank_addr_t)CONFIG_SYS_FLASH_BASE);
220
221         /*
222          * protect monitor and environment sectors
223          */
224
225 #if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
226         (void)flash_protect (FLAG_PROTECT_SET,
227                       CONFIG_SYS_MONITOR_BASE,
228                       CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
229                       &flash_info[0]);
230 #endif
231
232 #if defined(CONFIG_SYS_FLASH_ENV_ADDR)
233         (void)flash_protect (FLAG_PROTECT_SET,
234                       CONFIG_SYS_FLASH_ENV_ADDR,
235 #if defined(CONFIG_SYS_FLASH_ENV_BUF)
236                       CONFIG_SYS_FLASH_ENV_ADDR + CONFIG_SYS_FLASH_ENV_BUF - 1,
237 #else
238                       CONFIG_SYS_FLASH_ENV_ADDR + CONFIG_SYS_FLASH_ENV_SIZE - 1,
239 #endif
240                       &flash_info[0]);
241 #endif
242
243         return flash_info[0].size;
244 }
245
246 /*-----------------------------------------------------------------------
247  */
248 void
249 flash_print_info (flash_info_t *info)
250 {
251         int i;
252
253         if (info->flash_id == FLASH_UNKNOWN) {
254                 printf ("missing or unknown FLASH type\n");
255                 return;
256         }
257
258         switch (info->flash_id & FLASH_VENDMASK) {
259         case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
260         default:                printf ("Unknown Vendor ");     break;
261         }
262
263         switch (info->flash_id & FLASH_TYPEMASK) {
264         case FLASH_28F320J5:    printf ("28F320J5 (32 Mbit, 2 x 16bit)\n");
265                                 break;
266         case FLASH_28F640J5:    printf ("28F640J5 (64 Mbit, 2 x 16bit)\n");
267                                 break;
268         case FLASH_28F320J3A:   printf ("28F320J3A (32 Mbit, 2 x 16bit)\n");
269                                 break;
270         case FLASH_28F640J3A:   printf ("28F640J3A (64 Mbit, 2 x 16bit)\n");
271                                 break;
272         case FLASH_28F128J3A:   printf ("28F320J3A (128 Mbit, 2 x 16bit)\n");
273                                 break;
274         default:                printf ("Unknown Chip Type\n");
275                                 break;
276         }
277
278         printf ("  Size: %ld MB in %d Sectors\n",
279                 info->size >> 20, info->sector_count);
280
281         printf ("  Sector Start Addresses:");
282         for (i=0; i<info->sector_count; ++i) {
283                 if ((i % 5) == 0)
284                         printf ("\n   ");
285                 printf (" %08lX%s",
286                         info->start[i],
287                         info->protect[i] ? " (RO)" : "     "
288                 );
289         }
290         printf ("\n");
291         return;
292 }
293
294 /*
295  * The following code cannot be run from FLASH!
296  */
297
298 /*-----------------------------------------------------------------------
299  */
300
301 int
302 flash_erase (flash_info_t *info, int s_first, int s_last)
303 {
304         int prot, sect, haderr;
305         ulong start, now, last;
306         int rcode = 0;
307
308 #ifdef FLASH_DEBUG
309         printf ("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
310                 "  Bank # %d: ", s_last - s_first + 1, s_first, s_last,
311                 (info - flash_info) + 1);
312         flash_print_info (info);
313 #endif
314
315         if ((s_first < 0) || (s_first > s_last)) {
316                 if (info->flash_id == FLASH_UNKNOWN) {
317                         printf ("- missing\n");
318                 } else {
319                         printf ("- no sectors to erase\n");
320                 }
321                 return 1;
322         }
323
324         prot = 0;
325         for (sect = s_first; sect <= s_last; ++sect) {
326                 if (info->protect[sect]) {
327                         prot++;
328                 }
329         }
330
331         if (prot) {
332                 printf ("- Warning: %d protected sector%s will not be erased\n",
333                         prot, (prot > 1 ? "s" : ""));
334         }
335
336         start = get_timer (0);
337         last = 0;
338         haderr = 0;
339
340         for (sect = s_first; sect <= s_last; sect++) {
341                 if (info->protect[sect] == 0) { /* not protected */
342                         ulong estart;
343                         int sectdone;
344
345                         bank_erase_init (info, sect);
346
347                         /* wait at least 80us - let's wait 1 ms */
348                         udelay (1000);
349
350                         estart = get_timer (start);
351
352                         do {
353                                 now = get_timer (start);
354
355                                 if (now - estart > CONFIG_SYS_FLASH_ERASE_TOUT) {
356                                         printf ("Timeout (sect %d)\n", sect);
357                                         haderr = 1;
358                                         rcode = 1;
359                                         break;
360                                 }
361
362 #ifndef FLASH_DEBUG
363                                 /* show that we're waiting */
364                                 if ((now - last) > 1000) { /* every second */
365                                         putc ('.');
366                                         last = now;
367                                 }
368 #endif
369
370                                 sectdone = bank_erase_poll (info, sect);
371
372                                 if (sectdone < 0) {
373                                         haderr = 1;
374                                         rcode = 1;
375                                         break;
376                                 }
377
378                         } while (!sectdone);
379
380                         if (haderr)
381                                 break;
382                 }
383         }
384
385         if (haderr > 0)
386                 printf (" failed\n");
387         else
388                 printf (" done\n");
389
390         /* reset to read mode */
391         for (sect = s_first; sect <= s_last; sect++) {
392                 if (info->protect[sect] == 0) { /* not protected */
393                         bank_reset (info, sect);
394                 }
395         }
396         return rcode;
397 }
398
399 /*-----------------------------------------------------------------------
400  * Write a word to Flash, returns:
401  * 0 - OK
402  * 1 - write timeout
403  * 2 - Flash not erased
404  * 3 - Program failed
405  */
406 static int
407 write_word (flash_info_t *info, ulong dest, ulong data)
408 {
409         /* Check if Flash is (sufficiently) erased */
410         if ((*(ulong *)dest & data) != data)
411                 return (2);
412
413         return (bank_write_word ((bank_addr_t)dest, (bank_word_t)data));
414 }
415
416 /*-----------------------------------------------------------------------
417  * Copy memory to flash, returns:
418  * 0 - OK
419  * 1 - write timeout
420  * 2 - Flash not erased
421  * 3 - Program failed
422  */
423
424 int
425 write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
426 {
427         ulong cp, wp, data;
428         int i, l, rc;
429
430         wp = (addr & ~3);       /* get lower word aligned address */
431
432         /*
433          * handle unaligned start bytes
434          */
435         if ((l = addr - wp) != 0) {
436                 data = 0;
437                 for (i=0, cp=wp; i<l; ++i, ++cp) {
438                         data = (data << 8) | (*(uchar *)cp);
439                 }
440                 for (; i<4 && cnt>0; ++i) {
441                         data = (data << 8) | *src++;
442                         --cnt;
443                         ++cp;
444                 }
445                 for (; cnt==0 && i<4; ++i, ++cp) {
446                         data = (data << 8) | (*(uchar *)cp);
447                 }
448
449                 if ((rc = write_word (info, wp, data)) != 0) {
450                         return (rc);
451                 }
452                 wp += 4;
453         }
454
455         /*
456          * handle word aligned part
457          */
458         while (cnt >= 4) {
459                 data = 0;
460                 for (i=0; i<4; ++i) {
461                         data = (data << 8) | *src++;
462                 }
463                 if ((rc = write_word (info, wp, data)) != 0) {
464                         return (rc);
465                 }
466                 wp  += 4;
467                 cnt -= 4;
468         }
469
470         if (cnt == 0) {
471                 return (0);
472         }
473
474         /*
475          * handle unaligned tail bytes
476          */
477         data = 0;
478         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
479                 data = (data << 8) | *src++;
480                 --cnt;
481         }
482         for (; i<4; ++i, ++cp) {
483                 data = (data << 8) | (*(uchar *)cp);
484         }
485
486         return (write_word (info, wp, data));
487 }
488
489 /*-----------------------------------------------------------------------
490  */