Patchwork [2/5] Prepare wbsio_spi.c for check_trans().

login
register
about
Submitter Stefan Tauner
Date 2012-10-03 04:13:02
Message ID <1349237585-3904-3-git-send-email-stefan.tauner@student.tuwien.ac.at>
Download mbox | patch
Permalink /patch/3766/
State New
Headers show

Comments

Stefan Tauner - 2012-10-03 04:13:02
Introduce determine_mode() which contains the extracted bits of the init
function that do sanity checks but without altering the hardware state.

Signed-off-by: Stefan Tauner <stefan.tauner@student.tuwien.ac.at>
---
 wbsio_spi.c |  136 +++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 77 insertions(+), 59 deletions(-)
Carl-Daniel Hailfinger - 2012-10-15 21:12:22
Am 03.10.2012 06:13 schrieb Stefan Tauner:
> Introduce determine_mode() which contains the extracted bits of the init
> function that do sanity checks but without altering the hardware state.
>
> Signed-off-by: Stefan Tauner <stefan.tauner@student.tuwien.ac.at>

I see that you took great care to avoid the pitfalls in converting that
code. Good!

Side note: That hardware is just awful from a capability/interface
perspective. If I had a way to drive it by bitbanging, I'd do that
instantly. However, the two of the four essential SPI lines (MOSI and
MISO) are not usable as GPIO, so that way of working around hardware
limitations is not going to work.


> ---
>  wbsio_spi.c |  136 +++++++++++++++++++++++++++++++++--------------------------
>  1 file changed, 77 insertions(+), 59 deletions(-)
>
> diff --git a/wbsio_spi.c b/wbsio_spi.c
> index 7d4bb2a..778b983 100644
> --- a/wbsio_spi.c
> +++ b/wbsio_spi.c
> @@ -61,6 +61,53 @@ done:
>  	return flashport;
>  }
>  
> +/* W83627DHG has 11 command modes:
> + * 1=1 command only
> + * 2=1 command+1 data write
> + * 3=1 command+2 data read
> + * 4=1 command+3 address
> + * 5=1 command+3 address+1 data write
> + * 6=1 command+3 address+4 data write
> + * 7=1 command+3 address+1 dummy address inserted by wbsio+4 data read
> + * 8=1 command+3 address+1 data read
> + * 9=1 command+3 address+2 data read
> + * a=1 command+3 address+3 data read
> + * b=1 command+3 address+4 data read
> + *
> + * mode[7:4] holds the command mode
> + * mode[3:0] holds SPI address bits [19:16]
> + *
> + * The Winbond SPI master only supports 20 bit addresses on the SPI bus. :\
> + * Would one more byte of RAM in the chip (to get all 24 bits) really make
> + * such a big difference?
> + */
> +static uint8_t determine_mode(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
> +			      const unsigned char *writearr)
> +{
> +	if (1 == writecnt && 0 == readcnt) {
> +		return 0x10;
> +	} else if (2 == writecnt && 0 == readcnt) {
> +		return 0x20;
> +	} else if (1 == writecnt && 2 == readcnt) {
> +		return 0x30;
> +	} else if (4 == writecnt && 0 == readcnt) {
> +		return 0x40 | (writearr[1] & 0x0f);

Would it be possible to return only 0x40 here, and add the low nibble of
writearr[1] inside wbsio_send_command? That low nibble is not part of
the mode, it just happens to be stored in the same hw register for some
modes.
Same for other cases.

> +	} else if (5 == writecnt && 0 == readcnt) {
> +		return 0x50 | (writearr[1] & 0x0f);
> +	} else if (8 == writecnt && 0 == readcnt) {
> +		return 0x60 | (writearr[1] & 0x0f);
> +	} else if (5 == writecnt && 4 == readcnt) {
> +		/* XXX: TODO not supported by flashrom infrastructure!
> +		 * This mode, 7, discards the fifth byte in writecnt,
> +		 * but since we can not express that in flashrom, fail
> +		 * the operation for now.
> +		 */;
> +	} else if (4 == writecnt && readcnt >= 1 && readcnt <= 4) {
> +		return ((7 + readcnt) << 4) | (writearr[1] & 0x0f);
> +	}
> +	return 0;
> +}
> +
>  static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
>  				  unsigned int readcnt,
>  				  const unsigned char *writearr,
> @@ -95,52 +142,37 @@ int wbsio_check_for_spi(void)
>  	return 0;
>  }
>  
> -/* W83627DHG has 11 command modes:
> - * 1=1 command only
> - * 2=1 command+1 data write
> - * 3=1 command+2 data read
> - * 4=1 command+3 address
> - * 5=1 command+3 address+1 data write
> - * 6=1 command+3 address+4 data write
> - * 7=1 command+3 address+1 dummy address inserted by wbsio+4 data read
> - * 8=1 command+3 address+1 data read
> - * 9=1 command+3 address+2 data read
> - * a=1 command+3 address+3 data read
> - * b=1 command+3 address+4 data read
> - *
> - * mode[7:4] holds the command mode
> - * mode[3:0] holds SPI address bits [19:16]
> - *
> - * The Winbond SPI master only supports 20 bit addresses on the SPI bus. :\
> - * Would one more byte of RAM in the chip (to get all 24 bits) really make
> - * such a big difference?
> - */
>  static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
>  				  unsigned int readcnt,
>  				  const unsigned char *writearr,
>  				  unsigned char *readarr)
>  {
>  	int i;
> -	uint8_t mode = 0;
> +	uint8_t mode = determine_mode(flash, writecnt, readcnt, writearr);
>  
> -	msg_pspew("%s:", __func__);
> +	if (!mode) {
> +		msg_perr("%s: unsupported command type wr=%d rd=%d\n",
> +			__func__, writecnt, readcnt);
> +		/* Command type refers to the number of bytes read/written. */
> +		return SPI_INVALID_LENGTH;
> +	}
>  
> -	if (1 == writecnt && 0 == readcnt) {
> -		mode = 0x10;
> -	} else if (2 == writecnt && 0 == readcnt) {
> +	msg_pspew(" cmd=%02x mode=%02x\n", writearr[0], mode);
> +	switch (mode & 0xF0) {

That masking would become unnecessary.


> +	case 0x10: break;
> +	case 0x20:
>  		OUTB(writearr[1], wbsio_spibase + 4);
>  		msg_pspew(" data=0x%02x", writearr[1]);
> -		mode = 0x20;
> -	} else if (1 == writecnt && 2 == readcnt) {
> -		mode = 0x30;
> -	} else if (4 == writecnt && 0 == readcnt) {
> +		break;
> +	case 0x30: break;
> +	case 0x40:
>  		msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
>  		for (i = 2; i < writecnt; i++) {
>  			OUTB(writearr[i], wbsio_spibase + i);
>  			msg_pspew("%02x", writearr[i]);
>  		}
> -		mode = 0x40 | (writearr[1] & 0x0f);

And here you could use
mode |= (writearr[1] & 0x0f);
Same for other cases where mode >= 0x40.


> -	} else if (5 == writecnt && 0 == readcnt) {
> +		break;
> +	case 0x50:
>  		msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
>  		for (i = 2; i < 4; i++) {
>  			OUTB(writearr[i], wbsio_spibase + i);
> @@ -148,8 +180,8 @@ static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
>  		}
>  		OUTB(writearr[i], wbsio_spibase + i);
>  		msg_pspew(" data=0x%02x", writearr[i]);
> -		mode = 0x50 | (writearr[1] & 0x0f);
> -	} else if (8 == writecnt && 0 == readcnt) {
> +		break;
> +	case 0x60:
>  		msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
>  		for (i = 2; i < 4; i++) {
>  			OUTB(writearr[i], wbsio_spibase + i);
> @@ -160,44 +192,30 @@ static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
>  			OUTB(writearr[i], wbsio_spibase + i);
>  			msg_pspew("%02x", writearr[i]);
>  		}
> -		mode = 0x60 | (writearr[1] & 0x0f);
> -	} else if (5 == writecnt && 4 == readcnt) {
> -		/* XXX: TODO not supported by flashrom infrastructure!
> -		 * This mode, 7, discards the fifth byte in writecnt,
> -		 * but since we can not express that in flashrom, fail
> -		 * the operation for now.
> -		 */
> -		;
> -	} else if (4 == writecnt && readcnt >= 1 && readcnt <= 4) {
> +		break;
> +	case 0x70: /* unimplemented */
> +		break;
> +	default:
>  		msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
>  		for (i = 2; i < writecnt; i++) {
>  			OUTB(writearr[i], wbsio_spibase + i);
>  			msg_pspew("%02x", writearr[i]);
>  		}
> -		mode = ((7 + readcnt) << 4) | (writearr[1] & 0x0f);
> -	}
> -	msg_pspew(" cmd=%02x mode=%02x\n", writearr[0], mode);
> -
> -	if (!mode) {
> -		msg_perr("%s: unsupported command type wr=%d rd=%d\n",
> -			__func__, writecnt, readcnt);
> -		/* Command type refers to the number of bytes read/written. */
> -		return SPI_INVALID_LENGTH;
> +		break;
>  	}
>  
>  	OUTB(writearr[0], wbsio_spibase);
>  	OUTB(mode, wbsio_spibase + 1);
>  	programmer_delay(10);

Side note: I have absolutely no idea why this programmer_delay() is
here. It seems to be pointless... unless the hardware is even more
broken than I thought. No need to change it, I just wanted to point it out.


>  
> -	if (!readcnt)
> -		return 0;
> -
> -	msg_pspew("%s: returning data =", __func__);
> -	for (i = 0; i < readcnt; i++) {
> -		readarr[i] = INB(wbsio_spibase + 4 + i);
> -		msg_pspew(" 0x%02x", readarr[i]);
> +	if (readcnt > 0) {
> +		msg_pspew("%s: returning data =", __func__);
> +		for (i = 0; i < readcnt; i++) {
> +			readarr[i] = INB(wbsio_spibase + 4 + i);
> +			msg_pspew(" 0x%02x", readarr[i]);
> +		}
> +		msg_pspew("\n");
>  	}
> -	msg_pspew("\n");
>  	return 0;
>  }
>  

I don't see the point of this last hunk. Except for additional
indentation and an elimination of an early return, the code stays the
same. IMHO the early return is more readable, but I guess code
readability is in the eye of the beholder. I don't care that much either
way, it's your choice.

Regards,
Carl-Daniel

Patch

diff --git a/wbsio_spi.c b/wbsio_spi.c
index 7d4bb2a..778b983 100644
--- a/wbsio_spi.c
+++ b/wbsio_spi.c
@@ -61,6 +61,53 @@  done:
 	return flashport;
 }
 
+/* W83627DHG has 11 command modes:
+ * 1=1 command only
+ * 2=1 command+1 data write
+ * 3=1 command+2 data read
+ * 4=1 command+3 address
+ * 5=1 command+3 address+1 data write
+ * 6=1 command+3 address+4 data write
+ * 7=1 command+3 address+1 dummy address inserted by wbsio+4 data read
+ * 8=1 command+3 address+1 data read
+ * 9=1 command+3 address+2 data read
+ * a=1 command+3 address+3 data read
+ * b=1 command+3 address+4 data read
+ *
+ * mode[7:4] holds the command mode
+ * mode[3:0] holds SPI address bits [19:16]
+ *
+ * The Winbond SPI master only supports 20 bit addresses on the SPI bus. :\
+ * Would one more byte of RAM in the chip (to get all 24 bits) really make
+ * such a big difference?
+ */
+static uint8_t determine_mode(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+			      const unsigned char *writearr)
+{
+	if (1 == writecnt && 0 == readcnt) {
+		return 0x10;
+	} else if (2 == writecnt && 0 == readcnt) {
+		return 0x20;
+	} else if (1 == writecnt && 2 == readcnt) {
+		return 0x30;
+	} else if (4 == writecnt && 0 == readcnt) {
+		return 0x40 | (writearr[1] & 0x0f);
+	} else if (5 == writecnt && 0 == readcnt) {
+		return 0x50 | (writearr[1] & 0x0f);
+	} else if (8 == writecnt && 0 == readcnt) {
+		return 0x60 | (writearr[1] & 0x0f);
+	} else if (5 == writecnt && 4 == readcnt) {
+		/* XXX: TODO not supported by flashrom infrastructure!
+		 * This mode, 7, discards the fifth byte in writecnt,
+		 * but since we can not express that in flashrom, fail
+		 * the operation for now.
+		 */;
+	} else if (4 == writecnt && readcnt >= 1 && readcnt <= 4) {
+		return ((7 + readcnt) << 4) | (writearr[1] & 0x0f);
+	}
+	return 0;
+}
+
 static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
 				  unsigned int readcnt,
 				  const unsigned char *writearr,
@@ -95,52 +142,37 @@  int wbsio_check_for_spi(void)
 	return 0;
 }
 
-/* W83627DHG has 11 command modes:
- * 1=1 command only
- * 2=1 command+1 data write
- * 3=1 command+2 data read
- * 4=1 command+3 address
- * 5=1 command+3 address+1 data write
- * 6=1 command+3 address+4 data write
- * 7=1 command+3 address+1 dummy address inserted by wbsio+4 data read
- * 8=1 command+3 address+1 data read
- * 9=1 command+3 address+2 data read
- * a=1 command+3 address+3 data read
- * b=1 command+3 address+4 data read
- *
- * mode[7:4] holds the command mode
- * mode[3:0] holds SPI address bits [19:16]
- *
- * The Winbond SPI master only supports 20 bit addresses on the SPI bus. :\
- * Would one more byte of RAM in the chip (to get all 24 bits) really make
- * such a big difference?
- */
 static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
 				  unsigned int readcnt,
 				  const unsigned char *writearr,
 				  unsigned char *readarr)
 {
 	int i;
-	uint8_t mode = 0;
+	uint8_t mode = determine_mode(flash, writecnt, readcnt, writearr);
 
-	msg_pspew("%s:", __func__);
+	if (!mode) {
+		msg_perr("%s: unsupported command type wr=%d rd=%d\n",
+			__func__, writecnt, readcnt);
+		/* Command type refers to the number of bytes read/written. */
+		return SPI_INVALID_LENGTH;
+	}
 
-	if (1 == writecnt && 0 == readcnt) {
-		mode = 0x10;
-	} else if (2 == writecnt && 0 == readcnt) {
+	msg_pspew(" cmd=%02x mode=%02x\n", writearr[0], mode);
+	switch (mode & 0xF0) {
+	case 0x10: break;
+	case 0x20:
 		OUTB(writearr[1], wbsio_spibase + 4);
 		msg_pspew(" data=0x%02x", writearr[1]);
-		mode = 0x20;
-	} else if (1 == writecnt && 2 == readcnt) {
-		mode = 0x30;
-	} else if (4 == writecnt && 0 == readcnt) {
+		break;
+	case 0x30: break;
+	case 0x40:
 		msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
 		for (i = 2; i < writecnt; i++) {
 			OUTB(writearr[i], wbsio_spibase + i);
 			msg_pspew("%02x", writearr[i]);
 		}
-		mode = 0x40 | (writearr[1] & 0x0f);
-	} else if (5 == writecnt && 0 == readcnt) {
+		break;
+	case 0x50:
 		msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
 		for (i = 2; i < 4; i++) {
 			OUTB(writearr[i], wbsio_spibase + i);
@@ -148,8 +180,8 @@  static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
 		}
 		OUTB(writearr[i], wbsio_spibase + i);
 		msg_pspew(" data=0x%02x", writearr[i]);
-		mode = 0x50 | (writearr[1] & 0x0f);
-	} else if (8 == writecnt && 0 == readcnt) {
+		break;
+	case 0x60:
 		msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
 		for (i = 2; i < 4; i++) {
 			OUTB(writearr[i], wbsio_spibase + i);
@@ -160,44 +192,30 @@  static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
 			OUTB(writearr[i], wbsio_spibase + i);
 			msg_pspew("%02x", writearr[i]);
 		}
-		mode = 0x60 | (writearr[1] & 0x0f);
-	} else if (5 == writecnt && 4 == readcnt) {
-		/* XXX: TODO not supported by flashrom infrastructure!
-		 * This mode, 7, discards the fifth byte in writecnt,
-		 * but since we can not express that in flashrom, fail
-		 * the operation for now.
-		 */
-		;
-	} else if (4 == writecnt && readcnt >= 1 && readcnt <= 4) {
+		break;
+	case 0x70: /* unimplemented */
+		break;
+	default:
 		msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
 		for (i = 2; i < writecnt; i++) {
 			OUTB(writearr[i], wbsio_spibase + i);
 			msg_pspew("%02x", writearr[i]);
 		}
-		mode = ((7 + readcnt) << 4) | (writearr[1] & 0x0f);
-	}
-	msg_pspew(" cmd=%02x mode=%02x\n", writearr[0], mode);
-
-	if (!mode) {
-		msg_perr("%s: unsupported command type wr=%d rd=%d\n",
-			__func__, writecnt, readcnt);
-		/* Command type refers to the number of bytes read/written. */
-		return SPI_INVALID_LENGTH;
+		break;
 	}
 
 	OUTB(writearr[0], wbsio_spibase);
 	OUTB(mode, wbsio_spibase + 1);
 	programmer_delay(10);
 
-	if (!readcnt)
-		return 0;
-
-	msg_pspew("%s: returning data =", __func__);
-	for (i = 0; i < readcnt; i++) {
-		readarr[i] = INB(wbsio_spibase + 4 + i);
-		msg_pspew(" 0x%02x", readarr[i]);
+	if (readcnt > 0) {
+		msg_pspew("%s: returning data =", __func__);
+		for (i = 0; i < readcnt; i++) {
+			readarr[i] = INB(wbsio_spibase + 4 + i);
+			msg_pspew(" 0x%02x", readarr[i]);
+		}
+		msg_pspew("\n");
 	}
-	msg_pspew("\n");
 	return 0;
 }