diff options
author | hauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2013-07-14 13:44:45 +0000 |
---|---|---|
committer | hauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2013-07-14 13:44:45 +0000 |
commit | d1fe9ae4b4d812824fd58bfb65ae8370a6222524 (patch) | |
tree | bae55f3e27f76f5ad1220579179cacfbfb41d373 /target/linux/brcm47xx/patches-3.10/053-mtd_bcm47xxsflash_writing_support.patch | |
parent | 73ae2cd726a08be048725580c5abc492aa607aac (diff) |
brcm47xx: add initial support for kernel 3.10
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@37287 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/brcm47xx/patches-3.10/053-mtd_bcm47xxsflash_writing_support.patch')
-rw-r--r-- | target/linux/brcm47xx/patches-3.10/053-mtd_bcm47xxsflash_writing_support.patch | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/target/linux/brcm47xx/patches-3.10/053-mtd_bcm47xxsflash_writing_support.patch b/target/linux/brcm47xx/patches-3.10/053-mtd_bcm47xxsflash_writing_support.patch new file mode 100644 index 0000000000..1938a4177f --- /dev/null +++ b/target/linux/brcm47xx/patches-3.10/053-mtd_bcm47xxsflash_writing_support.patch @@ -0,0 +1,160 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Subject: [RFC][PATCH] mtd: bcm47xxsflash: writing support +Date: Wed, 22 May 2013 14:39:02 +0200 + +--- + drivers/mtd/devices/bcm47xxsflash.c | 130 +++++++++++++++++++++++++++++++++-- + 1 file changed, 126 insertions(+), 4 deletions(-) + +--- a/drivers/mtd/devices/bcm47xxsflash.c ++++ b/drivers/mtd/devices/bcm47xxsflash.c +@@ -116,6 +116,127 @@ static int bcm47xxsflash_read(struct mtd + return len; + } + ++static int bcm47xxsflash_write_st(struct mtd_info *mtd, u32 offset, size_t len, ++ const u_char *buf) ++{ ++ struct bcm47xxsflash *b47s = mtd->priv; ++ int written = 0; ++ ++ /* Enable writes */ ++ bcm47xxsflash_cmd(b47s, OPCODE_ST_WREN); ++ ++ /* Write first byte */ ++ b47s->cc_write(b47s, BCMA_CC_FLASHADDR, offset); ++ b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++); ++ ++ /* Program page */ ++ if (b47s->bcma_cc->core->id.rev < 20) { ++ bcm47xxsflash_cmd(b47s, OPCODE_ST_PP); ++ return 1; /* 1B written */ ++ } ++ ++ /* Program page and set CSA (on newer chips we can continue writing) */ ++ bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | OPCODE_ST_PP); ++ offset++; ++ len--; ++ written++; ++ ++ while (len > 0) { ++ /* Page boundary, another function call is needed */ ++ if ((offset & 0xFF) == 0) ++ break; ++ ++ bcm47xxsflash_cmd(b47s, OPCODE_ST_CSA | *buf++); ++ offset++; ++ len--; ++ written++; ++ } ++ ++ /* All done, drop CSA & poll */ ++ b47s->cc_write(b47s, BCMA_CC_FLASHCTL, 0); ++ udelay(1); ++ if (bcm47xxsflash_poll(b47s, HZ / 10)) ++ pr_err("Flash rejected dropping CSA\n"); ++ ++ return written; ++} ++ ++static int bcm47xxsflash_write_at(struct mtd_info *mtd, u32 offset, size_t len, ++ const u_char *buf) ++{ ++ struct bcm47xxsflash *b47s = mtd->priv; ++ u32 mask = b47s->blocksize - 1; ++ u32 page = (offset & ~mask) << 1; ++ u32 byte = offset & mask; ++ int written = 0; ++ ++ /* If we don't overwrite whole page, read it to the buffer first */ ++ if (byte || (len < b47s->blocksize)) { ++ int err; ++ ++ b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page); ++ bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_LOAD); ++ /* 250 us for AT45DB321B */ ++ err = bcm47xxsflash_poll(b47s, HZ / 1000); ++ if (err) { ++ pr_err("Timeout reading page 0x%X info buffer\n", page); ++ return err; ++ } ++ } ++ ++ /* Change buffer content with our data */ ++ while (len > 0) { ++ /* Page boundary, another function call is needed */ ++ if (byte == b47s->blocksize) ++ break; ++ ++ b47s->cc_write(b47s, BCMA_CC_FLASHADDR, byte++); ++ b47s->cc_write(b47s, BCMA_CC_FLASHDATA, *buf++); ++ bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_WRITE); ++ len--; ++ written++; ++ } ++ ++ /* Program page with the buffer content */ ++ b47s->cc_write(b47s, BCMA_CC_FLASHADDR, page); ++ bcm47xxsflash_cmd(b47s, OPCODE_AT_BUF1_PROGRAM); ++ ++ return written; ++} ++ ++static int bcm47xxsflash_write(struct mtd_info *mtd, loff_t to, size_t len, ++ size_t *retlen, const u_char *buf) ++{ ++ struct bcm47xxsflash *b47s = mtd->priv; ++ int written; ++ ++ /* Writing functions can return without writing all passed data, for ++ * example when the hardware is too old or when we git page boundary. ++ */ ++ while (len > 0) { ++ switch (b47s->type) { ++ case BCM47XXSFLASH_TYPE_ST: ++ written = bcm47xxsflash_write_st(mtd, to, len, buf); ++ break; ++ case BCM47XXSFLASH_TYPE_ATMEL: ++ written = bcm47xxsflash_write_at(mtd, to, len, buf); ++ break; ++ default: ++ BUG_ON(1); ++ } ++ if (written < 0) { ++ pr_err("Error writing at offset 0x%llX\n", to); ++ return written; ++ } ++ to += (loff_t)written; ++ len -= written; ++ *retlen += written; ++ buf += written; ++ } ++ ++ return 0; ++} ++ + static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s) + { + struct mtd_info *mtd = &b47s->mtd; +@@ -123,16 +244,17 @@ static void bcm47xxsflash_fill_mtd(struc + mtd->priv = b47s; + mtd->name = "bcm47xxsflash"; + mtd->owner = THIS_MODULE; +- mtd->type = MTD_ROM; + +- /* TODO: implement writing support and verify/change following code */ +- mtd->flags = MTD_CAP_ROM; ++ mtd->type = MTD_NORFLASH; ++ mtd->flags = MTD_CAP_NORFLASH; + mtd->size = b47s->size; + mtd->erasesize = b47s->blocksize; +- mtd->writebufsize = mtd->writesize = 1; ++ mtd->writesize = 1; ++ mtd->writebufsize = 1; + + mtd->_erase = bcm47xxsflash_erase; + mtd->_read = bcm47xxsflash_read; ++ mtd->_write = bcm47xxsflash_write; + } + + /************************************************** |