mpc83xx: moved to targets feed
[openwrt/svn-archive/archive.git] / target / linux / mpc83xx / patches-3.18 / 203-mtd-add-rbppc_nand-driver.patch
diff --git a/target/linux/mpc83xx/patches-3.18/203-mtd-add-rbppc_nand-driver.patch b/target/linux/mpc83xx/patches-3.18/203-mtd-add-rbppc_nand-driver.patch
deleted file mode 100644 (file)
index 2b4c0a8..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
---- a/drivers/mtd/nand/Kconfig
-+++ b/drivers/mtd/nand/Kconfig
-@@ -408,6 +408,13 @@ config MTD_NAND_PLATFORM
-         devices. You will need to provide platform-specific functions
-         via platform_data.
-+config MTD_NAND_RB_PPC
-+      tristate "MikroTik RB333/600 NAND support"
-+      depends on RB_PPC
-+      help
-+        This option enables support for the NAND device on MikroTik
-+        RouterBOARD 333/600 series boards.
-+
- config MTD_NAND_ORION
-       tristate "NAND Flash support for Marvell Orion SoC"
-       depends on PLAT_ORION
---- a/drivers/mtd/nand/Makefile
-+++ b/drivers/mtd/nand/Makefile
-@@ -32,6 +32,7 @@ obj-$(CONFIG_MTD_NAND_CM_X270)               += cmx27
- obj-$(CONFIG_MTD_NAND_PXA3xx)         += pxa3xx_nand.o
- obj-$(CONFIG_MTD_NAND_TMIO)           += tmio_nand.o
- obj-$(CONFIG_MTD_NAND_PLATFORM)               += plat_nand.o
-+obj-$(CONFIG_MTD_NAND_RB_PPC)         += rbppc_nand.o
- obj-$(CONFIG_MTD_NAND_PASEMI)         += pasemi_nand.o
- obj-$(CONFIG_MTD_NAND_ORION)          += orion_nand.o
- obj-$(CONFIG_MTD_NAND_FSL_ELBC)               += fsl_elbc_nand.o
---- /dev/null
-+++ b/drivers/mtd/nand/rbppc_nand.c
-@@ -0,0 +1,251 @@
-+/*
-+ * Copyright (C) 2008-2009 Noah Fontes <nfontes@transtruct.org>
-+ * Copyright (C) 2009 Michael Guntsche <mike@it-loops.com>
-+ * Copyright (C) Mikrotik 2007
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License as published by the
-+ * Free Software Foundation; either version 2 of the License, or (at your
-+ * option) any later version.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/mtd/nand.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/partitions.h>
-+#include <linux/of_platform.h>
-+#include <linux/of_device.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include <linux/of_address.h>
-+#include <asm/io.h>
-+
-+#define DRV_NAME      "rbppc_nand"
-+#define DRV_VERSION   "0.0.2"
-+
-+static struct mtd_info rmtd;
-+static struct nand_chip rnand;
-+
-+struct rbppc_nand_info {
-+      void *gpi;
-+      void *gpo;
-+      void *localbus;
-+
-+      unsigned gpio_rdy;
-+      unsigned gpio_nce;
-+      unsigned gpio_cle;
-+      unsigned gpio_ale;
-+      unsigned gpio_ctrls;
-+};
-+
-+/* We must use the OOB layout from yaffs 1 if we want this to be recognized
-+ * properly. Borrowed from the OpenWRT patches for the RB532.
-+ *
-+ * See <https://dev.openwrt.org/browser/trunk/target/linux/rb532/
-+ * patches-2.6.28/025-rb532_nand_fixup.patch> for more details.
-+ */
-+static struct nand_ecclayout rbppc_nand_oob_16 = {
-+      .eccbytes = 6,
-+      .eccpos = { 8, 9, 10, 13, 14, 15 },
-+      .oobavail = 9,
-+      .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
-+};
-+
-+static struct mtd_partition rbppc_nand_partition_info[] = {
-+      {
-+              name: "kernel",
-+              offset: 0,
-+              size: 4 * 1024 * 1024,
-+      },
-+      {
-+              name: "rootfs",
-+              offset: MTDPART_OFS_NXTBLK,
-+              size: MTDPART_SIZ_FULL,
-+      },
-+};
-+
-+static int rbppc_nand_dev_ready(struct mtd_info *mtd) {
-+      struct nand_chip *chip = mtd->priv;
-+      struct rbppc_nand_info *priv = chip->priv;
-+
-+      return in_be32(priv->gpi) & priv->gpio_rdy;
-+}
-+
-+static void rbppc_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) {
-+      struct nand_chip *chip = mtd->priv;
-+      struct rbppc_nand_info *priv = chip->priv;
-+
-+      if (ctrl & NAND_CTRL_CHANGE) {
-+              unsigned val = in_be32(priv->gpo);
-+              if (!(val & priv->gpio_nce)) {
-+                      /* make sure Local Bus has done NAND operations */
-+                      readb(priv->localbus);
-+              }
-+
-+              if (ctrl & NAND_CLE) {
-+                      val |= priv->gpio_cle;
-+              } else {
-+                      val &= ~priv->gpio_cle;
-+              }
-+              if (ctrl & NAND_ALE) {
-+                      val |= priv->gpio_ale;
-+              } else {
-+                      val &= ~priv->gpio_ale;
-+              }
-+              if (!(ctrl & NAND_NCE)) {
-+                      val |= priv->gpio_nce;
-+              } else {
-+                      val &= ~priv->gpio_nce;
-+              }
-+              out_be32(priv->gpo, val);
-+
-+              /* make sure GPIO output has changed */
-+              val ^= in_be32(priv->gpo);
-+              if (val & priv->gpio_ctrls) {
-+                      printk(KERN_ERR "rbppc_nand_hwcontrol: NAND GPO change failed 0x%08x\n", val);
-+              }
-+      }
-+
-+      if (cmd != NAND_CMD_NONE) writeb(cmd, chip->IO_ADDR_W);
-+}
-+
-+static void rbppc_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-+{
-+      struct nand_chip *chip = mtd->priv;
-+      memcpy(buf, chip->IO_ADDR_R, len);
-+}
-+
-+static unsigned init_ok = 0;
-+
-+static int rbppc_nand_probe(struct platform_device *pdev)
-+{
-+      struct device_node *gpio;
-+      struct device_node *nnand;
-+      struct resource res;
-+      struct rbppc_nand_info *info;
-+      void *baddr;
-+      const unsigned *rdy, *nce, *cle, *ale;
-+
-+      printk(KERN_INFO "rbppc_nand_probe: MikroTik RouterBOARD 333/600 series NAND driver, version " DRV_VERSION "\n");
-+
-+      info = kmalloc(sizeof(*info), GFP_KERNEL);
-+
-+      rdy = of_get_property(pdev->dev.of_node, "rdy", NULL);
-+      nce = of_get_property(pdev->dev.of_node, "nce", NULL);
-+      cle = of_get_property(pdev->dev.of_node, "cle", NULL);
-+      ale = of_get_property(pdev->dev.of_node, "ale", NULL);
-+
-+      if (!rdy || !nce || !cle || !ale) {
-+              printk(KERN_ERR "rbppc_nand_probe: GPIO properties are missing\n");
-+              goto err;
-+      }
-+      if (rdy[0] != nce[0] || rdy[0] != cle[0] || rdy[0] != ale[0]) {
-+              printk(KERN_ERR "rbppc_nand_probe: Different GPIOs are not supported\n");
-+              goto err;
-+      }
-+
-+      gpio = of_find_node_by_phandle(rdy[0]);
-+      if (!gpio) {
-+              printk(KERN_ERR "rbppc_nand_probe: No GPIO<%x> node found\n", *rdy);
-+              goto err;
-+      }
-+      if (of_address_to_resource(gpio, 0, &res)) {
-+              printk(KERN_ERR "rbppc_nand_probe: No reg property in GPIO found\n");
-+              goto err;
-+      }
-+      info->gpo = ioremap_nocache(res.start, res.end - res.start + 1);
-+
-+      if (!of_address_to_resource(gpio, 1, &res)) {
-+              info->gpi = ioremap_nocache(res.start, res.end - res.start + 1);
-+      } else {
-+              info->gpi = info->gpo;
-+      }
-+      of_node_put(gpio);
-+
-+      info->gpio_rdy = 1 << (31 - rdy[1]);
-+      info->gpio_nce = 1 << (31 - nce[1]);
-+      info->gpio_cle = 1 << (31 - cle[1]);
-+      info->gpio_ale = 1 << (31 - ale[1]);
-+      info->gpio_ctrls = info->gpio_nce | info->gpio_cle | info->gpio_ale;
-+
-+      nnand = of_find_node_by_name(NULL, "nnand");
-+      if (!nnand) {
-+              printk("rbppc_nand_probe: No nNAND found\n");
-+              goto err;
-+      }
-+      if (of_address_to_resource(nnand, 0, &res)) {
-+              printk("rbppc_nand_probe: No reg property in nNAND found\n");
-+              goto err;
-+      }
-+      of_node_put(nnand);
-+      info->localbus = ioremap_nocache(res.start, res.end - res.start + 1);
-+
-+      if (of_address_to_resource(pdev->dev.of_node, 0, &res)) {
-+          printk("rbppc_nand_probe: No reg property found\n");
-+          goto err;
-+      }
-+      baddr = ioremap_nocache(res.start, res.end - res.start + 1);
-+
-+      memset(&rnand, 0, sizeof(rnand));
-+      rnand.cmd_ctrl = rbppc_nand_cmd_ctrl;
-+      rnand.dev_ready = rbppc_nand_dev_ready;
-+      rnand.read_buf = rbppc_nand_read_buf;
-+      rnand.IO_ADDR_W = baddr;
-+      rnand.IO_ADDR_R = baddr;
-+      rnand.priv = info;
-+
-+      memset(&rmtd, 0, sizeof(rmtd));
-+      rnand.ecc.mode = NAND_ECC_SOFT;
-+      rnand.ecc.layout = &rbppc_nand_oob_16;
-+      rnand.chip_delay = 25;
-+      rmtd.priv = &rnand;
-+      rmtd.owner = THIS_MODULE;
-+
-+      if (nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1) && nand_scan(&rmtd, 1)) {
-+              printk(KERN_ERR "rbppc_nand_probe: RouterBOARD NAND device not found\n");
-+              return -ENXIO;
-+      }
-+
-+      mtd_device_parse_register(&rmtd, NULL, 0, rbppc_nand_partition_info, 2);
-+      init_ok = 1;
-+      return 0;
-+
-+err:
-+      kfree(info);
-+      return -1;
-+}
-+
-+static struct of_device_id rbppc_nand_ids[] = {
-+      { .name = "nand", },
-+      { },
-+};
-+
-+static struct platform_driver rbppc_nand_driver = {
-+      .probe  = rbppc_nand_probe,
-+      .driver = {
-+              .name = "rbppc-nand",
-+              .owner = THIS_MODULE,
-+              .of_match_table = rbppc_nand_ids,
-+      },
-+};
-+
-+static int __init rbppc_nand_init(void)
-+{
-+      return platform_driver_register(&rbppc_nand_driver);
-+}
-+
-+static void __exit rbppc_nand_exit(void)
-+{
-+      platform_driver_unregister(&rbppc_nand_driver);
-+}
-+
-+MODULE_AUTHOR("Mikrotikls SIA");
-+MODULE_AUTHOR("Noah Fontes");
-+MODULE_AUTHOR("Michael Guntsche");
-+MODULE_DESCRIPTION("MikroTik RouterBOARD 333/600 series NAND driver");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(DRV_VERSION);
-+
-+module_init(rbppc_nand_init);
-+module_exit(rbppc_nand_exit);