]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/rpxsuper/flash.c
ARM: highbank: use default prompt
[karo-tx-uboot.git] / board / rpxsuper / flash.c
1 /*
2  * (C) Copyright 2000
3  * Marius Groeger <mgroeger@sysgo.de>
4  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
5  *
6  * (C) Copyright 2000
7  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8  *
9  * Flash Routines for AMD 29F080B devices
10  * Added support for 64bit and AMD 29DL323B
11  *
12  *--------------------------------------------------------------------
13  * SPDX-License-Identifier:     GPL-2.0+
14  */
15
16 #include <common.h>
17 #include <mpc8xx.h>
18 #include <asm/io.h>
19
20 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
21
22 #define RD_SWP32(x) in_le32((volatile u32*)x)
23
24 /*-----------------------------------------------------------------------
25  * Functions
26  */
27
28 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
29 static int write_word (flash_info_t *info, ulong dest, ulong data);
30
31 /*-----------------------------------------------------------------------
32  */
33
34 unsigned long flash_init(void)
35 {
36         int i;
37
38         /* Init: no FLASHes known */
39         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i)
40                 flash_info[i].flash_id = FLASH_UNKNOWN;
41
42         /* for now, only support the 4 MB Flash SIMM */
43         (void)flash_get_size((vu_long *) CONFIG_SYS_FLASH0_BASE,
44                               &flash_info[0]);
45
46         /*
47          * protect monitor and environment sectors
48          */
49
50 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH0_BASE
51         flash_protect(FLAG_PROTECT_SET,
52                       CONFIG_SYS_MONITOR_BASE,
53                       CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
54                       &flash_info[0]);
55 #endif
56
57 #if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
58 #ifndef CONFIG_ENV_SIZE
59 #define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
60 #endif
61         flash_protect(FLAG_PROTECT_SET,
62                       CONFIG_ENV_ADDR,
63                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
64 #endif
65
66         return CONFIG_SYS_FLASH0_SIZE * 1024 * 1024;
67 }
68
69 /*-----------------------------------------------------------------------
70  */
71 void flash_print_info  (flash_info_t *info)
72 {
73     int i;
74
75     if (info->flash_id == FLASH_UNKNOWN) {
76         printf ("missing or unknown FLASH type\n");
77         return;
78     }
79
80     switch (info->flash_id & FLASH_VENDMASK) {
81     case (AMD_MANUFACT & FLASH_VENDMASK):
82         printf ("AMD ");
83         break;
84     case (FUJ_MANUFACT & FLASH_VENDMASK):
85         printf ("FUJITSU ");
86         break;
87     case (SST_MANUFACT & FLASH_VENDMASK):
88         printf ("SST ");
89         break;
90     default:
91         printf ("Unknown Vendor ");
92         break;
93     }
94
95     switch (info->flash_id & FLASH_TYPEMASK) {
96     case (AMD_ID_DL323B & FLASH_TYPEMASK):
97         printf("AM29DL323B (32 MBit)\n");
98         break;
99     default:
100         printf ("Unknown Chip Type\n");
101         break;
102     }
103
104     printf ("  Size: %ld MB in %d Sectors\n",
105             info->size >> 20, info->sector_count);
106
107     printf ("  Sector Start Addresses:");
108     for (i = 0; i < info->sector_count; ++i) {
109         if ((i % 5) == 0) printf ("\n   ");
110         printf (" %08lX%s",
111                 info->start[i],
112                 info->protect[i] ? " (RO)" : "     "
113                 );
114     }
115     printf ("\n");
116     return;
117 }
118
119 /*
120  * The following code cannot be run from FLASH!
121  */
122
123 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
124 {
125     short i;
126     vu_long vendor[2], devid[2];
127     ulong base = (ulong)addr;
128
129     /* Reset and Write auto select command: read Manufacturer ID */
130     addr[0] = 0xf0f0f0f0;
131     addr[2 * 0x0555] = 0xAAAAAAAA;
132     addr[2 * 0x02AA] = 0x55555555;
133     addr[2 * 0x0555] = 0x90909090;
134     addr[1] = 0xf0f0f0f0;
135     addr[2 * 0x0555 + 1] = 0xAAAAAAAA;
136     addr[2 * 0x02AA + 1] = 0x55555555;
137     addr[2 * 0x0555 + 1] = 0x90909090;
138     udelay (1000);
139
140     vendor[0] = RD_SWP32(&addr[0]);
141     vendor[1] = RD_SWP32(&addr[1]);
142     if (vendor[0] != vendor[1] || vendor[0] != AMD_MANUFACT) {
143         info->size = 0;
144         goto out;
145     }
146
147     devid[0] = RD_SWP32(&addr[2]);
148     devid[1] = RD_SWP32(&addr[3]);
149
150     if (devid[0] == AMD_ID_DL323B) {
151         /*
152         * we have 2 Banks
153         * Bank 1 (23 Sectors): 0-7=8kbyte, 8-22=64kbyte
154         * Bank 2 (48 Sectors): 23-70=64kbyte
155         */
156         info->flash_id     = (AMD_MANUFACT & FLASH_VENDMASK) |
157                              (AMD_ID_DL323B & FLASH_TYPEMASK);
158         info->sector_count = 71;
159         info->size         = 4 * (8 * 8 + 63 * 64) * 1024;
160     }
161     else {
162         info->size = 0;
163         goto out;
164     }
165
166     /* set up sector start address table */
167     for (i = 0; i < 8; i++) {
168         info->start[i] = base + (i * 0x8000);
169     }
170     for (i = 8; i < info->sector_count; i++) {
171         info->start[i] = base + (i * 0x40000) + 8 * 0x8000 - 8 * 0x40000;
172     }
173
174     /* check for protected sectors */
175     for (i = 0; i < info->sector_count; i++) {
176         /* read sector protection at sector address */
177         addr = (volatile unsigned long *)(info->start[i]);
178         addr[2 * 0x0555] = 0xAAAAAAAA;
179         addr[2 * 0x02AA] = 0x55555555;
180         addr[2 * 0x0555] = 0x90909090;
181         addr[2 * 0x0555 + 1] = 0xAAAAAAAA;
182         addr[2 * 0x02AA + 1] = 0x55555555;
183         addr[2 * 0x0555 + 1] = 0x90909090;
184         udelay (1000);
185         base = RD_SWP32(&addr[4]);
186         base |= RD_SWP32(&addr[5]);
187         info->protect[i] = base & 0x00010001 ? 1 : 0;
188     }
189     addr = (vu_long*)info->start[0];
190
191 out:
192     /* reset command */
193     addr[0] = 0xf0f0f0f0;
194     addr[1] = 0xf0f0f0f0;
195
196     return info->size;
197 }
198
199
200 /*-----------------------------------------------------------------------
201  */
202
203 int flash_erase (flash_info_t *info, int s_first, int s_last)
204 {
205     vu_long *addr = (vu_long*)(info->start[0]);
206     int flag, prot, sect, l_sect;
207     ulong start, now, last;
208
209     if ((s_first < 0) || (s_first > s_last)) {
210         if (info->flash_id == FLASH_UNKNOWN) {
211             printf ("- missing\n");
212         } else {
213             printf ("- no sectors to erase\n");
214         }
215         return 1;
216     }
217
218     prot = 0;
219     for (sect = s_first; sect <= s_last; sect++) {
220         if (info->protect[sect]) {
221             prot++;
222         }
223     }
224
225     if (prot) {
226         printf ("- Warning: %d protected sectors will not be erased!\n",
227                 prot);
228     } else {
229         printf ("\n");
230     }
231
232     l_sect = -1;
233
234     /* Disable interrupts which might cause a timeout here */
235     flag = disable_interrupts();
236
237     addr[2 * 0x0555] = 0xAAAAAAAA;
238     addr[2 * 0x02AA] = 0x55555555;
239     addr[2 * 0x0555] = 0x80808080;
240     addr[2 * 0x0555] = 0xAAAAAAAA;
241     addr[2 * 0x02AA] = 0x55555555;
242     addr[2 * 0x0555 + 1] = 0xAAAAAAAA;
243     addr[2 * 0x02AA + 1] = 0x55555555;
244     addr[2 * 0x0555 + 1] = 0x80808080;
245     addr[2 * 0x0555 + 1] = 0xAAAAAAAA;
246     addr[2 * 0x02AA + 1] = 0x55555555;
247     udelay (100);
248
249     /* Start erase on unprotected sectors */
250     for (sect = s_first; sect<=s_last; sect++) {
251         if (info->protect[sect] == 0) { /* not protected */
252             addr = (vu_long*)(info->start[sect]);
253             addr[0] = 0x30303030;
254             addr[1] = 0x30303030;
255             l_sect = sect;
256         }
257     }
258
259     /* re-enable interrupts if necessary */
260     if (flag)
261       enable_interrupts();
262
263     /* wait at least 80us - let's wait 1 ms */
264     udelay (1000);
265
266     /*
267      * We wait for the last triggered sector
268      */
269     if (l_sect < 0)
270       goto DONE;
271
272     start = get_timer (0);
273     last  = start;
274     addr = (vu_long*)(info->start[l_sect]);
275     while (     (addr[0] & 0x80808080) != 0x80808080 ||
276                 (addr[1] & 0x80808080) != 0x80808080) {
277         if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
278             printf ("Timeout\n");
279             return 1;
280         }
281         /* show that we're waiting */
282         if ((now - last) > 1000) {      /* every second */
283             serial_putc ('.');
284             last = now;
285         }
286     }
287
288     DONE:
289     /* reset to read mode */
290     addr = (volatile unsigned long *)info->start[0];
291     addr[0] = 0xF0F0F0F0;       /* reset bank */
292     addr[1] = 0xF0F0F0F0;       /* reset bank */
293
294     printf (" done\n");
295     return 0;
296 }
297
298 /*-----------------------------------------------------------------------
299  * Copy memory to flash, returns:
300  * 0 - OK
301  * 1 - write timeout
302  * 2 - Flash not erased
303  */
304
305 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
306 {
307     ulong cp, wp, data;
308     int i, l, rc;
309
310     wp = (addr & ~3);   /* get lower word aligned address */
311
312     /*
313      * handle unaligned start bytes
314      */
315     if ((l = addr - wp) != 0) {
316         data = 0;
317         for (i=0, cp=wp; i<l; ++i, ++cp) {
318             data = (data << 8) | (*(uchar *)cp);
319         }
320         for (; i<4 && cnt>0; ++i) {
321             data = (data << 8) | *src++;
322             --cnt;
323             ++cp;
324         }
325         for (; cnt==0 && i<4; ++i, ++cp) {
326             data = (data << 8) | (*(uchar *)cp);
327         }
328
329         if ((rc = write_word(info, wp, data)) != 0) {
330             return (rc);
331         }
332         wp += 4;
333     }
334
335     /*
336      * handle word aligned part
337      */
338     while (cnt >= 4) {
339         data = 0;
340         for (i=0; i<4; ++i) {
341             data = (data << 8) | *src++;
342         }
343         if ((rc = write_word(info, wp, data)) != 0) {
344             return (rc);
345         }
346         wp  += 4;
347         cnt -= 4;
348     }
349
350     if (cnt == 0) {
351         return (0);
352     }
353
354     /*
355      * handle unaligned tail bytes
356      */
357     data = 0;
358     for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
359         data = (data << 8) | *src++;
360         --cnt;
361     }
362     for (; i<4; ++i, ++cp) {
363         data = (data << 8) | (*(uchar *)cp);
364     }
365
366     return (write_word(info, wp, data));
367 }
368
369 /*-----------------------------------------------------------------------
370  * Write a word to Flash, returns:
371  * 0 - OK
372  * 1 - write timeout
373  * 2 - Flash not erased
374  */
375 static int write_word (flash_info_t *info, ulong dest, ulong data)
376 {
377     vu_long *addr = (vu_long*)(info->start[0]);
378     ulong start;
379     int flag;
380
381     /* Check if Flash is (sufficiently) erased */
382     if ((*((vu_long *)dest) & data) != data) {
383         return (2);
384     }
385     /* Disable interrupts which might cause a timeout here */
386     flag = disable_interrupts();
387
388     if ((dest & 0x00000004) == 0) {
389         addr[2 * 0x0555] = 0xAAAAAAAA;
390         addr[2 * 0x02AA] = 0x55555555;
391         addr[2 * 0x0555] = 0xA0A0A0A0;
392     }
393     else {
394         addr[2 * 0x0555 + 1] = 0xAAAAAAAA;
395         addr[2 * 0x02AA + 1] = 0x55555555;
396         addr[2 * 0x0555 + 1] = 0xA0A0A0A0;
397     }
398
399     *((vu_long *)dest) = data;
400
401     /* re-enable interrupts if necessary */
402     if (flag)
403       enable_interrupts();
404
405     /* data polling for D7 */
406     start = get_timer (0);
407     while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
408         if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
409             return (1);
410         }
411     }
412     return (0);
413 }
414
415 /*-----------------------------------------------------------------------
416  */