2 * flashutl.c - Flash Read/write/Erase routines
4 * Copyright (C) 2009, 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.46.2.1 2009/09/11 20:23:52 Exp $
18 #define DECLARE_FLASHES
29 #define ERR2 0x30 /* Mask for err UNUSED */
30 #define DONE 0x80 /* Mask for done */
31 #define WBUFSIZE 32 /* Write Buffer size */
32 #define FLASH_TRIES 4000000 /* retry count */
33 #define CMD_ADDR ((unsigned long)0xFFFFFFFF)
35 /* 'which' param for block() */
36 #define BLOCK_BASE 0 /* Base of block */
37 #define BLOCK_LIM 1 /* Limit of block */
39 #define FLASH_ADDR(off) ((unsigned long)flashutl_base + (off))
42 static si_t
*sih
= NULL
;
43 static chipcregs_t
*cc
= NULL
;
46 uint8
*flashutl_base
= NULL
;
47 flash_desc_t
*flashutl_desc
= NULL
;
48 flash_cmds_t
*flashutl_cmd
= NULL
;
49 uint8 flashutl_wsz
= sizeof(uint16
);
51 static void scmd(uint16 cmd
, unsigned long off
);
52 static void cmd(uint16 cmd
, unsigned long off
);
53 static void flash_reset(void);
54 static int flash_poll(unsigned long off
, uint16 data
);
55 static unsigned long block(unsigned long addr
, int which
);
56 static int flash_eraseblk(unsigned long off
);
57 static int flash_write(unsigned long off
, uint8
*src
, uint nbytes
);
58 static uint16 INLINE
flash_readword(unsigned long addr
);
59 static void INLINE
flash_writeword(unsigned long addr
, uint16 data
);
61 int sysFlashErase(uint off
, unsigned int numbytes
);
63 /* Read the flash ID and set the globals */
65 sysFlashInit(char *flash_str
)
68 uint32 fltype
= PFLASH
;
69 uint16 flash_vendid
= 0;
70 uint16 flash_devid
= 0;
72 struct sflash
*sflash
;
75 * Check for serial flash.
77 sih
= si_kattach(SI_OSH
);
82 cc
= (chipcregs_t
*)si_setcoreidx(sih
, SI_CC_IDX
);
85 flashutl_base
= (void *)OSL_UNCACHED((uintptr
)SI_FLASH2
);
87 fltype
= R_REG(osh
, &cc
->capabilities
) & CC_CAP_FLASH_MASK
;
88 if (fltype
== SFLASH_ST
|| fltype
== SFLASH_AT
) {
90 flashutl_base
= (void *)OSL_UNCACHED((uintptr
)SI_FLASH2
);
92 flashutl_base
= (void *)OSL_CACHED((uintptr
)SI_FLASH2
);
93 sflash
= sflash_init(sih
, cc
);
94 flashutl_cmd
= &sflash_cmd_t
;
95 flashutl_desc
= &sflash_desc
;
96 flashutl_desc
->size
= sflash
->size
;
98 sprintf(flash_str
, "SFLASH %d kB", sflash
->size
/1024);
102 flashutl_wsz
= (R_REG(osh
, &cc
->flash_config
) & CC_CFG_DS
) ? sizeof(uint16
) : sizeof(uint8
);
103 ASSERT(flashutl_wsz
== sizeof(uint8
) || flashutl_wsz
== sizeof(uint16
));
106 * Parallel flash support
107 * Some flashes have different unlock addresses, try each it turn
110 fltype
== PFLASH
&& idx
< ARRAYSIZE(flash_cmds
);
112 flashutl_cmd
= &flash_cmds
[idx
];
113 if (flashutl_cmd
->type
== OLD
)
116 if (flashutl_cmd
->read_id
) {
117 cmd(flashutl_cmd
->read_id
, CMD_ADDR
);
118 /* Delay for turn around time */
124 flash_vendid
= flash_readword(FLASH_ADDR(0)^6);
125 flash_devid
= flash_readword(FLASH_ADDR(2)^6);
126 #else /* !74K, bcm33xx */
127 flash_vendid
= flash_readword(FLASH_ADDR(2));
128 flash_devid
= flash_readword(FLASH_ADDR(0));
129 #endif /* BCMHND74K */
131 flash_vendid
= flash_readword(FLASH_ADDR(0));
132 flash_devid
= flash_readword(FLASH_ADDR(2));
135 /* Funky AMD, uses 3 byte device ID so use first byte (4th addr) to
136 * identify it is a 3-byte ID and use the next two bytes (5th & 6th addr)
137 * to form a word for unique identification of format xxyy, where
138 * xx = 5th addr and yy = 6th addr
140 if ((flash_vendid
== 1) &&
141 ((flash_devid
== 0x227e && flashutl_wsz
== sizeof(uint16
)) ||
142 (flash_devid
== 0x7e && flashutl_wsz
== sizeof(uint8
)))) {
144 uint16 flash_devid_5th
;
147 flash_devid_5th
= flash_readword(FLASH_ADDR(0x1c)^6) << 8;
148 flash_devid
= (flash_readword(FLASH_ADDR(0x1e)^6) & 0xff) | flash_devid_5th
;
149 #else /* !74K, bcm33xx */
150 flash_devid_5th
= flash_readword(FLASH_ADDR(0x1e)) << 8;
151 flash_devid
= (flash_readword(FLASH_ADDR(0x1c)) & 0xff) | flash_devid_5th
;
152 #endif /* BCMHND74K */
154 flash_devid_5th
= flash_readword(FLASH_ADDR(0x1c)) << 8;
155 flash_devid
= (flash_readword(FLASH_ADDR(0x1e)) & 0xff) | flash_devid_5th
;
159 flashutl_desc
= flashes
;
160 while (flashutl_desc
->mfgid
!= 0 &&
161 !(flashutl_desc
->mfgid
== flash_vendid
&&
162 flashutl_desc
->devid
== flash_devid
)) {
165 if (flashutl_desc
->mfgid
!= 0)
169 if (flashutl_desc
->mfgid
== 0) {
170 flashutl_desc
= NULL
;
173 flashutl_cmd
= flash_cmds
;
174 while (flashutl_cmd
->type
!= 0 && flashutl_cmd
->type
!= flashutl_desc
->type
)
176 if (flashutl_cmd
->type
== 0)
180 if (flashutl_cmd
!= NULL
) {
184 if (flashutl_desc
== NULL
) {
186 sprintf(flash_str
, "UNKNOWN 0x%x 0x%x", flash_vendid
, flash_devid
);
187 DPRINT(("Flash type UNKNOWN\n"));
192 strcpy(flash_str
, flashutl_desc
->desc
);
193 DPRINT(("Flash type \"%s\"\n", flashutl_desc
->desc
));
199 flash_eraseblk(unsigned long addr
)
204 a
= (unsigned long)addr
;
205 if (a
>= flashutl_desc
->size
)
208 a
= block(a
, BLOCK_BASE
);
210 /* Ensure blocks are unlocked (for intel chips) */
211 if (flashutl_cmd
->type
== BSC
) {
212 scmd((unsigned char)INTEL_UNLOCK1
, a
);
213 scmd((unsigned char)INTEL_UNLOCK2
, a
);
216 if (flashutl_cmd
->pre_erase
)
217 cmd(flashutl_cmd
->pre_erase
, CMD_ADDR
);
218 if (flashutl_cmd
->erase_block
)
219 cmd(flashutl_cmd
->erase_block
, a
);
220 if (flashutl_cmd
->confirm
)
221 scmd(flashutl_cmd
->confirm
, a
);
223 if (flashutl_wsz
== sizeof(uint8
))
224 st
= flash_poll(a
, 0xff);
226 st
= flash_poll(a
, 0xffff);
231 DPRINT(("Erase of block 0x%08lx-0x%08lx failed\n",
232 a
, block((unsigned long)addr
, BLOCK_LIM
)));
236 DPRINT(("Erase of block 0x%08lx-0x%08lx done\n", a
, block((unsigned long)addr
, BLOCK_LIM
)));
242 flash_write(unsigned long off
, uint8
*src
, uint nbytes
)
248 ASSERT(flashutl_desc
!= NULL
);
250 if (off
>= flashutl_desc
->size
)
253 ASSERT(!(off
& (flashutl_wsz
- 1)));
255 dest
= (uint8
*)FLASH_ADDR(off
);
259 if ((flashutl_desc
->type
== SCS
) &&
260 flashutl_cmd
->write_buf
&&
261 ((off
& (WBUFSIZE
- 1)) == 0)) {
262 /* issue write command */
263 if (flashutl_cmd
->write_buf
)
264 cmd(flashutl_cmd
->write_buf
, off
);
265 if ((st
= flash_poll(off
, DONE
)))
268 len
= MIN(nbytes
, WBUFSIZE
);
271 /* write (length - 1) */
272 cmd(len
/ sizeof(uint16
) - 1, off
);
275 for (i
= 0; i
< len
; i
+= sizeof(uint16
),
276 dest
+= sizeof(uint16
), src
+= sizeof(uint16
))
277 *(uint16
*)dest
= *(uint16
*)src
;
280 * BCM4710 endianness is word consistent but
281 * byte/short scrambled. This write buffer
282 * mechanism appears to be sensitive to the
283 * order of the addresses hence we need to
284 * unscramble them. We may also need to pad
285 * the source with two bytes of 0xffff in case
286 * an odd number of shorts are presented.
289 /* write (padded length - 1) */
290 cmd((ROUNDUP(len
, sizeof(uint32
)) / sizeof(uint16
)) - 1, off
);
292 /* write data (plus pad if necessary) */
293 for (i
= 0; i
< ROUNDUP(len
, sizeof(uint32
)); i
+= sizeof(uint32
),
294 dest
+= sizeof(uint32
), src
+= sizeof(uint32
)) {
295 *((uint16
*)dest
+ 1) = ((i
+ sizeof(uint16
)) < len
) ?
296 *((uint16
*)src
+ 1) : 0xffff;
297 *(uint16
*)dest
= *(uint16
*)src
;
302 if (flashutl_cmd
->confirm
)
303 cmd(flashutl_cmd
->confirm
, off
);
305 if ((st
= flash_poll(off
, DONE
)))
308 /* issue write command */
309 if (flashutl_cmd
->write_word
)
310 cmd(flashutl_cmd
->write_word
, CMD_ADDR
);
313 data
= flash_readword((unsigned long)src
);
314 flash_writeword((unsigned long)dest
, data
);
317 if ((st
= flash_poll(off
, data
)))
320 len
= MIN(nbytes
, flashutl_wsz
);
335 flash_readword(unsigned long addr
)
337 if (flashutl_wsz
== sizeof(uint8
))
338 return *(uint8
*)addr
;
340 return *(uint16
*)addr
;
344 flash_writeword(unsigned long addr
, uint16 data
)
346 if (flashutl_wsz
== sizeof(uint8
))
347 *(uint8
*)addr
= (uint8
)data
;
349 *(uint16
*)addr
= data
;
352 /* Writes a single command to the flash. */
354 scmd(uint16 cmd
, unsigned long off
)
356 /* cmd |= cmd << 8; */
358 flash_writeword(FLASH_ADDR(off
), cmd
);
361 /* Writes a command to flash, performing an unlock if needed. */
363 cmd(uint16 cmd
, unsigned long off
)
366 unlock_cmd_t
*ul
= NULL
;
368 ASSERT(flashutl_cmd
!= NULL
);
370 switch (flashutl_cmd
->type
) {
372 ul
= &unlock_cmd_amd
;
375 ul
= &unlock_cmd_sst
;
381 if (flashutl_cmd
->need_unlock
) {
383 for (i
= 0; i
< UNLOCK_CMD_WORDS
; i
++)
384 flash_writeword(FLASH_ADDR(ul
->addr
[i
]), ul
->cmd
[i
]);
387 /* cmd |= cmd << 8; */
389 if (off
== CMD_ADDR
) {
390 switch (flashutl_cmd
->type
) {
406 #else /* !74K, bcm33xx */
408 #endif /* BCMHND74K */
411 flash_writeword(FLASH_ADDR(off
), cmd
);
417 ASSERT(flashutl_cmd
!= NULL
);
419 if (flashutl_cmd
->clear_csr
)
420 scmd(flashutl_cmd
->clear_csr
, 0);
421 if (flashutl_cmd
->read_array
)
422 scmd(flashutl_cmd
->read_array
, 0);
426 flash_poll(unsigned long off
, uint16 data
)
429 int cnt
= FLASH_TRIES
;
432 ASSERT(flashutl_desc
!= NULL
);
434 if (flashutl_desc
->type
== AMD
|| flashutl_desc
->type
== SST
) {
435 /* AMD style poll checkes the address being written */
436 addr
= FLASH_ADDR(off
);
437 while ((st
= flash_readword(addr
)) != data
&& cnt
!= 0) {
442 DPRINT(("flash_poll: timeout, off %lx, read 0x%x, expected 0x%x\n",
447 /* INTEL style poll is at second word of the block being written */
448 addr
= FLASH_ADDR(block(off
, BLOCK_BASE
)+sizeof(uint16
));
449 while (((st
= flash_readword(addr
)) & DONE
) == 0 && cnt
!= 0) {
454 DPRINT(("flash_poll: timeout, error status = 0x%x\n", st
));
463 block(unsigned long addr
, int which
)
465 unsigned long b
, l
, sb
;
469 ASSERT(flashutl_desc
!= NULL
);
471 ASSERT(addr
< (unsigned long)flashutl_desc
->size
);
473 b
= addr
/ flashutl_desc
->bsize
;
474 /* check for an address a full size block */
475 if (b
>= flashutl_desc
->ff
&& b
<= flashutl_desc
->lf
) {
476 if (which
== BLOCK_LIM
) b
++;
477 return (b
* flashutl_desc
->bsize
);
480 /* search for the sub-block */
481 if (flashutl_desc
->ff
== 0) {
482 /* sub blocks are at the end of the flash */
483 sb
= flashutl_desc
->bsize
* (flashutl_desc
->lf
+ 1);
485 /* sub blocks are at the start of the flash */
489 sblocks
= flashutl_desc
->subblocks
;
490 for (i
= 0; i
< flashutl_desc
->nsub
; i
++) {
492 l
= sb
+ sblocks
[i
+1];
493 if (addr
>= b
&& addr
< l
) {
494 if (which
== BLOCK_BASE
)
505 nvWrite(unsigned short *data
, unsigned int len
)
507 uint off
= flashutl_desc
->size
- NVRAM_SPACE
;
508 sysFlashWrite(off
, (uchar
*)data
, len
);
512 nvWriteChars(unsigned char *data
, unsigned int len
)
514 uint off
= flashutl_desc
->size
- NVRAM_SPACE
;
517 if (flashutl_cmd
->type
== SFLASH
)
518 err
= sflash_commit(sih
, cc
, off
, len
, data
);
520 err
= flash_write(off
, data
, len
);
523 DPRINT(("nvWriteChars failed\n"));
525 DPRINT(("nvWriteChars succeeded\n"));
529 sysFlashErase(uint off
, unsigned int numbytes
)
531 unsigned long end
= off
+ numbytes
;
534 if (flashutl_cmd
->type
== SFLASH
) {
535 err
= sflash_commit(sih
, cc
, off
, numbytes
, NULL
);
538 err
= flash_eraseblk(off
);
541 off
= block(off
, BLOCK_LIM
);
546 DPRINT(("Block erase at 0x%x failed\n", off
));
554 sysFlashWrite(uint off
, uchar
*src
, uint numbytes
)
558 DPRINT(("Writing 0x%x bytes to flash @0x%x ...\n", (unsigned int)numbytes
, off
));
560 if (flashutl_cmd
->type
== SFLASH
)
561 err
= sflash_commit(sih
, cc
, off
, numbytes
, src
);
563 if (!sysFlashErase(off
, numbytes
))
565 err
= flash_write(off
, src
, numbytes
);
569 DPRINT(("Flash write failed\n"));
571 DPRINT(("Flash write succeeded\n"));
577 sysFlashRead(uint off
, uchar
*buf
, uint numbytes
)
579 uint read
, total_read
= 0;
581 if (flashutl_cmd
->type
== SFLASH
) {
583 read
= sflash_read(sih
, cc
, off
, numbytes
, buf
);
590 ASSERT(!(off
& (flashutl_wsz
- 1)));
591 ASSERT(!(numbytes
& (flashutl_wsz
- 1)));
594 flash_writeword((unsigned long)buf
, flash_readword(FLASH_ADDR(off
)));
595 numbytes
-= flashutl_wsz
;
598 total_read
+= flashutl_wsz
;