source: SVN/rincon/u-boot/board/bf533-ezkit/flash.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 12.0 KB
Line 
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 <asm/io.h>
30#include "flash-defines.h"
31
32void flash_reset(void)
33{
34        reset_flash();
35}
36
37unsigned long flash_get_size(ulong baseaddr, flash_info_t * info, 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
78unsigned 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,
107                            (flash_info[0].start[2] - 1), &flash_info[0]);
108
109        return (size_b0 + size_b1 + size_b2);
110}
111
112void flash_print_info(flash_info_t * info)
113{
114        int i;
115
116        if (info->flash_id == FLASH_UNKNOWN) {
117                printf("missing or unknown FLASH type\n");
118                return;
119        }
120
121        switch (info->flash_id) {
122        case FLASH_PSD4256GV:
123                printf("ST Microelectronics ");
124                break;
125        default:
126                printf("Unknown Vendor: (0x%08X) ", info->flash_id);
127                break;
128        }
129        for (i = 0; i < info->sector_count; ++i) {
130                if ((i % 5) == 0)
131                        printf("\n   ");
132                printf(" %08lX%s",
133                       info->start[i], info->protect[i] ? " (RO)" : "     ");
134        }
135        printf("\n");
136        return;
137}
138
139int 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",
152                       prot);
153        else
154                printf("\n");
155
156        cnt = s_last - s_first + 1;
157
158        if (cnt == FLASH_TOT_SECT) {
159                printf("Erasing flash, Please Wait \n");
160                if (erase_flash() < 0) {
161                        printf("Erasing flash failed \n");
162                        return FLASH_FAIL;
163                }
164        } else {
165                printf("Erasing Flash locations, Please Wait\n");
166                for (i = s_first; i <= s_last; i++) {
167                        if (info->protect[i] == 0) {    /* not protected */
168                                if (erase_block_flash(i, info->start[i]) < 0) {
169                                        printf("Error Sector erasing \n");
170                                        return FLASH_FAIL;
171                                }
172                        }
173                }
174        }
175        return FLASH_SUCCESS;
176}
177
178int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
179{
180        int ret;
181        int d;
182        if (addr % 2) {
183                read_flash(addr - 1 - CFG_FLASH_BASE, &d);
184                d = (int)((d & 0x00FF) | (*src++ << 8));
185                ret = write_data(addr - 1, 2, (uchar *) & d);
186                if (ret == FLASH_FAIL)
187                        return ERR_NOT_ERASED;
188                ret = write_data(addr + 1, cnt - 1, src);
189        } else
190                ret = write_data(addr, cnt, src);
191        if (ret == FLASH_FAIL)
192                return ERR_NOT_ERASED;
193        return FLASH_SUCCESS;
194}
195
196int write_data(long lStart, long lCount, uchar * pnData)
197{
198        long i = 0;
199        unsigned long ulOffset = lStart - CFG_FLASH_BASE;
200        int d;
201        int nSector = 0;
202        int flag = 0;
203
204        if (lCount % 2) {
205                flag = 1;
206                lCount = lCount - 1;
207        }
208
209        for (i = 0; i < lCount - 1; i += 2, ulOffset += 2) {
210                get_sector_number(ulOffset, &nSector);
211                read_flash(ulOffset, &d);
212                if (d != 0xffff) {
213                        printf
214                            ("Flash not erased at offset 0x%x Please erase to reprogram \n",
215                             ulOffset);
216                        return FLASH_FAIL;
217                }
218                unlock_flash(ulOffset);
219                d = (int)(pnData[i] | pnData[i + 1] << 8);
220                write_flash(ulOffset, d);
221                if (poll_toggle_bit(ulOffset) < 0) {
222                        printf("Error programming the flash \n");
223                        return FLASH_FAIL;
224                }
225                if ((i > 0) && (!(i % AFP_SectorSize2)))
226                        printf(".");
227        }
228        if (flag) {
229                get_sector_number(ulOffset, &nSector);
230                read_flash(ulOffset, &d);
231                if (d != 0xffff) {
232                        printf
233                            ("Flash not erased at offset 0x%x Please erase to reprogram \n",
234                             ulOffset);
235                        return FLASH_FAIL;
236                }
237                unlock_flash(ulOffset);
238                d = (int)(pnData[i] | (d & 0xFF00));
239                write_flash(ulOffset, d);
240                if (poll_toggle_bit(ulOffset) < 0) {
241                        printf("Error programming the flash \n");
242                        return FLASH_FAIL;
243                }
244        }
245        return FLASH_SUCCESS;
246}
247
248int read_data(long ulStart, long lCount, long lStride, int *pnData)
249{
250        long i = 0;
251        int j = 0;
252        long ulOffset = ulStart;
253        int iShift = 0;
254        int iNumWords = 2;
255        int nLeftover = lCount % 4;
256        int nHi, nLow;
257        int nSector = 0;
258
259        for (i = 0; (i < lCount / 4) && (i < BUFFER_SIZE); i++) {
260                for (iShift = 0, j = 0; j < iNumWords; j += 2) {
261                        if ((ulOffset >= INVALIDLOCNSTART)
262                            && (ulOffset < INVALIDLOCNEND))
263                                return FLASH_FAIL;
264
265                        get_sector_number(ulOffset, &nSector);
266                        read_flash(ulOffset, &nLow);
267                        ulOffset += (lStride * 2);
268                        read_flash(ulOffset, &nHi);
269                        ulOffset += (lStride * 2);
270                        pnData[i] = (nHi << 16) | nLow;
271                }
272        }
273        if (nLeftover > 0) {
274                if ((ulOffset >= INVALIDLOCNSTART)
275                    && (ulOffset < INVALIDLOCNEND))
276                        return FLASH_FAIL;
277
278                get_sector_number(ulOffset, &nSector);
279                read_flash(ulOffset, &pnData[i]);
280        }
281        return FLASH_SUCCESS;
282}
283
284int write_flash(long nOffset, int nValue)
285{
286        long addr;
287
288        addr = (CFG_FLASH_BASE + nOffset);
289        SSYNC();
290        *(unsigned volatile short *)addr = nValue;
291        SSYNC();
292        if (poll_toggle_bit(nOffset) < 0)
293                return FLASH_FAIL;
294        return FLASH_SUCCESS;
295}
296
297int read_flash(long nOffset, int *pnValue)
298{
299        int nValue = 0x0;
300        long addr = (CFG_FLASH_BASE + nOffset);
301
302        if (nOffset != 0x2)
303                reset_flash();
304        SSYNC();
305        nValue = *(volatile unsigned short *)addr;
306        SSYNC();
307        *pnValue = nValue;
308        return TRUE;
309}
310
311int poll_toggle_bit(long lOffset)
312{
313        unsigned int u1, u2;
314        unsigned long timeout = 0xFFFFFFFF;
315        volatile unsigned long *FB =
316            (volatile unsigned long *)(0x20000000 + lOffset);
317        while (1) {
318                if (timeout < 0)
319                        break;
320                u1 = *(volatile unsigned short *)FB;
321                u2 = *(volatile unsigned short *)FB;
322                if ((u1 & 0x0040) == (u2 & 0x0040))
323                        return FLASH_SUCCESS;
324                if ((u2 & 0x0020) == 0x0000)
325                        continue;
326                u1 = *(volatile unsigned short *)FB;
327                if ((u2 & 0x0040) == (u1 & 0x0040))
328                        return FLASH_SUCCESS;
329                else {
330                        reset_flash();
331                        return FLASH_FAIL;
332                }
333                timeout--;
334        }
335        printf("Time out occured \n");
336        if (timeout < 0)
337                return FLASH_FAIL;
338}
339
340void reset_flash(void)
341{
342        write_flash(WRITESEQ1, RESET_VAL);
343        /* Wait for 10 micro seconds */
344        udelay(10);
345}
346
347int erase_flash(void)
348{
349        write_flash(WRITESEQ1, WRITEDATA1);
350        write_flash(WRITESEQ2, WRITEDATA2);
351        write_flash(WRITESEQ3, WRITEDATA3);
352        write_flash(WRITESEQ4, WRITEDATA4);
353        write_flash(WRITESEQ5, WRITEDATA5);
354        write_flash(WRITESEQ6, WRITEDATA6);
355
356        if (poll_toggle_bit(0x0000) < 0)
357                return FLASH_FAIL;
358
359        write_flash(SecFlashAOff + WRITESEQ1, WRITEDATA1);
360        write_flash(SecFlashAOff + WRITESEQ2, WRITEDATA2);
361        write_flash(SecFlashAOff + WRITESEQ3, WRITEDATA3);
362        write_flash(SecFlashAOff + WRITESEQ4, WRITEDATA4);
363        write_flash(SecFlashAOff + WRITESEQ5, WRITEDATA5);
364        write_flash(SecFlashAOff + WRITESEQ6, WRITEDATA6);
365
366        if (poll_toggle_bit(SecFlashASec1Off) < 0)
367                return FLASH_FAIL;
368
369        write_flash(PriFlashBOff + WRITESEQ1, WRITEDATA1);
370        write_flash(PriFlashBOff + WRITESEQ2, WRITEDATA2);
371        write_flash(PriFlashBOff + WRITESEQ3, WRITEDATA3);
372        write_flash(PriFlashBOff + WRITESEQ4, WRITEDATA4);
373        write_flash(PriFlashBOff + WRITESEQ5, WRITEDATA5);
374        write_flash(PriFlashBOff + WRITESEQ6, WRITEDATA6);
375
376        if (poll_toggle_bit(PriFlashBOff) < 0)
377                return FLASH_FAIL;
378
379        write_flash(SecFlashBOff + WRITESEQ1, WRITEDATA1);
380        write_flash(SecFlashBOff + WRITESEQ2, WRITEDATA2);
381        write_flash(SecFlashBOff + WRITESEQ3, WRITEDATA3);
382        write_flash(SecFlashBOff + WRITESEQ4, WRITEDATA4);
383        write_flash(SecFlashBOff + WRITESEQ5, WRITEDATA5);
384        write_flash(SecFlashBOff + WRITESEQ6, WRITEDATA6);
385
386        if (poll_toggle_bit(SecFlashBOff) < 0)
387                return FLASH_FAIL;
388
389        return FLASH_SUCCESS;
390}
391
392int erase_block_flash(int nBlock, unsigned long address)
393{
394        long ulSectorOff = 0x0;
395
396        if ((nBlock < 0) || (nBlock > AFP_NumSectors))
397                return FALSE;
398
399        ulSectorOff = (address - CFG_FLASH_BASE);
400
401        write_flash((WRITESEQ1 | ulSectorOff), WRITEDATA1);
402        write_flash((WRITESEQ2 | ulSectorOff), WRITEDATA2);
403        write_flash((WRITESEQ3 | ulSectorOff), WRITEDATA3);
404        write_flash((WRITESEQ4 | ulSectorOff), WRITEDATA4);
405        write_flash((WRITESEQ5 | ulSectorOff), WRITEDATA5);
406
407        write_flash(ulSectorOff, BlockEraseVal);
408
409        if (poll_toggle_bit(ulSectorOff) < 0)
410                return FLASH_FAIL;
411
412        return FLASH_SUCCESS;
413}
414
415void unlock_flash(long ulOffset)
416{
417        unsigned long ulOffsetAddr = ulOffset;
418        ulOffsetAddr &= 0xFFFF0000;
419
420        write_flash((WRITESEQ1 | ulOffsetAddr), UNLOCKDATA1);
421        write_flash((WRITESEQ2 | ulOffsetAddr), UNLOCKDATA2);
422        write_flash((WRITESEQ3 | ulOffsetAddr), UNLOCKDATA3);
423}
424
425int get_codes()
426{
427        int dev_id = 0;
428
429        write_flash(WRITESEQ1, GETCODEDATA1);
430        write_flash(WRITESEQ2, GETCODEDATA2);
431        write_flash(WRITESEQ3, GETCODEDATA3);
432
433        read_flash(0x0002, &dev_id);
434        dev_id &= 0x00FF;
435
436        reset_flash();
437
438        return dev_id;
439}
440
441void get_sector_number(long ulOffset, int *pnSector)
442{
443        int nSector = 0;
444
445        if (ulOffset >= SecFlashAOff) {
446                if ((ulOffset < SecFlashASec1Off)
447                    && (ulOffset < SecFlashASec2Off)) {
448                        nSector = SECT32;
449                } else if ((ulOffset >= SecFlashASec2Off)
450                           && (ulOffset < SecFlashASec3Off)) {
451                        nSector = SECT33;
452                } else if ((ulOffset >= SecFlashASec3Off)
453                           && (ulOffset < SecFlashASec4Off)) {
454                        nSector = SECT34;
455                } else if ((ulOffset >= SecFlashASec4Off)
456                           && (ulOffset < SecFlashAEndOff)) {
457                        nSector = SECT35;
458                }
459        } else if (ulOffset >= SecFlashBOff) {
460                if ((ulOffset < SecFlashBSec1Off)
461                    && (ulOffset < SecFlashBSec2Off)) {
462                        nSector = SECT36;
463                }
464                if ((ulOffset < SecFlashBSec2Off)
465                    && (ulOffset < SecFlashBSec3Off)) {
466                        nSector = SECT37;
467                }
468                if ((ulOffset < SecFlashBSec3Off)
469                    && (ulOffset < SecFlashBSec4Off)) {
470                        nSector = SECT38;
471                }
472                if ((ulOffset < SecFlashBSec4Off)
473                    && (ulOffset < SecFlashBEndOff)) {
474                        nSector = SECT39;
475                }
476        } else if ((ulOffset >= PriFlashAOff) && (ulOffset < SecFlashAOff)) {
477                nSector = ulOffset & 0xffff0000;
478                nSector = ulOffset >> 16;
479                nSector = nSector & 0x000ff;
480        }
481
482        if ((nSector >= 0) && (nSector < AFP_NumSectors)) {
483                *pnSector = nSector;
484        }
485}
Note: See TracBrowser for help on using the repository browser.