FreeCalypso > hg > freecalypso-tools
diff loadtools/flashops.c @ 0:e7502631a0f9
initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 11 Jun 2016 00:13:35 +0000 |
parents | |
children | 545e1718f5fb |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadtools/flashops.c Sat Jun 11 00:13:35 2016 +0000 @@ -0,0 +1,218 @@ +/* + * This module implements those flash operations which are dependent + * on the AMD vs. Intel command set style. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <time.h> +#include "flash.h" + +/* common stub functions */ + +static +noop() +{ + return(0); +} + +static +invalid() +{ + fprintf(stderr, + "This operation is not applicable to the selected flash type\n"); + return(-1); +} + +/* AMD flash functions */ + +amd_reset_cmd(bi) + struct flash_bank_info *bi; +{ + if (do_w16(bi->base_addr + 0xAAA, 0xF0)) { + fprintf(stderr, + "unexpected response to w16 when resetting flash to read mode!\n"); + return(-1); + } + return(0); +} + +amd_sector_erase(bi, sp) + struct flash_bank_info *bi; + struct sector_info *sp; +{ + int stat; + uint16_t flstat; + time_t start_time, curtime; + + stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0xAA); + if (stat) { +bad_w16: fprintf(stderr, + "unexpected response to w16 in erase cmd sequence - aborting\n"); + return(-1); + } + stat = do_w16(bi->base_addr + sp->start + 0x554, 0x55); + if (stat) + goto bad_w16; + stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0x80); + if (stat) + goto bad_w16; + stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0xAA); + if (stat) + goto bad_w16; + stat = do_w16(bi->base_addr + sp->start + 0x554, 0x55); + if (stat) + goto bad_w16; + stat = do_w16(bi->base_addr + sp->start + 0xAAA, 0x30); + if (stat) + goto bad_w16; + start_time = time(0); + for (;;) { + stat = do_r16(bi->base_addr + sp->start, &flstat); + if (stat) + return(stat); /* error msg already printed */ + if (flstat == 0xFFFF) + return(0); + curtime = time(0); + if (curtime >= start_time + 20) { + fprintf(stderr, "erase timeout, aborting\n"); + return(-1); + } + } +} + +struct flash_cmdset flash_cmdset_amd = { + .cmdset_name = "AMD", + .reset_cmd = amd_reset_cmd, + .status_cmd = invalid, + .unlock_sector = invalid, + .erase_sector = amd_sector_erase, + .prep_for_program = noop, + .loadagent_setbase_cmd = "AMFB", + .loadagent_program_cmd = "AMFW", + .needs_unlock = 0, +}; + +/* Intel flash functions */ + +intel_reset_cmd(bi) + struct flash_bank_info *bi; +{ + if (do_w16(bi->base_addr, 0xFF)) { + fprintf(stderr, + "unexpected response to w16 when resetting flash to read mode!\n"); + return(-1); + } + return(0); +} + +intel_status_cmd(bi) + struct flash_bank_info *bi; +{ + int stat; + uint16_t sr; + + /* issue Read SR command */ + stat = do_w16(bi->base_addr, 0x70); + if (stat) { + fprintf(stderr, + "unexpected response to w16 for Read SR command\n"); + return(-1); + } + stat = do_r16(bi->base_addr, &sr); + if (stat) + return(stat); /* error msg already printed */ + sr &= 0xFF; + printf("Status Register: %02X\n", sr); + return(0); +} + +intel_sector_unlock(bi, sp) + struct flash_bank_info *bi; + struct sector_info *sp; +{ + int stat; + + stat = do_w16(bi->base_addr + sp->start, 0x60); + if (stat) { +bad_w16: fprintf(stderr, + "unexpected response to w16 in block unlock cmd sequence - aborting\n"); + return(-1); + } + stat = do_w16(bi->base_addr + sp->start, 0xD0); + if (stat) + goto bad_w16; + return(0); +} + +intel_sector_erase(bi, sp) + struct flash_bank_info *bi; + struct sector_info *sp; +{ + int stat; + uint16_t flstat; + time_t start_time, curtime; + + stat = intel_sector_unlock(bi, sp); + if (stat) + return(stat); /* error msg already printed */ + /* clear SR */ + stat = do_w16(bi->base_addr + sp->start, 0x50); + if (stat) { +bad_w16: fprintf(stderr, + "unexpected response to w16 in erase cmd sequence - aborting\n"); + return(-1); + } + /* send the actual block erase command */ + stat = do_w16(bi->base_addr + sp->start, 0x20); + if (stat) + goto bad_w16; + stat = do_w16(bi->base_addr + sp->start, 0xD0); + if (stat) + goto bad_w16; + /* wait for completion */ + start_time = time(0); + for (;;) { + stat = do_r16(bi->base_addr + sp->start, &flstat); + if (stat) + return(stat); /* error msg already printed */ + if (flstat & 0x80) + break; + curtime = time(0); + if (curtime >= start_time + 20) { + fprintf(stderr, "erase timeout, aborting\n"); + return(-1); + } + } + if (flstat & 0x20) { + fprintf(stderr, "block erase failed!\n"); + return(-1); + } else + return(0); +} + +intel_clear_sr(bi) + struct flash_bank_info *bi; +{ + printf("Clearing Intel flash SR\n"); + if (do_w16(bi->base_addr, 0x50)) { + fprintf(stderr, + "unexpected response to w16 for Clear SR command\n"); + return(-1); + } + return(0); +} + +struct flash_cmdset flash_cmdset_intel = { + .cmdset_name = "Intel", + .reset_cmd = intel_reset_cmd, + .status_cmd = intel_status_cmd, + .unlock_sector = intel_sector_unlock, + .erase_sector = intel_sector_erase, + .prep_for_program = intel_clear_sr, + .loadagent_setbase_cmd = "INFB", + .loadagent_program_cmd = "INFW", + .needs_unlock = 1, +};