]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/mtd/devices/bcm47xxsflash.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / drivers / mtd / devices / bcm47xxsflash.c
index 4decd8c0360a91c5ccf6bcb2648dbed07464e341..e2bd81817df44b89bc8ed2b04d074949496785dc 100644 (file)
@@ -105,15 +105,33 @@ static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
                              size_t *retlen, u_char *buf)
 {
        struct bcm47xxsflash *b47s = mtd->priv;
+       size_t orig_len = len;
 
        /* Check address range */
        if ((from + len) > mtd->size)
                return -EINVAL;
 
-       memcpy_fromio(buf, b47s->window + from, len);
-       *retlen = len;
+       /* Read as much as possible using fast MMIO window */
+       if (from < BCM47XXSFLASH_WINDOW_SZ) {
+               size_t memcpy_len;
 
-       return len;
+               memcpy_len = min(len, (size_t)(BCM47XXSFLASH_WINDOW_SZ - from));
+               memcpy_fromio(buf, b47s->window + from, memcpy_len);
+               from += memcpy_len;
+               len -= memcpy_len;
+               buf += memcpy_len;
+       }
+
+       /* Use indirect access for content out of the window */
+       for (; len; len--) {
+               b47s->cc_write(b47s, BCMA_CC_FLASHADDR, from++);
+               bcm47xxsflash_cmd(b47s, OPCODE_ST_READ4B);
+               *buf++ = b47s->cc_read(b47s, BCMA_CC_FLASHDATA);
+       }
+
+       *retlen = orig_len;
+
+       return orig_len;
 }
 
 static int bcm47xxsflash_write_st(struct mtd_info *mtd, u32 offset, size_t len,