[flashrom] [PATCH 8/8] squash! ichspi:c add support for Intel Hardware Sequencing

Stefan Tauner stefan.tauner at student.tuwien.ac.at
Tue Jun 28 05:33:23 CEST 2011


- add SPI_CONTROLLER_ICH_HWSEQ support to ich_set_bbar although unused atm
- remove ich_hwseq_get_flash_boundary
- use all fdata registers for transfers
- allow 25b addresses and add ich_hwseq_set_addr

Signed-off-by: Stefan Tauner <stefan.tauner at student.tuwien.ac.at>
---
 ichspi.c |   83 ++++++++++++++++++++++++++++---------------------------------
 1 files changed, 38 insertions(+), 45 deletions(-)

diff --git a/ichspi.c b/ichspi.c
index 361006d..fd3b808 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -577,6 +577,7 @@ static void ich_set_bbar(uint32_t min_addr)
 		bbar_off = 0x50;
 		break;
 	case SPI_CONTROLLER_ICH9:
+	case SPI_CONTROLLER_ICH_HWSEQ:
 		bbar_off = ICH9_REG_BBAR;
 		break;
 	default:
@@ -1092,9 +1093,10 @@ static int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
 	return result;
 }
 
-static uint32_t ich_hwseq_get_flash_boundary(void)
+static void ich_hwseq_set_addr(uint32_t addr)
 {
-	return (REGREAD32(ICH9_REG_FPB) & FPB_FPBA) << 12;
+	uint32_t addr_old = REGREAD32(ICH9_REG_FADDR) & ~0x01FFFFFF;
+	REGWRITE32(ICH9_REG_FADDR, (addr & 0x01FFFFFF) | addr_old);
 }
 
 /* Sets FADDR.FLA to 'addr' and returns the erase block size in bytes
@@ -1109,7 +1111,7 @@ static uint32_t ich_hwseq_get_erase_block_size(unsigned int addr)
 		64 * 1024
 	};
 
-	REGWRITE32(ICH9_REG_FADDR, (addr & 0x00FFFFFF));
+	ich_hwseq_set_addr(addr);
 	enc_berase = (REGREAD16(ICH9_REG_HSFS) & HSFS_BERASE) >>
 		     HSFS_BERASE_OFF;
 	return dec_berase[enc_berase];
@@ -1132,9 +1134,9 @@ static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout,
 	}
 	REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
 	if (!timeout) {
-		addr = REGREAD32(ICH9_REG_FADDR);
-		msg_perr("Timeout error between offset 0x%06x and "
-			 "0x%06x + %d (=0x%06x)!\n",
+		addr = REGREAD32(ICH9_REG_FADDR) & 0x01FFFFFF;
+		msg_perr("Timeout error between offset 0x%08x and "
+			 "0x%08x + %d (=0x%08x)!\n",
 			 addr, addr, len - 1, addr + len - 1);
 		prettyprint_ich9_reg_hsfs(hsfs);
 		prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC));
@@ -1142,9 +1144,9 @@ static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout,
 	}
 
 	if (hsfs & HSFS_FCERR) {
-		addr = REGREAD32(ICH9_REG_FADDR);
-		msg_perr("Transaction error between offset 0x%06x and "
-			 "0x%06x + %d (=0x%06x)!\n",
+		addr = REGREAD32(ICH9_REG_FADDR) & 0x01FFFFFF;
+		msg_perr("Transaction error between offset 0x%08x and "
+			 "0x%08x + %d (=0x%08x)!\n",
 			 addr, addr, len - 1, addr + len - 1);
 		prettyprint_ich9_reg_hsfs(hsfs);
 		prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC));
@@ -1175,8 +1177,8 @@ int ich_hwseq_probe(struct flashchip *flash)
 		msg_cdbg("not met.\n");
 		return 0;
 	}
-
 	msg_cdbg("met.\n");
+
 	total_size = (getFCBA_component_density(0) +
 		      getFCBA_component_density(1));
 	msg_cdbg("Found %d attached SPI flash chip", fdbar.NC + 1);
@@ -1188,7 +1190,7 @@ int ich_hwseq_probe(struct flashchip *flash)
 	flash->total_size = total_size / 1024;
 
 	eraser = &(flash->block_erasers[0]);
-	boundary = ich_hwseq_get_flash_boundary();
+	boundary = (REGREAD32(ICH9_REG_FPB) & FPB_FPBA) << 12;
 	size_high = total_size - boundary;
 	erase_size_high = ich_hwseq_get_erase_block_size(boundary);
 
@@ -1292,10 +1294,9 @@ int ich_hwseq_block_erase(struct flashchip *flash,
 
 int ich_hwseq_read(struct flashchip *flash, uint8_t *buf, int addr, int len)
 {
-	uint32_t *buf32 = (uint32_t *)buf;
 	uint16_t hsfc;
 	uint16_t timeout = 100 * 60;
-	int i;
+	uint8_t block_len;
 
 	if (flash->manufacture_id != INTEL_ID ||
 	    flash->model_id != INTEL_HWSEQ) {
@@ -1304,14 +1305,8 @@ int ich_hwseq_read(struct flashchip *flash, uint8_t *buf, int addr, int len)
 		return -1;
 	}
 
-	if (len % 4 != 0) {
-		msg_perr("Read size has to be a multiple of 4 for this "
-			 "implementation of hardware sequencing mode.\n");
-		return -1;
-	}
-
-	if (addr < 0 || addr + len > 0x00FFFFFF) {
-		msg_perr("Request to read from inaccessible memory address "
+	if (addr < 0 || addr + len > 0x01FFFFFF) {
+		msg_perr("Request to read from an inaccessible memory address "
 			 "(addr=0x%x, len=%d).\n", addr, len);
 		return -1;
 	}
@@ -1320,30 +1315,32 @@ int ich_hwseq_read(struct flashchip *flash, uint8_t *buf, int addr, int len)
 	/* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
 	REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
 
-	for (i = 0; i < len; i += 4) {
-		/* FIXME: reserved bits */
-		REGWRITE32(ICH9_REG_FADDR, (addr & 0x00FFFFFF));
+	while (len > 0) {
+		block_len = min(len, spi_programmer->max_data_read);
+		ich_hwseq_set_addr(addr);
 		hsfc = REGREAD16(ICH9_REG_HSFC);
 		hsfc &= ~HSFC_FCYCLE; /* set read operation */
 		hsfc &= ~HSFC_FDBC; /* clear byte count */
-		hsfc |= (3 << HSFC_FDBC_OFF); /* set byte count to 3+1 */
+		hsfc |= ((block_len - 1) << HSFC_FDBC_OFF); /* set byte count */
 		hsfc |= HSFC_FGO; /* start */
 		REGWRITE16(ICH9_REG_HSFC, hsfc);
 
 		if (ich_hwseq_wait_for_cycle_complete(timeout, 4))
 			return 1;
-		*buf32++ = REGREAD32(ICH9_REG_FDATA0);
-		addr += 4;
+		ich_read_data(buf, block_len, ICH9_REG_FDATA0);
+		addr += block_len;
+		buf += block_len;
+		len -= block_len;
 	}
 	return 0;
 }
 
 int ich_hwseq_write_256(struct flashchip *flash, uint8_t *buf, int addr, int len)
 {
-	uint32_t *buf32 = (uint32_t *)buf;
 	uint16_t hsfc;
 	uint16_t timeout = 100 * 60;
-	int i;
+	uint8_t block_len;
+
 	if (flash->manufacture_id != INTEL_ID ||
 	    flash->model_id != INTEL_HWSEQ) {
 		msg_perr("This chip (%s) is not supported in hardware"
@@ -1351,14 +1348,8 @@ int ich_hwseq_write_256(struct flashchip *flash, uint8_t *buf, int addr, int len
 		return -1;
 	}
 
-	if ((len % 4 != 0)) {
-		msg_perr("Write size has to be a multiple of 4 for this "
-			 "implementation of hardware sequencing mode\n");
-		return -1;
-	}
-
 	if (addr < 0 || addr + len > 0x00FFFFFF) {
-		msg_perr("Request to write to inaccessible memory address "
+		msg_perr("Request to write to an inaccessible memory address "
 			 "(addr=0x%x, len=%d).\n", addr, len);
 		return -1;
 	}
@@ -1367,22 +1358,24 @@ int ich_hwseq_write_256(struct flashchip *flash, uint8_t *buf, int addr, int len
 	/* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
 	REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
 
-	for (i = 0; i < len; i += 4) {
-		/* FIXME: reserved bits */
-		REGWRITE32(ICH9_REG_FADDR, (addr & 0x00FFFFFF));
-		REGWRITE32(ICH9_REG_FDATA0, *buf32);
+	while (len > 0) {
+		ich_hwseq_set_addr(addr);
+		block_len = ich_fill_data(buf, len, ICH9_REG_FDATA0);
+		if (block_len < 0)
+			return block_len;
 		hsfc = REGREAD16(ICH9_REG_HSFC);
 		hsfc &= ~HSFC_FCYCLE; /* clear operation */
 		hsfc |= (0x2 << HSFC_FCYCLE_OFF); /* set write operation */
 		hsfc &= ~HSFC_FDBC; /* clear byte count */
-		hsfc |= (3 << HSFC_FDBC_OFF); /* set byte count to 3+1 */
+		hsfc |= ((block_len - 1) << HSFC_FDBC_OFF); /* set byte count */
 		hsfc |= HSFC_FGO; /* start */
 		REGWRITE16(ICH9_REG_HSFC, hsfc);
 
-		if (ich_hwseq_wait_for_cycle_complete(timeout, 4))
-			return 1;
-		addr += 4;
-		buf32++;
+		if (ich_hwseq_wait_for_cycle_complete(timeout, block_len))
+			return -1;
+		addr += block_len;
+		buf += block_len;
+		len -= block_len;
 	}
 	return 0;
 }
-- 
1.7.1





More information about the flashrom mailing list