Merge with /home/wd/git/u-boot/custodian/u-boot-net
[oweals/u-boot.git] / board / bf537-stamp / flash.c
1 /*
2  * U-boot - flash.c Flash driver for PSD4256GV
3  *
4  * Copyright (c) 2005-2007 Analog Devices Inc.
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., 51 Franklin St, Fifth Floor, Boston,
26  * MA 02110-1301 USA
27  */
28
29 #include <malloc.h>
30 #include <config.h>
31 #include <asm/io.h>
32 #include "flash-defines.h"
33
34 void flash_reset(void)
35 {
36         reset_flash();
37 }
38
39 unsigned long flash_get_size(ulong baseaddr, flash_info_t * info, int bank_flag)
40 {
41         int id = 0, i = 0;
42         static int FlagDev = 1;
43
44         id = get_codes();
45         if (FlagDev) {
46                 FlagDev = 0;
47         }
48         info->flash_id = id;
49         switch (bank_flag) {
50         case 0:
51                 for (i = PriFlashABegin; i < SecFlashABegin; i++)
52                         info->start[i] = (baseaddr + (i * AFP_SectorSize1));
53                 for (i = SecFlashABegin; i < NUM_SECTORS; i++)
54                         info->start[i] =
55                             (baseaddr + SecFlashAOff +
56                              ((i - SecFlashABegin) * AFP_SectorSize2));
57                 info->size = 0x400000;
58                 info->sector_count = NUM_SECTORS;
59                 break;
60         case 1:
61                 info->start[0] = baseaddr + SecFlashASec1Off;
62                 info->start[1] = baseaddr + SecFlashASec2Off;
63                 info->start[2] = baseaddr + SecFlashASec3Off;
64                 info->start[3] = baseaddr + SecFlashASec4Off;
65                 info->size = 0x10000;
66                 info->sector_count = 4;
67                 break;
68         case 2:
69                 info->start[0] = baseaddr + SecFlashBSec1Off;
70                 info->start[1] = baseaddr + SecFlashBSec2Off;
71                 info->start[2] = baseaddr + SecFlashBSec3Off;
72                 info->start[3] = baseaddr + SecFlashBSec4Off;
73                 info->size = 0x10000;
74                 info->sector_count = 4;
75                 break;
76         }
77         return (info->size);
78 }
79
80 unsigned long flash_init(void)
81 {
82         unsigned long size_b;
83         int i;
84
85         size_b = 0;
86         for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
87                 flash_info[i].flash_id = FLASH_UNKNOWN;
88         }
89
90         size_b = flash_get_size(CFG_FLASH_BASE, &flash_info[0], 0);
91
92         if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b == 0) {
93                 printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
94                        size_b, size_b >> 20);
95         }
96
97         /* flash_protect (int flag, ulong from, ulong to, flash_info_t *info) */
98         (void)flash_protect(FLAG_PROTECT_SET, CFG_FLASH_BASE,
99                             (flash_info[0].start[2] - 1), &flash_info[0]);
100 #if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT)
101         (void)flash_protect(FLAG_PROTECT_SET, 0x203F0000, 0x203FFFFF,
102                             &flash_info[0]);
103 #endif
104
105         return (size_b);
106 }
107
108 void flash_print_info(flash_info_t * info)
109 {
110         int i;
111
112         if (info->flash_id == FLASH_UNKNOWN) {
113                 printf("missing or unknown FLASH type\n");
114                 return;
115         }
116
117         switch (info->flash_id) {
118         case (STM_ID_29W320EB & 0xFFFF):
119         case (STM_ID_29W320DB & 0xFFFF):
120                 printf("ST Microelectronics ");
121                 break;
122         default:
123                 printf("Unknown Vendor: (0x%08X) ", info->flash_id);
124                 break;
125         }
126         for (i = 0; i < info->sector_count; ++i) {
127                 if ((i % 5) == 0)
128                         printf("\n   ");
129                 printf(" %08lX%s",
130                        info->start[i], info->protect[i] ? " (RO)" : "     ");
131         }
132         printf("\n");
133         return;
134 }
135
136 int flash_erase(flash_info_t * info, int s_first, int s_last)
137 {
138         int cnt = 0, i;
139         int prot, sect;
140
141         prot = 0;
142         for (sect = s_first; sect <= s_last; ++sect) {
143                 if (info->protect[sect])
144                         prot++;
145         }
146         if (prot)
147                 printf("- Warning: %d protected sectors will not be erased!\n",
148                        prot);
149         else
150                 printf("\n");
151
152         cnt = s_last - s_first + 1;
153
154 #if (BFIN_BOOT_MODE == BF537_BYPASS_BOOT)
155         printf("Erasing Flash locations, Please Wait\n");
156         for (i = s_first; i <= s_last; i++) {
157                 if (info->protect[i] == 0) {    /* not protected */
158                         if (erase_block_flash(i) < 0) {
159                                 printf("Error Sector erasing \n");
160                                 return FLASH_FAIL;
161                         }
162                 }
163         }
164 #elif (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)
165         if (cnt == FLASH_TOT_SECT) {
166                 printf("Erasing flash, Please Wait \n");
167                 if (erase_flash() < 0) {
168                         printf("Erasing flash failed \n");
169                         return FLASH_FAIL;
170                 }
171         } else {
172                 printf("Erasing Flash locations, Please Wait\n");
173                 for (i = s_first; i <= s_last; i++) {
174                         if (info->protect[i] == 0) {    /* not protected */
175                                 if (erase_block_flash(i) < 0) {
176                                         printf("Error Sector erasing \n");
177                                         return FLASH_FAIL;
178                                 }
179                         }
180                 }
181         }
182 #endif
183         printf("\n");
184         return FLASH_SUCCESS;
185 }
186
187 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
188 {
189         int d;
190         if (addr % 2) {
191                 read_flash(addr - 1 - CFG_FLASH_BASE, &d);
192                 d = (int)((d & 0x00FF) | (*src++ << 8));
193                 write_data(addr - 1, 2, (uchar *) & d);
194                 write_data(addr + 1, cnt - 1, src);
195         } else
196                 write_data(addr, cnt, src);
197         return FLASH_SUCCESS;
198 }
199
200 int write_data(long lStart, long lCount, uchar * pnData)
201 {
202         long i = 0;
203         unsigned long ulOffset = lStart - CFG_FLASH_BASE;
204         int d;
205         int nSector = 0;
206         int flag = 0;
207
208         if (lCount % 2) {
209                 flag = 1;
210                 lCount = lCount - 1;
211         }
212
213         for (i = 0; i < lCount - 1; i += 2, ulOffset += 2) {
214                 get_sector_number(ulOffset, &nSector);
215                 read_flash(ulOffset, &d);
216                 if (d != 0xffff) {
217                         printf
218                             ("Flash not erased at offset 0x%x Please erase to reprogram \n",
219                              ulOffset);
220                         return FLASH_FAIL;
221                 }
222                 unlock_flash(ulOffset);
223                 d = (int)(pnData[i] | pnData[i + 1] << 8);
224                 write_flash(ulOffset, d);
225                 if (poll_toggle_bit(ulOffset) < 0) {
226                         printf("Error programming the flash \n");
227                         return FLASH_FAIL;
228                 }
229                 if ((i > 0) && (!(i % AFP_SectorSize2)))
230                         printf(".");
231         }
232         if (flag) {
233                 get_sector_number(ulOffset, &nSector);
234                 read_flash(ulOffset, &d);
235                 if (d != 0xffff) {
236                         printf
237                             ("Flash not erased at offset 0x%x Please erase to reprogram \n",
238                              ulOffset);
239                         return FLASH_FAIL;
240                 }
241                 unlock_flash(ulOffset);
242                 d = (int)(pnData[i] | (d & 0xFF00));
243                 write_flash(ulOffset, d);
244                 if (poll_toggle_bit(ulOffset) < 0) {
245                         printf("Error programming the flash \n");
246                         return FLASH_FAIL;
247                 }
248         }
249         return FLASH_SUCCESS;
250 }
251
252 int write_flash(long nOffset, int nValue)
253 {
254         long addr;
255
256         addr = (CFG_FLASH_BASE + nOffset);
257         *(unsigned volatile short *)addr = nValue;
258         sync();
259 #if (BFIN_BOOT_MODE == BF537_SPI_MASTER_BOOT)
260         if (icache_status())
261                 udelay(CONFIG_CCLK_HZ / 1000000);
262 #endif
263         return FLASH_SUCCESS;
264 }
265
266 int read_flash(long nOffset, int *pnValue)
267 {
268         unsigned short *pFlashAddr =
269             (unsigned short *)(CFG_FLASH_BASE + nOffset);
270
271         *pnValue = *pFlashAddr;
272
273         return TRUE;
274 }
275
276 int poll_toggle_bit(long lOffset)
277 {
278         unsigned int u1, u2;
279         volatile unsigned long *FB =
280             (volatile unsigned long *)(CFG_FLASH_BASE + lOffset);
281         while (1) {
282                 u1 = *(volatile unsigned short *)FB;
283                 u2 = *(volatile unsigned short *)FB;
284                 u1 ^= u2;
285                 if (!(u1 & 0x0040))
286                         break;
287                 if (!(u2 & 0x0020))
288                         continue;
289                 else {
290                         u1 = *(volatile unsigned short *)FB;
291                         u2 = *(volatile unsigned short *)FB;
292                         u1 ^= u2;
293                         if (!(u1 & 0x0040))
294                                 break;
295                         else {
296                                 reset_flash();
297                                 return FLASH_FAIL;
298                         }
299                 }
300         }
301         return FLASH_SUCCESS;
302 }
303
304 void reset_flash(void)
305 {
306         write_flash(WRITESEQ1, RESET_VAL);
307         /* Wait for 10 micro seconds */
308         udelay(10);
309 }
310
311 int erase_flash(void)
312 {
313         write_flash(WRITESEQ1, WRITEDATA1);
314         write_flash(WRITESEQ2, WRITEDATA2);
315         write_flash(WRITESEQ3, WRITEDATA3);
316         write_flash(WRITESEQ4, WRITEDATA4);
317         write_flash(WRITESEQ5, WRITEDATA5);
318         write_flash(WRITESEQ6, WRITEDATA6);
319
320         if (poll_toggle_bit(0x0000) < 0)
321                 return FLASH_FAIL;
322
323         return FLASH_SUCCESS;
324 }
325
326 int erase_block_flash(int nBlock)
327 {
328         long ulSectorOff = 0x0;
329
330         if ((nBlock < 0) || (nBlock > AFP_NumSectors))
331                 return FALSE;
332
333         /* figure out the offset of the block in flash */
334         if ((nBlock >= 0) && (nBlock < SecFlashABegin))
335                 ulSectorOff = nBlock * AFP_SectorSize1;
336
337         else if ((nBlock >= SecFlashABegin) && (nBlock < NUM_SECTORS))
338                 ulSectorOff =
339                     SecFlashAOff + (nBlock - SecFlashABegin) * AFP_SectorSize2;
340         /* no such sector */
341         else
342                 return FLASH_FAIL;
343
344         write_flash((WRITESEQ1 | ulSectorOff), WRITEDATA1);
345         write_flash((WRITESEQ2 | ulSectorOff), WRITEDATA2);
346         write_flash((WRITESEQ3 | ulSectorOff), WRITEDATA3);
347         write_flash((WRITESEQ4 | ulSectorOff), WRITEDATA4);
348         write_flash((WRITESEQ5 | ulSectorOff), WRITEDATA5);
349
350         write_flash(ulSectorOff, BlockEraseVal);
351
352         if (poll_toggle_bit(ulSectorOff) < 0)
353                 return FLASH_FAIL;
354         printf(".");
355
356         return FLASH_SUCCESS;
357 }
358
359 void unlock_flash(long ulOffset)
360 {
361         unsigned long ulOffsetAddr = ulOffset;
362         ulOffsetAddr &= 0xFFFF0000;
363
364         write_flash((WRITESEQ1 | ulOffsetAddr), UNLOCKDATA1);
365         write_flash((WRITESEQ2 | ulOffsetAddr), UNLOCKDATA2);
366         write_flash((WRITESEQ3 | ulOffsetAddr), UNLOCKDATA3);
367 }
368
369 int get_codes()
370 {
371         int dev_id = 0;
372
373         write_flash(WRITESEQ1, GETCODEDATA1);
374         write_flash(WRITESEQ2, GETCODEDATA2);
375         write_flash(WRITESEQ3, GETCODEDATA3);
376
377         read_flash(0x0402, &dev_id);
378         dev_id &= 0x0000FFFF;
379
380         reset_flash();
381
382         return dev_id;
383 }
384
385 void get_sector_number(long ulOffset, int *pnSector)
386 {
387         int nSector = 0;
388         long lMainEnd = 0x400000;
389         long lBootEnd = 0x10000;
390
391         /* sector numbers for the FLASH A boot sectors */
392         if (ulOffset < lBootEnd) {
393                 nSector = (int)ulOffset / AFP_SectorSize1;
394         }
395         /* sector numbers for the FLASH B boot sectors */
396         else if ((ulOffset >= lBootEnd) && (ulOffset < lMainEnd)) {
397                 nSector = ((ulOffset / (AFP_SectorSize2)) + 7);
398         }
399         /* if it is a valid sector, set it */
400         if ((nSector >= 0) && (nSector < AFP_NumSectors))
401                 *pnSector = nSector;
402
403 }