[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