Add common master API to adapt voltage

We start by setting the voltage in prepare_flash_access() and, if we
were told to probe for a specific chip, before the probing. For now,
we leave the programmer driver's default voltage during the probing,
otherwise.

Once the probing is more bus centric, we can implement a more elabo-
rate scheme. For instance, we can probe at the lowest voltage first
and only increase it if there was no response at all.

Change-Id: I6689813f83abe654ba7a18f2e0537314047bf15f
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/414
diff --git a/flashprog.c b/flashprog.c
index e4151da..fd9cd74 100644
--- a/flashprog.c
+++ b/flashprog.c
@@ -649,6 +649,13 @@
 		*flash->chip = *chip;
 		flash->mst.par = &mst->par; /* both `mst` are unions, so we need only one pointer */
 
+		/* If we probe for a specific chip, we can adapt the voltage early. */
+		if (chip_to_probe && flash->mst.common->adapt_voltage) {
+			if (flash->mst.common->adapt_voltage(flash->mst.common,
+					chip->voltage.min, chip->voltage.max))
+				goto free_chip;
+		}
+
 		if (flash->chip->prepare_access && flash->chip->prepare_access(flash, PREPARE_PROBE))
 			goto free_chip;
 
@@ -1690,6 +1697,12 @@
 		return 1;
 	}
 
+	if (flash->mst.common->adapt_voltage) {
+		if (flash->mst.common->adapt_voltage(flash->mst.common,
+				flash->chip->voltage.min, flash->chip->voltage.max))
+			return 1;
+	}
+
 	if (flash->chip->prepare_access && flash->chip->prepare_access(flash, PREPARE_FULL))
 		return 1;
 
diff --git a/include/flash.h b/include/flash.h
index b3ad235..a67e64c 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -445,6 +445,7 @@
 	uintptr_t physical_registers;
 	chipaddr virtual_registers;
 	union {
+		struct master_common *common;
 		struct par_master *par;
 		struct spi_master *spi;
 		struct opaque_master *opaque;
diff --git a/include/programmer.h b/include/programmer.h
index 3270e0e..df5f51f 100644
--- a/include/programmer.h
+++ b/include/programmer.h
@@ -273,6 +273,10 @@
 extern unsigned long flashbase;
 char *extract_programmer_param(const char *param_name);
 
+struct master_common {
+	int (*adapt_voltage)(const struct master_common *, unsigned int min_mv, unsigned int max_mv);
+};
+
 /* spi.c */
 #define MAX_DATA_UNSPECIFIED 0
 #define MAX_DATA_READ_UNLIMITED 64 * 1024
@@ -301,6 +305,9 @@
 
 struct spi_command;
 struct spi_master {
+	/* XXX: Keep common struct first, it is overlayed with other master types. */
+	struct master_common common;
+
 	uint32_t features;
 	unsigned int max_data_read; // (Ideally,) maximum data read size in one go (excluding opcode+address).
 	unsigned int max_data_write; // (Ideally,) maximum data write size in one go (excluding opcode+address).
@@ -416,6 +423,9 @@
 
 /* opaque.c */
 struct opaque_master {
+	/* XXX: Keep common struct first, it is overlayed with other master types. */
+	struct master_common common;
+
 	int max_data_read;
 	int max_data_write;
 	/* Specific functions for this master */
@@ -430,6 +440,9 @@
 
 /* parallel.c */
 struct par_master {
+	/* XXX: Keep common struct first, it is overlayed with other master types. */
+	struct master_common common;
+
 	void (*chip_writeb) (const struct flashctx *flash, uint8_t val, chipaddr addr);
 	void (*chip_writew) (const struct flashctx *flash, uint16_t val, chipaddr addr);
 	void (*chip_writel) (const struct flashctx *flash, uint32_t val, chipaddr addr);
@@ -462,6 +475,7 @@
 	size_t max_rom_decode;
 	enum chipbustype buses_supported;
 	union {
+		struct master_common common;
 		struct par_master par;
 		struct spi_master spi;
 		struct opaque_master opaque;