]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/esd/pf5200/flash.c
ARM: atmel: sama5d4_xplained: enable usb ethernet gadget
[karo-tx-uboot.git] / board / esd / pf5200 / flash.c
1 /*
2  * (C) Copyright 2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9
10 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];    /* info for FLASH chips */
11
12 typedef unsigned short FLASH_PORT_WIDTH;
13 typedef volatile unsigned short FLASH_PORT_WIDTHV;
14
15 #define FLASH_ID_MASK           0x00FF
16
17 #define FPW                     FLASH_PORT_WIDTH
18 #define FPWV                    FLASH_PORT_WIDTHV
19
20 #define FLASH_CYCLE1            0x0555
21 #define FLASH_CYCLE2            0x0aaa
22 #define FLASH_ID1               0x00
23 #define FLASH_ID2               0x01
24 #define FLASH_ID3               0x0E
25 #define FLASH_ID4               0x0F
26
27 /*-----------------------------------------------------------------------
28  * Functions
29  */
30 static ulong flash_get_size(FPWV * addr, flash_info_t * info);
31 static void flash_reset(flash_info_t * info);
32 static int write_word_amd(flash_info_t * info, FPWV * dest, FPW data);
33 static flash_info_t *flash_get_info(ulong base);
34
35 /*-----------------------------------------------------------------------
36  * flash_init()
37  *
38  * sets up flash_info and returns size of FLASH (bytes)
39  */
40 unsigned long flash_init(void)
41 {
42         unsigned long size = 0;
43         int i = 0;
44         extern void flash_preinit(void);
45         extern void flash_afterinit(uint, ulong, ulong);
46
47         ulong flashbase = CONFIG_SYS_FLASH_BASE;
48
49         flash_preinit();
50
51         /* There is only ONE FLASH device */
52         memset(&flash_info[i], 0, sizeof(flash_info_t));
53         flash_info[i].size = flash_get_size((FPW *) flashbase, &flash_info[i]);
54         size += flash_info[i].size;
55
56 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
57         /* monitor protection ON by default */
58         flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE,
59                       CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
60                       flash_get_info(CONFIG_SYS_MONITOR_BASE));
61 #endif
62
63 #ifdef  CONFIG_ENV_IS_IN_FLASH
64         /* ENV protection ON by default */
65         flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR,
66                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
67                       flash_get_info(CONFIG_ENV_ADDR));
68 #endif
69
70         flash_afterinit(i, flash_info[i].start[0], flash_info[i].size);
71         return size ? size : 1;
72 }
73
74 /*-----------------------------------------------------------------------
75  */
76 static void flash_reset(flash_info_t * info) {
77         FPWV *base = (FPWV *) (info->start[0]);
78
79         /* Put FLASH back in read mode */
80         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
81                 *base = (FPW) 0x00FF00FF;       /* Intel Read Mode */
82         } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) {
83                 *base = (FPW) 0x00F000F0;       /* AMD Read Mode */
84         }
85 }
86
87 /*-----------------------------------------------------------------------
88  */
89
90 static flash_info_t *flash_get_info(ulong base) {
91         int i;
92         flash_info_t *info;
93
94         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
95                 info = &flash_info[i];
96                 if ((info->size) && (info->start[0] <= base)
97                     && (base <= info->start[0] + info->size - 1)) {
98                         break;
99                 }
100         }
101         return (i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info);
102 }
103
104 /*-----------------------------------------------------------------------
105  */
106
107 void flash_print_info(flash_info_t * info) {
108         int i;
109         char *fmt;
110
111         if (info->flash_id == FLASH_UNKNOWN) {
112                 printf("missing or unknown FLASH type\n");
113                 return;
114         }
115
116         switch (info->flash_id & FLASH_VENDMASK) {
117         case FLASH_MAN_AMD:
118                 printf("AMD ");
119                 break;
120         default:
121                 printf("Unknown Vendor ");
122                 break;
123         }
124
125         switch (info->flash_id & FLASH_TYPEMASK) {
126         case FLASH_AMLV256U:
127                 fmt = "29LV256M (256 Mbit)\n";
128                 break;
129         default:
130                 fmt = "Unknown Chip Type\n";
131                 break;
132         }
133
134         printf(fmt);
135         printf("  Size: %ld MB in %d Sectors\n", info->size >> 20,
136                info->sector_count);
137         printf("  Sector Start Addresses:");
138
139         for (i = 0; i < info->sector_count; ++i) {
140                 ulong size;
141                 int erased;
142                 ulong *flash = (unsigned long *)info->start[i];
143
144                 if ((i % 5) == 0) {
145                         printf("\n   ");
146                 }
147
148                 /*
149                  * Check if whole sector is erased
150                  */
151                 size =
152                     (i !=
153                      (info->sector_count - 1)) ? (info->start[i + 1] -
154                                                   info->start[i]) >> 2 : (info->
155                                                                           start
156                                                                           [0] +
157                                                                           info->
158                                                                           size -
159                                                                           info->
160                                                                           start
161                                                                           [i])
162                     >> 2;
163
164                 for (flash = (unsigned long *)info->start[i], erased = 1;
165                      (flash != (unsigned long *)info->start[i] + size)
166                      && erased; flash++) {
167                         erased = *flash == ~0x0UL;
168                 }
169                 printf(" %08lX %s %s", info->start[i], erased ? "E" : " ",
170                        info->protect[i] ? "(RO)" : "    ");
171         }
172
173         printf("\n");
174 }
175
176 /*-----------------------------------------------------------------------
177  */
178
179 /*
180  * The following code cannot be run from FLASH!
181  */
182
183 ulong flash_get_size(FPWV * addr, flash_info_t * info) {
184         int i;
185
186         /* Write auto select command: read Manufacturer ID                     */
187         /* Write auto select command sequence and test FLASH answer            */
188         addr[FLASH_CYCLE1] = (FPW) 0x00AA00AA;  /* for AMD, Intel ignores this */
189         addr[FLASH_CYCLE2] = (FPW) 0x00550055;  /* for AMD, Intel ignores this */
190         addr[FLASH_CYCLE1] = (FPW) 0x00900090;  /* selects Intel or AMD        */
191
192         /* The manufacturer codes are only 1 byte, so just use 1 byte.         */
193         /* This works for any bus width and any FLASH device width.            */
194         udelay(100);
195         switch (addr[FLASH_ID1] & 0x00ff) {
196         case (uchar) AMD_MANUFACT:
197                 info->flash_id = FLASH_MAN_AMD;
198                 break;
199         default:
200                 printf("unknown vendor=%x ", addr[FLASH_ID1] & 0xff);
201                 info->flash_id = FLASH_UNKNOWN;
202                 info->sector_count = 0;
203                 info->size = 0;
204                 break;
205         }
206
207         /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus.     */
208         if (info->flash_id != FLASH_UNKNOWN) {
209                 switch ((FPW) addr[FLASH_ID2]) {
210                 case (FPW) AMD_ID_MIRROR:
211                         /* MIRROR BIT FLASH, read more ID bytes */
212                         if ((FPW) addr[FLASH_ID3] == (FPW) AMD_ID_LV256U_2
213                             && (FPW) addr[FLASH_ID4] == (FPW) AMD_ID_LV256U_3) {
214                                 /* attention: only the first 16 MB will be used in u-boot */
215                                 info->flash_id += FLASH_AMLV256U;
216                                 info->sector_count = 512;
217                                 info->size = 0x02000000;
218                                 for (i = 0; i < info->sector_count; i++) {
219                                         info->start[i] =
220                                             (ulong) addr + 0x10000 * i;
221                                 }
222                                 break;
223                         }
224                         /* fall thru to here ! */
225                 default:
226                         printf("unknown AMD device=%x %x %x",
227                                (FPW) addr[FLASH_ID2], (FPW) addr[FLASH_ID3],
228                                (FPW) addr[FLASH_ID4]);
229                         info->flash_id = FLASH_UNKNOWN;
230                         info->sector_count = 0;
231                         info->size = 0x800000;
232                         break;
233                 }
234
235                 /* Put FLASH back in read mode */
236                 flash_reset(info);
237         }
238         return (info->size);
239 }
240
241 /*-----------------------------------------------------------------------
242  */
243
244 int flash_erase(flash_info_t * info, int s_first, int s_last) {
245         FPWV *addr;
246         int flag, prot, sect;
247         int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
248         ulong start, now, last;
249         int rcode = 0;
250
251         if ((s_first < 0) || (s_first > s_last)) {
252                 if (info->flash_id == FLASH_UNKNOWN) {
253                         printf("- missing\n");
254                 } else {
255                         printf("- no sectors to erase\n");
256                 }
257                 return 1;
258         }
259
260         switch (info->flash_id & FLASH_TYPEMASK) {
261         case FLASH_AMLV256U:
262                 break;
263         case FLASH_UNKNOWN:
264         default:
265                 printf("Can't erase unknown flash type %08lx - aborted\n",
266                        info->flash_id);
267                 return 1;
268         }
269
270         prot = 0;
271         for (sect = s_first; sect <= s_last; ++sect) {
272                 if (info->protect[sect]) {
273                         prot++;
274                 }
275         }
276
277         if (prot) {
278                 printf("- Warning: %d protected sectors will not be erased!\n",
279                        prot);
280         } else {
281                 printf("\n");
282         }
283
284         last = get_timer(0);
285
286         /* Start erase on unprotected sectors */
287         for (sect = s_first; sect <= s_last && rcode == 0; sect++) {
288                 if (info->protect[sect] != 0) { /* protected, skip it */
289                         continue;
290                 }
291                 /* Disable interrupts which might cause a timeout here */
292                 flag = disable_interrupts();
293
294                 addr = (FPWV *) (info->start[sect]);
295                 if (intel) {
296                         *addr = (FPW) 0x00500050;       /* clear status register */
297                         *addr = (FPW) 0x00200020;       /* erase setup */
298                         *addr = (FPW) 0x00D000D0;       /* erase confirm */
299                 } else {
300                         /* must be AMD style if not Intel */
301                         FPWV *base;     /* first address in bank */
302
303                         base = (FPWV *) (info->start[0]);
304                         base[FLASH_CYCLE1] = (FPW) 0x00AA00AA;  /* unlock */
305                         base[FLASH_CYCLE2] = (FPW) 0x00550055;  /* unlock */
306                         base[FLASH_CYCLE1] = (FPW) 0x00800080;  /* erase mode */
307                         base[FLASH_CYCLE1] = (FPW) 0x00AA00AA;  /* unlock */
308                         base[FLASH_CYCLE2] = (FPW) 0x00550055;  /* unlock */
309                         *addr = (FPW) 0x00300030;       /* erase sector */
310                 }
311
312                 /* re-enable interrupts if necessary */
313                 if (flag) {
314                         enable_interrupts();
315                 }
316                 start = get_timer(0);
317
318                 /* wait at least 50us for AMD, 80us for Intel. */
319                 /* Let's wait 1 ms.                            */
320                 udelay(1000);
321
322                 while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) {
323                         if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
324                                 printf("Timeout\n");
325                                 if (intel) {
326                                         /* suspend erase        */
327                                         *addr = (FPW) 0x00B000B0;
328                                 }
329                                 flash_reset(info);      /* reset to read mode */
330                                 rcode = 1;      /* failed */
331                                 break;
332                         }
333                         /* show that we're waiting */
334                         if ((get_timer(last)) > CONFIG_SYS_HZ) {
335                                 /* every second */
336                                 putc('.');
337                                 last = get_timer(0);
338                         }
339                 }
340                 /* show that we're waiting */
341                 if ((get_timer(last)) > CONFIG_SYS_HZ) {
342                         /* every second */
343                         putc('.');
344                         last = get_timer(0);
345                 }
346                 flash_reset(info);      /* reset to read mode */
347         }
348         printf(" done\n");
349         return (rcode);
350 }
351
352 /*-----------------------------------------------------------------------
353  * Copy memory to flash, returns:
354  * 0 - OK
355  * 1 - write timeout
356  * 2 - Flash not erased
357  */
358 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
359 {
360         FPW data = 0;           /* 16 or 32 bit word, matches flash bus width on MPC8XX */
361         int bytes;              /* number of bytes to program in current word         */
362         int left;               /* number of bytes left to program                    */
363         int i, res;
364
365         for (left = cnt, res = 0;
366              left > 0 && res == 0;
367              addr += sizeof(data), left -= sizeof(data) - bytes) {
368
369                 bytes = addr & (sizeof(data) - 1);
370                 addr &= ~(sizeof(data) - 1);
371
372                 /* combine source and destination data so can program
373                  * an entire word of 16 or 32 bits
374                  */
375                 for (i = 0; i < sizeof(data); i++) {
376                         data <<= 8;
377                         if (i < bytes || i - bytes >= left)
378                                 data += *((uchar *) addr + i);
379                         else
380                                 data += *src++;
381                 }
382
383                 /* write one word to the flash */
384                 switch (info->flash_id & FLASH_VENDMASK) {
385                 case FLASH_MAN_AMD:
386                         res = write_word_amd(info, (FPWV *) addr, data);
387                         break;
388                 default:
389                         /* unknown flash type, error! */
390                         printf("missing or unknown FLASH type\n");
391                         res = 1;        /* not really a timeout, but gives error */
392                         break;
393                 }
394         }
395         return (res);
396 }
397
398 /*-----------------------------------------------------------------------
399  * Write a word to Flash for AMD FLASH
400  * A word is 16 or 32 bits, whichever the bus width of the flash bank
401  * (not an individual chip) is.
402  *
403  * returns:
404  * 0 - OK
405  * 1 - write timeout
406  * 2 - Flash not erased
407  */
408 static int write_word_amd(flash_info_t * info, FPWV * dest, FPW data) {
409         ulong start;
410         int flag;
411         int res = 0;            /* result, assume success       */
412         FPWV *base;             /* first address in flash bank  */
413
414         /* Check if Flash is (sufficiently) erased */
415         if ((*dest & data) != data) {
416                 return (2);
417         }
418
419         base = (FPWV *) (info->start[0]);
420
421         /* Disable interrupts which might cause a timeout here */
422         flag = disable_interrupts();
423
424         base[FLASH_CYCLE1] = (FPW) 0x00AA00AA;  /* unlock */
425         base[FLASH_CYCLE2] = (FPW) 0x00550055;  /* unlock */
426         base[FLASH_CYCLE1] = (FPW) 0x00A000A0;  /* selects program mode */
427
428         *dest = data;           /* start programming the data   */
429
430         /* re-enable interrupts if necessary */
431         if (flag) {
432                 enable_interrupts();
433         }
434         start = get_timer(0);
435
436         /* data polling for D7 */
437         while (res == 0
438                && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) {
439                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
440                         *dest = (FPW) 0x00F000F0;       /* reset bank */
441                         res = 1;
442                 }
443         }
444         return (res);
445 }