summaryrefslogtreecommitdiff
path: root/target/linux/brcm47xx/patches-3.10/051-mtd_bcm47xxsflash_implement_polling_chip_status.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm47xx/patches-3.10/051-mtd_bcm47xxsflash_implement_polling_chip_status.patch')
-rw-r--r--target/linux/brcm47xx/patches-3.10/051-mtd_bcm47xxsflash_implement_polling_chip_status.patch87
1 files changed, 87 insertions, 0 deletions
diff --git a/target/linux/brcm47xx/patches-3.10/051-mtd_bcm47xxsflash_implement_polling_chip_status.patch b/target/linux/brcm47xx/patches-3.10/051-mtd_bcm47xxsflash_implement_polling_chip_status.patch
new file mode 100644
index 0000000..3b45234
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.10/051-mtd_bcm47xxsflash_implement_polling_chip_status.patch
@@ -0,0 +1,87 @@
+commit 7026e9844112fa33e5ffcd562daf0c919b16a9d1
+Author: Rafał Miłecki <zajec5@gmail.com>
+Date: Sun Mar 24 21:51:31 2013 +0100
+
+ mtd: bcm47xxsflash: implement polling chip status
+
+ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+ Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
+
+--- a/drivers/mtd/devices/bcm47xxsflash.c
++++ b/drivers/mtd/devices/bcm47xxsflash.c
+@@ -1,6 +1,7 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/delay.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/platform_device.h>
+ #include <linux/bcma/bcma.h>
+@@ -12,6 +13,57 @@ MODULE_DESCRIPTION("Serial flash driver
+
+ static const char * const probes[] = { "bcm47xxpart", NULL };
+
++/**************************************************
++ * Various helpers
++ **************************************************/
++
++static void bcm47xxsflash_cmd(struct bcm47xxsflash *b47s, u32 opcode)
++{
++ int i;
++
++ b47s->cc_write(b47s, BCMA_CC_FLASHCTL, BCMA_CC_FLASHCTL_START | opcode);
++ for (i = 0; i < 1000; i++) {
++ if (!(b47s->cc_read(b47s, BCMA_CC_FLASHCTL) &
++ BCMA_CC_FLASHCTL_BUSY))
++ return;
++ cpu_relax();
++ }
++ pr_err("Control command failed (timeout)!\n");
++}
++
++static int bcm47xxsflash_poll(struct bcm47xxsflash *b47s, int timeout)
++{
++ unsigned long deadline = jiffies + timeout;
++
++ do {
++ switch (b47s->type) {
++ case BCM47XXSFLASH_TYPE_ST:
++ bcm47xxsflash_cmd(b47s, OPCODE_ST_RDSR);
++ if (!(b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
++ SR_ST_WIP))
++ return 0;
++ break;
++ case BCM47XXSFLASH_TYPE_ATMEL:
++ bcm47xxsflash_cmd(b47s, OPCODE_AT_STATUS);
++ if (b47s->cc_read(b47s, BCMA_CC_FLASHDATA) &
++ SR_AT_READY)
++ return 0;
++ break;
++ }
++
++ cpu_relax();
++ udelay(1);
++ } while (!time_after_eq(jiffies, deadline));
++
++ pr_err("Timeout waiting for flash to be ready!\n");
++
++ return -EBUSY;
++}
++
++/**************************************************
++ * MTD ops
++ **************************************************/
++
+ static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+ {
+@@ -97,6 +149,9 @@ static int bcm47xxsflash_bcma_probe(stru
+ goto err_dev_reg;
+ }
+
++ if (bcm47xxsflash_poll(b47s, HZ / 10))
++ pr_warn("Serial flash busy\n");
++
+ return 0;
+
+ err_dev_reg: