* [RFC][PATCH] mtd: bcm47xxsflash: writing support
@ 2013-05-22 12:39 Rafał Miłecki
2013-05-22 20:17 ` Rafał Miłecki
2013-08-22 19:43 ` Brian Norris
0 siblings, 2 replies; 5+ messages in thread
From: Rafał Miłecki @ 2013-05-22 12:39 UTC (permalink / raw)
To: linux-mtd; +Cc: Hauke Mehrtens, Rafał Miłecki
---
drivers/mtd/devices/bcm47xxsflash.c | 130 +++++++++++++++++++++++++++++++++--
1 file changed, 126 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c
index c485d96..effe624 100644
--- a/drivers/mtd/devices/bcm47xxsflash.c
+++ b/drivers/mtd/devices/bcm47xxsflash.c
@@ -116,6 +116,127 @@ static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
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(struct bcm47xxsflash *b47s)
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;
}
/**************************************************
--
1.7.10.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC][PATCH] mtd: bcm47xxsflash: writing support
2013-05-22 12:39 [RFC][PATCH] mtd: bcm47xxsflash: writing support Rafał Miłecki
@ 2013-05-22 20:17 ` Rafał Miłecki
2013-08-22 19:43 ` Brian Norris
1 sibling, 0 replies; 5+ messages in thread
From: Rafał Miłecki @ 2013-05-22 20:17 UTC (permalink / raw)
To: linux-mtd; +Cc: Hauke Mehrtens
2013/5/22 Rafał Miłecki <zajec5@gmail.com>:
> ---
> drivers/mtd/devices/bcm47xxsflash.c | 130 +++++++++++++++++++++++++++++++++--
> 1 file changed, 126 insertions(+), 4 deletions(-)
To make it clear, it was successfully tested with BCM4706.
--
Rafał
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC][PATCH] mtd: bcm47xxsflash: writing support
2013-05-22 12:39 [RFC][PATCH] mtd: bcm47xxsflash: writing support Rafał Miłecki
2013-05-22 20:17 ` Rafał Miłecki
@ 2013-08-22 19:43 ` Brian Norris
2013-08-22 20:03 ` Rafał Miłecki
1 sibling, 1 reply; 5+ messages in thread
From: Brian Norris @ 2013-08-22 19:43 UTC (permalink / raw)
To: Rafał Miłecki; +Cc: Hauke Mehrtens, linux-mtd
Hi Rafal,
On Wed, May 22, 2013 at 02:39:02PM +0200, Rafał Miłecki wrote:
> ---
> drivers/mtd/devices/bcm47xxsflash.c | 130 +++++++++++++++++++++++++++++++++--
> 1 file changed, 126 insertions(+), 4 deletions(-)
Can I get a 'Signed-off-by'? Otherwise, is this patch good to go?
>
> diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c
> index c485d96..effe624 100644
> --- a/drivers/mtd/devices/bcm47xxsflash.c
> +++ b/drivers/mtd/devices/bcm47xxsflash.c
> @@ -116,6 +116,127 @@ static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
> 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(struct bcm47xxsflash *b47s)
> 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;
> }
>
> /**************************************************
Brian
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC][PATCH] mtd: bcm47xxsflash: writing support
2013-08-22 19:43 ` Brian Norris
@ 2013-08-22 20:03 ` Rafał Miłecki
2013-08-22 20:59 ` Brian Norris
0 siblings, 1 reply; 5+ messages in thread
From: Rafał Miłecki @ 2013-08-22 20:03 UTC (permalink / raw)
To: Brian Norris; +Cc: Hauke Mehrtens, linux-mtd
2013/8/22 Brian Norris <computersforpeace@gmail.com>:
> Hi Rafal,
>
> On Wed, May 22, 2013 at 02:39:02PM +0200, Rafał Miłecki wrote:
>> ---
>> drivers/mtd/devices/bcm47xxsflash.c | 130 +++++++++++++++++++++++++++++++++--
>> 1 file changed, 126 insertions(+), 4 deletions(-)
>
> Can I get a 'Signed-off-by'? Otherwise, is this patch good to go?
Of course! I posted it as RFC, so didn't add S-o-b, but no-one
objected and this patch seems to be fine. I use it daily for half a
year, it was recently picked up by OpenWrt and I didn't get any bug
reports. So I think it's totally fine to push it :)
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC][PATCH] mtd: bcm47xxsflash: writing support
2013-08-22 20:03 ` Rafał Miłecki
@ 2013-08-22 20:59 ` Brian Norris
0 siblings, 0 replies; 5+ messages in thread
From: Brian Norris @ 2013-08-22 20:59 UTC (permalink / raw)
To: Rafał Miłecki; +Cc: Hauke Mehrtens, linux-mtd
On Thu, Aug 22, 2013 at 10:03:22PM +0200, Rafał Miłecki wrote:
> 2013/8/22 Brian Norris <computersforpeace@gmail.com>:
> > Hi Rafal,
> >
> > On Wed, May 22, 2013 at 02:39:02PM +0200, Rafał Miłecki wrote:
> >> ---
> >> drivers/mtd/devices/bcm47xxsflash.c | 130 +++++++++++++++++++++++++++++++++--
> >> 1 file changed, 126 insertions(+), 4 deletions(-)
> >
> > Can I get a 'Signed-off-by'? Otherwise, is this patch good to go?
>
> Of course! I posted it as RFC, so didn't add S-o-b, but no-one
> objected and this patch seems to be fine. I use it daily for half a
> year, it was recently picked up by OpenWrt and I didn't get any bug
> reports. So I think it's totally fine to push it :)
>
> Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Applied to l2-mtd.git.
Brian
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-08-22 20:59 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-22 12:39 [RFC][PATCH] mtd: bcm47xxsflash: writing support Rafał Miłecki
2013-05-22 20:17 ` Rafał Miłecki
2013-08-22 19:43 ` Brian Norris
2013-08-22 20:03 ` Rafał Miłecki
2013-08-22 20:59 ` Brian Norris
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.