2 * flashutl.c - Flash Read/write/Erase routines
4 * Copyright 2005, Broadcom Corporation
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
12 * $Id: flashutl.c,v 1.8 2005/03/07 08:35:32 kanki Exp $
21 #define DECLARE_FLASHES
36 #define FLASH_TRIES 4000000 /* retry count */
37 #define CMD_ADDR ((unsigned long)0xFFFFFFFF)
39 /* 'which' param for block() */
43 #define FLASH_ADDR(off) ((unsigned long)flashutl_base + (off))
45 static chipcregs_t
*cc
;
48 char* flashutl_base
= NULL
;
49 flash_desc_t
* flashutl_desc
= NULL
;
50 flash_cmds_t
* flashutl_cmd
= NULL
;
52 static void scmd(uint16 cmd
, unsigned long off
);
53 static void cmd(uint16 cmd
, unsigned long off
);
54 static void flash_reset(void);
55 static int flash_poll(unsigned long off
, uint16 data
);
56 static unsigned long block(unsigned long addr
, int which
);
57 static int flash_erase(void);
58 static int flash_eraseblk(unsigned long off
);
59 static int flash_write(unsigned long off
, uint16
*src
, uint nbytes
);
60 static unsigned long flash_block_base(unsigned long off
);
61 static unsigned long flash_block_lim(unsigned long off
);
62 static chipcregs_t
*cc
;
64 /* Read the flash ID and set the globals */
66 sysFlashInit(char *flash_str
)
68 uint32 fltype
= PFLASH
;
69 uint16 flash_vendid
= 0;
70 uint16 flash_devid
= 0;
71 uint16
* flash
= (uint16
*)0xbfc00000;
73 struct sflash
*sflash
;
77 * Check for serial flash.
81 cc
= (chipcregs_t
*) sb_setcore(sbh
, SB_CC
, 0);
84 flash
= (uint16
*)0xbc000000;
85 fltype
= R_REG(&cc
->capabilities
) & CAP_FLASH_MASK
;
87 if (fltype
== SFLASH_ST
|| fltype
== SFLASH_AT
) {
88 sflash
= sflash_init(cc
);
89 flashutl_cmd
= &sflash_cmd_t
;
90 flashutl_desc
= &sflash_desc
;
91 flashutl_desc
->size
= sflash
->size
;
93 sprintf(flash_str
, "SFLASH %d kB", sflash
->size
/1024);
98 flashutl_base
= (uint8
*)flash
;
101 * Parallel flash support
102 * Some flashes have different unlock addresses, try each it turn
104 idx
= sizeof(flash_cmds
)/sizeof(flash_cmds_t
) - 2;
105 flashutl_cmd
= &flash_cmds
[idx
--];
106 while((fltype
== PFLASH
) && flashutl_cmd
->type
) {
108 if (flashutl_cmd
->read_id
)
109 cmd(flashutl_cmd
->read_id
, CMD_ADDR
);
112 flash_vendid
= *(flash
+ 1);
113 flash_devid
= *flash
;
115 flash_vendid
= *flash
;
116 flash_devid
= *(flash
+ 1);
120 if ((flash_vendid
== 1) && (flash_devid
== 0x227e)) {
123 flash_devid
= *(flash
+0xe);
125 flash_devid
= *(flash
+0xf);
129 flashutl_desc
= flashes
;
130 while (flashutl_desc
->mfgid
!= 0 &&
131 !(flashutl_desc
->mfgid
== flash_vendid
&&
132 flashutl_desc
->devid
== flash_devid
)) {
135 if (flashutl_desc
->mfgid
!= 0)
138 flashutl_cmd
= &flash_cmds
[idx
--];
141 if (flashutl_desc
->mfgid
== 0) {
142 flashutl_desc
= NULL
;
145 flashutl_cmd
= flash_cmds
;
146 while (flashutl_cmd
->type
!= 0 && flashutl_cmd
->type
!= flashutl_desc
->type
)
148 if (flashutl_cmd
->type
== 0)
152 if (flashutl_cmd
!= NULL
) {
156 if (flashutl_desc
== NULL
) {
158 sprintf(flash_str
, "UNKNOWN 0x%x 0x%x", flash_vendid
, flash_devid
);
159 DPRINT(("Flash type UNKNOWN\n"));
164 strcpy(flash_str
, flashutl_desc
->desc
);
165 DPRINT(("Flash type \"%s\"\n", flashutl_desc
->desc
));
173 unsigned long size
= flashutl_desc
->size
;
177 for (addr
= 0; addr
< size
; addr
= block(addr
, BLOCK_LIM
)) {
178 err
= flash_eraseblk(addr
);
186 flash_eraseblk(unsigned long addr
)
191 a
= (unsigned long)addr
;
192 if (a
>= flashutl_desc
->size
)
195 a
= block(a
, BLOCK_BASE
);
197 /* Ensure blocks are unlocked (for intel chips)*/
198 if (flashutl_cmd
->type
== BSC
) {
199 scmd((unsigned char)INTEL_UNLOCK1
, a
);
200 scmd((unsigned char)INTEL_UNLOCK2
, a
);
203 if (flashutl_cmd
->pre_erase
)
204 cmd(flashutl_cmd
->pre_erase
, CMD_ADDR
);
205 if (flashutl_cmd
->erase_block
)
206 cmd(flashutl_cmd
->erase_block
, a
);
207 if (flashutl_cmd
->confirm
)
208 scmd(flashutl_cmd
->confirm
, a
);
210 st
= flash_poll(a
, 0xffff);
215 DPRINT(("Erase of block 0x%08lx-0x%08lx failed\n",
216 a
, block((unsigned long)addr
, BLOCK_LIM
)));
220 DPRINT(("Erase of block 0x%08lx-0x%08lx done", a
, block((unsigned long)addr
, BLOCK_LIM
)));
226 flash_write(unsigned long off
, uint16
*src
, uint nbytes
)
233 ASSERT(flashutl_desc
!= NULL
);
235 if (off
>= flashutl_desc
->size
)
238 dest
= (uint16
*)FLASH_ADDR(off
);
242 if((nbytes
% 40000)==0)
246 for(cnts
=0;cnts
<10000;cnts
++);
247 if(k
==1)k
=0;else k
=1;
250 if ((flashutl_desc
->type
== SCS
) &&
251 flashutl_cmd
->write_buf
&&
252 ((off
& (WBUFSIZE
- 1)) == 0)) {
253 /* issue write command */
254 if (flashutl_cmd
->write_buf
)
255 cmd(flashutl_cmd
->write_buf
, off
);
256 if ((st
= flash_poll(off
, DONE
)))
259 len
= MIN(nbytes
, WBUFSIZE
);
262 /* write (length - 1) */
263 cmd((len
/ 2) - 1, off
);
266 for (i
= 0; i
< len
; i
+= 2, dest
++, src
++)
270 * BCM4710 endianness is word consistent but
271 * byte/short scrambled. This write buffer
272 * mechanism appears to be sensitive to the
273 * order of the addresses hence we need to
274 * unscramble them. We may also need to pad
275 * the source with two bytes of 0xffff in case
276 * an odd number of shorts are presented.
279 /* write (padded length - 1) */
280 cmd((ROUNDUP(len
, 4) / 2) - 1, off
);
282 /* write data (plus pad if necessary) */
283 for (i
= 0; i
< ROUNDUP(len
, 4); i
+= 4, dest
+= 2, src
+= 2) {
284 *(dest
+ 1) = ((i
+ 2) < len
) ? *(src
+ 1) : 0xffff;
290 if (flashutl_cmd
->confirm
)
291 cmd(flashutl_cmd
->confirm
, off
);
293 if ((st
= flash_poll(off
, DONE
)))
296 /* issue write command */
297 if (flashutl_cmd
->write_word
)
298 cmd(flashutl_cmd
->write_word
, CMD_ADDR
);
301 len
= MIN(nbytes
, 2);
306 if ((st
= flash_poll(off
, data
)))
320 flash_block_base(unsigned long off
)
322 return block(off
, BLOCK_BASE
);
326 flash_block_lim(unsigned long off
)
328 return block(off
, BLOCK_LIM
);
331 /* Writes a single command to the flash. */
333 scmd(uint16 cmd
, unsigned long off
)
335 ASSERT(flashutl_base
!= NULL
);
337 /* cmd |= cmd << 8; */
339 *(uint16
*)(flashutl_base
+ off
) = cmd
;
342 /* Writes a command to flash, performing an unlock if needed. */
344 cmd(uint16 cmd
, unsigned long off
)
347 unlock_cmd_t
*ul
=NULL
;
348 unsigned long cmd_off
;
350 ASSERT(flashutl_cmd
!= NULL
);
352 switch (flashutl_cmd
->type
) {
354 ul
= &unlock_cmd_amd
;
358 ul
= &unlock_cmd_sst
;
366 if (flashutl_cmd
->need_unlock
) {
367 for (i
= 0; i
< UNLOCK_CMD_WORDS
; i
++)
368 *(uint16
*)(flashutl_base
+ ul
->addr
[i
]) = ul
->cmd
[i
];
371 /* cmd |= cmd << 8; */
380 *(uint16
*)(flashutl_base
+ off
) = cmd
;
386 ASSERT(flashutl_desc
!= NULL
);
388 if (flashutl_cmd
->clear_csr
)
389 scmd(flashutl_cmd
->clear_csr
, 0);
390 if (flashutl_cmd
->read_array
)
391 scmd(flashutl_cmd
->read_array
, 0);
395 flash_poll(unsigned long off
, uint16 data
)
397 volatile uint16
* addr
;
398 int cnt
= FLASH_TRIES
;
401 ASSERT(flashutl_desc
!= NULL
);
403 if (flashutl_desc
->type
== AMD
|| flashutl_desc
->type
== SST
) {
404 /* AMD style poll checkes the address being written */
405 addr
= (volatile uint16
*)FLASH_ADDR(off
);
406 while ((st
= *addr
) != data
&& cnt
!= 0)
409 DPRINT(("flash_poll: timeout, read 0x%x, expected 0x%x\n", st
, data
));
413 /* INTEL style poll is at second word of the block being written */
414 addr
= (volatile uint16
*)FLASH_ADDR(block(off
, BLOCK_BASE
));
416 while (((st
= *addr
) & DONE
) == 0 && cnt
!= 0)
419 DPRINT(("flash_poll: timeout, error status = 0x%x\n", st
));
428 block(unsigned long addr
, int which
)
430 unsigned long b
, l
, sb
;
434 ASSERT(flashutl_desc
!= NULL
);
435 ASSERT(addr
< (unsigned long)flashutl_desc
->size
);
437 b
= addr
/ flashutl_desc
->bsize
;
438 /* check for an address a full size block */
439 if (b
>= flashutl_desc
->ff
&& b
<= flashutl_desc
->lf
) {
440 if (which
== BLOCK_LIM
) b
++;
441 return (b
* flashutl_desc
->bsize
);
444 /* search for the sub-block */
445 if (flashutl_desc
->ff
== 0) {
446 /* sub blocks are at the end of the flash */
447 sb
= flashutl_desc
->bsize
* (flashutl_desc
->lf
+ 1);
449 /* sub blocks are at the start of the flash */
453 sblocks
= flashutl_desc
->subblocks
;
454 for (i
= 0; i
< flashutl_desc
->nsub
; i
++) {
456 l
= sb
+ sblocks
[i
+1];
457 if (addr
>= b
&& addr
< l
) {
458 if (which
== BLOCK_BASE
)
470 nvWrite(unsigned short *data
, unsigned int len
)
472 uint off
= flashutl_desc
->size
- NVRAM_SPACE
;
473 sysFlashWrite(off
, (uchar
*)data
, len
);
477 sysFlashErase(uint off
, unsigned int numbytes
)
479 unsigned long end
= off
+ numbytes
;
483 if (flashutl_cmd
->type
== SFLASH
) {
484 err
= sflash_commit(cc
, off
, numbytes
, NULL
);
491 err
= flash_eraseblk(off
);
494 off
= flash_block_lim(off
);
499 DPRINT(("Block erase at 0x%x failed\n", off
));
507 sysFlashWrite(uint off
, uchar
*src
, uint numbytes
)
511 DPRINT(("Writing 0x%x bytes to flash off @0x%x ...\n", (unsigned int)numbytes
, off
));
513 if (flashutl_cmd
->type
== SFLASH
)
514 err
= sflash_commit(cc
, off
, numbytes
, src
);
517 if (!sysFlashErase(off
, numbytes
))
519 err
= flash_write(off
, (uint16
*)src
, numbytes
);
523 DPRINT(("Flash write failed\n"));
525 DPRINT(("Flash write succeeded\n"));
531 sysFlashRead(uint off
, uchar
*buf
, uint numbytes
)
533 uint read
, total_read
=0;
536 if (flashutl_cmd
->type
== SFLASH
) {
538 read
= sflash_read(cc
, off
, numbytes
, buf
);
546 ASSERT(!(numbytes
& 1));
548 src
= (uint16
*)(flashutl_base
+ off
);