]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/pm826/flash.c
e8d4176e37aa2f78508cae019f7fdadb4e8c97c8
[karo-tx-uboot.git] / board / pm826 / flash.c
1 /*
2  * (C) Copyright 2001, 2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * Flash Routines for Intel devices
6  *
7  *--------------------------------------------------------------------
8  * SPDX-License-Identifier:     GPL-2.0+ 
9  */
10
11 #include <common.h>
12 #include <mpc8xx.h>
13
14
15 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
16
17 /*-----------------------------------------------------------------------
18  */
19 ulong flash_get_size (volatile unsigned long *baseaddr,
20                                           flash_info_t * info)
21 {
22         short i;
23         unsigned long flashtest_h, flashtest_l;
24
25         info->sector_count = info->size = 0;
26         info->flash_id = FLASH_UNKNOWN;
27
28         /* Write query command sequence and test FLASH answer
29          */
30         baseaddr[0] = 0x00980098;
31         baseaddr[1] = 0x00980098;
32
33         flashtest_h = baseaddr[0];      /* manufacturer ID      */
34         flashtest_l = baseaddr[1];
35
36         if (flashtest_h != INTEL_MANUFACT || flashtest_l != INTEL_MANUFACT)
37                 return (0);             /* no or unknown flash  */
38
39         flashtest_h = baseaddr[2];      /* device ID            */
40         flashtest_l = baseaddr[3];
41
42         if (flashtest_h != flashtest_l)
43                 return (0);
44
45         switch (flashtest_h) {
46         case INTEL_ID_28F160C3B:
47                 info->flash_id = FLASH_28F160C3B;
48                 info->sector_count = 39;
49                 info->size = 0x00800000;        /* 4 * 2 MB = 8 MB      */
50                 break;
51         case INTEL_ID_28F160F3B:
52                 info->flash_id = FLASH_28F160F3B;
53                 info->sector_count = 39;
54                 info->size = 0x00800000;        /* 4 * 2 MB = 8 MB      */
55                 break;
56         case INTEL_ID_28F640C3B:
57                 info->flash_id = FLASH_28F640C3B;
58                 info->sector_count = 135;
59                 info->size = 0x02000000;        /* 16 * 2 MB = 32 MB    */
60                 break;
61         default:
62                 return (0);                     /* no or unknown flash  */
63         }
64
65         info->flash_id |= INTEL_MANUFACT << 16; /* set manufacturer offset */
66
67         if (info->flash_id & FLASH_BTYPE) {
68                 volatile unsigned long *tmp = baseaddr;
69
70                 /* set up sector start adress table (bottom sector type)
71                  * AND unlock the sectors (if our chip is 160C3 or 640C3)
72                  */
73                 for (i = 0; i < info->sector_count; i++) {
74                         if (((info->flash_id & FLASH_TYPEMASK) == FLASH_28F160C3B) ||
75                             ((info->flash_id & FLASH_TYPEMASK) == FLASH_28F640C3B)) {
76                                 tmp[0] = 0x00600060;
77                                 tmp[1] = 0x00600060;
78                                 tmp[0] = 0x00D000D0;
79                                 tmp[1] = 0x00D000D0;
80                         }
81                         info->start[i] = (uint) tmp;
82                         tmp += i < 8 ? 0x2000 : 0x10000; /* pointer arith       */
83                 }
84         }
85
86         memset (info->protect, 0, info->sector_count);
87
88         baseaddr[0] = 0x00FF00FF;
89         baseaddr[1] = 0x00FF00FF;
90
91         return (info->size);
92 }
93
94 /*-----------------------------------------------------------------------
95  */
96 unsigned long flash_init (void)
97 {
98         unsigned long size_b0 = 0;
99         int i;
100
101         /* Init: no FLASHes known
102          */
103         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
104                 flash_info[i].flash_id = FLASH_UNKNOWN;
105         }
106
107         /* Static FLASH Bank configuration here (only one bank) */
108
109         size_b0 = flash_get_size ((ulong *) CONFIG_SYS_FLASH0_BASE, &flash_info[0]);
110         if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) {
111                 printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
112                                 size_b0, size_b0 >> 20);
113         }
114
115         /* protect monitor and environment sectors
116          */
117
118 #ifndef CONFIG_BOOT_ROM
119         /* If U-Boot is  booted from ROM the CONFIG_SYS_MONITOR_BASE > CONFIG_SYS_FLASH0_BASE
120          * but we shouldn't protect it.
121          */
122
123 # if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH0_BASE
124         flash_protect (FLAG_PROTECT_SET,
125                        CONFIG_SYS_MONITOR_BASE,
126                        CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]
127         );
128 # endif
129 #endif  /* CONFIG_BOOT_ROM */
130
131 #if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
132 # ifndef  CONFIG_ENV_SIZE
133 #  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
134 # endif
135         flash_protect (FLAG_PROTECT_SET,
136                        CONFIG_ENV_ADDR,
137                        CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
138 #endif
139
140         return (size_b0);
141 }
142
143 /*-----------------------------------------------------------------------
144  */
145 void flash_print_info (flash_info_t * info)
146 {
147         int i;
148
149         if (info->flash_id == FLASH_UNKNOWN) {
150                 printf ("missing or unknown FLASH type\n");
151                 return;
152         }
153
154         switch ((info->flash_id >> 16) & 0xff) {
155         case 0x89:
156                 printf ("INTEL ");
157                 break;
158         default:
159                 printf ("Unknown Vendor ");
160                 break;
161         }
162
163         switch (info->flash_id & FLASH_TYPEMASK) {
164         case FLASH_28F160C3B:
165                 printf ("28F160C3B (16 M, bottom sector)\n");
166                 break;
167         case FLASH_28F160F3B:
168                 printf ("28F160F3B (16 M, bottom sector)\n");
169                 break;
170         case FLASH_28F640C3B:
171                 printf ("28F640C3B (64 M, bottom sector)\n");
172                 break;
173         default:
174                 printf ("Unknown Chip Type\n");
175                 break;
176         }
177
178         printf ("  Size: %ld MB in %d Sectors\n",
179                         info->size >> 20, info->sector_count);
180
181         printf ("  Sector Start Addresses:");
182         for (i = 0; i < info->sector_count; ++i) {
183                 if ((i % 5) == 0)
184                         printf ("\n   ");
185                 printf (" %08lX%s",
186                         info->start[i],
187                         info->protect[i] ? " (RO)" : "     "
188                 );
189         }
190         printf ("\n");
191 }
192
193 /*-----------------------------------------------------------------------
194  */
195 int flash_erase (flash_info_t * info, int s_first, int s_last)
196 {
197         int flag, prot, sect;
198         ulong start, now, last;
199
200         if ((s_first < 0) || (s_first > s_last)) {
201                 if (info->flash_id == FLASH_UNKNOWN) {
202                         printf ("- missing\n");
203                 } else {
204                         printf ("- no sectors to erase\n");
205                 }
206                 return 1;
207         }
208
209         prot = 0;
210         for (sect = s_first; sect <= s_last; sect++) {
211                 if (info->protect[sect])
212                         prot++;
213         }
214
215         if (prot) {
216                 printf ("- Warning: %d protected sectors will not be erased!\n",
217                                 prot);
218         } else {
219                 printf ("\n");
220         }
221
222         /* Start erase on unprotected sectors
223          */
224         for (sect = s_first; sect <= s_last; sect++) {
225                 volatile ulong *addr =
226                                 (volatile unsigned long *) info->start[sect];
227
228                 start = get_timer (0);
229                 last = start;
230                 if (info->protect[sect] == 0) {
231                         /* Disable interrupts which might cause a timeout here
232                          */
233                         flag = disable_interrupts ();
234
235                         /* Erase the block
236                          */
237                         addr[0] = 0x00200020;
238                         addr[1] = 0x00200020;
239                         addr[0] = 0x00D000D0;
240                         addr[1] = 0x00D000D0;
241
242                         /* re-enable interrupts if necessary
243                          */
244                         if (flag)
245                                 enable_interrupts ();
246
247                         /* wait at least 80us - let's wait 1 ms
248                          */
249                         udelay (1000);
250
251                         last = start;
252                         while ((addr[0] & 0x00800080) != 0x00800080 ||
253                                    (addr[1] & 0x00800080) != 0x00800080) {
254                                 if ((now = get_timer (start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
255                                         printf ("Timeout (erase suspended!)\n");
256                                         /* Suspend erase
257                                          */
258                                         addr[0] = 0x00B000B0;
259                                         addr[1] = 0x00B000B0;
260                                         goto DONE;
261                                 }
262                                 /* show that we're waiting
263                                  */
264                                 if ((now - last) > 1000) {      /* every second */
265                                         serial_putc ('.');
266                                         last = now;
267                                 }
268                         }
269                         if (addr[0] & 0x00220022 || addr[1] & 0x00220022) {
270                                 printf ("*** ERROR: erase failed!\n");
271                                 goto DONE;
272                         }
273                 }
274                 /* Clear status register and reset to read mode
275                  */
276                 addr[0] = 0x00500050;
277                 addr[1] = 0x00500050;
278                 addr[0] = 0x00FF00FF;
279                 addr[1] = 0x00FF00FF;
280         }
281
282         printf (" done\n");
283
284 DONE:
285         return 0;
286 }
287
288 static int write_word (flash_info_t *, volatile unsigned long *, ulong);
289
290 /*-----------------------------------------------------------------------
291  * Copy memory to flash, returns:
292  * 0 - OK
293  * 1 - write timeout
294  * 2 - Flash not erased
295  */
296 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
297 {
298         ulong v;
299         int i, l, cc = cnt, res = 0;
300
301
302         for (v=0; cc > 0; addr += 4, cc -= 4 - l) {
303                 l = (addr & 3);
304                 addr &= ~3;
305
306                 for (i = 0; i < 4; i++) {
307                         v = (v << 8) + (i < l || i - l >= cc ?
308                                 *((unsigned char *) addr + i) : *src++);
309                 }
310
311                 if ((res = write_word (info, (volatile unsigned long *) addr, v)) != 0)
312                         break;
313         }
314
315         return (res);
316 }
317
318 /*-----------------------------------------------------------------------
319  * Write a word to Flash, returns:
320  * 0 - OK
321  * 1 - write timeout
322  * 2 - Flash not erased
323  */
324 static int write_word (flash_info_t * info, volatile unsigned long *addr,
325                                            ulong data)
326 {
327         int flag, res = 0;
328         ulong start;
329
330         /* Check if Flash is (sufficiently) erased
331          */
332         if ((*addr & data) != data)
333                 return (2);
334
335         /* Disable interrupts which might cause a timeout here
336          */
337         flag = disable_interrupts ();
338
339         *addr = 0x00400040;
340         *addr = data;
341
342         /* re-enable interrupts if necessary
343          */
344         if (flag)
345                 enable_interrupts ();
346
347         start = get_timer (0);
348         while ((*addr & 0x00800080) != 0x00800080) {
349                 if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
350                         /* Suspend program
351                          */
352                         *addr = 0x00B000B0;
353                         res = 1;
354                         goto OUT;
355                 }
356         }
357
358         if (*addr & 0x00220022) {
359                 printf ("*** ERROR: program failed!\n");
360                 res = 1;
361         }
362
363 OUT:
364         /* Clear status register and reset to read mode
365          */
366         *addr = 0x00500050;
367         *addr = 0x00FF00FF;
368
369         return (res);
370 }