Run .prepare_access only once per flash context

There's only a single path now to create a flash context,  after
probing, and only when we want to access the flash chip next. So
there's no need to defer this preparation step anymore.

All preparation will be done in a single step. Hence we drop the
PREPARE_POST_PROBE and PREPARE_FULL steps and the enum.

Change-Id: I7cd4058dd0b52ad0e4be45e494c4533f689893d9
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/492
diff --git a/at45db.c b/at45db.c
index f84f3f4..2768ace 100644
--- a/at45db.c
+++ b/at45db.c
@@ -172,14 +172,11 @@
 }
 
 /* Adapt chip entry for AT45DB* chips that support multiple page sizes. */
-int spi_prepare_at45db(struct flashctx *const flash, const enum preparation_steps prep)
+int spi_prepare_at45db(struct flashctx *const flash)
 {
 	struct flashchip *const chip = flash->chip;
 	uint8_t status;
 
-	if (prep != PREPARE_POST_PROBE)
-		return 0;
-
 	/* Power-of-2 check */
 	if (chip->page_size & (chip->page_size - 1))
 		return 0;
diff --git a/edi.c b/edi.c
index 0f83a40..efe41c5 100644
--- a/edi.c
+++ b/edi.c
@@ -470,7 +470,7 @@
 	return 0;
 }
 
-static void edi_finish(struct flashctx *flash)
+void edi_finish(struct flashctx *flash)
 {
 	const struct spi_master *const spi = flash->mst.spi;
 
@@ -502,19 +502,15 @@
 	return edi_chip_probe(spi);
 }
 
-int edi_prepare(struct flashctx *flash, enum preparation_steps step)
+int edi_prepare(struct flashctx *flash)
 {
 	int rc;
 
-	if (step < PREPARE_FULL)
-		return 0;
-
 	rc = edi_8051_reset(flash->mst.spi);
 	if (rc < 0) {
 		msg_perr("%s: Unable to reset 8051!\n", __func__);
 		return rc;
 	}
 
-	flash->chip->finish_access = edi_finish;
 	return 0;
 }
diff --git a/flashchips.c b/flashchips.c
index e38f5e4..dfea1f6 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -4145,6 +4145,7 @@
 		.voltage	= {2700, 3600},
 		.gran		= write_gran_128bytes,
 		.prepare_access	= edi_prepare,
+		.finish_access	= edi_finish,
 	},
 
 	{
diff --git a/flashprog.c b/flashprog.c
index ca2038c..f647f75 100644
--- a/flashprog.c
+++ b/flashprog.c
@@ -1548,9 +1548,6 @@
 		return 1;
 	}
 
-	if (flash->chip->prepare_access && flash->chip->prepare_access(flash, PREPARE_FULL))
-		return 1;
-
 	/* Initialize chip_restore_fn_count before chip unlock calls. */
 	flash->chip_restore_fn_count = 0;
 
@@ -1565,8 +1562,6 @@
 void finalize_flash_access(struct flashctx *const flash)
 {
 	deregister_chip_restore(flash);
-	if (flash->chip->finish_access)
-		flash->chip->finish_access(flash);
 }
 
 /**
diff --git a/include/chipdrivers/edi.h b/include/chipdrivers/edi.h
index 4d641cc..ad0e1db 100644
--- a/include/chipdrivers/edi.h
+++ b/include/chipdrivers/edi.h
@@ -29,6 +29,7 @@
 int edi_chip_block_erase(struct flashprog_flashctx *, unsigned int page, unsigned int size);
 int edi_chip_write(struct flashprog_flashctx *, const uint8_t *buf, unsigned int start, unsigned int len);
 int edi_chip_read(struct flashprog_flashctx *, uint8_t *buf, unsigned int start, unsigned int len);
-int edi_prepare(struct flashprog_flashctx *, enum preparation_steps);
+int edi_prepare(struct flashprog_flashctx *);
+void edi_finish(struct flashprog_flashctx *);
 
 #endif /* !__CHIPDRIVERS_EDI_H__ */
diff --git a/include/chipdrivers/memory_bus.h b/include/chipdrivers/memory_bus.h
index b4eede4..86a82a0 100644
--- a/include/chipdrivers/memory_bus.h
+++ b/include/chipdrivers/memory_bus.h
@@ -115,9 +115,8 @@
 void *programmer_map_flash_data(const struct par_master *, chipsize_t, const char *descr);
 void programmer_unmap_flash_region(const struct par_master *, void *, chipsize_t);
 
-enum preparation_steps;
-int prepare_memory_access(struct flashprog_flashctx *, enum preparation_steps);
-int prepare_memory_register_access(struct flashprog_flashctx *, enum preparation_steps);
+int prepare_memory_access(struct flashprog_flashctx *);
+int prepare_memory_register_access(struct flashprog_flashctx *);
 void finish_memory_access(struct flashprog_flashctx *);
 
 #endif /* !__CHIPDRIVERS_MEMORY_BUS_H__ */
diff --git a/include/chipdrivers/opaque.h b/include/chipdrivers/opaque.h
index d6d3eba..8d9f660 100644
--- a/include/chipdrivers/opaque.h
+++ b/include/chipdrivers/opaque.h
@@ -25,8 +25,7 @@
 
 struct found_id *probe_opaque(const struct bus_probe *, const struct master_common *, const struct flashchip *);
 
-enum preparation_steps;
-int prepare_opaque(struct flashprog_flashctx *, enum preparation_steps);
+int prepare_opaque(struct flashprog_flashctx *);
 
 int read_opaque(struct flashprog_flashctx *, uint8_t *buf, unsigned int start, unsigned int len);
 int write_opaque(struct flashprog_flashctx *, const uint8_t *buf, unsigned int start, unsigned int len);
diff --git a/include/chipdrivers/spi.h b/include/chipdrivers/spi.h
index 94a6a1f..d99d903 100644
--- a/include/chipdrivers/spi.h
+++ b/include/chipdrivers/spi.h
@@ -57,8 +57,7 @@
 int spi_write_chunked(struct flashprog_flashctx *, const uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);
 int spi_set_extended_address(struct flashprog_flashctx *, uint8_t addr_high);
 
-enum preparation_steps;
-int spi_prepare_io(struct flashprog_flashctx *, enum preparation_steps);
+int spi_prepare_io(struct flashprog_flashctx *);
 void spi_finish_io(struct flashprog_flashctx *);
 
 enum flash_reg;
@@ -107,7 +106,7 @@
 int spi_disable_blockprotect_sst26_global_unprotect(struct flashprog_flashctx *);
 
 /* at45db.c */
-int spi_prepare_at45db(struct flashprog_flashctx *, enum preparation_steps);
+int spi_prepare_at45db(struct flashprog_flashctx *);
 int spi_prettyprint_status_register_at45db(struct flashprog_flashctx *);
 int spi_disable_blockprotect_at45db(struct flashprog_flashctx *);
 int spi_read_at45db(struct flashprog_flashctx *, uint8_t *buf, unsigned int start, unsigned int len);
@@ -132,6 +131,6 @@
 
 /* sfdp.c */
 struct found_id *probe_spi_sfdp(const struct bus_probe *, const struct master_common *, const struct flashchip *);
-int spi_prepare_sfdp(struct flashprog_flashctx *, enum preparation_steps);
+int spi_prepare_sfdp(struct flashprog_flashctx *);
 
 #endif /* !__CHIPDRIVERS_SPI_H__ */
diff --git a/include/flash.h b/include/flash.h
index 32824a7..5566067 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -246,11 +246,6 @@
 
 struct wp_bits;
 
-enum preparation_steps {
-	PREPARE_POST_PROBE,
-	PREPARE_FULL,
-};
-
 struct flashchip {
 	const char *vendor;
 	const char *name;
@@ -412,7 +407,7 @@
 	/* and determines what protection range they select. */
 	void (*decode_range)(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len);
 
-	int (*prepare_access)(struct flashctx *, enum preparation_steps);
+	int (*prepare_access)(struct flashctx *);
 	void (*finish_access)(struct flashctx *);
 };
 
diff --git a/libflashprog.c b/libflashprog.c
index 900ecc2..212293f 100644
--- a/libflashprog.c
+++ b/libflashprog.c
@@ -300,15 +300,19 @@
 	*flash->chip = *chip;
 	flash->mst.common = bus; /* `mst` is a union, so we need only one pointer */
 
-	if (chip->prepare_access && chip->prepare_access(flash, PREPARE_POST_PROBE))
-		goto free_flash;
+	if (chip->prepare_access && chip->prepare_access(flash)) {
+		free(flash);
+		return 4;
+	}
 
 	/* Fill default layout covering the whole chip. */
 	if (flashprog_layout_new(&flash->default_layout) ||
 	    flashprog_layout_add_region(flash->default_layout,
 			0, flash->chip->total_size * 1024 - 1, "complete flash") ||
-	    flashprog_layout_include_region(flash->default_layout, "complete flash"))
-		goto free_flash;
+	    flashprog_layout_include_region(flash->default_layout, "complete flash")) {
+		flashprog_flash_release(flash);
+		return 1;
+	}
 
 	char *const tmp = flashbuses_to_text(flash->chip->bustype);
 	msg_cinfo("Using %s flash chip \"%s\" (%d kB, %s) ",
@@ -323,18 +327,8 @@
 	if (flash->chip->printlock)
 		flash->chip->printlock(flash);
 
-	if (flash->chip->finish_access)
-		flash->chip->finish_access(flash);
-
 	*flashctx = flash;
 	return 0;
-
-free_flash:
-	if (flash->chip && flash->chip->finish_access)
-		flash->chip->finish_access(flash);
-	free(flash->chip);
-	free(flash);
-	return 4;
 }
 
 /**
@@ -389,6 +383,8 @@
 	if (!flashctx)
 		return;
 
+	if (flashctx->chip->finish_access)
+		flashctx->chip->finish_access(flashctx);
 	flashprog_layout_release(flashctx->default_layout);
 	free(flashctx->chip);
 	free(flashctx);
diff --git a/memory_bus.c b/memory_bus.c
index fafe385..edc48e6 100644
--- a/memory_bus.c
+++ b/memory_bus.c
@@ -61,7 +61,7 @@
 	return addr;
 }
 
-int prepare_memory_access(struct flashctx *flash, enum preparation_steps prep)
+int prepare_memory_access(struct flashctx *flash)
 {
 	const struct par_master *const par = flash->mst.par;
 
@@ -80,11 +80,11 @@
 	return 0;
 }
 
-int prepare_memory_register_access(struct flashctx *flash, enum preparation_steps prep)
+int prepare_memory_register_access(struct flashctx *flash)
 {
 	const struct par_master *const par = flash->mst.par;
 
-	if (prepare_memory_access(flash, prep))
+	if (prepare_memory_access(flash))
 		return 1;
 
 	/*
diff --git a/opaque.c b/opaque.c
index 6db03cc..d62fe3b 100644
--- a/opaque.c
+++ b/opaque.c
@@ -47,10 +47,8 @@
 	return found;
 }
 
-int prepare_opaque(struct flashctx *flash, enum preparation_steps step)
+int prepare_opaque(struct flashctx *flash)
 {
-	if (step != PREPARE_POST_PROBE)
-		return 0;
 	return flash->mst.opaque->prepare(flash) ? 0 : -1;
 }
 
diff --git a/sfdp.c b/sfdp.c
index a324f9c..b1d7777 100644
--- a/sfdp.c
+++ b/sfdp.c
@@ -342,7 +342,7 @@
 	return 0;
 }
 
-int spi_prepare_sfdp(struct flashctx *flash, enum preparation_steps step)
+int spi_prepare_sfdp(struct flashctx *flash)
 {
 	const struct spi_master *const spi = flash->mst.spi;
 	int ret;
@@ -355,9 +355,6 @@
 	uint8_t *hbuf;
 	uint8_t *tbuf;
 
-	if (step != PREPARE_POST_PROBE)
-		return 0;
-
 	ret = spi_sfdp_read_sfdp(spi, 0x04, buf, 3);
 	if (ret) {
 		msg_cdbg("Receiving SFDP revision and number of parameter "
@@ -490,7 +487,12 @@
 		  "Thanks for your help!\n"
 		  "===\n");
 
-	return 0;
+	/* Chain preparation in case we replaced the .prepare_access
+	   pointer, e.g. spi_prepare_io() is needed for 4BA mode. */
+	if (flash->chip->prepare_access != spi_prepare_sfdp)
+		ret = flash->chip->prepare_access(flash);
+
+	return ret;
 }
 
 struct found_id *probe_spi_sfdp(const struct bus_probe *probe,
diff --git a/spi25_prepare.c b/spi25_prepare.c
index aaf240d..03fb54b 100644
--- a/spi25_prepare.c
+++ b/spi25_prepare.c
@@ -248,11 +248,8 @@
 	return fast_read_copy;
 }
 
-int spi_prepare_io(struct flashctx *const flash, const enum preparation_steps prep)
+int spi_prepare_io(struct flashctx *const flash)
 {
-	if (prep != PREPARE_FULL)
-		return 0;
-
 	int ret = spi_prepare_4ba(flash);
 	if (ret)
 		return ret;