1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2000-2003
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6 * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
7 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
14 #include <asm/immap.h>
16 #ifndef CONFIG_SYS_FLASH_CFI
17 typedef unsigned short FLASH_PORT_WIDTH;
18 typedef volatile unsigned short FLASH_PORT_WIDTHV;
20 #define FPW FLASH_PORT_WIDTH
21 #define FPWV FLASH_PORT_WIDTHV
23 #define FLASH_CYCLE1 0x5555
24 #define FLASH_CYCLE2 0x2aaa
26 #define SYNC __asm__("nop")
28 /*-----------------------------------------------------------------------
32 ulong flash_get_size(FPWV * addr, flash_info_t * info);
33 int flash_get_offsets(ulong base, flash_info_t * info);
34 int write_word(flash_info_t * info, FPWV * dest, u16 data);
35 static inline void spin_wheel(void);
37 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
39 ulong flash_init(void)
44 fbase = (ulong) CONFIG_SYS_FLASH_BASE;
45 flash_get_size((FPWV *) fbase, &flash_info[0]);
46 flash_get_offsets((ulong) fbase, &flash_info[0]);
47 fbase += flash_info[0].size;
48 size += flash_info[0].size;
50 /* Protect monitor and environment sectors */
51 flash_protect(FLAG_PROTECT_SET,
52 CONFIG_SYS_MONITOR_BASE,
53 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]);
58 int flash_get_offsets(ulong base, flash_info_t * info)
62 if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
64 info->start[0] = base;
66 for (i = 1; i < CONFIG_SYS_SST_SECT; i++) {
67 info->start[i] = info->start[i - 1]
68 + CONFIG_SYS_SST_SECTSZ;
76 void flash_print_info(flash_info_t * info)
80 switch (info->flash_id & FLASH_VENDMASK) {
85 printf("Unknown Vendor ");
89 switch (info->flash_id & FLASH_TYPEMASK) {
91 printf("SST39VF6401B\n");
94 printf("Unknown Chip Type\n");
98 if (info->size > 0x100000) {
101 printf(" Size: %ld", info->size >> 20);
103 remainder = (info->size % 0x100000);
106 remainder = (int)((float)
107 (((float)remainder / (float)1024) *
109 printf(".%d ", remainder);
112 printf("MB in %d Sectors\n", info->sector_count);
114 printf(" Size: %ld KB in %d Sectors\n",
115 info->size >> 10, info->sector_count);
117 printf(" Sector Start Addresses:");
118 for (i = 0; i < info->sector_count; ++i) {
122 info->start[i], info->protect[i] ? " (RO)" : " ");
128 * The following code cannot be run from FLASH!
130 ulong flash_get_size(FPWV * addr, flash_info_t * info)
134 addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA; /* for Atmel, Intel ignores this */
135 addr[FLASH_CYCLE2] = (FPWV) 0x00550055; /* for Atmel, Intel ignores this */
136 addr[FLASH_CYCLE1] = (FPWV) 0x00900090; /* selects Intel or Atmel */
138 switch (addr[0] & 0xffff) {
139 case (u8) SST_MANUFACT:
140 info->flash_id = FLASH_MAN_SST;
144 printf("Unknown Flash\n");
145 info->flash_id = FLASH_UNKNOWN;
146 info->sector_count = 0;
149 *addr = (FPW) 0x00F000F0;
150 return (0); /* no or unknown flash */
154 case (u16) SST_ID_xF6401B:
155 info->flash_id += FLASH_SST6401B;
158 info->flash_id = FLASH_UNKNOWN;
162 info->sector_count = 0;
164 info->sector_count = CONFIG_SYS_SST_SECT;
165 info->size = CONFIG_SYS_SST_SECT * CONFIG_SYS_SST_SECTSZ;
168 *addr = (FPWV) 0x00F000F0;
170 if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
171 printf("** ERROR: sector count %d > max (%d) **\n",
172 info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
173 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
179 int flash_erase(flash_info_t * info, int s_first, int s_last)
182 int flag, prot, sect, count;
184 int rcode = 0, flashtype = 0;
186 if ((s_first < 0) || (s_first > s_last)) {
187 if (info->flash_id == FLASH_UNKNOWN)
188 printf("- missing\n");
190 printf("- no sectors to erase\n");
194 type = (info->flash_id & FLASH_VENDMASK);
201 type = (info->flash_id & FLASH_VENDMASK);
202 printf("Can't erase unknown flash type %08lx - aborted\n",
208 for (sect = s_first; sect <= s_last; ++sect) {
209 if (info->protect[sect]) {
215 printf("- Warning: %d protected sectors will not be erased!\n",
220 flag = disable_interrupts();
222 start = get_timer(0);
224 if ((s_last - s_first) == (CONFIG_SYS_SST_SECT - 1)) {
226 addr = (FPWV *) info->start[0];
228 addr[FLASH_CYCLE1] = 0x00AA; /* unlock */
229 addr[FLASH_CYCLE2] = 0x0055; /* unlock */
230 addr[FLASH_CYCLE1] = 0x0080; /* erase mode */
231 addr[FLASH_CYCLE1] = 0x00AA; /* unlock */
232 addr[FLASH_CYCLE2] = 0x0055; /* unlock */
233 *addr = 0x0030; /* erase chip */
236 start = get_timer(0);
238 while ((*addr & 0x0080) != 0x0080) {
239 if (count++ > 0x10000) {
244 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
246 *addr = 0x00F0; /* reset to read mode */
252 *addr = 0x00F0; /* reset to read mode */
254 printf("\b. done\n");
260 } else if (prot == CONFIG_SYS_SST_SECT) {
265 /* Start erase on unprotected sectors */
266 for (sect = s_first; sect <= s_last; sect++) {
267 if (info->protect[sect] == 0) { /* not protected */
269 addr = (FPWV *) (info->start[sect]);
273 /* arm simple, non interrupt dependent timer */
274 start = get_timer(0);
279 FPWV *base; /* first address in bank */
281 flag = disable_interrupts();
283 base = (FPWV *) (CONFIG_SYS_FLASH_BASE); /* First sector */
285 base[FLASH_CYCLE1] = 0x00AA; /* unlock */
286 base[FLASH_CYCLE2] = 0x0055; /* unlock */
287 base[FLASH_CYCLE1] = 0x0080; /* erase mode */
288 base[FLASH_CYCLE1] = 0x00AA; /* unlock */
289 base[FLASH_CYCLE2] = 0x0055; /* unlock */
290 *addr = 0x0050; /* erase sector */
295 while ((*addr & 0x0080) != 0x0080) {
296 if (get_timer(start) >
297 CONFIG_SYS_FLASH_ERASE_TOUT) {
299 *addr = 0x00F0; /* reset to read mode */
306 *addr = 0x00F0; /* reset to read mode */
309 } /* switch (flashtype) */
320 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
326 if (info->flash_id == FLASH_UNKNOWN)
329 /* get lower word aligned address */
332 /* handle unaligned start bytes */
334 data = *((FPWV *) wp);
335 data = (data << 8) | *src;
337 if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
347 * handle word aligned part
350 data = *((FPWV *) src);
352 if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
359 if (count++ > 0x800) {
364 /* handle word aligned part */
366 /* handle word aligned part */
368 data = *((FPWV *) wp);
370 data = (data & 0x00FF) | (*src << 8);
372 if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
378 if (count++ > 0x800) {
390 /*-----------------------------------------------------------------------
391 * Write a word to Flash
392 * A word is 16 bits, whichever the bus width of the flash bank
393 * (not an individual chip) is.
398 * 2 - Flash not erased
400 int write_word(flash_info_t * info, FPWV * dest, u16 data)
404 int res = 0; /* result, assume success */
405 FPWV *base; /* first address in flash bank */
407 /* Check if Flash is (sufficiently) erased */
408 if ((*dest & (u8) data) != (u8) data) {
412 base = (FPWV *) (CONFIG_SYS_FLASH_BASE);
414 /* Disable interrupts which might cause a timeout here */
415 flag = disable_interrupts();
417 base[FLASH_CYCLE1] = (u8) 0x00AA00AA; /* unlock */
418 base[FLASH_CYCLE2] = (u8) 0x00550055; /* unlock */
419 base[FLASH_CYCLE1] = (u8) 0x00A000A0; /* selects program mode */
421 *dest = data; /* start programming the data */
423 /* re-enable interrupts if necessary */
427 start = get_timer(0);
429 /* data polling for D7 */
431 && (*dest & (u8) 0x00800080) != (data & (u8) 0x00800080)) {
432 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
433 *dest = (u8) 0x00F000F0; /* reset bank */
438 *dest++ = (u8) 0x00F000F0; /* reset bank */
443 static inline void spin_wheel(void)
446 static char w[] = "\\/-";
448 printf("\010%c", w[p]);
449 (++p == 3) ? (p = 0) : 0;