[5/6] Integrate new infrastructure with existing codebase

Message ID 1467750485-29158-6-git-send-email-hatim@hatimak.me
State New
Headers show

Commit Message

Hatim Kanchwala July 5, 2016, 8:28 p.m.
- New infrastructure is used to read status register (for chips that have support for struct status_register) throughout spi25.c.
- New infrastructure is used to prettyprint status register and write protection mode of status register (for chips that have support for struct status_register) in flashrom.c.
- New disable from access protection infrastructure is used (for chips that have support for struct wp) in flashrom.c

Signed-off-by: Hatim Kanchwala <hatim@hatimak.me>
---
 flashrom.c |  17 +++++--
 spi25.c    | 164 ++++++++++++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 145 insertions(+), 36 deletions(-)

Patch

diff --git a/flashrom.c b/flashrom.c
index 25e53f2..3e19cd6 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -26,26 +26,27 @@ 
 #ifndef __LIBPAYLOAD__
 #include <fcntl.h>
 #include <sys/stat.h>
 #endif
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <ctype.h>
 #include <getopt.h>
 #if HAVE_UTSNAME == 1
 #include <sys/utsname.h>
 #endif
+#include "chipdrivers.h"
 #include "flash.h"
 #include "flashchips.h"
 #include "programmer.h"
 #include "hwaccess.h"
 
 const char flashrom_version[] = FLASHROM_VERSION;
 const char *chip_to_probe = NULL;
 
 static enum programmer programmer = PROGRAMMER_INVALID;
 static const char *programmer_param = NULL;
 
 /*
  * Programmers supporting multiple buses can have differing size limits on
@@ -1250,29 +1251,37 @@  notfound:
 	msg_cinfo("%s %s flash chip \"%s\" (%d kB, %s) ", force ? "Assuming" : "Found",
 		  flash->chip->vendor, flash->chip->name, flash->chip->total_size, tmp);
 	free(tmp);
 #if CONFIG_INTERNAL == 1
 	if (programmer_table[programmer].map_flash_region == physmap)
 		msg_cinfo("mapped at physical address 0x%0*" PRIxPTR ".\n",
 			  PRIxPTR_WIDTH, flash->physical_memory);
 	else
 #endif
 		msg_cinfo("on %s.\n", programmer_table[programmer].name);
 
 	/* Flash registers may more likely not be mapped if the chip was forced.
 	 * Lock info may be stored in registers, so avoid lock info printing. */
-	if (!force)
-		if (flash->chip->printlock)
+	if (!force) {
+		if (flash->chip->status_register) {
+			for (enum status_register_num SRn = SR1; SRn <= top_status_register(flash); SRn++)
+				flash->chip->status_register->print(flash, SRn);
+			flash->chip->status_register->print_wp_mode(flash);
+			if (flash->chip->wp)
+				print_range_generic(flash);
+		} else if (flash->chip->printlock) {
 			flash->chip->printlock(flash);
+		}
+	}
 
 	/* Get out of the way for later runs. */
 	unmap_flash(flash);
 
 	/* Return position of matching chip. */
 	return chip - flashchips;
 }
 
 int read_buf_from_file(unsigned char *buf, unsigned long size,
 		       const char *filename)
 {
 #ifdef __LIBPAYLOAD__
 	msg_gerr("Error: No file I/O support in libpayload\n");
@@ -1988,27 +1997,29 @@  int doit(struct flashctx *flash, int force, const char *filename, int read_it,
 	if (chip_safety_check(flash, force, read_it, write_it, erase_it, verify_it)) {
 		msg_cerr("Aborting.\n");
 		return 1;
 	}
 
 	if (normalize_romentries(flash)) {
 		msg_cerr("Requested regions can not be handled. Aborting.\n");
 		return 1;
 	}
 
 	/* Given the existence of read locks, we want to unlock for read,
 	 * erase and write.
 	 */
-	if (flash->chip->unlock)
+	if (flash->chip->wp)
+		flash->chip->wp->disable(flash);
+	else if (flash->chip->unlock)
 		flash->chip->unlock(flash);
 
 	if (read_it) {
 		return read_flash_to_file(flash, filename);
 	}
 
 	oldcontents = malloc(size);
 	if (!oldcontents) {
 		msg_gerr("Out of memory!\n");
 		exit(1);
 	}
 	/* Assume worst case: All bits are 0. */
 	memset(oldcontents, 0x00, size);
diff --git a/spi25.c b/spi25.c
index af4b6db..51db4c8 100644
--- a/spi25.c
+++ b/spi25.c
@@ -341,29 +341,35 @@  int spi_chip_erase_60(struct flashctx *flash)
 		.readcnt	= 0,
 		.readarr	= NULL,
 	}};
 	
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution\n",
 			__func__);
 		return result;
 	}
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 1-85 s, so wait in 1 s steps.
 	 */
-	/* FIXME: We assume spi_read_status_register will never fail. */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(1000 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(1000 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(1000 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 int spi_chip_erase_62(struct flashctx *flash)
 {
 	int result;
 	struct spi_command cmds[] = {
 	{
 		.writecnt	= JEDEC_WREN_OUTSIZE,
 		.writearr	= (const unsigned char[]){ JEDEC_WREN },
 		.readcnt	= 0,
 		.readarr	= NULL,
@@ -378,29 +384,35 @@  int spi_chip_erase_62(struct flashctx *flash)
 		.readcnt	= 0,
 		.readarr	= NULL,
 	}};
 	
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution\n",
 			__func__);
 		return result;
 	}
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 2-5 s, so wait in 100 ms steps.
 	 */
-	/* FIXME: We assume spi_read_status_register will never fail. */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(100 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(100 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(100 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 int spi_chip_erase_c7(struct flashctx *flash)
 {
 	int result;
 	struct spi_command cmds[] = {
 	{
 		.writecnt	= JEDEC_WREN_OUTSIZE,
 		.writearr	= (const unsigned char[]){ JEDEC_WREN },
 		.readcnt	= 0,
 		.readarr	= NULL,
@@ -414,29 +426,35 @@  int spi_chip_erase_c7(struct flashctx *flash)
 		.writearr	= NULL,
 		.readcnt	= 0,
 		.readarr	= NULL,
 	}};
 
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution\n", __func__);
 		return result;
 	}
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 1-85 s, so wait in 1 s steps.
 	 */
-	/* FIXME: We assume spi_read_status_register will never fail. */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(1000 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(1000 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(1000 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 int spi_block_erase_52(struct flashctx *flash, unsigned int addr,
 		       unsigned int blocklen)
 {
 	int result;
 	struct spi_command cmds[] = {
 	{
 		.writecnt	= JEDEC_WREN_OUTSIZE,
 		.writearr	= (const unsigned char[]){ JEDEC_WREN },
 		.readcnt	= 0,
@@ -457,28 +475,35 @@  int spi_block_erase_52(struct flashctx *flash, unsigned int addr,
 		.readcnt	= 0,
 		.readarr	= NULL,
 	}};
 
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n",
 			__func__, addr);
 		return result;
 	}
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 100-4000 ms, so wait in 100 ms steps.
 	 */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(100 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(100 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(100 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 /* Block size is usually
  * 32M (one die) for Micron
  */
 int spi_block_erase_c4(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
 {
 	int result;
 	struct spi_command cmds[] = {
 	{
 		.writecnt	= JEDEC_WREN_OUTSIZE,
@@ -500,28 +525,35 @@  int spi_block_erase_c4(struct flashctx *flash, unsigned int addr, unsigned int b
 		.writearr	= NULL,
 		.readcnt	= 0,
 		.readarr	= NULL,
 	}};
 
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n", __func__, addr);
 		return result;
 	}
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 240-480 s, so wait in 500 ms steps.
 	 */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(500 * 1000 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(500 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(500 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 /* Block size is usually
  * 64k for Macronix
  * 32k for SST
  * 4-32k non-uniform for EON
  */
 int spi_block_erase_d8(struct flashctx *flash, unsigned int addr,
 		       unsigned int blocklen)
 {
 	int result;
@@ -547,28 +579,35 @@  int spi_block_erase_d8(struct flashctx *flash, unsigned int addr,
 		.readcnt	= 0,
 		.readarr	= NULL,
 	}};
 
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n",
 			__func__, addr);
 		return result;
 	}
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 100-4000 ms, so wait in 100 ms steps.
 	 */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(100 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(100 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(100 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 /* Block size is usually
  * 4k for PMC
  */
 int spi_block_erase_d7(struct flashctx *flash, unsigned int addr,
 		       unsigned int blocklen)
 {
 	int result;
 	struct spi_command cmds[] = {
 	{
@@ -592,28 +631,35 @@  int spi_block_erase_d7(struct flashctx *flash, unsigned int addr,
 		.readcnt	= 0,
 		.readarr	= NULL,
 	}};
 
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n",
 			__func__, addr);
 		return result;
 	}
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 100-4000 ms, so wait in 100 ms steps.
 	 */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(100 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(100 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(100 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 /* Page erase (usually 256B blocks) */
 int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
 {
 	int result;
 	struct spi_command cmds[] = {
 	{
 		.writecnt	= JEDEC_WREN_OUTSIZE,
 		.writearr	= (const unsigned char[]){ JEDEC_WREN },
 		.readcnt	= 0,
@@ -633,28 +679,35 @@  int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int b
 		.writearr	= NULL,
 		.readcnt	= 0,
 		.readarr	= NULL,
 	} };
 
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n", __func__, addr);
 		return result;
 	}
 
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This takes up to 20 ms usually (on worn out devices up to the 0.5s range), so wait in 1 ms steps. */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(1 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(1 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(1 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 /* Sector size is usually 4k, though Macronix eliteflash has 64k */
 int spi_block_erase_20(struct flashctx *flash, unsigned int addr,
 		       unsigned int blocklen)
 {
 	int result;
 	struct spi_command cmds[] = {
 	{
 		.writecnt	= JEDEC_WREN_OUTSIZE,
 		.writearr	= (const unsigned char[]){ JEDEC_WREN },
@@ -676,28 +729,35 @@  int spi_block_erase_20(struct flashctx *flash, unsigned int addr,
 		.readcnt	= 0,
 		.readarr	= NULL,
 	}};
 
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n",
 			__func__, addr);
 		return result;
 	}
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 15-800 ms, so wait in 10 ms steps.
 	 */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(10 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(10 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(10 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 int spi_block_erase_50(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
 {
 	int result;
 	struct spi_command cmds[] = {
 	{
 /*		.writecnt	= JEDEC_WREN_OUTSIZE,
 		.writearr	= (const unsigned char[]){ JEDEC_WREN },
 		.readcnt	= 0,
 		.readarr	= NULL,
@@ -716,28 +776,35 @@  int spi_block_erase_50(struct flashctx *flash, unsigned int addr, unsigned int b
 		.writearr	= NULL,
 		.readcnt	= 0,
 		.readarr	= NULL,
 	}};
 
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n", __func__, addr);
 		return result;
 	}
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 10 ms, so wait in 1 ms steps.
 	 */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(1 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(1 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(1 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 int spi_block_erase_81(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
 {
 	int result;
 	struct spi_command cmds[] = {
 	{
 /*		.writecnt	= JEDEC_WREN_OUTSIZE,
 		.writearr	= (const unsigned char[]){ JEDEC_WREN },
 		.readcnt	= 0,
 		.readarr	= NULL,
@@ -756,28 +823,35 @@  int spi_block_erase_81(struct flashctx *flash, unsigned int addr, unsigned int b
 		.writearr	= NULL,
 		.readcnt	= 0,
 		.readarr	= NULL,
 	}};
 
 	result = spi_send_multicommand(flash, cmds);
 	if (result) {
 		msg_cerr("%s failed during command execution at address 0x%x\n", __func__, addr);
 		return result;
 	}
 	/* Wait until the Write-In-Progress bit is cleared.
 	 * This usually takes 8 ms, so wait in 1 ms steps.
 	 */
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(1 * 1000);
+	/* FIXME: We assume reading status register(s) will never fail. */
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(1 * 1000);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(1 * 1000);
+	}
 	/* FIXME: Check the status register for errors. */
 	return 0;
 }
 
 int spi_block_erase_60(struct flashctx *flash, unsigned int addr,
 		       unsigned int blocklen)
 {
 	if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
 		msg_cerr("%s called with incorrect arguments\n",
 			__func__);
 		return -1;
 	}
 	return spi_chip_erase_60(flash);
@@ -1004,54 +1078,66 @@  int spi_write_chunked(struct flashctx *flash, const uint8_t *buf, unsigned int s
 	 * page as well, the loop condition uses <=.
 	 */
 	for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
 		/* Byte position of the first byte in the range in this page. */
 		/* starthere is an offset to the base address of the chip. */
 		starthere = max(start, i * page_size);
 		/* Length of bytes in the range in this page. */
 		lenhere = min(start + len, (i + 1) * page_size) - starthere;
 		for (j = 0; j < lenhere; j += chunksize) {
 			towrite = min(chunksize, lenhere - j);
 			rc = spi_nbyte_program(flash, starthere + j, buf + starthere - start + j, towrite);
 			if (rc)
 				break;
-			while (spi_read_status_register(flash) & SPI_SR_WIP)
-				programmer_delay(10);
+			// TODO(hatim): Switch to newer infrastructure completely after integration
+			if (flash->chip->status_register) {
+				while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+					programmer_delay(10);
+			} else {
+				while (spi_read_status_register(flash) & SPI_SR_WIP)
+					programmer_delay(10);
+			}
 		}
 		if (rc)
 			break;
 	}
 
 	return rc;
 }
 
 /*
  * Program chip using byte programming. (SLOW!)
  * This is for chips which can only handle one byte writes
  * and for chips where memory mapped programming is impossible
  * (e.g. due to size constraints in IT87* for over 512 kB)
  */
 /* real chunksize is 1, logical chunksize is 1 */
 int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
 {
 	unsigned int i;
 	int result = 0;
 
 	for (i = start; i < start + len; i++) {
 		result = spi_byte_program(flash, i, buf[i - start]);
 		if (result)
 			return 1;
-		while (spi_read_status_register(flash) & SPI_SR_WIP)
-			programmer_delay(10);
+		// TODO(hatim): Switch to newer infrastructure completely after integration
+		if (flash->chip->status_register) {
+			while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+				programmer_delay(10);
+		} else {
+			while (spi_read_status_register(flash) & SPI_SR_WIP)
+				programmer_delay(10);
+		}
 	}
 
 	return 0;
 }
 
 int default_spi_write_aai(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
 {
 	uint32_t pos = start;
 	int result;
 	unsigned char cmd[JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE] = {
 		JEDEC_AAI_WORD_PROGRAM,
 	};
 	struct spi_command cmds[] = {
@@ -1120,43 +1206,55 @@  int default_spi_write_aai(struct flashctx *flash, const uint8_t *buf, unsigned i
 	if (len % 2) {
 		msg_cerr("%s: total write length not even! Please report a "
 			 "bug at flashrom@flashrom.org\n", __func__);
 		/* Do not return an error for now. */
 		//return SPI_GENERIC_ERROR;
 	}
 
 
 	result = spi_send_multicommand(flash, cmds);
 	if (result != 0) {
 		msg_cerr("%s failed during start command execution: %d\n", __func__, result);
 		goto bailout;
 	}
-	while (spi_read_status_register(flash) & SPI_SR_WIP)
-		programmer_delay(10);
+	// TODO(hatim): Switch to newer infrastructure completely after integration
+	if (flash->chip->status_register) {
+		while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+			programmer_delay(10);
+	} else {
+		while (spi_read_status_register(flash) & SPI_SR_WIP)
+			programmer_delay(10);
+	}
 
 	/* We already wrote 2 bytes in the multicommand step. */
 	pos += 2;
 
 	/* Are there at least two more bytes to write? */
 	while (pos < start + len - 1) {
 		cmd[1] = buf[pos++ - start];
 		cmd[2] = buf[pos++ - start];
 		result = spi_send_command(flash, JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL);
 		if (result != 0) {
 			msg_cerr("%s failed during followup AAI command execution: %d\n", __func__, result);
 			goto bailout;
 		}
-		while (spi_read_status_register(flash) & SPI_SR_WIP)
-			programmer_delay(10);
+		// TODO(hatim): Switch to newer infrastructure completely after integration
+		if (flash->chip->status_register) {
+			while (flash->chip->status_register->read(flash, SR1) & SPI_SR_WIP)
+				programmer_delay(10);
+		} else {
+			while (spi_read_status_register(flash) & SPI_SR_WIP)
+				programmer_delay(10);
+		}
 	}
 
 	/* Use WRDI to exit AAI mode. This needs to be done before issuing any other non-AAI command. */
 	result = spi_write_disable(flash);
 	if (result != 0) {
 		msg_cerr("%s failed to disable AAI mode.\n", __func__);
 		return SPI_GENERIC_ERROR;
 	}
 
 	/* Write remaining byte (if any). */
 	if (pos < start + len) {
 		if (spi_chip_write_1(flash, buf + pos - start, pos, pos % 2))
 			return SPI_GENERIC_ERROR;