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,
+};