changeset 994:ad3041e19884

fc-loadtool flash: implement PPB ops for Spansion PL-N
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 03 Dec 2023 06:16:30 +0000
parents 84c9869a3659
children 74024eb17e04
files loadtools/flamdsec.c loadtools/fldevs.c
diffstat 2 files changed, 69 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/loadtools/flamdsec.c	Sun Dec 03 04:58:50 2023 +0000
+++ b/loadtools/flamdsec.c	Sun Dec 03 06:16:30 2023 +0000
@@ -10,6 +10,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <strings.h>
+#include <time.h>
 #include <unistd.h>
 #include "flash.h"
 
@@ -436,6 +437,68 @@
 }
 
 /*
+ * Spansion PL-N PPB write functions, referenced from lock_info structures
+ * in fldevs.c device descriptions.
+ */
+
+static
+pln_ppb_write_op(oper_addr, write1, write2, expect_stat)
+	uint32_t oper_addr;
+	uint16_t write1, write2, expect_stat;
+{
+	int rc;
+	uint16_t read_stat, prev_stat;
+	time_t start_time, curtime;
+
+	rc = pln_special_mode_entry(oper_addr, 0xC0);
+	if (rc < 0)
+		return(rc);
+	if (do_w16(oper_addr, write1)) {
+bad_w16:	fprintf(stderr,
+	"unexpected response to w16 in PPB command sequence - aborting\n");
+		return(-1);
+	}
+	if (do_w16(oper_addr, write2))
+		goto bad_w16;
+	printf("Polling for completion status\n");
+	usleep(10000);	/* make sure we don't get state before op starts */
+	start_time = time(0);
+	rc = do_r16(oper_addr, &read_stat);
+	if (rc < 0)
+		return(rc);
+	for (;;) {
+		prev_stat = read_stat;
+		rc = do_r16(oper_addr, &read_stat);
+		if (rc < 0)
+			return(rc);
+		if (read_stat == expect_stat && prev_stat == expect_stat)
+			break;
+		curtime = time(0);
+		if (curtime >= start_time + 10) {
+			fprintf(stderr, "operation timeout, aborting\n");
+			return(-1);
+		}
+	}
+	printf("Operation completed successfully\n");
+	return pln_special_mode_exit(oper_addr);
+}
+
+pln_ppb_program_one(bi, sector_addr)
+	struct flash_bank_info *bi;
+	uint32_t sector_addr;
+{
+	printf("Issuing PPB Program command\n");
+	return pln_ppb_write_op(bi->base_addr + sector_addr, 0xA0, 0, 0);
+}
+
+pln_ppb_erase_all(bi, raw_mode)
+	struct flash_bank_info *bi;
+{
+	printf("Issuing All PPB Erase command\n");
+	return pln_ppb_write_op(bi->base_addr, 0x80, 0x30, 1);
+}
+
+/*
  * Front end functions for PPB operation commands.
  */
 
--- a/loadtools/fldevs.c	Sun Dec 03 04:58:50 2023 +0000
+++ b/loadtools/fldevs.c	Sun Dec 03 06:16:30 2023 +0000
@@ -14,6 +14,9 @@
 extern int plj_ppb_erase_all_single();
 extern int plj_ppb_erase_all_dualbank();
 
+extern int pln_ppb_program_one();
+extern int pln_ppb_erase_all();
+
 /* flash bank geometries */
 
 static struct flash_geom geom_2M_topboot = {
@@ -556,6 +559,8 @@
 		{0x40000, 24, 0, 1, 1}},
 	.have_status_word_3	= 1,
 	.have_pln_lock_reg	= 1,
+	.ppb_program_one	= pln_ppb_program_one,
+	.ppb_erase_all		= pln_ppb_erase_all,
 };
 
 static struct amd_lock_info PL129N_lock_info_1 = {
@@ -565,6 +570,7 @@
 		{0x40000, 7, 0, 1, 0},
 		{0x10000, 4, 0, 0, 1}},
 	.have_status_word_3	= 1,
+	.ppb_program_one	= pln_ppb_program_one,
 };
 
 struct flash_device flashdev_PL129N = {