ppc4xx: Add function to check and dynamically change PCI sync clock
[platform/kernel/u-boot.git] / board / ml2 / flash.c
1 /*
2  * flash.c: Support code for the flash chips on the Xilinx ML2 board
3  *
4  * Copyright 2002 Mind NV
5  *
6  * http://www.mind.be/
7  *
8  * Author : Peter De Schrijver (p2@mind.be)
9  *
10  * This software may be used and distributed according to the terms of
11  * the GNU General Public License (GPL) version 2, incorporated herein by
12  * reference. Drivers based on or derived from this code fall under the GPL
13  * and must retain the authorship, copyright and this license notice. This
14  * file is not a complete program and may only be used when the entire program
15  * is licensed under the GPL.
16  *
17  */
18
19 #include <common.h>
20 #include <asm/u-boot.h>
21 #include <configs/ML2.h>
22
23 #define FLASH_BANK_SIZE (64*1024*1024)
24
25 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
26
27 #define SECT_SIZE               (512*1024)
28
29 #define CMD_READ_ARRAY  0x00FF00FF00FF00FULL
30 #define CMD_IDENTIFY        0x0090009000900090ULL
31 #define CMD_ERASE_SETUP     0x0020002000200020ULL
32 #define CMD_ERASE_CONFIRM   0x00D000D000D000D0ULL
33 #define CMD_PROGRAM     0x0040004000400040ULL
34 #define CMD_RESUME      0x00D000D000D000D0ULL
35 #define CMD_SUSPEND     0x00B000B000B000B0ULL
36 #define CMD_STATUS_READ     0x0070007000700070ULL
37 #define CMD_STATUS_RESET    0x0050005000500050ULL
38
39 #define BIT_BUSY        0x0080008000800080ULL
40 #define BIT_ERASE_SUSPEND   0x004000400400040ULL
41 #define BIT_ERASE_ERROR     0x0020002000200020ULL
42 #define BIT_PROGRAM_ERROR   0x0010001000100010ULL
43 #define BIT_VPP_RANGE_ERROR 0x0008000800080008ULL
44 #define BIT_PROGRAM_SUSPEND 0x0004000400040004ULL
45 #define BIT_PROTECT_ERROR   0x0002000200020002ULL
46 #define BIT_UNDEFINED       0x0001000100010001ULL
47
48 #define BIT_SEQUENCE_ERROR  0x0030003000300030ULL
49
50 #define BIT_TIMEOUT     0x80000000
51
52
53 inline void eieio(void) {
54
55         __asm__ __volatile__ ("eieio" : : : "memory");
56
57 }
58
59 ulong flash_init(void) {
60
61         int i, j;
62         ulong size = 0;
63
64         for(i=0;i<CONFIG_SYS_MAX_FLASH_BANKS;i++) {
65                 ulong flashbase = 0;
66
67                 flash_info[i].flash_id = (INTEL_MANUFACT & FLASH_VENDMASK) |
68                                                                  (INTEL_ID_28F128J3A & FLASH_TYPEMASK);
69                 flash_info[i].size = FLASH_BANK_SIZE;
70                 flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
71                 memset(flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
72                 if (i==0)
73                         flashbase = CONFIG_SYS_FLASH_BASE;
74                 else
75                         panic("configured too many flash banks!\n");
76                 for (j = 0; j < flash_info[i].sector_count; j++)
77                                 flash_info[i].start[j]=flashbase + j * SECT_SIZE;
78
79                 size += flash_info[i].size;
80         }
81
82         return size;
83 }
84
85 void flash_print_info  (flash_info_t *info) {
86
87         int i;
88
89         switch (info->flash_id & FLASH_VENDMASK) {
90                 case (INTEL_MANUFACT & FLASH_VENDMASK):
91                         printf("Intel: ");
92                         break;
93                 default:
94                         printf("Unknown Vendor ");
95                         break;
96         }
97
98         switch (info->flash_id & FLASH_TYPEMASK) {
99                 case (INTEL_ID_28F128J3A & FLASH_TYPEMASK):
100                         printf("4x 28F128J3A (128Mbit)\n");
101                         break;
102                 default:
103                         printf("Unknown Chip Type\n");
104                         break;
105         }
106
107         printf("  Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count);
108         printf("  Sector Start Addresses:");
109         for (i = 0; i < info->sector_count; i++) {
110                 if ((i % 5) == 0)
111                         printf("\n   ");
112                 printf (" %08lX%s", info->start[i],
113                                  info->protect[i] ? " (RO)" : "     ");
114         }
115         printf ("\n");
116 }
117
118 int flash_error (unsigned long long code) {
119
120         if (code & BIT_TIMEOUT) {
121                 printf ("Timeout\n");
122                 return ERR_TIMOUT;
123         }
124
125         if (~code & BIT_BUSY) {
126                 printf ("Busy\n");
127                 return ERR_PROG_ERROR;
128         }
129
130         if (code & BIT_VPP_RANGE_ERROR) {
131                 printf ("Vpp range error\n");
132                 return ERR_PROG_ERROR;
133         }
134
135         if (code & BIT_PROTECT_ERROR) {
136                 printf ("Device protect error\n");
137                 return ERR_PROG_ERROR;
138         }
139
140         if (code & BIT_SEQUENCE_ERROR) {
141                 printf ("Command seqence error\n");
142                 return ERR_PROG_ERROR;
143         }
144
145         if (code & BIT_ERASE_ERROR) {
146                 printf ("Block erase error\n");
147                 return ERR_PROG_ERROR;
148         }
149
150         if (code & BIT_PROGRAM_ERROR) {
151                 printf ("Program error\n");
152                 return ERR_PROG_ERROR;
153         }
154
155         if (code & BIT_ERASE_SUSPEND) {
156                 printf ("Block erase suspended\n");
157                 return ERR_PROG_ERROR;
158         }
159
160         if (code & BIT_PROGRAM_SUSPEND) {
161                 printf ("Program suspended\n");
162                 return ERR_PROG_ERROR;
163         }
164
165         return ERR_OK;
166
167 }
168
169 int flash_erase (flash_info_t *info, int s_first, int s_last) {
170
171         int rc = ERR_OK;
172         int sect;
173         unsigned long long result;
174
175         if (info->flash_id == FLASH_UNKNOWN)
176                 return ERR_UNKNOWN_FLASH_TYPE;
177
178         if ((s_first < 0) || (s_first > s_last))
179                 return ERR_INVAL;
180
181         if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK))
182                 return ERR_UNKNOWN_FLASH_VENDOR;
183
184         for (sect=s_first; sect<=s_last; ++sect)
185                 if (info->protect[sect])
186                         return ERR_PROTECTED;
187
188         for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
189                 volatile unsigned long long *addr=
190                                                                         (unsigned long long *)(info->start[sect]);
191
192                 printf("Erasing sector %2d ... ", sect);
193
194                 *addr=CMD_STATUS_RESET;
195                 eieio();
196                 *addr=CMD_ERASE_SETUP;
197                 eieio();
198                 *addr=CMD_ERASE_CONFIRM;
199                 eieio();
200
201                 do {
202                         result = *addr;
203                 } while(~result & BIT_BUSY);
204
205                 *addr=CMD_READ_ARRAY;
206
207                 if ((rc = flash_error(result)) == ERR_OK)
208                         printf("ok.\n");
209                 else
210                         break;
211         }
212
213         if (ctrlc())
214                 printf("User Interrupt!\n");
215
216         return rc;
217 }
218
219 static int write_word (flash_info_t *info, ulong dest, unsigned long long data) {
220
221         volatile unsigned long long *addr=(unsigned long long *)dest;
222         unsigned long long result;
223         int rc = ERR_OK;
224
225         result = *addr;
226         if ((result & data) != data)
227                 return ERR_NOT_ERASED;
228
229         *addr=CMD_STATUS_RESET;
230         eieio();
231         *addr=CMD_PROGRAM;
232         eieio();
233         *addr=data;
234         eieio();
235
236         do {
237                 result = *addr;
238         } while(~result & BIT_BUSY);
239
240         *addr=CMD_READ_ARRAY;
241
242         rc = flash_error(result);
243
244         return rc;
245
246 }
247
248 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) {
249
250         ulong cp, wp;
251         unsigned long long data;
252         int l;
253         int i,rc;
254
255         wp=(addr & ~7);
256
257         if((l=addr-wp) != 0) {
258                 data=0;
259                 for(i=0,cp=wp;i<l;++i,++cp)
260                         data = (data >> 8) | (*(uchar *)cp << 24);
261
262                 for (; i<8 && cnt>0; ++i) {
263                         data = (data >> 8) | (*src++ << 24);
264                         --cnt;
265                         ++cp;
266                 }
267
268                 for (; i<8; ++i, ++cp)
269                         data = (data >> 8) | (*(uchar *)cp << 24);
270
271                 if ((rc = write_word(info, wp, data)) != 0)
272                         return rc;
273
274                 wp+=8;
275         }
276
277         while(cnt>=8) {
278                 data = *((unsigned long long *)src);
279                 if ((rc = write_word(info, wp, data)) != 0)
280                         return rc;
281                 src+=8;
282                 wp+=8;
283                 cnt-=8;
284         }
285
286         if(cnt == 0)
287                 return ERR_OK;
288
289         data = 0;
290         for (i=0, cp=wp; i<8 && cnt>0; ++i, ++cp) {
291                 data = (data >> 8) | (*src++ << 24);
292                 --cnt;
293         }
294         for (; i<8; ++i, ++cp) {
295                 data = (data >> 8) | (*(uchar *)cp << 24);
296         }
297
298         return write_word(info, wp, data);
299
300 }