5 * Sangmoon Kim, Etin Systems, dogoil@etinsys.com.
7 * See file CREDITS for list of people who contributed to this
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 #include <asm/processor.h>
28 #include <asm/pci_io.h>
31 int (*do_flash_erase
)(flash_info_t
*, uint32_t, uint32_t);
32 int (*write_dword
)(flash_info_t
*, ulong
, uint64_t);
34 typedef uint64_t cfi_word
;
36 #define cfi_read(flash, addr) *((volatile cfi_word*)(flash->start[0] + addr))
38 #define cfi_write(flash, val, addr) \
39 move64((cfi_word*)&val, \
40 (cfi_word*)(flash->start[0] + addr))
42 #define CMD(x) ((((cfi_word)x)<<48)|(((cfi_word)x)<<32)|(((cfi_word)x)<<16)|(((cfi_word)x)))
44 static void write32(unsigned long addr
, uint32_t value
)
46 *(volatile uint32_t*)(addr
) = value
;
50 static uint32_t read32(unsigned long addr
)
53 value
= *(volatile uint32_t*)addr
;
58 static cfi_word
cfi_cmd(flash_info_t
*flash
, uint8_t cmd
, uint32_t addr
)
60 uint32_t base
= flash
->start
[0];
61 uint32_t val
=(cmd
<< 16) | cmd
;
63 write32(base
+ addr
, val
);
67 static uint16_t cfi_read_query(flash_info_t
*flash
, uint32_t addr
)
69 uint32_t base
= flash
->start
[0];
71 return (uint16_t)read32(base
+ addr
);
74 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
76 static void move64(uint64_t *src
, uint64_t *dest
)
78 asm volatile("lfd 0, 0(3)\n\t" /* fpr0 = *scr */
79 "stfd 0, 0(4)" /* *dest = fpr0 */
80 : : : "fr0" ); /* Clobbers fr0 */
84 static int cfi_write_dword(flash_info_t
*flash
, ulong dest
, cfi_word data
)
89 status
= cfi_read(flash
, dest
);
92 cfi_cmd(flash
, 0x40, 0);
93 cfi_write(flash
, data
, dest
);
96 start
= get_timer (0);
98 status
= cfi_read(flash
, dest
);
100 if(status
== CMD(0x80))
102 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {
103 cfi_cmd(flash
, 0xff, 0);
108 cfi_cmd(flash
, 0xff, 0);
113 static int jedec_write_dword (flash_info_t
*flash
, ulong dest
, cfi_word data
)
118 status
= cfi_read(flash
, dest
);
119 if(status
!= CMD(0xffff)) return 2;
121 cfi_cmd(flash
, 0xaa, 0x555);
122 cfi_cmd(flash
, 0x55, 0x2aa);
123 cfi_cmd(flash
, 0xa0, 0x555);
125 cfi_write(flash
, data
, dest
);
128 start
= get_timer (0);
130 while(status
!= data
) {
131 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
)
133 status
= cfi_read(flash
, dest
);
139 static __inline__
unsigned long get_msr(void)
142 __asm__
__volatile__ ("mfmsr %0" : "=r" (msr
) :);
146 static __inline__
void set_msr(unsigned long msr
)
148 __asm__
__volatile__ ("mtmsr %0" : : "r" (msr
));
151 int write_buff (flash_info_t
*flash
, uchar
*src
, ulong addr
, ulong cnt
)
156 uint8_t *t
= (uint8_t*)&data
;
157 unsigned long base
= flash
->start
[0];
160 if (flash
->flash_id
== FLASH_UNKNOWN
)
171 wp
= (addr
& ~7); /* get lower word aligned address */
174 data
= cfi_read(flash
, wp
);
176 l
= ( cnt
< (8-s
) ) ? cnt
: (8-s
);
177 for(i
= 0; i
< l
; i
++)
179 if ((rc
= write_dword(flash
, wp
, data
)) != 0)
186 for (i
= 0; i
< 8; i
++)
188 if ((rc
= write_dword(flash
, wp
, data
)) != 0)
199 data
= cfi_read(flash
, wp
);
200 for(i
= 0; i
< cnt
; i
++)
202 rc
= write_dword(flash
, wp
, data
);
208 static int cfi_erase_oneblock(flash_info_t
*flash
, uint32_t sect
)
212 ulong start
, last
, now
;
215 flag
= disable_interrupts();
217 sa
= (flash
->start
[sect
] - flash
->start
[0]);
218 write32(flash
->start
[sect
], 0x00200020);
219 write32(flash
->start
[sect
], 0x00d000d0);
225 start
= get_timer (0);
229 status
= cfi_read(flash
, sa
);
231 if (status
== CMD(0x80))
233 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
234 cfi_cmd(flash
, 0xff, 0);
235 printf ("Timeout\n");
239 if ((now
- last
) > 1000) {
245 cfi_cmd(flash
, 0xff, 0);
249 static int cfi_erase(flash_info_t
*flash
, uint32_t s_first
, uint32_t s_last
)
254 for (sect
= s_first
; sect
<= s_last
; sect
++) {
255 if (flash
->protect
[sect
] == 0) {
256 rc
= cfi_erase_oneblock(flash
, sect
);
257 if (rc
!= ERR_OK
) break;
264 static int jedec_erase(flash_info_t
*flash
, uint32_t s_first
, uint32_t s_last
)
270 ulong start
, last
, now
;
272 flag
= disable_interrupts();
274 cfi_cmd(flash
, 0xaa, 0x555);
275 cfi_cmd(flash
, 0x55, 0x2aa);
276 cfi_cmd(flash
, 0x80, 0x555);
277 cfi_cmd(flash
, 0xaa, 0x555);
278 cfi_cmd(flash
, 0x55, 0x2aa);
279 for ( sect
= s_first
; sect
<= s_last
; sect
++) {
280 if (flash
->protect
[sect
] == 0) {
281 sa
= flash
->start
[sect
] - flash
->start
[0];
282 write32(flash
->start
[sect
], 0x00300030);
292 start
= get_timer (0);
295 status
= cfi_read(flash
, sa
);
296 if (status
== CMD(0xffff))
299 if ((now
= get_timer(start
)) > CFG_FLASH_ERASE_TOUT
) {
300 printf ("Timeout\n");
304 if ((now
- last
) > 1000) {
311 cfi_cmd(flash
, 0xf0, 0);
318 int flash_erase (flash_info_t
*flash
, int s_first
, int s_last
)
323 if ((s_first
< 0) || (s_first
> s_last
)) {
324 if (flash
->flash_id
== FLASH_UNKNOWN
)
325 printf ("- missing\n");
327 printf ("- no sectors to erase\n");
328 return ERR_NOT_ERASED
;
330 if (flash
->flash_id
== FLASH_UNKNOWN
) {
331 printf ("Can't erase unknown flash type - aborted\n");
332 return ERR_NOT_ERASED
;
336 for (sect
= s_first
; sect
<= s_last
; sect
++)
337 if (flash
->protect
[sect
]) prot
++;
340 printf ("- Warning: %d protected sectors will not be erased!\n",
345 return do_flash_erase(flash
, s_first
, s_last
);
348 struct jedec_flash_info
{
349 const uint16_t mfr_id
;
350 const uint16_t dev_id
;
353 const int InterfaceDesc
;
354 const int NumEraseRegions
;
355 const ulong regions
[4];
358 #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
364 static const struct jedec_flash_info jedec_table
[] = {
366 mfr_id
: (uint16_t)AMD_MANUFACT
,
367 dev_id
: (uint16_t)AMD_ID_LV800T
,
368 name
: "AMD AM29LV800T",
371 regions
: {ERASEINFO(0x10000,15),
372 ERASEINFO(0x08000,1),
373 ERASEINFO(0x02000,2),
377 mfr_id
: (uint16_t)AMD_MANUFACT
,
378 dev_id
: (uint16_t)AMD_ID_LV800B
,
379 name
: "AMD AM29LV800B",
382 regions
: {ERASEINFO(0x10000,15),
383 ERASEINFO(0x08000,1),
384 ERASEINFO(0x02000,2),
388 mfr_id
: (uint16_t)AMD_MANUFACT
,
389 dev_id
: (uint16_t)AMD_ID_LV160T
,
390 name
: "AMD AM29LV160T",
393 regions
: {ERASEINFO(0x10000,31),
394 ERASEINFO(0x08000,1),
395 ERASEINFO(0x02000,2),
399 mfr_id
: (uint16_t)AMD_MANUFACT
,
400 dev_id
: (uint16_t)AMD_ID_LV160B
,
401 name
: "AMD AM29LV160B",
404 regions
: {ERASEINFO(0x04000,1),
405 ERASEINFO(0x02000,2),
406 ERASEINFO(0x08000,1),
407 ERASEINFO(0x10000,31)
410 mfr_id
: (uint16_t)AMD_MANUFACT
,
411 dev_id
: (uint16_t)AMD_ID_LV320T
,
412 name
: "AMD AM29LV320T",
415 regions
: {ERASEINFO(0x10000,63),
420 mfr_id
: (uint16_t)AMD_MANUFACT
,
421 dev_id
: (uint16_t)AMD_ID_LV320B
,
422 name
: "AMD AM29LV320B",
425 regions
: {ERASEINFO(0x02000,8),
426 ERASEINFO(0x10000,63)
431 static ulong
cfi_init(uint32_t base
, flash_info_t
*flash
)
442 flash
->start
[0] = base
;
443 cfi_cmd(flash
, 0xF0, 0);
444 cfi_cmd(flash
, 0x98, 0);
445 if ( !( cfi_read_query(flash
, 0x10) == 'Q' &&
446 cfi_read_query(flash
, 0x11) == 'R' &&
447 cfi_read_query(flash
, 0x12) == 'Y' )) {
448 cfi_cmd(flash
, 0xff, 0);
452 flash
->size
= 1 << cfi_read_query(flash
, 0x27);
454 block_count
= cfi_read_query(flash
, 0x2c);
455 primary
= cfi_read_query(flash
, 0x15);
456 if ( cfi_read_query(flash
, primary
+ 4) == 0x30)
457 reverse
= (cfi_read_query(flash
, 0x1) & 0x01);
459 reverse
= (cfi_read_query(flash
, primary
+15) == 3);
461 flash
->sector_count
= 0;
463 for ( block
= reverse
? block_count
- 1 : 0;
464 reverse
? block
>= 0 : block
< block_count
;
465 reverse
? block
-- : block
++) {
467 (cfi_read_query(flash
, 0x2d + block
*4+2) |
468 (cfi_read_query(flash
, 0x2d + block
*4+3) << 8)) << 8;
470 (cfi_read_query(flash
, 0x2d + block
*4+0) |
471 (cfi_read_query(flash
, 0x2d + block
*4+1) << 8)) + 1;
472 for(sector
= 0; sector
< sector_count
; sector
++) {
473 flash
->start
[flash
->sector_count
++] = base
+ offset
;
474 offset
+= sector_size
* 4;
477 mfr_id
= cfi_read_query(flash
, 0x00);
478 dev_id
= cfi_read_query(flash
, 0x01);
480 cfi_cmd(flash
, 0xff, 0);
482 flash
->flash_id
= (mfr_id
<< 16) | dev_id
;
484 for (sector
= 0; sector
< flash
->sector_count
; sector
++) {
485 write32(flash
->start
[sector
], 0x00600060);
486 write32(flash
->start
[sector
], 0x00d000d0);
488 cfi_cmd(flash
, 0xff, 0);
490 for (sector
= 0; sector
< flash
->sector_count
; sector
++)
491 flash
->protect
[sector
] = 0;
493 do_flash_erase
= cfi_erase
;
494 write_dword
= cfi_write_dword
;
499 static ulong
jedec_init(unsigned long base
, flash_info_t
*flash
)
502 int block
, block_count
;
505 flash
->start
[0] = base
;
506 cfi_cmd(flash
, 0xF0, 0x000);
507 cfi_cmd(flash
, 0xAA, 0x555);
508 cfi_cmd(flash
, 0x55, 0x2AA);
509 cfi_cmd(flash
, 0x90, 0x555);
510 mfr_id
= cfi_read_query(flash
, 0x000);
511 dev_id
= cfi_read_query(flash
, 0x0001);
512 cfi_cmd(flash
, 0xf0, 0x000);
514 for(i
=0; i
<sizeof(jedec_table
)/sizeof(struct jedec_flash_info
); i
++) {
515 if((jedec_table
[i
].mfr_id
== mfr_id
) &&
516 (jedec_table
[i
].dev_id
== dev_id
)) {
518 flash
->flash_id
= (mfr_id
<< 16) | dev_id
;
519 flash
->size
= 1 << jedec_table
[0].DevSize
;
521 block_count
= jedec_table
[i
].NumEraseRegions
;
523 flash
->sector_count
= 0;
524 for (block
= 0; block
< block_count
; block
++) {
525 int sector_size
= jedec_table
[i
].regions
[block
];
526 int sector_count
= (sector_size
& 0xff) + 1;
528 for (sector
=0; sector
<sector_count
; sector
++) {
529 flash
->start
[flash
->sector_count
++] =
531 offset
+= sector_size
* 4;
538 for (sector
= 0; sector
< flash
->sector_count
; sector
++)
539 flash
->protect
[sector
] = 0;
541 do_flash_erase
= jedec_erase
;
542 write_dword
= jedec_write_dword
;
547 inline void mtibat1u(unsigned int x
)
549 __asm__
__volatile__ ("mtspr 530, %0" :: "r" (x
));
552 inline void mtibat1l(unsigned int x
)
554 __asm__
__volatile__ ("mtspr 531, %0" :: "r" (x
));
557 inline void mtdbat1u(unsigned int x
)
559 __asm__
__volatile__ ("mtspr 538, %0" :: "r" (x
));
562 inline void mtdbat1l(unsigned int x
)
564 __asm__
__volatile__ ("mtspr 539, %0" :: "r" (x
));
567 unsigned long flash_init (void)
569 unsigned long size
= 0;
574 CONFIG_WRITE_WORD(ERCR3
, 0x0C00000C);
575 CONFIG_WRITE_WORD(ERCR4
, 0x0800000C);
577 set_msr(msr
& ~(MSR_IR
| MSR_DR
));
578 mtibat1l(0x70000000 | BATL_PP_10
| BATL_CACHEINHIBIT
);
579 mtibat1u(0x70000000 | BATU_BL_256M
| BATU_VS
| BATU_VP
);
580 mtdbat1l(0x70000000 | BATL_PP_10
| BATL_CACHEINHIBIT
);
581 mtdbat1u(0x70000000 | BATU_BL_256M
| BATU_VS
| BATU_VP
);
584 for (i
= 0; i
< CFG_MAX_FLASH_BANKS
; i
++)
585 flash_info
[i
].flash_id
= FLASH_UNKNOWN
;
586 size
= cfi_init(FLASH_BASE0_PRELIM
, &flash_info
[0]);
588 size
= jedec_init(FLASH_BASE0_PRELIM
, &flash_info
[0]);
590 if (flash_info
[0].flash_id
== FLASH_UNKNOWN
)
591 printf ("# Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
597 void flash_print_info (flash_info_t
*flash
)
603 volatile unsigned long *p
;
605 if (flash
->flash_id
== FLASH_UNKNOWN
) {
606 printf ("missing or unknown FLASH type\n");
610 if (flash
->flash_id
== FLASH_UNKNOWN
) {
611 printf ("missing or unknown FLASH type\n");
615 switch (((flash
->flash_id
) >> 16) & 0xff) {
633 printf ("Unknown Vendor ");
637 switch ((flash
->flash_id
) & 0xffff) {
638 case (uint16_t)AMD_ID_LV800T
:
639 printf ("AM29LV800T\n");
641 case (uint16_t)AMD_ID_LV800B
:
642 printf ("AM29LV800B\n");
644 case (uint16_t)AMD_ID_LV160T
:
645 printf ("AM29LV160T\n");
647 case (uint16_t)AMD_ID_LV160B
:
648 printf ("AM29LV160B\n");
650 case (uint16_t)AMD_ID_LV320T
:
651 printf ("AM29LV320T\n");
653 case (uint16_t)AMD_ID_LV320B
:
654 printf ("AM29LV320B\n");
656 case (uint16_t)INTEL_ID_28F800C3T
:
657 printf ("28F800C3T\n");
659 case (uint16_t)INTEL_ID_28F800C3B
:
660 printf ("28F800C3B\n");
662 case (uint16_t)INTEL_ID_28F160C3T
:
663 printf ("28F160C3T\n");
665 case (uint16_t)INTEL_ID_28F160C3B
:
666 printf ("28F160C3B\n");
668 case (uint16_t)INTEL_ID_28F320C3T
:
669 printf ("28F320C3T\n");
671 case (uint16_t)INTEL_ID_28F320C3B
:
672 printf ("28F320C3B\n");
674 case (uint16_t)INTEL_ID_28F640C3T
:
675 printf ("28F640C3T\n");
677 case (uint16_t)INTEL_ID_28F640C3B
:
678 printf ("28F640C3B\n");
681 printf ("Unknown Chip Type\n");
685 if (flash
->size
>= (1 << 20)) {
686 printf (" Size: %ld MB in %d Sectors\n",
687 flash
->size
>> 20, flash
->sector_count
);
689 printf (" Size: %ld kB in %d Sectors\n",
690 flash
->size
>> 10, flash
->sector_count
);
693 printf (" Sector Start Addresses:");
694 for (i
= 0; i
< flash
->sector_count
; ++i
) {
695 /* Check if whole sector is erased*/
696 if (i
!= (flash
->sector_count
-1))
697 size
= flash
->start
[i
+1] - flash
->start
[i
];
699 size
= flash
->start
[0] + flash
->size
- flash
->start
[i
];
702 p
= (volatile unsigned long *)flash
->start
[i
];
703 size
= size
>> 2; /* divide by 4 for longword access */
704 for (k
=0; k
<size
; k
++) {
705 if (*p
++ != 0xffffffff) {
714 printf (" %08lX%s%s",
717 flash
->protect
[i
] ? "RO " : " ");