- 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@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; }