]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/ezkit533/flash.c
Add missing Blackfin files.
[karo-tx-uboot.git] / board / ezkit533 / flash.c
1 /*
2  * U-boot - flash.c Flash driver for PSD4256GV
3  *
4  * Copyright (c) 2005 blackfin.uclinux.org
5  * This file is based on BF533EzFlash.c originally written by Analog Devices, Inc.
6  *
7  * (C) Copyright 2000-2004
8  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
9  *
10  * See file CREDITS for list of people who contributed to this
11  * project.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License as
15  * published by the Free Software Foundation; either version 2 of
16  * the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26  * MA 02111-1307 USA
27  */
28
29 #include "flash-defines.h"
30
31 void flash_reset(void)
32 {
33         reset_flash();
34 }
35
36 unsigned long flash_get_size(ulong baseaddr, flash_info_t * info,
37                              int bank_flag)
38 {
39         int id = 0, i = 0;
40         static int FlagDev = 1;
41
42         id = get_codes();
43         if(FlagDev)     {
44 #ifdef DEBUG
45                 printf("Device ID of the Flash is %x\n", id);
46 #endif
47                 FlagDev = 0;
48         }
49         info->flash_id = id;
50
51         switch (bank_flag) {
52         case 0:
53                 for (i = PriFlashABegin; i < SecFlashABegin; i++)
54                         info->start[i] = (baseaddr + (i * AFP_SectorSize1));
55                 info->size = 0x200000;
56                 info->sector_count = 32;
57                 break;
58         case 1:
59                 info->start[0] = baseaddr + SecFlashASec1Off;
60                 info->start[1] = baseaddr + SecFlashASec2Off;
61                 info->start[2] = baseaddr + SecFlashASec3Off;
62                 info->start[3] = baseaddr + SecFlashASec4Off;
63                 info->size = 0x10000;
64                 info->sector_count = 4;
65                 break;
66         case 2:
67                 info->start[0] = baseaddr + SecFlashBSec1Off;
68                 info->start[1] = baseaddr + SecFlashBSec2Off;
69                 info->start[2] = baseaddr + SecFlashBSec3Off;
70                 info->start[3] = baseaddr + SecFlashBSec4Off;
71                 info->size = 0x10000;
72                 info->sector_count = 4;
73                 break;
74         }
75         return (info->size);
76 }
77
78 unsigned long flash_init(void)
79 {
80         unsigned long size_b0, size_b1, size_b2;
81         int i;
82
83         size_b0 = size_b1 = size_b2 = 0;
84 #ifdef DEBUG
85         printf("Flash Memory Start 0x%x\n", CFG_FLASH_BASE);
86         printf("Memory Map for the Flash\n");
87         printf("0x20000000 - 0x200FFFFF Flash A Primary (1MB)\n");
88         printf("0x20100000 - 0x201FFFFF Flash B Primary (1MB)\n");
89         printf("0x20200000 - 0x2020FFFF Flash A Secondary (64KB)\n");
90         printf("0x20280000 - 0x2028FFFF Flash B Secondary (64KB)\n");
91         printf("Please type command flinfo for information on Sectors \n");
92 #endif
93         for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
94                 flash_info[i].flash_id = FLASH_UNKNOWN;
95         }
96
97         size_b0 = flash_get_size(CFG_FLASH0_BASE, &flash_info[0], 0);
98         size_b1 = flash_get_size(CFG_FLASH0_BASE, &flash_info[1], 1);
99         size_b2 = flash_get_size(CFG_FLASH0_BASE, &flash_info[2], 2);
100
101         if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) {
102                 printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
103                         size_b0, size_b0 >> 20);
104         }
105
106         (void)flash_protect(FLAG_PROTECT_SET,CFG_FLASH0_BASE,(flash_info[0].start[2] - 1),&flash_info[0]);
107
108         return (size_b0 + size_b1 + size_b2);
109 }
110
111 void flash_print_info(flash_info_t * info)
112 {
113         int i;
114
115         if (info->flash_id == FLASH_UNKNOWN) {
116                 printf("missing or unknown FLASH type\n");
117                 return;
118         }
119
120         switch (info->flash_id) {
121         case FLASH_PSD4256GV:
122                 printf("ST Microelectronics ");
123                 break;
124         default:
125                 printf("Unknown Vendor ");
126                 break;
127         }
128         for (i = 0; i < info->sector_count; ++i) {
129                 if ((i % 5) == 0)
130                         printf("\n   ");
131                 printf(" %08lX%s",
132                         info->start[i],
133                         info->protect[i] ? " (RO)" : "     ");
134         }
135         printf("\n");
136         return;
137 }
138
139 int flash_erase(flash_info_t * info, int s_first, int s_last)
140 {
141         int cnt = 0,i;
142         int prot,sect;
143
144         prot = 0;
145         for (sect = s_first; sect <= s_last; ++sect) {
146                 if (info->protect[sect])
147                         prot++;
148         }
149
150         if (prot)
151                 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
152         else
153                 printf ("\n");  
154
155         cnt = s_last - s_first + 1;
156
157         if (cnt == FLASH_TOT_SECT) {
158                 printf("Erasing flash, Please Wait \n");
159                 if(erase_flash() < 0) {
160                         printf("Erasing flash failed \n");
161                         return FLASH_FAIL;
162                 }
163         } else {
164                 printf("Erasing Flash locations, Please Wait\n");
165                 for (i = s_first; i <= s_last; i++) {
166                         if (info->protect[i] == 0) {    /* not protected */
167                                 if(erase_block_flash(i, info->start[i]) < 0) {
168                                         printf("Error Sector erasing \n");
169                                         return FLASH_FAIL;
170                                 }
171                         }
172                 }
173         }
174         return FLASH_SUCCESS;
175 }
176
177 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
178 {
179         int ret;
180
181         ret = write_data(addr, cnt, 1, (int *) src);
182         if(ret == FLASH_FAIL)
183                 return ERR_NOT_ERASED;
184         return FLASH_SUCCESS;
185 }
186
187
188 int write_data(long lStart, long lCount, long lStride, int *pnData)
189 {
190         long i = 0;
191         int j = 0;
192         unsigned long ulOffset = lStart - CFG_FLASH_BASE;
193         int d;
194         int iShift = 0;
195         int iNumWords = 2;
196         int nLeftover = lCount % 4;
197         int nSector = 0;
198
199         for (i = 0; (i < lCount / 4) && (i < BUFFER_SIZE); i++) {
200                 for (iShift = 0, j = 0; (j < iNumWords);
201                         j++, ulOffset += (lStride * 2)) {
202                         if ((ulOffset >= INVALIDLOCNSTART)
203                         && (ulOffset < INVALIDLOCNEND)) {
204                                 printf("Invalid locations, Try writing to another location \n");
205                                 return FLASH_FAIL;
206                         }
207                         get_sector_number(ulOffset, &nSector);
208                         read_flash(ulOffset,&d);
209                         if(d != 0xffff) {
210                                 printf("Flash not erased at offset 0x%x Please erase to reprogram \n",ulOffset);
211                                 return FLASH_FAIL;
212                         }
213                         unlock_flash(ulOffset);
214                         if(write_flash(ulOffset, (pnData[i] >> iShift)) < 0) {
215                                 printf("Error programming the flash \n");
216                                 return FLASH_FAIL;
217                         }
218                         iShift += 16;
219                 }
220         }
221         if (nLeftover > 0) {
222                 if ((ulOffset >= INVALIDLOCNSTART)
223                         && (ulOffset < INVALIDLOCNEND))
224                                 return FLASH_FAIL;
225                 get_sector_number(ulOffset, &nSector);
226                 read_flash(ulOffset,&d);
227                 if(d != 0xffff) {
228                         printf("Flash already programmed. Please erase to reprogram \n");
229                         printf("uloffset = 0x%x \t d = 0x%x\n",ulOffset,d);
230                         return FLASH_FAIL;
231                 }
232                 unlock_flash(ulOffset);
233                 if(write_flash(ulOffset, pnData[i]) < 0) {
234                         printf("Error programming the flash \n");
235                         return FLASH_FAIL;
236                 }
237         }
238         return FLASH_SUCCESS;
239 }
240
241 int read_data(long ulStart, long lCount, long lStride, int *pnData)
242 {
243         long i = 0;
244         int j = 0;
245         long ulOffset = ulStart;
246         int iShift = 0;
247         int iNumWords = 2;
248         int nLeftover = lCount % 4;
249         int nHi, nLow;
250         int nSector = 0;
251
252         for (i = 0; (i < lCount / 4) && (i < BUFFER_SIZE); i++) {
253                 for (iShift = 0, j = 0; j < iNumWords; j += 2) {
254                         if ((ulOffset >= INVALIDLOCNSTART)
255                                 && (ulOffset < INVALIDLOCNEND))
256                                         return FLASH_FAIL;
257
258                         get_sector_number(ulOffset, &nSector);
259                         read_flash(ulOffset, &nLow);
260                         ulOffset += (lStride * 2);
261                         read_flash(ulOffset, &nHi);
262                         ulOffset += (lStride * 2);
263                         pnData[i] = (nHi << 16) | nLow;
264                 }
265         }
266         if (nLeftover > 0) {
267                 if ((ulOffset >= INVALIDLOCNSTART)
268                         && (ulOffset < INVALIDLOCNEND))
269                                 return FLASH_FAIL;
270
271                 get_sector_number(ulOffset, &nSector);
272                 read_flash(ulOffset, &pnData[i]);
273         }
274         return FLASH_SUCCESS;
275 }
276
277 int write_flash(long nOffset, int nValue)
278 {
279         long addr;
280
281         addr = (CFG_FLASH_BASE + nOffset);
282         asm("ssync;");
283         *(unsigned volatile short *) addr = nValue;
284         asm("ssync;");
285         if(poll_toggle_bit(nOffset) < 0)
286                 return FLASH_FAIL;
287         return FLASH_SUCCESS;
288 }
289
290 int read_flash(long nOffset, int *pnValue)
291 {
292         int nValue = 0x0;
293         long addr = (CFG_FLASH_BASE + nOffset);
294
295         if (nOffset != 0x2)
296                 reset_flash();
297         asm("ssync;");
298         nValue = *(volatile unsigned short *) addr;
299         asm("ssync;");
300         *pnValue = nValue;
301         return TRUE;
302 }
303
304 int poll_toggle_bit(long lOffset)
305 {
306         unsigned int u1,u2;
307         unsigned long timeout = 0xFFFFFFFF;
308         volatile unsigned long *FB = (volatile unsigned long *)(0x20000000 + lOffset);
309         while(1) {
310                 if(timeout < 0)
311                         break;
312                 u1 = *(volatile unsigned short *)FB;
313                 u2 = *(volatile unsigned short *)FB;
314                 if((u1 & 0x0040) == (u2 & 0x0040))
315                         return FLASH_SUCCESS;
316                 if((u2 & 0x0020) == 0x0000)
317                         continue;
318                 u1 = *(volatile unsigned short *)FB;
319                 if((u2 & 0x0040) == (u1 & 0x0040))
320                         return FLASH_SUCCESS;
321                 else {
322                         reset_flash();
323                         return FLASH_FAIL;
324                 }
325                 timeout--;
326         }
327         printf("Time out occured \n");
328         if(timeout <0)  return FLASH_FAIL;
329 }
330
331 void reset_flash(void)
332 {
333         write_flash(WRITESEQ1, RESET_VAL);
334         /* Wait for 10 micro seconds */
335         udelay(10);
336 }
337
338 int erase_flash(void)
339 {
340         write_flash(WRITESEQ1, WRITEDATA1);
341         write_flash(WRITESEQ2, WRITEDATA2);
342         write_flash(WRITESEQ3, WRITEDATA3);
343         write_flash(WRITESEQ4, WRITEDATA4);
344         write_flash(WRITESEQ5, WRITEDATA5);
345         write_flash(WRITESEQ6, WRITEDATA6);
346
347         if(poll_toggle_bit(0x0000) < 0)
348                 return FLASH_FAIL;
349
350         write_flash(SecFlashAOff + WRITESEQ1, WRITEDATA1);
351         write_flash(SecFlashAOff + WRITESEQ2, WRITEDATA2);
352         write_flash(SecFlashAOff + WRITESEQ3, WRITEDATA3);
353         write_flash(SecFlashAOff + WRITESEQ4, WRITEDATA4);
354         write_flash(SecFlashAOff + WRITESEQ5, WRITEDATA5);
355         write_flash(SecFlashAOff + WRITESEQ6, WRITEDATA6);
356
357         if(poll_toggle_bit(SecFlashASec1Off) < 0)
358                 return FLASH_FAIL;
359
360         write_flash(PriFlashBOff + WRITESEQ1, WRITEDATA1);
361         write_flash(PriFlashBOff + WRITESEQ2, WRITEDATA2);
362         write_flash(PriFlashBOff + WRITESEQ3, WRITEDATA3);
363         write_flash(PriFlashBOff + WRITESEQ4, WRITEDATA4);
364         write_flash(PriFlashBOff + WRITESEQ5, WRITEDATA5);
365         write_flash(PriFlashBOff + WRITESEQ6, WRITEDATA6);
366
367         if(poll_toggle_bit(PriFlashBOff) <0)
368                 return FLASH_FAIL;
369
370         write_flash(SecFlashBOff + WRITESEQ1, WRITEDATA1);
371         write_flash(SecFlashBOff + WRITESEQ2, WRITEDATA2);
372         write_flash(SecFlashBOff + WRITESEQ3, WRITEDATA3);
373         write_flash(SecFlashBOff + WRITESEQ4, WRITEDATA4);
374         write_flash(SecFlashBOff + WRITESEQ5, WRITEDATA5);
375         write_flash(SecFlashBOff + WRITESEQ6, WRITEDATA6);
376
377         if(poll_toggle_bit(SecFlashBOff) < 0)
378                 return FLASH_FAIL;
379
380         return FLASH_SUCCESS;
381 }
382
383 int erase_block_flash(int nBlock, unsigned long address)
384 {
385         long ulSectorOff = 0x0;
386
387         if ((nBlock < 0) || (nBlock > AFP_NumSectors))
388                 return FALSE;
389
390         ulSectorOff = (address - CFG_FLASH_BASE);
391
392         write_flash((WRITESEQ1 | ulSectorOff), WRITEDATA1);
393         write_flash((WRITESEQ2 | ulSectorOff), WRITEDATA2);
394         write_flash((WRITESEQ3 | ulSectorOff), WRITEDATA3);
395         write_flash((WRITESEQ4 | ulSectorOff), WRITEDATA4);
396         write_flash((WRITESEQ5 | ulSectorOff), WRITEDATA5);
397
398         write_flash(ulSectorOff, BlockEraseVal);
399
400         if(poll_toggle_bit(ulSectorOff) < 0)
401                 return FLASH_FAIL;
402
403         return FLASH_SUCCESS;
404 }
405
406 void unlock_flash(long ulOffset)
407 {
408         unsigned long ulOffsetAddr = ulOffset;
409         ulOffsetAddr &= 0xFFFF0000;
410
411         write_flash((WRITESEQ1 | ulOffsetAddr), UNLOCKDATA1);
412         write_flash((WRITESEQ2 | ulOffsetAddr), UNLOCKDATA2);
413         write_flash((WRITESEQ3 | ulOffsetAddr), UNLOCKDATA3);
414 }
415
416 int get_codes()
417 {
418         int dev_id = 0;
419
420         write_flash(WRITESEQ1, GETCODEDATA1);
421         write_flash(WRITESEQ2, GETCODEDATA2);
422         write_flash(WRITESEQ3, GETCODEDATA3);
423
424         read_flash(0x0002, &dev_id);
425         dev_id &= 0x00FF;
426
427         reset_flash();
428
429         return dev_id;
430 }
431
432 void get_sector_number(long ulOffset, int *pnSector)
433 {
434         int nSector = 0;
435
436         if (ulOffset >= SecFlashAOff) {
437                 if ((ulOffset < SecFlashASec1Off)
438                         && (ulOffset < SecFlashASec2Off)) {
439                                 nSector = SECT32;
440                 } else if ((ulOffset >= SecFlashASec2Off)
441                         && (ulOffset < SecFlashASec3Off)) {
442                                 nSector = SECT33;
443                 } else if ((ulOffset >= SecFlashASec3Off)
444                         && (ulOffset < SecFlashASec4Off)) {
445                                 nSector = SECT34;
446                 } else if ((ulOffset >= SecFlashASec4Off)
447                         && (ulOffset < SecFlashAEndOff)) {
448                                 nSector = SECT35;
449                 }
450         } else if (ulOffset >= SecFlashBOff) {
451                 if ((ulOffset < SecFlashBSec1Off)
452                         && (ulOffset < SecFlashBSec2Off)) {
453                                 nSector = SECT36;
454                 }
455                 if ((ulOffset < SecFlashBSec2Off)
456                         && (ulOffset < SecFlashBSec3Off)) {
457                                 nSector = SECT37;
458                 }
459                 if ((ulOffset < SecFlashBSec3Off)
460                         && (ulOffset < SecFlashBSec4Off)) {
461                                 nSector = SECT38;
462                 }
463                 if ((ulOffset < SecFlashBSec4Off)
464                         && (ulOffset < SecFlashBEndOff)) {
465                                 nSector = SECT39;
466                 }
467         } else if ((ulOffset >= PriFlashAOff) && (ulOffset < SecFlashAOff)) {
468                 nSector = ulOffset & 0xffff0000;
469                 nSector = ulOffset >> 16;
470                 nSector = nSector & 0x000ff;
471         }
472
473         if ((nSector >= 0) && (nSector < AFP_NumSectors)) {
474                 *pnSector = nSector;
475         }
476 }