O2DNT platform specific code.
[platform/kernel/u-boot.git] / board / o2dnt / flash.c
1 /*
2  * (C) Copyright 2005
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25
26 flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips   */
27
28 /* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
29  *        has nothing to do with the flash chip being 8-bit or 16-bit.
30  */
31 #ifdef CONFIG_FLASH_16BIT
32 typedef unsigned short FLASH_PORT_WIDTH;
33 typedef volatile unsigned short FLASH_PORT_WIDTHV;
34 #define FLASH_ID_MASK   0xFFFF
35 #else
36 typedef unsigned char FLASH_PORT_WIDTH;
37 typedef volatile unsigned char FLASH_PORT_WIDTHV;
38 #define FLASH_ID_MASK   0xFF
39 #endif
40
41 #define FPW     FLASH_PORT_WIDTH
42 #define FPWV    FLASH_PORT_WIDTHV
43
44 #define ORMASK(size) ((-size) & OR_AM_MSK)
45
46 #define FLASH_CYCLE1    0x0555
47 #define FLASH_CYCLE2    0x02aa
48
49 /*-----------------------------------------------------------------------
50  * Functions
51  */
52 static ulong flash_get_size(FPWV *addr, flash_info_t *info);
53 static void flash_reset(flash_info_t *info);
54 static flash_info_t *flash_get_info(ulong base);
55 static int write_data (flash_info_t *info, FPWV *dest, FPW data); /* O2D */
56
57 /*-----------------------------------------------------------------------
58  * flash_init()
59  *
60  * sets up flash_info and returns size of FLASH (bytes)
61  */
62 unsigned long flash_init (void)
63 {
64         unsigned long size = 0;
65         int i;
66         extern void flash_preinit(void);
67         extern void flash_afterinit(ulong);
68
69         flash_preinit();
70
71         /* Init: no FLASHes known */
72         for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
73                 memset(&flash_info[i], 0, sizeof(flash_info_t));
74                 flash_info[i].flash_id = FLASH_UNKNOWN;
75         }
76
77         /* Query flash chip */
78         flash_info[0].size =
79                 flash_get_size((FPW *)CFG_FLASH_BASE, &flash_info[0]);
80         size += flash_info[0].size;
81
82 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
83         /* monitor protection ON by default */
84         flash_protect(FLAG_PROTECT_SET,
85                         CFG_MONITOR_BASE,
86                         CFG_MONITOR_BASE+monitor_flash_len-1,
87                         flash_get_info(CFG_MONITOR_BASE));
88 #endif
89
90 #ifdef  CFG_ENV_IS_IN_FLASH
91         /* ENV protection ON by default */
92         flash_protect(FLAG_PROTECT_SET,
93                         CFG_ENV_ADDR,
94                         CFG_ENV_ADDR+CFG_ENV_SIZE-1,
95                         flash_get_info(CFG_ENV_ADDR));
96 #endif
97
98
99         flash_afterinit(size);
100         return (size ? size : 1);
101 }
102
103 /*-----------------------------------------------------------------------
104  */
105 static void flash_reset(flash_info_t *info)
106 {
107         FPWV *base = (FPWV *)(info->start[0]);
108
109         /* Put FLASH back in read mode */
110         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
111                 *base = (FPW)0x00FF00FF;        /* Intel Read Mode */
112 }
113
114 /*-----------------------------------------------------------------------
115  */
116
117 static flash_info_t *flash_get_info(ulong base)
118 {
119         int i;
120         flash_info_t * info;
121
122         for (i = 0; i < CFG_MAX_FLASH_BANKS; i ++) {
123                 info = & flash_info[i];
124                 if (info->size &&
125                                 info->start[0] <= base &&
126                                 base <= info->start[0] + info->size - 1)
127                         break;
128         }
129
130         return (i == CFG_MAX_FLASH_BANKS ? 0 : info);
131 }
132
133 /*-----------------------------------------------------------------------
134  */
135
136 void flash_print_info (flash_info_t *info)
137 {
138         int i;
139         uchar *boottype;
140         uchar *bootletter;
141         uchar *fmt;
142         uchar botbootletter[] = "B";
143         uchar topbootletter[] = "T";
144         uchar botboottype[] = "bottom boot sector";
145         uchar topboottype[] = "top boot sector";
146
147         if (info->flash_id == FLASH_UNKNOWN) {
148                 printf ("missing or unknown FLASH type\n");
149                 return;
150         }
151
152         switch (info->flash_id & FLASH_VENDMASK) {
153                 case FLASH_MAN_INTEL:
154                         printf ("INTEL ");
155                         break;
156                 default:
157                         printf ("Unknown Vendor ");
158                         break;
159         }
160
161         /* check for top or bottom boot, if it applies */
162         if (info->flash_id & FLASH_BTYPE) {
163                 boottype = botboottype;
164                 bootletter = botbootletter;
165         } else {
166                 boottype = topboottype;
167                 bootletter = topbootletter;
168         }
169
170         switch (info->flash_id & FLASH_TYPEMASK) {
171                 case FLASH_28F128J3A:
172                         fmt = "28F128J3 (128 Mbit, uniform sectors)\n";
173                         break;
174                 default:
175                         fmt = "Unknown Chip Type\n";
176                         break;
177         }
178
179         printf (fmt, bootletter, boottype);
180         printf ("  Size: %ld MB in %d Sectors\n",
181                         info->size >> 20,
182                         info->sector_count);
183
184         printf ("  Sector Start Addresses:");
185         for (i=0; i<info->sector_count; ++i) {
186                 if ((i % 5) == 0)
187                         printf ("\n   ");
188
189                 printf (" %08lX%s", info->start[i],
190                                 info->protect[i] ? " (RO)" : "     ");
191         }
192         printf ("\n");
193 }
194
195 /*-----------------------------------------------------------------------
196  */
197
198 /*
199  * The following code cannot be run from FLASH!
200  */
201 ulong flash_get_size (FPWV *addr, flash_info_t *info)
202 {
203         int i;
204
205         /* Write auto select command: read Manufacturer ID */
206         /* Write auto select command sequence and test FLASH answer */
207         addr[FLASH_CYCLE1] = (FPW)0x00900090;   /* selects Intel or AMD */
208
209         /* The manufacturer codes are only 1 byte, so just use 1 byte.
210          * This works for any bus width and any FLASH device width.
211          */
212         udelay(100);
213         switch (addr[0] & 0xff) {
214                 case (uchar)INTEL_MANUFACT:
215                         info->flash_id = FLASH_MAN_INTEL;
216                         break;
217                 default:
218                         info->flash_id = FLASH_UNKNOWN;
219                         info->sector_count = 0;
220                         info->size = 0;
221                         break;
222         }
223
224         /* Strataflash is configurable to 8/16bit Bus,
225          * but the Query-Structure is Word-orientated */
226         if (info->flash_id != FLASH_UNKNOWN) {
227                 switch ((FPW)addr[2]) {
228                         case (FPW)INTEL_ID_28F128J3:
229                                 info->flash_id += FLASH_28F128J3A;
230                                 info->sector_count = 128;
231                                 info->size = 0x01000000;
232                                 for( i = 0; i < info->sector_count; i++ )
233                                         info->start[i] = (ulong)addr + (i * 0x20000);
234                                 break;                          /* => Intel Strataflash 16MB */
235                         default:
236                                 printf("Flash_id != %xd\n", (FPW)addr[2]);
237                                 info->flash_id = FLASH_UNKNOWN;
238                                 info->sector_count = 0;
239                                 info->size = 0;
240                                 return (0);                     /* => no or unknown flash */
241                 }
242         }
243
244         /* Put FLASH back in read mode */
245         flash_reset(info);
246
247         return (info->size);
248 }
249
250 /*-----------------------------------------------------------------------
251  */
252
253 int flash_erase (flash_info_t *info, int s_first, int s_last)
254 {
255         FPWV *addr;
256         int flag, prot, sect;
257         ulong start, now, last;
258         int rcode = 0;
259
260         if ((s_first < 0) || (s_first > s_last)) {
261                 if (info->flash_id == FLASH_UNKNOWN) {
262                         printf ("- missing\n");
263                 } else {
264                         printf ("- no sectors to erase\n");
265                 }
266                 return 1;
267         }
268
269         switch (info->flash_id & FLASH_TYPEMASK) {
270                 case FLASH_28F128J3A:
271                         break;
272                 case FLASH_UNKNOWN:
273                 default:
274                         printf ("Can't erase unknown flash type %08lx - aborted\n",
275                                         info->flash_id);
276                         return 1;
277         }
278
279         prot = 0;
280         for (sect = s_first; sect <= s_last; ++sect)
281                 if (info->protect[sect])
282                         prot++;
283
284         if (prot)
285                 printf ("- Warning: %d protected sectors will not be erased!",
286                                 prot);
287
288         printf ("\n");
289         last = get_timer(0);
290
291         /* Start erase on unprotected sectors */
292         for (sect = s_first; sect <= s_last && rcode == 0; sect++) {
293
294                 if (info->protect[sect] != 0)   /* protected, skip it */
295                         continue;
296
297                 /* Disable interrupts which might cause a timeout here */
298                 flag = disable_interrupts();
299
300                 addr = (FPWV *)(info->start[sect]);
301                 *addr = (FPW)0x00500050; /* clear status register */
302                 *addr = (FPW)0x00200020; /* erase setup */
303                 *addr = (FPW)0x00D000D0; /* erase confirm */
304
305                 /* re-enable interrupts if necessary */
306                 if (flag)
307                         enable_interrupts();
308
309                 start = get_timer(0);
310
311                 /* wait at least 80us for Intel - let's wait 1 ms */
312                 udelay (1000);
313
314                 while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
315                         if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
316                                 printf ("Timeout\n");
317                                 *addr = (FPW)0x00B000B0;/* suspend erase */
318                                 flash_reset(info);      /* reset to read mode */
319                                 rcode = 1;              /* failed */
320                                 break;
321                         }
322
323                         /* show that we're waiting */
324                         if ((get_timer(last)) > CFG_HZ) { /* every second */
325                                 putc ('.');
326                                 last = get_timer(0);
327                         }
328                 }
329
330                 flash_reset(info);      /* reset to read mode */
331         }
332
333         printf (" done\n");
334         return rcode;
335 }
336
337 /*-----------------------------------------------------------------------
338  * Copy memory to flash, returns:
339  * 0 - OK
340  * 1 - write timeout
341  * 2 - Flash not erased
342  */
343 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
344 {
345         FPW data = 0;   /* 16 or 32 bit word, matches flash bus width on MPC8XX */
346         int bytes;      /* number of bytes to program in current word           */
347         int left;       /* number of bytes left to program                      */
348         int i, res;
349
350         for (left = cnt, res = 0;
351                         left > 0 && res == 0;
352                         addr += sizeof(data), left -= sizeof(data) - bytes) {
353
354                 bytes = addr & (sizeof(data) - 1);
355                 addr &= ~(sizeof(data) - 1);
356
357                 /* combine source and destination data so can program
358                  * an entire word of 16 or 32 bits  */
359                 for (i = 0; i < sizeof(data); i++) {
360                         data <<= 8;
361                         if (i < bytes || i - bytes >= left )
362                                 data += *((uchar *)addr + i);
363                         else
364                                 data += *src++;
365                 }
366
367                 /* write one word to the flash */
368                 switch (info->flash_id & FLASH_VENDMASK) {
369                         case FLASH_MAN_INTEL:
370                                 res = write_data(info, (FPWV *)addr, data);
371                                 break;
372                         default:
373                                 /* unknown flash type, error! */
374                                 printf ("missing or unknown FLASH type\n");
375                                 res = 1;        /* not really a timeout, but gives error */
376                                 break;
377                 }
378         }
379
380         return (res);
381 }
382
383 /*-----------------------------------------------------------------------
384  * Write a word or halfword to Flash, returns:
385  * 0 - OK
386  * 1 - write timeout
387  * 2 - Flash not erased
388  */
389 static int write_data (flash_info_t *info, FPWV *dest, FPW data)
390 {
391         FPWV *addr = dest;
392         ulong status;
393         ulong start;
394         int flag;
395
396         /* Check if Flash is (sufficiently) erased */
397         if ((*addr & data) != data) {
398                 printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr);
399                 return (2);
400         }
401         /* Disable interrupts which might cause a timeout here */
402         flag = disable_interrupts ();
403
404         *addr = (FPW) 0x00400040;       /* write setup */
405         *addr = data;
406
407         /* arm simple, non interrupt dependent timer */
408         start = get_timer(0);
409
410         /* wait while polling the status register */
411         while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
412                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
413                         *addr = (FPW) 0x00FF00FF;       /* restore read mode */
414                         return (1);
415                 }
416         }
417
418         *addr = (FPW) 0x00FF00FF;       /* restore read mode */
419         if (flag)
420                 enable_interrupts();
421
422         return (0);
423 }