2 * U-boot - flash.c Flash driver for PSD4256GV
4 * Copyright (c) 2005-2007 Analog Devices Inc.
5 * This file is based on BF533EzFlash.c originally written by Analog Devices, Inc.
7 * (C) Copyright 2000-2004
8 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
10 * SPDX-License-Identifier: GPL-2.0+
14 #include "flash-defines.h"
16 int AFP_NumSectors
= 40;
17 long AFP_SectorSize1
= 0x10000;
18 int AFP_SectorSize2
= 0x4000;
20 void flash_reset(void)
25 unsigned long flash_get_size(ulong baseaddr
, flash_info_t
* info
, int bank_flag
)
28 static int FlagDev
= 1;
33 printf("Device ID of the Flash is %x\n", id
);
41 for (i
= PriFlashABegin
; i
< SecFlashABegin
; i
++)
42 info
->start
[i
] = (baseaddr
+ (i
* AFP_SectorSize1
));
43 info
->size
= 0x200000;
44 info
->sector_count
= 32;
47 info
->start
[0] = baseaddr
+ SecFlashASec1Off
;
48 info
->start
[1] = baseaddr
+ SecFlashASec2Off
;
49 info
->start
[2] = baseaddr
+ SecFlashASec3Off
;
50 info
->start
[3] = baseaddr
+ SecFlashASec4Off
;
52 info
->sector_count
= 4;
55 info
->start
[0] = baseaddr
+ SecFlashBSec1Off
;
56 info
->start
[1] = baseaddr
+ SecFlashBSec2Off
;
57 info
->start
[2] = baseaddr
+ SecFlashBSec3Off
;
58 info
->start
[3] = baseaddr
+ SecFlashBSec4Off
;
60 info
->sector_count
= 4;
66 unsigned long flash_init(void)
68 unsigned long size_b0
, size_b1
, size_b2
;
71 size_b0
= size_b1
= size_b2
= 0;
73 printf("Flash Memory Start 0x%x\n", CONFIG_SYS_FLASH_BASE
);
74 printf("Memory Map for the Flash\n");
75 printf("0x20000000 - 0x200FFFFF Flash A Primary (1MB)\n");
76 printf("0x20100000 - 0x201FFFFF Flash B Primary (1MB)\n");
77 printf("0x20200000 - 0x2020FFFF Flash A Secondary (64KB)\n");
78 printf("0x20280000 - 0x2028FFFF Flash B Secondary (64KB)\n");
79 printf("Please type command flinfo for information on Sectors \n");
81 for (i
= 0; i
< CONFIG_SYS_MAX_FLASH_BANKS
; ++i
) {
82 flash_info
[i
].flash_id
= FLASH_UNKNOWN
;
85 size_b0
= flash_get_size(CONFIG_SYS_FLASH0_BASE
, &flash_info
[0], 0);
86 size_b1
= flash_get_size(CONFIG_SYS_FLASH0_BASE
, &flash_info
[1], 1);
87 size_b2
= flash_get_size(CONFIG_SYS_FLASH0_BASE
, &flash_info
[2], 2);
89 if (flash_info
[0].flash_id
== FLASH_UNKNOWN
|| size_b0
== 0) {
90 printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
91 size_b0
, size_b0
>> 20);
94 (void)flash_protect(FLAG_PROTECT_SET
, CONFIG_SYS_FLASH0_BASE
,
95 (flash_info
[0].start
[2] - 1), &flash_info
[0]);
97 return (size_b0
+ size_b1
+ size_b2
);
100 void flash_print_info(flash_info_t
* info
)
104 if (info
->flash_id
== FLASH_UNKNOWN
) {
105 printf("missing or unknown FLASH type\n");
109 switch (info
->flash_id
) {
110 case FLASH_PSD4256GV
:
111 printf("ST Microelectronics ");
114 printf("Unknown Vendor: (0x%08lX) ", info
->flash_id
);
117 for (i
= 0; i
< info
->sector_count
; ++i
) {
121 info
->start
[i
], info
->protect
[i
] ? " (RO)" : " ");
127 int flash_erase(flash_info_t
* info
, int s_first
, int s_last
)
133 for (sect
= s_first
; sect
<= s_last
; ++sect
) {
134 if (info
->protect
[sect
])
139 printf("- Warning: %d protected sectors will not be erased!\n",
144 cnt
= s_last
- s_first
+ 1;
146 if (cnt
== FLASH_TOT_SECT
) {
147 printf("Erasing flash, Please Wait \n");
148 if (erase_flash() < 0) {
149 printf("Erasing flash failed \n");
153 printf("Erasing Flash locations, Please Wait\n");
154 for (i
= s_first
; i
<= s_last
; i
++) {
155 if (info
->protect
[i
] == 0) { /* not protected */
156 if (erase_block_flash(i
, info
->start
[i
]) < 0) {
157 printf("Error Sector erasing \n");
163 return FLASH_SUCCESS
;
166 int write_buff(flash_info_t
* info
, uchar
* src
, ulong addr
, ulong cnt
)
171 read_flash(addr
- 1 - CONFIG_SYS_FLASH_BASE
, &d
);
172 d
= (int)((d
& 0x00FF) | (*src
++ << 8));
173 ret
= write_data(addr
- 1, 2, (uchar
*) & d
);
174 if (ret
== FLASH_FAIL
)
175 return ERR_NOT_ERASED
;
176 ret
= write_data(addr
+ 1, cnt
- 1, src
);
178 ret
= write_data(addr
, cnt
, src
);
179 if (ret
== FLASH_FAIL
)
180 return ERR_NOT_ERASED
;
181 return FLASH_SUCCESS
;
184 int write_data(long lStart
, long lCount
, uchar
* pnData
)
187 unsigned long ulOffset
= lStart
- CONFIG_SYS_FLASH_BASE
;
197 for (i
= 0; i
< lCount
- 1; i
+= 2, ulOffset
+= 2) {
198 get_sector_number(ulOffset
, &nSector
);
199 read_flash(ulOffset
, &d
);
202 ("Flash not erased at offset 0x%lx Please erase to reprogram\n",
206 unlock_flash(ulOffset
);
207 d
= (int)(pnData
[i
] | pnData
[i
+ 1] << 8);
208 write_flash(ulOffset
, d
);
209 if (poll_toggle_bit(ulOffset
) < 0) {
210 printf("Error programming the flash \n");
213 if ((i
> 0) && (!(i
% AFP_SectorSize2
)))
217 get_sector_number(ulOffset
, &nSector
);
218 read_flash(ulOffset
, &d
);
221 ("Flash not erased at offset 0x%lx Please erase to reprogram\n",
225 unlock_flash(ulOffset
);
226 d
= (int)(pnData
[i
] | (d
& 0xFF00));
227 write_flash(ulOffset
, d
);
228 if (poll_toggle_bit(ulOffset
) < 0) {
229 printf("Error programming the flash \n");
233 return FLASH_SUCCESS
;
236 int read_data(long ulStart
, long lCount
, long lStride
, int *pnData
)
240 long ulOffset
= ulStart
;
243 int nLeftover
= lCount
% 4;
247 for (i
= 0; (i
< lCount
/ 4) && (i
< BUFFER_SIZE
); i
++) {
248 for (iShift
= 0, j
= 0; j
< iNumWords
; j
+= 2) {
249 if ((ulOffset
>= INVALIDLOCNSTART
)
250 && (ulOffset
< INVALIDLOCNEND
))
253 get_sector_number(ulOffset
, &nSector
);
254 read_flash(ulOffset
, &nLow
);
255 ulOffset
+= (lStride
* 2);
256 read_flash(ulOffset
, &nHi
);
257 ulOffset
+= (lStride
* 2);
258 pnData
[i
] = (nHi
<< 16) | nLow
;
262 if ((ulOffset
>= INVALIDLOCNSTART
)
263 && (ulOffset
< INVALIDLOCNEND
))
266 get_sector_number(ulOffset
, &nSector
);
267 read_flash(ulOffset
, &pnData
[i
]);
269 return FLASH_SUCCESS
;
272 int write_flash(long nOffset
, int nValue
)
276 addr
= (CONFIG_SYS_FLASH_BASE
+ nOffset
);
278 *(unsigned volatile short *)addr
= nValue
;
280 if (poll_toggle_bit(nOffset
) < 0)
282 return FLASH_SUCCESS
;
285 int read_flash(long nOffset
, int *pnValue
)
288 long addr
= (CONFIG_SYS_FLASH_BASE
+ nOffset
);
293 nValue
= *(volatile unsigned short *)addr
;
299 int poll_toggle_bit(long lOffset
)
302 unsigned long timeout
= 0xFFFFFFFF;
303 volatile unsigned long *FB
=
304 (volatile unsigned long *)(0x20000000 + lOffset
);
308 u1
= *(volatile unsigned short *)FB
;
309 u2
= *(volatile unsigned short *)FB
;
310 if ((u1
& 0x0040) == (u2
& 0x0040))
311 return FLASH_SUCCESS
;
312 if ((u2
& 0x0020) == 0x0000)
314 u1
= *(volatile unsigned short *)FB
;
315 if ((u2
& 0x0040) == (u1
& 0x0040))
316 return FLASH_SUCCESS
;
323 printf("Time out occured \n");
328 void reset_flash(void)
330 write_flash(WRITESEQ1
, RESET_VAL
);
331 /* Wait for 10 micro seconds */
335 int erase_flash(void)
337 write_flash(WRITESEQ1
, WRITEDATA1
);
338 write_flash(WRITESEQ2
, WRITEDATA2
);
339 write_flash(WRITESEQ3
, WRITEDATA3
);
340 write_flash(WRITESEQ4
, WRITEDATA4
);
341 write_flash(WRITESEQ5
, WRITEDATA5
);
342 write_flash(WRITESEQ6
, WRITEDATA6
);
344 if (poll_toggle_bit(0x0000) < 0)
347 write_flash(SecFlashAOff
+ WRITESEQ1
, WRITEDATA1
);
348 write_flash(SecFlashAOff
+ WRITESEQ2
, WRITEDATA2
);
349 write_flash(SecFlashAOff
+ WRITESEQ3
, WRITEDATA3
);
350 write_flash(SecFlashAOff
+ WRITESEQ4
, WRITEDATA4
);
351 write_flash(SecFlashAOff
+ WRITESEQ5
, WRITEDATA5
);
352 write_flash(SecFlashAOff
+ WRITESEQ6
, WRITEDATA6
);
354 if (poll_toggle_bit(SecFlashASec1Off
) < 0)
357 write_flash(PriFlashBOff
+ WRITESEQ1
, WRITEDATA1
);
358 write_flash(PriFlashBOff
+ WRITESEQ2
, WRITEDATA2
);
359 write_flash(PriFlashBOff
+ WRITESEQ3
, WRITEDATA3
);
360 write_flash(PriFlashBOff
+ WRITESEQ4
, WRITEDATA4
);
361 write_flash(PriFlashBOff
+ WRITESEQ5
, WRITEDATA5
);
362 write_flash(PriFlashBOff
+ WRITESEQ6
, WRITEDATA6
);
364 if (poll_toggle_bit(PriFlashBOff
) < 0)
367 write_flash(SecFlashBOff
+ WRITESEQ1
, WRITEDATA1
);
368 write_flash(SecFlashBOff
+ WRITESEQ2
, WRITEDATA2
);
369 write_flash(SecFlashBOff
+ WRITESEQ3
, WRITEDATA3
);
370 write_flash(SecFlashBOff
+ WRITESEQ4
, WRITEDATA4
);
371 write_flash(SecFlashBOff
+ WRITESEQ5
, WRITEDATA5
);
372 write_flash(SecFlashBOff
+ WRITESEQ6
, WRITEDATA6
);
374 if (poll_toggle_bit(SecFlashBOff
) < 0)
377 return FLASH_SUCCESS
;
380 int erase_block_flash(int nBlock
, unsigned long address
)
382 long ulSectorOff
= 0x0;
384 if ((nBlock
< 0) || (nBlock
> AFP_NumSectors
))
387 ulSectorOff
= (address
- CONFIG_SYS_FLASH_BASE
);
389 write_flash((WRITESEQ1
| ulSectorOff
), WRITEDATA1
);
390 write_flash((WRITESEQ2
| ulSectorOff
), WRITEDATA2
);
391 write_flash((WRITESEQ3
| ulSectorOff
), WRITEDATA3
);
392 write_flash((WRITESEQ4
| ulSectorOff
), WRITEDATA4
);
393 write_flash((WRITESEQ5
| ulSectorOff
), WRITEDATA5
);
395 write_flash(ulSectorOff
, BlockEraseVal
);
397 if (poll_toggle_bit(ulSectorOff
) < 0)
400 return FLASH_SUCCESS
;
403 void unlock_flash(long ulOffset
)
405 unsigned long ulOffsetAddr
= ulOffset
;
406 ulOffsetAddr
&= 0xFFFF0000;
408 write_flash((WRITESEQ1
| ulOffsetAddr
), UNLOCKDATA1
);
409 write_flash((WRITESEQ2
| ulOffsetAddr
), UNLOCKDATA2
);
410 write_flash((WRITESEQ3
| ulOffsetAddr
), UNLOCKDATA3
);
417 write_flash(WRITESEQ1
, GETCODEDATA1
);
418 write_flash(WRITESEQ2
, GETCODEDATA2
);
419 write_flash(WRITESEQ3
, GETCODEDATA3
);
421 read_flash(0x0002, &dev_id
);
429 void get_sector_number(long ulOffset
, int *pnSector
)
433 if (ulOffset
>= SecFlashAOff
) {
434 if ((ulOffset
< SecFlashASec1Off
)
435 && (ulOffset
< SecFlashASec2Off
)) {
437 } else if ((ulOffset
>= SecFlashASec2Off
)
438 && (ulOffset
< SecFlashASec3Off
)) {
440 } else if ((ulOffset
>= SecFlashASec3Off
)
441 && (ulOffset
< SecFlashASec4Off
)) {
443 } else if ((ulOffset
>= SecFlashASec4Off
)
444 && (ulOffset
< SecFlashAEndOff
)) {
447 } else if (ulOffset
>= SecFlashBOff
) {
448 if ((ulOffset
< SecFlashBSec1Off
)
449 && (ulOffset
< SecFlashBSec2Off
)) {
452 if ((ulOffset
< SecFlashBSec2Off
)
453 && (ulOffset
< SecFlashBSec3Off
)) {
456 if ((ulOffset
< SecFlashBSec3Off
)
457 && (ulOffset
< SecFlashBSec4Off
)) {
460 if ((ulOffset
< SecFlashBSec4Off
)
461 && (ulOffset
< SecFlashBEndOff
)) {
464 } else if ((ulOffset
>= PriFlashAOff
) && (ulOffset
< SecFlashAOff
)) {
465 nSector
= ulOffset
& 0xffff0000;
466 nSector
= ulOffset
>> 16;
467 nSector
= nSector
& 0x000ff;
470 if ((nSector
>= 0) && (nSector
< AFP_NumSectors
)) {