FreeCalypso > hg > freecalypso-tools
view target-utils/loadagent/amdflash.c @ 733:bed7981ac8ca
doc/Compal-FFS: update for IMEI found in OTP cells
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 28 Aug 2020 15:58:46 +0000 |
parents | b34384991094 |
children |
line wrap: on
line source
/* * This module implements the AMFB and AMFW commands for programming * AMD-style flash memories. Syntax: * * AMFB <baseaddr> -- sets the base address for subsequent AMFW commands * AMFW <offset> <hexstring> -- the actual flash write operation * * The flash memory is assumed to be 16 bits wide. The hex string * argument to the AMFW command is just data, with no header, address, * length, checksum or other additions. The number of hex digits in the * string must be a multiple of 4, and the byte order is the same as * that of TI's *.m0 files: we interpret the string as consisting of * 16-bit words rather than bytes. * * The address to which each flash write is directed is the sum of the * base given to AMFB and the offset given to AMFW. The fixed offsets * of 0xAAA and 0x554 (0x555 and 0x2AA in words) prescribed for the flash * programming command sequence are also made from the base set with AMFB. */ #include <sys/types.h> #include "types.h" static u32 base_addr; void cmd_AMFB(argbulk) char *argbulk; { char *argv[2]; u_long addr; if (parse_args(argbulk, 1, 1, argv, 0) < 0) return; if (parse_hexarg(argv[0], 8, &addr) < 0) { printf("ERROR: argument must be a valid 32-bit hex address\n"); return; } if (addr & 1) { printf("ERROR: odd address\n"); return; } base_addr = addr; } void cmd_AMFW(argbulk) char *argbulk; { char *argv[3], *s; u_long offset; volatile u16 *flashptr; u32 datum; /* needs to be u32 for decode_hex_digits() */ int i; if (parse_args(argbulk, 2, 2, argv, 0) < 0) return; if (parse_hexarg(argv[0], 8, &offset) < 0) { printf("ERROR: offset argument must a valid 32-bit hex value\n"); return; } if (offset & 1) { printf("ERROR: odd offset argument\n"); return; } flashptr = (volatile u16 *)(base_addr + offset); for (s = argv[1]; *s; flashptr++, s += 4) { if (decode_hex_digits(s, 4, &datum) < 0) { printf("ERROR: bad AMFW hex string argument\n"); return; } if (*flashptr != 0xFFFF) { printf("ERROR: flash not blank at %08X\n", (u_long) flashptr); return; } *(volatile u16 *)(base_addr + 0xAAA) = 0xAA; *(volatile u16 *)(base_addr + 0x554) = 0x55; *(volatile u16 *)(base_addr + 0xAAA) = 0xA0; *flashptr = datum; for (i = 10000; i; i--) if (*flashptr == datum) break; if (!i) { printf("ERROR: flash write timeout at %08X\n", (u_long) flashptr); return; } } } amdflash_binary_prog(offset, nwords, data) u32 offset; unsigned nwords; u16 *data; { volatile u16 *flashptr; int i; flashptr = (volatile u16 *)(base_addr + offset); while (nwords) { if (*flashptr != 0xFFFF) { serial_out(0x15); /* NAK */ printf("ERROR: flash not blank at %08X\n", (u_long) flashptr); return(-1); } *(volatile u16 *)(base_addr + 0xAAA) = 0xAA; *(volatile u16 *)(base_addr + 0x554) = 0x55; *(volatile u16 *)(base_addr + 0xAAA) = 0xA0; *flashptr = *data; for (i = 10000; i; i--) if (*flashptr == *data) break; if (!i) { serial_out(0x15); /* NAK */ printf("ERROR: flash write timeout at %08X\n", (u_long) flashptr); return(-1); } flashptr++; data++; nwords--; } return(0); } void cmd_AMFWB() { binary_flash_prog_main(amdflash_binary_prog); }