writeprotect: Hook wp functions into the chip driver

Change-Id: I17a06210ec329aba337cf459d581463827182108
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/72532
diff --git a/flashchips.c b/flashchips.c
index bce9435..3c5962c 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -21,6 +21,7 @@
 #include "flash.h"
 #include "flashchips.h"
 #include "chipdrivers.h"
+#include "writeprotect.h"
 
 /**
  * List of supported flash chips.
@@ -2459,6 +2460,9 @@
 			.sec    = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -5224,6 +5228,9 @@
 			.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}},
 			.tb     = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -5307,6 +5314,9 @@
 			.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}},
 			.tb     = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -5393,6 +5403,9 @@
 			.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}},
 			.tb     = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25_64k_block,
 	},
 
@@ -6538,6 +6551,9 @@
 			.sec    = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -6704,6 +6720,9 @@
 			.sec    = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -6832,6 +6851,9 @@
 			.sec    = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -6965,6 +6987,9 @@
 			.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}},
 			.tb     = {STATUS1, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 		.prepare_access	= spi_prepare_4ba,
 	},
@@ -7015,6 +7040,9 @@
 			.sec    = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -7137,6 +7165,9 @@
 			.sec    = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -11411,6 +11442,9 @@
 			.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}},
 			.tb     = {STATUS1, 5, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -11456,6 +11490,9 @@
 			.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}},
 			.tb     = {STATUS1, 5, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -11501,6 +11538,9 @@
 			.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 6, RW}},
 			.tb     = {STATUS1, 5, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -11546,6 +11586,9 @@
 			.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 6, RW}},
 			.tb     = {STATUS1, 5, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -12202,6 +12245,9 @@
 			.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 6, RW}},
 			.tb     = {STATUS1, 5, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 		.prepare_access	= spi_prepare_4ba,
 	},
@@ -16725,6 +16771,9 @@
 			.cmp	= {STATUS2, 6, RW},
 			.wps	= {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -17156,6 +17205,9 @@
 			.cmp	= {STATUS2, 6, RW},
 			.wps	= {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 		.prepare_access	= spi_prepare_4ba,
 	},
@@ -17680,6 +17732,9 @@
 			.cmp	= {STATUS2, 6, RW},
 			.wps	= {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -17728,6 +17783,9 @@
 			.sec    = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -17778,6 +17836,9 @@
 			.sec    = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -17826,6 +17887,9 @@
 			.sec    = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -17996,6 +18060,9 @@
 			.tb     = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 		.prepare_access	= spi_prepare_4ba,
 	},
@@ -18052,6 +18119,9 @@
 			.tb     = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 		.prepare_access	= spi_prepare_4ba,
 	},
@@ -18108,6 +18178,9 @@
 			.tb     = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 		.prepare_access	= spi_prepare_4ba,
 	},
@@ -18213,6 +18286,9 @@
 			.cmp	= {STATUS2, 6, RW},
 			.wps	= {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 		.prepare_access	= spi_prepare_4ba,
 	},
@@ -18264,6 +18340,9 @@
 			.sec    = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -18316,6 +18395,9 @@
 			.cmp    = {STATUS2, 6, RW},
 			.wps    = {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -18368,6 +18450,9 @@
 			.cmp    = {STATUS2, 6, RW},
 			.wps    = {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -18418,6 +18503,9 @@
 			.sec    = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -18470,6 +18558,9 @@
 			.cmp    = {STATUS2, 6, RW},
 			.wps    = {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -18522,6 +18613,9 @@
 			.cmp    = {STATUS2, 6, RW},
 			.wps    = {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -18574,6 +18668,9 @@
 			.cmp    = {STATUS2, 6, RW},
 			.wps    = {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -18791,6 +18888,9 @@
 			.cmp	= {STATUS2, 6, RW},
 			.wps	= {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 		.prepare_access	= spi_prepare_4ba,
 	},
@@ -18842,6 +18942,9 @@
 			.sec	= {STATUS1, 6, RW},
 			.cmp	= {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -18894,6 +18997,9 @@
 			.cmp	= {STATUS2, 6, RW},
 			.wps	= {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -18984,6 +19090,9 @@
 			.sec    = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -19035,6 +19144,9 @@
 			.cmp    = {STATUS2, 6, RW},
 			.wps	= {STATUS3, 2, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -20349,6 +20461,9 @@
 			.sec    = {STATUS1, 6, RW},
 			.cmp    = {STATUS2, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 	},
 
@@ -20402,6 +20517,9 @@
 			.bp     = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}},
 			.tb     = {STATUS1, 6, RW},
 		},
+		.wp_write_cfg	= spi_wp_write_cfg,
+		.wp_read_cfg	= spi_wp_read_cfg,
+		.wp_get_ranges	= spi_wp_get_available_ranges,
 		.decode_range	= decode_range_spi25,
 		.prepare_access	= spi_prepare_4ba,
 	},
diff --git a/include/flash.h b/include/flash.h
index 561a597..340af59 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -323,6 +323,12 @@
 		struct reg_bit_info wps;
 	} reg_bits;
 
+	/* Write WP configuration to the chip */
+	enum flashprog_wp_result (*wp_write_cfg)(struct flashctx *, const struct flashprog_wp_cfg *);
+	/* Read WP configuration from the chip */
+	enum flashprog_wp_result (*wp_read_cfg)(struct flashprog_wp_cfg *, struct flashctx *);
+	/* Get a list of protection ranges supported by the chip */
+	enum flashprog_wp_result (*wp_get_ranges)(struct flashprog_wp_ranges **, struct flashctx *);
 	/* Function that takes a set of WP config bits (e.g. BP, SEC, TB, etc) */
 	/* and determines what protection range they select. */
 	void (*decode_range)(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len);
diff --git a/include/writeprotect.h b/include/writeprotect.h
index 0e5a86e..356ffb2 100644
--- a/include/writeprotect.h
+++ b/include/writeprotect.h
@@ -78,12 +78,12 @@
 struct flashprog_flashctx;
 
 /* Write WP configuration to the chip */
-enum flashprog_wp_result wp_write_cfg(struct flashprog_flashctx *, const struct flashprog_wp_cfg *);
+enum flashprog_wp_result spi_wp_write_cfg(struct flashprog_flashctx *, const struct flashprog_wp_cfg *);
 
 /* Read WP configuration from the chip */
-enum flashprog_wp_result wp_read_cfg(struct flashprog_wp_cfg *, struct flashprog_flashctx *);
+enum flashprog_wp_result spi_wp_read_cfg(struct flashprog_wp_cfg *, struct flashprog_flashctx *);
 
 /* Get a list of protection ranges supported by the chip */
-enum flashprog_wp_result wp_get_available_ranges(struct flashprog_wp_ranges **, struct flashprog_flashctx *);
+enum flashprog_wp_result spi_wp_get_available_ranges(struct flashprog_wp_ranges **, struct flashprog_flashctx *);
 
 #endif /* !__WRITEPROTECT_H__ */
diff --git a/libflashprog.c b/libflashprog.c
index a7f15b5..6c2a9c9 100644
--- a/libflashprog.c
+++ b/libflashprog.c
@@ -619,15 +619,10 @@
  */
 enum flashprog_wp_result flashprog_wp_write_cfg(struct flashctx *flash, const struct flashprog_wp_cfg *cfg)
 {
-	/*
-	 * TODO: Call custom implementation if the programmer is opaque, as
-	 * direct WP operations require SPI access. In particular, linux_mtd
-	 * has its own WP operations we should use instead.
-	 */
-	if (flash->mst->buses_supported & BUS_SPI)
-		return wp_write_cfg(flash, cfg);
+	if (!flash->chip->wp_write_cfg)
+		return FLASHPROG_WP_ERR_CHIP_UNSUPPORTED;
 
-	return FLASHPROG_WP_ERR_OTHER;
+	return flash->chip->wp_write_cfg(flash, cfg);
 }
 
 /**
@@ -641,15 +636,10 @@
  */
 enum flashprog_wp_result flashprog_wp_read_cfg(struct flashprog_wp_cfg *cfg, struct flashctx *flash)
 {
-	/*
-	 * TODO: Call custom implementation if the programmer is opaque, as
-	 * direct WP operations require SPI access. In particular, linux_mtd
-	 * has its own WP operations we should use instead.
-	 */
-	if (flash->mst->buses_supported & BUS_SPI)
-		return wp_read_cfg(cfg, flash);
+	if (!flash->chip->wp_read_cfg)
+		return FLASHPROG_WP_ERR_CHIP_UNSUPPORTED;
 
-	return FLASHPROG_WP_ERR_OTHER;
+	return flash->chip->wp_read_cfg(cfg, flash);
 }
 
 /**
@@ -666,16 +656,10 @@
  */
 enum flashprog_wp_result flashprog_wp_get_available_ranges(struct flashprog_wp_ranges **list, struct flashprog_flashctx *flash)
 {
-	/*
-	 * TODO: Call custom implementation if the programmer is opaque, as
-	 * direct WP operations require SPI access. We actually can't implement
-	 * this in linux_mtd right now, but we should adopt a proper generic
-	 * architechure to match the read and write functions anyway.
-	 */
-	if (flash->mst->buses_supported & BUS_SPI)
-		return wp_get_available_ranges(list, flash);
+	if (!flash->chip->wp_get_ranges)
+		return FLASHPROG_WP_ERR_CHIP_UNSUPPORTED;
 
-	return FLASHPROG_WP_ERR_OTHER;
+	return flash->chip->wp_get_ranges(list, flash);
 }
 
 /**
diff --git a/writeprotect.c b/writeprotect.c
index b91f3e8..5424518 100644
--- a/writeprotect.c
+++ b/writeprotect.c
@@ -454,7 +454,7 @@
 	return (flash->chip != NULL) && (flash->chip->decode_range != NULL);
 }
 
-enum flashprog_wp_result wp_read_cfg(struct flashprog_wp_cfg *cfg, struct flashctx *flash)
+enum flashprog_wp_result spi_wp_read_cfg(struct flashprog_wp_cfg *cfg, struct flashctx *flash)
 {
 	struct wp_bits bits;
 	enum flashprog_wp_result ret = FLASHPROG_WP_OK;
@@ -474,7 +474,7 @@
 	return ret;
 }
 
-enum flashprog_wp_result wp_write_cfg(struct flashctx *flash, const struct flashprog_wp_cfg *cfg)
+enum flashprog_wp_result spi_wp_write_cfg(struct flashctx *flash, const struct flashprog_wp_cfg *cfg)
 {
 	struct wp_bits bits;
 	enum flashprog_wp_result ret = FLASHPROG_WP_OK;
@@ -500,7 +500,7 @@
 	return ret;
 }
 
-enum flashprog_wp_result wp_get_available_ranges(struct flashprog_wp_ranges **list, struct flashprog_flashctx *flash)
+enum flashprog_wp_result spi_wp_get_available_ranges(struct flashprog_wp_ranges **list, struct flashprog_flashctx *flash)
 {
 	struct wp_bits bits;
 	struct wp_range_and_bits *range_pairs = NULL;