X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=board%2Fcmc_pu2%2Fflash.c;h=d832e6209f83f0f3e2a9d4323bfc28c83258a3be;hb=922d27b596c179c5a7d68abe45ede5adb1b6589c;hp=5220fcf5d96435ccc22c959bf08b136e7fe357af;hpb=2cbe571a5676a41aa32ff98e9b1a2934e3922574;p=u-boot diff --git a/board/cmc_pu2/flash.c b/board/cmc_pu2/flash.c index 5220fcf5d9..d832e6209f 100644 --- a/board/cmc_pu2/flash.c +++ b/board/cmc_pu2/flash.c @@ -1,11 +1,12 @@ /* - * (C) Copyright 2002 - * Lineo, Inc. - * Bernhard Kuhn + * (C) Copyright 2003-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH - * Alex Zuepke + * (C) Copyright 2004 + * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de + * + * Modified for the CMC PU2 by (C) Copyright 2004 Gary Jennejohn + * garyj@denx.de * * See file CREDITS for list of people who contributed to this * project. @@ -28,444 +29,352 @@ #include -ulong myflush(void); - - -/* Flash Organization Structure */ -typedef struct OrgDef -{ - unsigned int sector_number; - unsigned int sector_size; -} OrgDef; - - -/* Flash Organizations */ -OrgDef OrgAT49BV16x4[] = -{ - { 8, 8*1024 }, /* 8 * 8 kBytes sectors */ - { 2, 32*1024 }, /* 2 * 32 kBytes sectors */ - { 30, 64*1024 }, /* 30 * 64 kBytes sectors */ -}; - -OrgDef OrgAT49BV16x4A[] = -{ - { 8, 8*1024 }, /* 8 * 8 kBytes sectors */ - { 31, 64*1024 }, /* 31 * 64 kBytes sectors */ -}; - -OrgDef OrgAT49BV6416[] = -{ - { 8, 8*1024 }, /* 8 * 8 kBytes sectors */ - { 127, 64*1024 }, /* 127 * 64 kBytes sectors */ -}; - -flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; - -/* AT49BV1614A Codes */ -#define FLASH_CODE1 0xAA -#define FLASH_CODE2 0x55 -#define ID_IN_CODE 0x90 -#define ID_OUT_CODE 0xF0 - - -#define CMD_READ_ARRAY 0x00F0 -#define CMD_UNLOCK1 0x00AA -#define CMD_UNLOCK2 0x0055 -#define CMD_ERASE_SETUP 0x0080 -#define CMD_ERASE_CONFIRM 0x0030 -#define CMD_PROGRAM 0x00A0 -#define CMD_UNLOCK_BYPASS 0x0020 -#define CMD_SECTOR_UNLOCK 0x0070 +#ifndef CONFIG_ENV_ADDR +#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET) +#endif -#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00005555<<1))) -#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00002AAA<<1))) +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */ -#define BIT_ERASE_DONE 0x0080 -#define BIT_RDY_MASK 0x0080 -#define BIT_PROGRAM_ERROR 0x0020 -#define BIT_TIMEOUT 0x80000000 /* our flag */ +#define FLASH_CYCLE1 0x0555 +#define FLASH_CYCLE2 0x02AA -#define READY 1 -#define ERR 2 -#define TMO 4 +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size(vu_short *addr, flash_info_t *info); +static void flash_reset(flash_info_t *info); +static int write_word_amd(flash_info_t *info, vu_short *dest, ushort data); +static flash_info_t *flash_get_info(ulong base); /*----------------------------------------------------------------------- + * flash_init() + * + * sets up flash_info and returns size of FLASH (bytes) */ -void flash_identification (flash_info_t * info) +unsigned long flash_init (void) { - volatile u16 manuf_code, device_code, add_device_code; + unsigned long size = 0; + ulong flashbase = CONFIG_SYS_FLASH_BASE; - MEM_FLASH_ADDR1 = FLASH_CODE1; - MEM_FLASH_ADDR2 = FLASH_CODE2; - MEM_FLASH_ADDR1 = ID_IN_CODE; + /* Init: no FLASHes known */ + memset(&flash_info[0], 0, sizeof(flash_info_t)); - manuf_code = *(volatile u16 *) CFG_FLASH_BASE; - device_code = *(volatile u16 *) (CFG_FLASH_BASE + 2); - add_device_code = *(volatile u16 *) (CFG_FLASH_BASE + (3 << 1)); + flash_info[0].size = flash_get_size((vu_short *)flashbase, &flash_info[0]); - MEM_FLASH_ADDR1 = FLASH_CODE1; - MEM_FLASH_ADDR2 = FLASH_CODE2; - MEM_FLASH_ADDR1 = ID_OUT_CODE; + size = flash_info[0].size; - /* Vendor type */ - info->flash_id = ATM_MANUFACT & FLASH_VENDMASK; - printf ("Atmel: "); +#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_SYS_MONITOR_BASE, + CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1, + flash_get_info(CONFIG_SYS_MONITOR_BASE)); +#endif - if ((device_code & FLASH_TYPEMASK) == (ATM_ID_BV1614 & FLASH_TYPEMASK)) { - - if ((add_device_code & FLASH_TYPEMASK) == - (ATM_ID_BV1614A & FLASH_TYPEMASK)) { - info->flash_id |= ATM_ID_BV1614A & FLASH_TYPEMASK; - printf ("AT49BV1614A (16Mbit)\n"); - } else { /* AT49BV1614 Flash */ - info->flash_id |= ATM_ID_BV1614 & FLASH_TYPEMASK; - printf ("AT49BV1614 (16Mbit)\n"); - } +#ifdef CONFIG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_ENV_ADDR, + CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1, + flash_get_info(CONFIG_ENV_ADDR)); +#endif - } else if ((device_code & FLASH_TYPEMASK) == (ATM_ID_BV6416 & FLASH_TYPEMASK)) { - info->flash_id |= ATM_ID_BV6416 & FLASH_TYPEMASK; - printf ("AT49BV6416 (64Mbit)\n"); - } -} - -ushort flash_number_sector(OrgDef *pOrgDef, unsigned int nb_blocks) -{ - int i, nb_sectors = 0; - - for (i=0; istart[sector]); + vu_short *base = (vu_short *)(info->start[0]); - MEM_FLASH_ADDR1 = CMD_UNLOCK1; - *addr = CMD_SECTOR_UNLOCK; + /* Put FLASH back in read mode */ + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) + *base = 0x00FF; /* Intel Read Mode */ + else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) + *base = 0x00F0; /* AMD Read Mode */ } +/*----------------------------------------------------------------------- + */ -ulong flash_init (void) +static flash_info_t *flash_get_info(ulong base) { - int i, j, k; - unsigned int flash_nb_blocks, sector; - unsigned int start_address; - OrgDef *pOrgDef; - - ulong size = 0; - - for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { - ulong flashbase = 0; - - flash_identification (&flash_info[i]); - - if ((flash_info[i].flash_id & FLASH_TYPEMASK) == - (ATM_ID_BV1614 & FLASH_TYPEMASK)) { - - pOrgDef = OrgAT49BV16x4; - flash_nb_blocks = sizeof (OrgAT49BV16x4) / sizeof (OrgDef); - } else if ((flash_info[i].flash_id & FLASH_TYPEMASK) == - (ATM_ID_BV1614A & FLASH_TYPEMASK)){ /* AT49BV1614A Flash */ - - pOrgDef = OrgAT49BV16x4A; - flash_nb_blocks = sizeof (OrgAT49BV16x4A) / sizeof (OrgDef); - } else if ((flash_info[i].flash_id & FLASH_TYPEMASK) == - (ATM_ID_BV6416 & FLASH_TYPEMASK)){ /* AT49BV6416 Flash */ - - pOrgDef = OrgAT49BV6416; - flash_nb_blocks = sizeof (OrgAT49BV6416) / sizeof (OrgDef); - } else { - flash_nb_blocks = 0; - pOrgDef = OrgAT49BV16x4; - } - - flash_info[i].sector_count = flash_number_sector(pOrgDef, flash_nb_blocks); - memset (flash_info[i].protect, 0, flash_info[i].sector_count); - - if (i == 0) - flashbase = PHYS_FLASH_1; - else - panic ("configured too many flash banks!\n"); - - sector = 0; - start_address = flashbase; - flash_info[i].size = 0; - - for (j = 0; j < flash_nb_blocks; j++) { - for (k = 0; k < pOrgDef[j].sector_number; k++) { - flash_info[i].start[sector++] = start_address; - start_address += pOrgDef[j].sector_size; - flash_info[i].size += pOrgDef[j].sector_size; - } - } - - size += flash_info[i].size; - - if ((flash_info[i].flash_id & FLASH_TYPEMASK) == - (ATM_ID_BV6416 & FLASH_TYPEMASK)){ /* AT49BV6416 Flash */ + int i; + flash_info_t * info; - /* Unlock all sectors at reset */ - for (j=0; jsize && info->start[0] <= base && + base <= info->start[0] + info->size - 1) + break; } - /* Protect binary boot image */ - flash_protect (FLAG_PROTECT_SET, - CFG_FLASH_BASE, - CFG_FLASH_BASE + CFG_BOOT_SIZE - 1, &flash_info[0]); - - /* Protect environment variables */ - flash_protect (FLAG_PROTECT_SET, - CFG_ENV_ADDR, - CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]); - - /* Protect U-Boot gzipped image */ - flash_protect (FLAG_PROTECT_SET, - CFG_U_BOOT_BASE, - CFG_U_BOOT_BASE + CFG_U_BOOT_SIZE - 1, &flash_info[0]); - - return size; + return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info; } /*----------------------------------------------------------------------- */ -void flash_print_info (flash_info_t * info) + +void flash_print_info (flash_info_t *info) { int i; + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + switch (info->flash_id & FLASH_VENDMASK) { - case (ATM_MANUFACT & FLASH_VENDMASK): - printf ("Atmel: "); - break; - default: - printf ("Unknown Vendor "); - break; + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_BM: printf ("BRIGHT MICRO "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + case FLASH_MAN_SST: printf ("SST "); break; + case FLASH_MAN_STM: printf ("STM "); break; + case FLASH_MAN_INTEL: printf ("INTEL "); break; + default: printf ("Unknown Vendor "); break; } switch (info->flash_id & FLASH_TYPEMASK) { - case (ATM_ID_BV1614 & FLASH_TYPEMASK): - printf ("AT49BV1614 (16Mbit)\n"); - break; - case (ATM_ID_BV1614A & FLASH_TYPEMASK): - printf ("AT49BV1614A (16Mbit)\n"); - break; - case (ATM_ID_BV6416 & FLASH_TYPEMASK): - printf ("AT49BV6416 (64Mbit)\n"); + case FLASH_S29GL064M: + printf ("S29GL064M-R6 (64Mbit, uniform sector size)\n"); break; default: printf ("Unknown Chip Type\n"); - goto Done; break; } printf (" Size: %ld MB in %d Sectors\n", - info->size >> 20, info->sector_count); + info->size >> 20, + info->sector_count); printf (" Sector Start Addresses:"); - for (i = 0; i < info->sector_count; i++) { + + for (i=0; isector_count; ++i) { if ((i % 5) == 0) { printf ("\n "); } - printf (" %08lX%s", info->start[i], + printf (" %08lX%s", + info->start[i], info->protect[i] ? " (RO)" : " "); } printf ("\n"); - -Done: ; + return; } /*----------------------------------------------------------------------- */ -int flash_erase (flash_info_t * info, int s_first, int s_last) -{ - ulong result; - int iflag, cflag, prot, sect; - int rc = ERR_OK; - int chip1; - - /* first look for protection bits */ - - if (info->flash_id == FLASH_UNKNOWN) - return ERR_UNKNOWN_FLASH_TYPE; - - if ((s_first < 0) || (s_first > s_last)) { - return ERR_INVAL; - } - - if ((info->flash_id & FLASH_VENDMASK) != - (ATM_MANUFACT & FLASH_VENDMASK)) { - return ERR_UNKNOWN_FLASH_VENDOR; - } - - prot = 0; - for (sect = s_first; sect <= s_last; ++sect) { - if (info->protect[sect]) { - prot++; - } - } - if (prot) - return ERR_PROTECTED; - - /* - * Disable interrupts which might cause a timeout - * here. Remember that our exception vectors are - * at address 0 in the flash, and we don't want a - * (ticker) exception to happen while the flash - * chip is in programming mode. - */ - cflag = icache_status (); - icache_disable (); - iflag = disable_interrupts (); +/* + * The following code cannot be run from FLASH! + */ - /* Start erase on unprotected sectors */ - for (sect = s_first; sect <= s_last && !ctrlc (); sect++) { - printf ("Erasing sector %2d ... ", sect); +ulong flash_get_size (vu_short *addr, flash_info_t *info) +{ + int i; + ushort value; + ulong base = (ulong)addr; - /* arm simple, non interrupt dependent timer */ - reset_timer_masked (); + /* Write auto select command sequence */ + addr[FLASH_CYCLE1] = 0x00AA; /* for AMD, Intel ignores this */ + addr[FLASH_CYCLE2] = 0x0055; /* for AMD, Intel ignores this */ + addr[FLASH_CYCLE1] = 0x0090; /* selects Intel or AMD */ - if (info->protect[sect] == 0) { /* not protected */ - volatile u16 *addr = (volatile u16 *) (info->start[sect]); + /* read Manufacturer ID */ + udelay(100); + value = addr[0]; + debug ("Manufacturer ID: %04X\n", value); - MEM_FLASH_ADDR1 = CMD_UNLOCK1; - MEM_FLASH_ADDR2 = CMD_UNLOCK2; - MEM_FLASH_ADDR1 = CMD_ERASE_SETUP; + switch (value) { - MEM_FLASH_ADDR1 = CMD_UNLOCK1; - MEM_FLASH_ADDR2 = CMD_UNLOCK2; - *addr = CMD_ERASE_CONFIRM; + case (AMD_MANUFACT & 0xFFFF): + debug ("Manufacturer: AMD (Spansion)\n"); + info->flash_id = FLASH_MAN_AMD; + break; - /* wait until flash is ready */ - chip1 = 0; + case (INTEL_MANUFACT & 0xFFFF): + debug ("Manufacturer: Intel (not supported yet)\n"); + info->flash_id = FLASH_MAN_INTEL; + break; - do { - result = *addr; + default: + printf ("Unknown Manufacturer ID: %04X\n", value); + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + goto out; + } - /* check timeout */ - if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) { - MEM_FLASH_ADDR1 = CMD_READ_ARRAY; - chip1 = TMO; - break; + value = addr[1]; + debug ("Device ID: %04X\n", value); + + switch (addr[1]) { + + case (AMD_ID_MIRROR & 0xFFFF): + debug ("Mirror Bit flash: addr[14] = %08X addr[15] = %08X\n", + addr[14], addr[15]); + + switch(addr[14]) { + case (AMD_ID_GL064M_2 & 0xFFFF): + if (addr[15] != (AMD_ID_GL064M_3 & 0xffff)) { + printf ("Chip: S29GLxxxM -> unknown\n"); + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + } else { + debug ("Chip: S29GL064M-R6\n"); + info->flash_id += FLASH_S29GL064M; + info->sector_count = 128; + info->size = 0x00800000; + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base; + base += 0x10000; } - - if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE) - chip1 = READY; - - } while (!chip1); - - MEM_FLASH_ADDR1 = CMD_READ_ARRAY; - - if (chip1 == ERR) { - rc = ERR_PROG_ERROR; - goto outahere; - } - if (chip1 == TMO) { - rc = ERR_TIMOUT; - goto outahere; } - - printf ("ok.\n"); - } else { /* it was protected */ - printf ("protected!\n"); + break; /* => 16 MB */ + default: + printf ("Chip: *** unknown ***\n"); + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + break; } - } - - if (ctrlc ()) - printf ("User Interrupt!\n"); - -outahere: - /* allow flash to settle - wait 10 ms */ - udelay_masked (10000); + break; - if (iflag) - enable_interrupts (); + default: + printf ("Unknown Device ID: %04X\n", value); + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + break; + } - if (cflag) - icache_enable (); +out: + /* Put FLASH back in read mode */ + flash_reset(info); - return rc; + return (info->size); } /*----------------------------------------------------------------------- - * Copy memory to flash */ -volatile static int write_word (flash_info_t * info, ulong dest, - ulong data) +int flash_erase (flash_info_t *info, int s_first, int s_last) { - volatile u16 *addr = (volatile u16 *) dest; - ulong result; - int rc = ERR_OK; - int cflag, iflag; - int chip1; + vu_short *addr = (vu_short *)(info->start[0]); + int flag, prot, sect, ssect, l_sect; + ulong now, last; - /* - * Check if Flash is (sufficiently) erased - */ - result = *addr; - if ((result & data) != data) - return ERR_NOT_ERASED; + debug ("flash_erase: first: %d last: %d\n", s_first, s_last); + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } - /* - * Disable interrupts which might cause a timeout - * here. Remember that our exception vectors are - * at address 0 in the flash, and we don't want a - * (ticker) exception to happen while the flash - * chip is in programming mode. - */ - cflag = icache_status (); - icache_disable (); - iflag = disable_interrupts (); + if ((info->flash_id == FLASH_UNKNOWN) || + (info->flash_id > FLASH_AMD_COMP)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } - MEM_FLASH_ADDR1 = CMD_UNLOCK1; - MEM_FLASH_ADDR2 = CMD_UNLOCK2; - MEM_FLASH_ADDR1 = CMD_PROGRAM; - *addr = data; + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } - /* arm simple, non interrupt dependent timer */ - reset_timer_masked (); + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } - /* wait until flash is ready */ - chip1 = 0; - do { - result = *addr; + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); - /* check timeout */ - if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) { - chip1 = ERR | TMO; - break; + /* + * Start erase on unprotected sectors. + * Since the flash can erase multiple sectors with one command + * we take advantage of that by doing the erase in chunks of + * 3 sectors. + */ + for (sect = s_first; sect <= s_last; ) { + l_sect = -1; + + addr[FLASH_CYCLE1] = 0x00AA; + addr[FLASH_CYCLE2] = 0x0055; + addr[FLASH_CYCLE1] = 0x0080; + addr[FLASH_CYCLE1] = 0x00AA; + addr[FLASH_CYCLE2] = 0x0055; + + /* do the erase in chunks of at most 3 sectors */ + for (ssect = 0; ssect < 3; ssect++) { + if ((sect + ssect) > s_last) + break; + if (info->protect[sect + ssect] == 0) { /* not protected */ + addr = (vu_short *)(info->start[sect + ssect]); + addr[0] = 0x0030; + l_sect = sect + ssect; + } } - if (!chip1 && ((result & 0x80) == (data & 0x80))) - chip1 = READY; + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); - } while (!chip1); + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; - *addr = CMD_READ_ARRAY; - - if (chip1 == ERR || *addr != data) - rc = ERR_PROG_ERROR; + reset_timer_masked (); + last = 0; + addr = (vu_short *)(info->start[l_sect]); + while ((addr[0] & 0x0080) != 0x0080) { + if ((now = get_timer_masked ()) > CONFIG_SYS_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + addr = (vu_short *)info->start[0]; + addr[0] = 0x00F0; /* reset bank */ + sect += ssect; + } - if (iflag) - enable_interrupts (); + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); - if (cflag) - icache_enable (); +DONE: + /* reset to read mode */ + addr = (vu_short *)info->start[0]; + addr[0] = 0x00F0; /* reset bank */ - return rc; + printf (" done\n"); + return 0; } /*----------------------------------------------------------------------- - * Copy memory to flash. + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased */ -int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) { ulong wp, data; int rc; @@ -483,8 +392,9 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) wp = addr; while (cnt >= 2) { - data = *((volatile u16 *) src); - if ((rc = write_word (info, wp, data)) != 0) { + data = *((vu_short *)src); + if ((rc = write_word_amd(info, (vu_short *)wp, data)) != 0) { +printf ("write_buff 1: write_word_amd() rc=%d\n", rc); return (rc); } src += 2; @@ -492,16 +402,67 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) cnt -= 2; } + if (cnt == 0) { + return (ERR_OK); + } + if (cnt == 1) { - data = (*((volatile u8 *) src)) | (*((volatile u8 *) (wp + 1)) << - 8); - if ((rc = write_word (info, wp, data)) != 0) { + data = (*((volatile u8 *) src)) | (*((volatile u8 *) (wp + 1)) << 8); + if ((rc = write_word_amd(info, (vu_short *)wp, data)) != 0) { +printf ("write_buff 1: write_word_amd() rc=%d\n", rc); return (rc); } src += 1; wp += 1; cnt -= 1; - }; + } return ERR_OK; } + +/*----------------------------------------------------------------------- + * Write a word to Flash for AMD FLASH + * A word is 16 or 32 bits, whichever the bus width of the flash bank + * (not an individual chip) is. + * + * returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word_amd (flash_info_t *info, vu_short *dest, ushort data) +{ + int flag; + vu_short *base; /* first address in flash bank */ + + /* Check if Flash is (sufficiently) erased */ + if ((*dest & data) != data) { + return (2); + } + + base = (vu_short *)(info->start[0]); + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + base[FLASH_CYCLE1] = 0x00AA; /* unlock */ + base[FLASH_CYCLE2] = 0x0055; /* unlock */ + base[FLASH_CYCLE1] = 0x00A0; /* selects program mode */ + + *dest = data; /* start programming the data */ + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + reset_timer_masked (); + + /* data polling for D7 */ + while ((*dest & 0x0080) != (data & 0x0080)) { + if (get_timer_masked () > CONFIG_SYS_FLASH_WRITE_TOUT) { + *dest = 0x00F0; /* reset bank */ + return (1); + } + } + return (0); +}