diff options
Diffstat (limited to 'target/linux/brcm47xx/patches-3.9/052-mtd-add-serial-flash-driver.patch')
-rw-r--r-- | target/linux/brcm47xx/patches-3.9/052-mtd-add-serial-flash-driver.patch | 345 |
1 files changed, 0 insertions, 345 deletions
diff --git a/target/linux/brcm47xx/patches-3.9/052-mtd-add-serial-flash-driver.patch b/target/linux/brcm47xx/patches-3.9/052-mtd-add-serial-flash-driver.patch deleted file mode 100644 index 844f89d4b3..0000000000 --- a/target/linux/brcm47xx/patches-3.9/052-mtd-add-serial-flash-driver.patch +++ /dev/null @@ -1,345 +0,0 @@ ---- a/drivers/mtd/devices/bcm47xxsflash.c -+++ b/drivers/mtd/devices/bcm47xxsflash.c -@@ -1,47 +1,153 @@ --#include <linux/kernel.h> -+/* -+ * Broadcom SiliconBackplane chipcommon serial flash interface -+ * -+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> -+ * Copyright 2006, Broadcom Corporation -+ * All Rights Reserved. -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#define pr_fmt(fmt) "bcm47xxsflash: " fmt - #include <linux/module.h> - #include <linux/slab.h> -+#include <linux/ioport.h> -+#include <linux/sched.h> - #include <linux/mtd/mtd.h> -+#include <linux/mtd/map.h> -+#include <linux/mtd/partitions.h> -+#include <linux/errno.h> -+#include <linux/delay.h> - #include <linux/platform_device.h> --#include <linux/bcma/bcma.h> -- --#include "bcm47xxsflash.h" -+#include <linux/mtd/bcm47xxsflash.h> - - MODULE_LICENSE("GPL"); --MODULE_DESCRIPTION("Serial flash driver for BCMA bus"); -+MODULE_DESCRIPTION("BCM47XX serial flash driver"); - - static const char *probes[] = { "bcm47xxpart", NULL }; - -+static int -+sflash_mtd_poll(struct bcm47xxsflash *sflash, unsigned int offset, int timeout) -+{ -+ unsigned long now = jiffies; -+ -+ for (;;) { -+ if (!sflash->poll(sflash, offset)) { -+ break; -+ } -+ if (time_after(jiffies, now + timeout)) { -+ pr_err("timeout while polling\n"); -+ return -ETIMEDOUT; -+ -+ } -+ cpu_relax(); -+ udelay(1); -+ } -+ -+ return 0; -+} -+ - 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; -+ struct bcm47xxsflash *sflash = (struct bcm47xxsflash *)mtd->priv; - - /* Check address range */ -+ if (!len) -+ return 0; -+ - if ((from + len) > mtd->size) - return -EINVAL; - -- memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(b47s->window + from), -+ memcpy_fromio(buf, (void __iomem *)KSEG0ADDR(sflash->window + from), - len); - *retlen = len; - - return len; - } - --static void bcm47xxsflash_fill_mtd(struct bcm47xxsflash *b47s) -+static int -+sflash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) - { -- struct mtd_info *mtd = &b47s->mtd; -+ int bytes; -+ int ret; -+ struct bcm47xxsflash *sflash = (struct bcm47xxsflash *)mtd->priv; - -- mtd->priv = b47s; -- mtd->name = "bcm47xxsflash"; -- mtd->owner = THIS_MODULE; -- mtd->type = MTD_ROM; -- mtd->size = b47s->size; -- mtd->_read = bcm47xxsflash_read; -+ /* Check address range */ -+ if (!len) -+ return 0; -+ -+ if ((to + len) > mtd->size) -+ return -EINVAL; -+ -+ *retlen = 0; -+ while (len) { -+ ret = sflash->write(sflash, to, len, buf); -+ if (ret < 0) -+ return ret; -+ -+ bytes = ret; -+ -+ ret = sflash_mtd_poll(sflash, (unsigned int) to, HZ / 10); -+ if (ret) -+ return ret; -+ -+ to += (loff_t) bytes; -+ len -= bytes; -+ buf += bytes; -+ *retlen += bytes; -+ } - -- /* TODO: implement writing support and verify/change following code */ -- mtd->flags = MTD_CAP_ROM; -- mtd->writebufsize = mtd->writesize = 1; -+ return 0; -+} -+ -+static int -+sflash_mtd_erase(struct mtd_info *mtd, struct erase_info *erase) -+{ -+ struct bcm47xxsflash *sflash = (struct bcm47xxsflash *) mtd->priv; -+ int i, j, ret = 0; -+ unsigned int addr, len; -+ -+ /* Check address range */ -+ if (!erase->len) -+ return 0; -+ if ((erase->addr + erase->len) > mtd->size) -+ return -EINVAL; -+ -+ addr = erase->addr; -+ len = erase->len; -+ -+ /* Ensure that requested regions are aligned */ -+ for (i = 0; i < mtd->numeraseregions; i++) { -+ for (j = 0; j < mtd->eraseregions[i].numblocks; j++) { -+ if (addr == mtd->eraseregions[i].offset + -+ mtd->eraseregions[i].erasesize * j && -+ len >= mtd->eraseregions[i].erasesize) { -+ ret = sflash->erase(sflash, addr); -+ if (ret < 0) -+ break; -+ ret = sflash_mtd_poll(sflash, addr, 10 * HZ); -+ if (ret) -+ break; -+ addr += mtd->eraseregions[i].erasesize; -+ len -= mtd->eraseregions[i].erasesize; -+ } -+ } -+ if (ret) -+ break; -+ } -+ -+ /* Set erase status */ -+ if (ret) -+ erase->state = MTD_ERASE_FAILED; -+ else -+ erase->state = MTD_ERASE_DONE; -+ -+ /* Call erase callback */ -+ if (erase->callback) -+ erase->callback(erase); -+ -+ return ret; - } - - /************************************************** -@@ -50,53 +156,94 @@ static void bcm47xxsflash_fill_mtd(struc - - static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) - { -- struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); -- struct bcm47xxsflash *b47s; -- int err; -+ struct bcm47xxsflash *sflash = dev_get_platdata(&pdev->dev); -+ struct mtd_info *mtd; -+ struct mtd_erase_region_info *eraseregions; -+ int ret = 0; -+ -+ mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); -+ if (!mtd){ -+ ret = -ENOMEM; -+ goto err_out; -+ } - -- b47s = kzalloc(sizeof(*b47s), GFP_KERNEL); -- if (!b47s) { -- err = -ENOMEM; -- goto out; -- } -- sflash->priv = b47s; -- -- b47s->window = sflash->window; -- b47s->blocksize = sflash->blocksize; -- b47s->numblocks = sflash->numblocks; -- b47s->size = sflash->size; -- bcm47xxsflash_fill_mtd(b47s); -- -- err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0); -- if (err) { -- pr_err("Failed to register MTD device: %d\n", err); -- goto err_dev_reg; -+ eraseregions = kzalloc(sizeof(struct mtd_erase_region_info), GFP_KERNEL); -+ if (!eraseregions) { -+ ret = -ENOMEM; -+ goto err_free_mtd; - } - -+ pr_info("found serial flash: blocksize=%dKB, numblocks=%d, size=%dKB\n", -+ sflash->blocksize / 1024, sflash->numblocks, sflash->size / 1024); -+ -+ /* Setup region info */ -+ eraseregions->offset = 0; -+ eraseregions->erasesize = sflash->blocksize; -+ eraseregions->numblocks = sflash->numblocks; -+ if (eraseregions->erasesize > mtd->erasesize) -+ mtd->erasesize = eraseregions->erasesize; -+ mtd->size = sflash->size; -+ mtd->numeraseregions = 1; -+ -+ /* Register with MTD */ -+ mtd->name = "bcm47xx-sflash"; -+ mtd->type = MTD_NORFLASH; -+ mtd->flags = MTD_CAP_NORFLASH; -+ mtd->eraseregions = eraseregions; -+ mtd->_erase = sflash_mtd_erase; -+ mtd->_read = bcm47xxsflash_read; -+ mtd->_write = sflash_mtd_write; -+ mtd->writesize = 1; -+ mtd->priv = sflash; -+ ret = dev_set_drvdata(&pdev->dev, mtd); -+ mtd->owner = THIS_MODULE; -+ if (ret) { -+ pr_err("adding private data failed\n"); -+ goto err_free_eraseregions; -+ } -+ -+ ret = mtd_device_parse_register(mtd, probes, NULL, NULL, 0); -+ -+ if (ret) { -+ pr_err("mtd_device_register failed\n"); -+ goto err_free_eraseregions; -+ } - return 0; - --err_dev_reg: -- kfree(&b47s->mtd); --out: -- return err; -+err_free_eraseregions: -+ kfree(eraseregions); -+err_free_mtd: -+ kfree(mtd); -+err_out: -+ return ret; - } - - static int bcm47xxsflash_bcma_remove(struct platform_device *pdev) - { -- struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev); -- struct bcm47xxsflash *b47s = sflash->priv; -- -- mtd_device_unregister(&b47s->mtd); -- kfree(b47s); -+ struct mtd_info *mtd = dev_get_drvdata(&pdev->dev); - -+ if (mtd) { -+ mtd_device_unregister(mtd); -+ map_destroy(mtd); -+ kfree(mtd->eraseregions); -+ kfree(mtd); -+ dev_set_drvdata(&pdev->dev, NULL); -+ } - return 0; - } - -+static const struct platform_device_id bcm47xxsflash_table[] = { -+ { "bcm47xx-sflash", 0 }, -+ { } -+}; -+MODULE_DEVICE_TABLE(platform, bcm47xxsflash_table); -+ - static struct platform_driver bcma_sflash_driver = { -+ .id_table = bcm47xxsflash_table, - .probe = bcm47xxsflash_bcma_probe, - .remove = bcm47xxsflash_bcma_remove, - .driver = { -- .name = "bcma_sflash", -+ .name = "bcm47xx-sflash", - .owner = THIS_MODULE, - }, - }; -@@ -111,8 +258,7 @@ static int __init bcm47xxsflash_init(voi - - err = platform_driver_register(&bcma_sflash_driver); - if (err) -- pr_err("Failed to register BCMA serial flash driver: %d\n", -- err); -+ pr_err("error registering platform driver: %i\n", err); - - return err; - } ---- /dev/null -+++ b/include/linux/mtd/bcm47xxsflash.h -@@ -0,0 +1,33 @@ -+#ifndef LINUX_MTD_BCM47XX_SFLASH_H_ -+#define LINUX_MTD_BCM47XX_SFLASH_H_ -+ -+#include <linux/mtd/mtd.h> -+ -+enum bcm47xxsflash_type { -+ BCM47XX_SFLASH_SSB, -+ BCM47XX_SFLASH_BCMA, -+}; -+ -+struct ssb_chipcommon; -+struct bcma_drv_cc; -+ -+struct bcm47xxsflash { -+ enum bcm47xxsflash_type type; -+ union { -+ struct ssb_chipcommon *scc; -+ struct bcma_drv_cc *bcc; -+ }; -+ -+ bool present; -+ u16 numblocks; -+ u32 window; -+ u32 blocksize; -+ u32 size; -+ -+ int (*poll)(struct bcm47xxsflash *dev, u32 offset); -+ int (*write)(struct bcm47xxsflash *dev, u32 offset, u32 len, const u8 *buf); -+ int (*erase)(struct bcm47xxsflash *dev, u32 offset); -+ -+ struct mtd_info *mtd; -+}; -+#endif /* LINUX_MTD_BCM47XX_SFLASH_H_ */ |