- 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 <[email protected]>
---
 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


_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to