board/genietv/flash.c: CodingStyle cleanup
[platform/kernel/u-boot.git] / board / RPXClassic / flash.c
1 /*
2  * (C)  Copyright 2001
3  * Stäubli Faverges - <www.staubli.com>
4  * Pierre AUBERT  p.aubert@staubli.com
5  * U-Boot port on RPXClassic LF (CLLF_BW31) board
6  *
7  * RPXClassic uses Am29DL323B flash memory with 2 banks
8  *
9  *
10  * (C) Copyright 2000
11  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
12  *
13  * See file CREDITS for list of people who contributed to this
14  * project.
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License as
18  * published by the Free Software Foundation; either version 2 of
19  * the License, or (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29  * MA 02111-1307 USA
30  */
31
32
33 #include <common.h>
34 #include <mpc8xx.h>
35
36 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
37
38 /*-----------------------------------------------------------------------
39  * Functions
40  */
41 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
42 static int write_word (flash_info_t *info, ulong dest, ulong data);
43 static void flash_get_offsets (ulong base, flash_info_t *info);
44
45 /*-----------------------------------------------------------------------
46  */
47
48 unsigned long flash_init (void)
49 {
50         unsigned long size_b0 ;
51         int i;
52
53         /* Init: no FLASHes known */
54         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
55                 flash_info[i].flash_id = FLASH_UNKNOWN;
56         }
57
58         size_b0 = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
59
60
61         flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
62
63 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
64         /* monitor protection ON by default */
65         flash_protect(FLAG_PROTECT_SET,
66                       CONFIG_SYS_MONITOR_BASE,
67                       CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
68                       &flash_info[0]);
69 #endif
70
71         flash_info[0].size = size_b0;
72
73         return (size_b0);
74 }
75
76 /*-----------------------------------------------------------------------
77  */
78 static void flash_get_offsets (ulong base, flash_info_t *info)
79 {
80         int i;
81
82         if (info->flash_id & FLASH_BTYPE) {
83                 /* set sector offsets for bottom boot block type        */
84                 info->start[0] = base + 0x00000000;
85                 info->start[1] = base + 0x00008000;
86                 info->start[2] = base + 0x00010000;
87                 info->start[3] = base + 0x00018000;
88                 info->start[4] = base + 0x00020000;
89                 info->start[5] = base + 0x00028000;
90                 info->start[6] = base + 0x00030000;
91                 info->start[7] = base + 0x00038000;
92                 for (i = 8; i < info->sector_count; i++) {
93                         info->start[i] = base + ((i-7) * 0x00040000) ;
94                 }
95         }
96 }
97
98 /*-----------------------------------------------------------------------
99  */
100 void flash_print_info  (flash_info_t *info)
101 {
102         int i;
103
104         if (info->flash_id == FLASH_UNKNOWN) {
105                 printf ("missing or unknown FLASH type\n");
106                 return;
107         }
108
109         switch (info->flash_id & FLASH_VENDMASK) {
110         case FLASH_MAN_AMD:     printf ("AMD ");                break;
111         default:                printf ("Unknown Vendor ");     break;
112         }
113
114         switch (info->flash_id & FLASH_TYPEMASK) {
115         case FLASH_AMDL323B:
116             printf ("AMDL323DB (16 Mbytes, bottom boot sect)\n");
117             break;
118         default:
119             printf ("Unknown Chip Type\n");
120             break;
121         }
122
123         printf ("  Size: %ld MB in %d Sectors\n",
124                 info->size >> 20, info->sector_count);
125
126         printf ("  Sector Start Addresses:");
127         for (i=0; i<info->sector_count; ++i) {
128                 if ((i % 5) == 0)
129                         printf ("\n   ");
130                 printf (" %08lX%s",
131                         info->start[i],
132                         info->protect[i] ? " (RO)" : "     "
133                 );
134         }
135         printf ("\n");
136 }
137
138 /*-----------------------------------------------------------------------
139  */
140
141
142 /*-----------------------------------------------------------------------
143  */
144
145 /*
146  * The following code cannot be run from FLASH!
147  */
148
149 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
150 {
151         short i;
152         ulong value;
153         ulong base = (ulong)addr;
154
155         /* Reset flash componeny                                             */
156         addr [0] = 0xf0f0f0f0;
157
158         /* Write auto select command: read Manufacturer ID */
159         addr[0xAAA] = 0xAAAAAAAA ;
160         addr[0x555] = 0x55555555 ;
161         addr[0xAAA] = 0x90909090 ;
162
163         value = addr[0] ;
164
165         switch (value & 0x00FF00FF) {
166         case AMD_MANUFACT:
167                 info->flash_id = FLASH_MAN_AMD;
168                 break;
169         default:
170                 info->flash_id = FLASH_UNKNOWN;
171                 info->sector_count = 0;
172                 info->size = 0;
173                 return (0);                     /* no or unknown flash  */
174         }
175
176         value = addr[2] ;               /* device ID            */
177
178         switch (value & 0x00FF00FF) {
179         case (AMD_ID_DL323B & 0x00FF00FF):
180             info->flash_id += FLASH_AMDL323B;
181             info->sector_count = 71;
182             info->size = 0x01000000;            /* 16 Mb                     */
183
184             break;
185         default:
186                 info->flash_id = FLASH_UNKNOWN;
187                 return (0);                     /* => no or unknown flash */
188
189         }
190         /* set up sector start address table */
191         /* set sector offsets for bottom boot block type        */
192         info->start[0] = base + 0x00000000;
193         info->start[1] = base + 0x00008000;
194         info->start[2] = base + 0x00010000;
195         info->start[3] = base + 0x00018000;
196         info->start[4] = base + 0x00020000;
197         info->start[5] = base + 0x00028000;
198         info->start[6] = base + 0x00030000;
199         info->start[7] = base + 0x00038000;
200         for (i = 8; i < info->sector_count; i++) {
201             info->start[i] = base + ((i-7) * 0x00040000) ;
202         }
203
204         /* check for protected sectors */
205         for (i = 0; i < 23; i++) {
206             /* read sector protection at sector address, (A7 .. A0) = 0x02 */
207             /* D0 = 1 if protected */
208             addr = (volatile unsigned long *)(info->start[i]);
209             info->protect[i] = addr[4] & 1 ;
210         }
211         /* Check for protected sectors in the 2nd bank                       */
212         addr[0x100AAA] = 0xAAAAAAAA ;
213         addr[0x100555] = 0x55555555 ;
214         addr[0x100AAA] = 0x90909090 ;
215
216         for (i = 23; i < info->sector_count; i++) {
217             /* read sector protection at sector address, (A7 .. A0) = 0x02 */
218             /* D0 = 1 if protected */
219             addr = (volatile unsigned long *)(info->start[i]);
220             info->protect[i] = addr[4] & 1 ;
221         }
222
223         /*
224          * Prevent writes to uninitialized FLASH.
225          */
226         if (info->flash_id != FLASH_UNKNOWN) {
227                 addr = (volatile unsigned long *)info->start[0];
228
229                 *addr = 0xF0F0F0F0;     /* reset bank 1                      */
230                 addr = (volatile unsigned long *)info->start[23];
231
232                 *addr = 0xF0F0F0F0;     /* reset bank 2                      */
233
234         }
235
236         return (info->size);
237 }
238
239
240 /*-----------------------------------------------------------------------
241  */
242
243 int     flash_erase (flash_info_t *info, int s_first, int s_last)
244 {
245         vu_long *addr = (vu_long*)(info->start[0]);
246         int flag, prot, sect, l_sect;
247         ulong start, now, last;
248
249         if ((s_first < 0) || (s_first > s_last)) {
250                 if (info->flash_id == FLASH_UNKNOWN) {
251                         printf ("- missing\n");
252                 } else {
253                         printf ("- no sectors to erase\n");
254                 }
255                 return 1;
256         }
257
258         if ((info->flash_id == FLASH_UNKNOWN) ||
259             (info->flash_id > FLASH_AMD_COMP)) {
260                 printf ("Can't erase unknown flash type %08lx - aborted\n",
261                         info->flash_id);
262                 return 1;
263         }
264
265         prot = 0;
266         for (sect=s_first; sect<=s_last; ++sect) {
267                 if (info->protect[sect]) {
268                         prot++;
269                 }
270         }
271
272         if (prot) {
273                 printf ("- Warning: %d protected sectors will not be erased!\n",
274                         prot);
275         } else {
276                 printf ("\n");
277         }
278
279         l_sect = -1;
280
281         /* Disable interrupts which might cause a timeout here */
282         flag = disable_interrupts();
283
284         addr[0xAAA] = 0xAAAAAAAA;
285         addr[0x555] = 0x55555555;
286         addr[0xAAA] = 0x80808080;
287         addr[0xAAA] = 0xAAAAAAAA;
288         addr[0x555] = 0x55555555;
289
290         /* Start erase on unprotected sectors */
291         for (sect = s_first; sect<=s_last; sect++) {
292                 if (info->protect[sect] == 0) { /* not protected */
293                         addr = (vu_long *)(info->start[sect]) ;
294                         addr[0] = 0x30303030 ;
295                         l_sect = sect;
296                 }
297         }
298
299         /* re-enable interrupts if necessary */
300         if (flag)
301                 enable_interrupts();
302
303         /* wait at least 80us - let's wait 1 ms */
304         udelay (1000);
305
306         /*
307          * We wait for the last triggered sector
308          */
309         if (l_sect < 0)
310                 goto DONE;
311
312         start = get_timer (0);
313         last  = start;
314         addr = (vu_long *)(info->start[l_sect]);
315         while ((addr[0] & 0x80808080) != 0x80808080) {
316                 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
317                         printf ("Timeout\n");
318                         return 1;
319                 }
320                 /* show that we're waiting */
321                 if ((now - last) > 1000) {      /* every second */
322                         putc ('.');
323                         last = now;
324                 }
325         }
326
327 DONE:
328         /* reset to read mode */
329         addr = (vu_long *)info->start[0];
330         addr[0] = 0xF0F0F0F0;   /* reset bank */
331
332         printf (" done\n");
333         return 0;
334 }
335
336 /*-----------------------------------------------------------------------
337  * Copy memory to flash, returns:
338  * 0 - OK
339  * 1 - write timeout
340  * 2 - Flash not erased
341  */
342
343 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
344 {
345         ulong cp, wp, data;
346         int i, l, rc;
347
348         wp = (addr & ~3);       /* get lower word aligned address */
349
350         /*
351          * handle unaligned start bytes
352          */
353         if ((l = addr - wp) != 0) {
354                 data = 0;
355                 for (i=0, cp=wp; i<l; ++i, ++cp) {
356                         data = (data << 8) | (*(uchar *)cp);
357                 }
358                 for (; i<4 && cnt>0; ++i) {
359                         data = (data << 8) | *src++;
360                         --cnt;
361                         ++cp;
362                 }
363                 for (; cnt==0 && i<4; ++i, ++cp) {
364                         data = (data << 8) | (*(uchar *)cp);
365                 }
366
367                 if ((rc = write_word(info, wp, data)) != 0) {
368                         return (rc);
369                 }
370                 wp += 4;
371         }
372
373         /*
374          * handle word aligned part
375          */
376         while (cnt >= 4) {
377                 data = 0;
378                 for (i=0; i<4; ++i) {
379                         data = (data << 8) | *src++;
380                 }
381                 if ((rc = write_word(info, wp, data)) != 0) {
382                         return (rc);
383                 }
384                 wp  += 4;
385                 cnt -= 4;
386         }
387
388         if (cnt == 0) {
389                 return (0);
390         }
391
392         /*
393          * handle unaligned tail bytes
394          */
395         data = 0;
396         for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
397                 data = (data << 8) | *src++;
398                 --cnt;
399         }
400         for (; i<4; ++i, ++cp) {
401                 data = (data << 8) | (*(uchar *)cp);
402         }
403
404         return (write_word(info, wp, data));
405 }
406
407 /*-----------------------------------------------------------------------
408  * Write a word to Flash, returns:
409  * 0 - OK
410  * 1 - write timeout
411  * 2 - Flash not erased
412  */
413 static int write_word (flash_info_t *info, ulong dest, ulong data)
414 {
415         vu_long *addr = (vu_long *)(info->start[0]);
416         ulong start;
417         int flag;
418
419         /* Check if Flash is (sufficiently) erased */
420         if ((*((vu_long *)dest) & data) != data) {
421                 return (2);
422         }
423         /* Disable interrupts which might cause a timeout here */
424         flag = disable_interrupts();
425
426         addr[0xAAA] = 0xAAAAAAAA;
427         addr[0x555] = 0x55555555;
428         addr[0xAAA] = 0xA0A0A0A0;
429
430         *((vu_long *)dest) = data;
431
432         /* re-enable interrupts if necessary */
433         if (flag)
434                 enable_interrupts();
435
436         /* data polling for D7 */
437         start = get_timer (0);
438         while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
439                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
440                         return (1);
441                 }
442         }
443         return (0);
444 }
445
446 /*-----------------------------------------------------------------------
447  */