aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2014-12-17 14:53:25 +0000
committerRafał Miłecki <zajec5@gmail.com>2014-12-17 14:53:25 +0000
commite21e9c55484762a3bc4fe6521d5b1fc84bfa1a1e (patch)
tree9fced2f084635096d5d48098385ea49590f36f4f /target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch
parentd27c682def7cdaa887e06b0edb1b4a29c0130eb4 (diff)
downloadupstream-e21e9c55484762a3bc4fe6521d5b1fc84bfa1a1e.tar.gz
upstream-e21e9c55484762a3bc4fe6521d5b1fc84bfa1a1e.tar.bz2
upstream-e21e9c55484762a3bc4fe6521d5b1fc84bfa1a1e.zip
bcm53xx: backport spi-nor changes and update bcm53xxspiflash
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 43738
Diffstat (limited to 'target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch')
-rw-r--r--target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch244
1 files changed, 0 insertions, 244 deletions
diff --git a/target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch b/target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch
index 9a9d903f82..41ef3b300e 100644
--- a/target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch
+++ b/target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch
@@ -17,247 +17,3 @@
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
+obj-$(CONFIG_MTD_SPI_BCM53XXSPIFLASH) += bcm53xxspiflash.o
---- /dev/null
-+++ b/drivers/mtd/spi-nor/bcm53xxspiflash.c
-@@ -0,0 +1,241 @@
-+#include <linux/module.h>
-+#include <linux/delay.h>
-+#include <linux/spi/spi.h>
-+#include <linux/mtd/spi-nor.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/cfi.h>
-+
-+static const char * const probes[] = { "bcm47xxpart", NULL };
-+
-+struct bcm53xxsf {
-+ struct spi_device *spi;
-+ struct mtd_info mtd;
-+ struct spi_nor nor;
-+};
-+
-+/**************************************************
-+ * spi-nor API
-+ **************************************************/
-+
-+static int bcm53xxspiflash_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
-+ int len)
-+{
-+ struct bcm53xxsf *b53sf = nor->priv;
-+
-+ return spi_write_then_read(b53sf->spi, &opcode, 1, buf, len);
-+}
-+
-+static int bcm53xxspiflash_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
-+ int len, int write_enable)
-+{
-+ struct bcm53xxsf *b53sf = nor->priv;
-+ u8 *cmd = kzalloc(len + 1, GFP_KERNEL);
-+ int err;
-+
-+ if (!cmd)
-+ return -ENOMEM;
-+
-+ cmd[0] = opcode;
-+ memcpy(&cmd[1], buf, len);
-+ err = spi_write(b53sf->spi, cmd, len + 1);
-+
-+ kfree(cmd);
-+
-+ return err;
-+}
-+
-+static int bcm53xxspiflash_read(struct spi_nor *nor, loff_t from, size_t len,
-+ size_t *retlen, u_char *buf)
-+{
-+ struct bcm53xxsf *b53sf = nor->priv;
-+ struct spi_message m;
-+ struct spi_transfer t[2] = { { 0 }, { 0 } };
-+ unsigned char cmd[5];
-+ int cmd_len = 0;
-+ int err;
-+
-+ spi_message_init(&m);
-+
-+ cmd[cmd_len++] = SPINOR_OP_READ;
-+ if (b53sf->mtd.size > 0x1000000)
-+ cmd[cmd_len++] = (from & 0xFF000000) >> 24;
-+ cmd[cmd_len++] = (from & 0x00FF0000) >> 16;
-+ cmd[cmd_len++] = (from & 0x0000FF00) >> 8;
-+ cmd[cmd_len++] = (from & 0x000000FF) >> 0;
-+
-+ t[0].tx_buf = cmd;
-+ t[0].len = cmd_len;
-+ spi_message_add_tail(&t[0], &m);
-+
-+ t[1].rx_buf = buf;
-+ t[1].len = len;
-+ spi_message_add_tail(&t[1], &m);
-+
-+ err = spi_sync(b53sf->spi, &m);
-+ if (err)
-+ return err;
-+
-+ if (retlen && m.actual_length > cmd_len)
-+ *retlen = m.actual_length - cmd_len;
-+
-+ return 0;
-+}
-+
-+static void bcm53xxspiflash_write(struct spi_nor *nor, loff_t to, size_t len,
-+ size_t *retlen, const u_char *buf)
-+{
-+ struct bcm53xxsf *b53sf = nor->priv;
-+ struct spi_message m;
-+ struct spi_transfer t = { 0 };
-+ u8 *cmd = kzalloc(len + 5, GFP_KERNEL);
-+ int cmd_len = 0;
-+ int err;
-+
-+ if (!cmd)
-+ return;
-+
-+ spi_message_init(&m);
-+
-+ cmd[cmd_len++] = nor->program_opcode;
-+ if (b53sf->mtd.size > 0x1000000)
-+ cmd[cmd_len++] = (to & 0xFF000000) >> 24;
-+ cmd[cmd_len++] = (to & 0x00FF0000) >> 16;
-+ cmd[cmd_len++] = (to & 0x0000FF00) >> 8;
-+ cmd[cmd_len++] = (to & 0x000000FF) >> 0;
-+ memcpy(&cmd[cmd_len], buf, len);
-+
-+ t.tx_buf = cmd;
-+ t.len = cmd_len + len;
-+ spi_message_add_tail(&t, &m);
-+
-+ err = spi_sync(b53sf->spi, &m);
-+ if (err)
-+ goto out;
-+
-+ if (retlen && m.actual_length > cmd_len)
-+ *retlen += m.actual_length - cmd_len;
-+
-+out:
-+ kfree(cmd);
-+}
-+
-+static int bcm53xxspiflash_erase(struct spi_nor *nor, loff_t offs)
-+{
-+ struct bcm53xxsf *b53sf = nor->priv;
-+ unsigned char cmd[5];
-+ int i;
-+
-+ i = 0;
-+ cmd[i++] = nor->erase_opcode;
-+ if (b53sf->mtd.size > 0x1000000)
-+ cmd[i++] = (offs & 0xFF000000) >> 24;
-+ cmd[i++] = ((offs & 0x00FF0000) >> 16);
-+ cmd[i++] = ((offs & 0x0000FF00) >> 8);
-+ cmd[i++] = ((offs & 0x000000FF) >> 0);
-+
-+ return spi_write(b53sf->spi, cmd, i);
-+}
-+
-+static const struct spi_device_id *bcm53xxspiflash_read_id(struct spi_nor *nor)
-+{
-+ struct bcm53xxsf *b53sf = nor->priv;
-+ struct device *dev = &b53sf->spi->dev;
-+ const struct spi_device_id *id;
-+ unsigned char cmd[4];
-+ unsigned char resp[2];
-+ char *name = NULL;
-+ int err;
-+
-+ /* SST and Winbond/NexFlash specific command */
-+ cmd[0] = 0x90; /* Read Manufacturer / Device ID */
-+ cmd[1] = 0;
-+ cmd[2] = 0;
-+ cmd[3] = 0;
-+ err = spi_write_then_read(b53sf->spi, cmd, 4, resp, 2);
-+ if (err < 0) {
-+ dev_err(dev, "error reading SPI flash id\n");
-+ return ERR_PTR(-EBUSY);
-+ }
-+ switch (resp[0]) {
-+ case 0xef: /* Winbond/NexFlash */
-+ switch (resp[1]) {
-+ case 0x17:
-+ name = "w25q128";
-+ break;
-+ }
-+ if (!name) {
-+ dev_err(dev, "Unknown Winbond/NexFlash flash: %02X %02X\n",
-+ resp[0], resp[1]);
-+ return ERR_PTR(-ENOTSUPP);
-+ }
-+ goto found_name;
-+ }
-+
-+ /* TODO: Try more ID commands */
-+
-+ return ERR_PTR(-ENODEV);
-+
-+found_name:
-+ id = spi_nor_match_id(name);
-+ if (!id) {
-+ dev_err(dev, "No matching entry for %s flash\n", name);
-+ return ERR_PTR(-ENOENT);
-+ }
-+
-+ return id;
-+}
-+
-+/**************************************************
-+ * SPI driver
-+ **************************************************/
-+
-+static int bcm53xxspiflash_probe(struct spi_device *spi)
-+{
-+ struct bcm53xxsf *b53sf;
-+ int err;
-+
-+ b53sf = devm_kzalloc(&spi->dev, sizeof(*b53sf), GFP_KERNEL);
-+ if (!b53sf)
-+ return -ENOMEM;
-+ spi_set_drvdata(spi, b53sf);
-+
-+ b53sf->spi = spi;
-+
-+ b53sf->mtd.priv = &b53sf->nor;
-+
-+ b53sf->nor.mtd = &b53sf->mtd;
-+ b53sf->nor.dev = &spi->dev;
-+ b53sf->nor.read_reg = bcm53xxspiflash_read_reg;
-+ b53sf->nor.write_reg = bcm53xxspiflash_write_reg;
-+ b53sf->nor.read = bcm53xxspiflash_read;
-+ b53sf->nor.write = bcm53xxspiflash_write;
-+ b53sf->nor.erase = bcm53xxspiflash_erase;
-+ b53sf->nor.read_id = bcm53xxspiflash_read_id;
-+ b53sf->nor.priv = b53sf;
-+
-+ err = spi_nor_scan(&b53sf->nor, NULL, SPI_NOR_NORMAL);
-+ if (err)
-+ return err;
-+
-+ err = mtd_device_parse_register(&b53sf->mtd, probes, NULL, NULL, 0);
-+ if (err)
-+ return err;
-+
-+ return 0;
-+}
-+
-+static int bcm53xxspiflash_remove(struct spi_device *spi)
-+{
-+ return 0;
-+}
-+
-+static struct spi_driver bcm53xxspiflash_driver = {
-+ .driver = {
-+ .name = "bcm53xxspiflash",
-+ .owner = THIS_MODULE,
-+ },
-+ .probe = bcm53xxspiflash_probe,
-+ .remove = bcm53xxspiflash_remove,
-+};
-+
-+module_spi_driver(bcm53xxspiflash_driver);