Re: [PATCH 2/3] [POWERPC][NAND] FSL UPM NAND driver

2007-12-23 Thread Anton Vorontsov
On Sun, Dec 23, 2007 at 01:33:29PM +1100, Stephen Rothwell wrote:
> On Fri, 21 Dec 2007 23:41:30 +0300 Anton Vorontsov <[EMAIL PROTECTED]> wrote:
> >
> > +static int __devinit upm_chip_probe(struct of_device *ofdev,
> > +   const struct of_device_id *ofid)
> > +{
> > +   struct upm_data *ud;
> > +   struct resource io_res;
> > +   const u32 *prop;
> > +   int ret;
> > +   int size;
> > +
> > +   ud = kzalloc(sizeof(*ud), GFP_KERNEL);
> > +   if (!ud)
> > +   return -ENOMEM;
> > +
> > +   ret = of_address_to_resource(ofdev->node, 0, &io_res);
> > +   if (ret) {
> > +   dev_err(&ofdev->dev, "can't get IO base\n");
> > +   goto err;
> > +   }
> > +
> > +   prop = of_get_property(ofdev->node, "width", &size);
> > +   if (!prop || size != sizeof(u32)) {
> > +   dev_err(&ofdev->dev, "can't get chip width\n");
> > +   goto err;
> 
> Here ret is 0, is that the correct return code?

Nope.

> > +   ud->rnb_gpio = of_get_gpio(ofdev->node, 0);
> > +   if (ud->rnb_gpio >= 0) {
> > +   ret = gpio_request(ud->rnb_gpio, ofdev->dev.bus_id);
> > +   if (ret) {
> > +   dev_err(&ofdev->dev, "can't request RNB gpio\n");
> > +   goto err;
> > +   }
> > +   gpio_direction_input(ud->rnb_gpio);
> > +   } else if (ud->rnb_gpio == -EINVAL) {
> > +   dev_err(&ofdev->dev, "specified RNB gpio is invalid\n");
> > +   goto err;
> 
> Again ret is 0 here.

Much thanks for catching that!

-- 
Anton Vorontsov
email: [EMAIL PROTECTED]
backup email: [EMAIL PROTECTED]
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 2/3] [POWERPC][NAND] FSL UPM NAND driver

2007-12-22 Thread Stephen Rothwell
On Fri, 21 Dec 2007 23:41:30 +0300 Anton Vorontsov <[EMAIL PROTECTED]> wrote:
>
> +static int __devinit upm_chip_probe(struct of_device *ofdev,
> + const struct of_device_id *ofid)
> +{
> + struct upm_data *ud;
> + struct resource io_res;
> + const u32 *prop;
> + int ret;
> + int size;
> +
> + ud = kzalloc(sizeof(*ud), GFP_KERNEL);
> + if (!ud)
> + return -ENOMEM;
> +
> + ret = of_address_to_resource(ofdev->node, 0, &io_res);
> + if (ret) {
> + dev_err(&ofdev->dev, "can't get IO base\n");
> + goto err;
> + }
> +
> + prop = of_get_property(ofdev->node, "width", &size);
> + if (!prop || size != sizeof(u32)) {
> + dev_err(&ofdev->dev, "can't get chip width\n");
> + goto err;

Here ret is 0, is that the correct return code?

> + ud->rnb_gpio = of_get_gpio(ofdev->node, 0);
> + if (ud->rnb_gpio >= 0) {
> + ret = gpio_request(ud->rnb_gpio, ofdev->dev.bus_id);
> + if (ret) {
> + dev_err(&ofdev->dev, "can't request RNB gpio\n");
> + goto err;
> + }
> + gpio_direction_input(ud->rnb_gpio);
> + } else if (ud->rnb_gpio == -EINVAL) {
> + dev_err(&ofdev->dev, "specified RNB gpio is invalid\n");
> + goto err;

Again ret is 0 here.

-- 
Cheers,
Stephen Rothwell[EMAIL PROTECTED]
http://www.canb.auug.org.au/~sfr/


pgp5WbcxRuGTQ.pgp
Description: PGP signature
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

[PATCH 2/3] [POWERPC][NAND] FSL UPM NAND driver

2007-12-21 Thread Anton Vorontsov
It's using FSL UPM infrastructure. So far only 8 bit accessors
are implemented.

Signed-off-by: Anton Vorontsov <[EMAIL PROTECTED]>
---
 drivers/mtd/nand/Kconfig   |7 +
 drivers/mtd/nand/Makefile  |1 +
 drivers/mtd/nand/fsl_upm.c |  313 
 3 files changed, 321 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/fsl_upm.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 246d451..91b448f 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -306,4 +306,11 @@ config MTD_ALAUDA
  These two (and possibly other) Alauda-based cardreaders for
  SmartMedia and xD allow raw flash access.
 
+config MTD_NAND_FSL_UPM
+   tristate "MTD driver for NAND on Freescale UPM"
+   depends on MTD_NAND && FSL_UPM && GENERIC_GPIO
+   help
+ Enables support for NAND Flash wired to Freescale processors'
+ localbus with pre-programmed User-Programmable Machine.
+
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 3ad6c01..d553ea3 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -29,5 +29,6 @@ obj-$(CONFIG_MTD_NAND_CM_X270)+= cmx270_nand.o
 obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)   += excite_nandflash.o
 obj-$(CONFIG_MTD_NAND_PLATFORM)+= plat_nand.o
 obj-$(CONFIG_MTD_ALAUDA)   += alauda.o
+obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
new file mode 100644
index 000..ac26199
--- /dev/null
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -0,0 +1,313 @@
+/*
+ * Freescale UPM NAND driver.
+ *
+ * Copyright (c) 2007  MontaVista Software, Inc.
+ * Copyright (c) 2007  Anton Vorontsov <[EMAIL PROTECTED]>
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct upm_data {
+   struct device *dev;
+   struct mtd_info mtd;
+   struct nand_chip chip;
+   int last_ctrl;
+#ifdef CONFIG_MTD_PARTITIONS
+   struct mtd_partition *parts;
+#endif
+
+   struct fsl_upm upm;
+
+   int width;
+   int upm_addr_offset;
+   int upm_cmd_offset;
+   void __iomem *io_base;
+   int rnb_gpio;
+   const u32 *wait_pattern;
+   const u32 *wait_write;
+   int chip_delay;
+};
+
+#define to_upm_data(mtd) container_of(mtd, struct upm_data, mtd)
+
+static int upm_chip_ready(struct mtd_info *mtd)
+{
+   struct upm_data *ud = to_upm_data(mtd);
+
+   if (gpio_get_value(ud->rnb_gpio))
+   return 1;
+
+   dev_vdbg(ud->dev, "busy\n");
+   return 0;
+}
+
+static void upm_wait_rnb(struct upm_data *ud)
+{
+   int cnt = 100;
+
+   if (ud->rnb_gpio >= 0) {
+   while (--cnt && !upm_chip_ready(&ud->mtd))
+   cpu_relax();
+   }
+
+   if (!cnt)
+   dev_err(ud->dev, "tired waiting for RNB\n");
+}
+
+static void upm_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+   struct upm_data *ud = to_upm_data(mtd);
+
+   if (!(ctrl & ud->last_ctrl)) {
+   fsl_upm_end_pattern(&ud->upm);
+
+   if (cmd == NAND_CMD_NONE)
+   return;
+
+   ud->last_ctrl = ctrl & (NAND_ALE | NAND_CLE);
+   }
+
+   if (ctrl & NAND_CTRL_CHANGE) {
+   if (ctrl & NAND_ALE)
+   fsl_upm_start_pattern(&ud->upm, ud->upm_addr_offset);
+   else if (ctrl & NAND_CLE)
+   fsl_upm_start_pattern(&ud->upm, ud->upm_cmd_offset);
+   }
+
+   fsl_upm_run_pattern(&ud->upm, ud->io_base, ud->width, cmd);
+
+   if (ud->wait_pattern)
+   upm_wait_rnb(ud);
+}
+
+static uint8_t upm_read_byte(struct mtd_info *mtd)
+{
+   struct upm_data *ud = to_upm_data(mtd);
+
+   return in_8(ud->chip.IO_ADDR_R);
+}
+
+static void upm_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+   struct upm_data *ud = to_upm_data(mtd);
+   int i;
+
+   for (i = 0; i < len; i++)
+   buf[i] = in_8(ud->chip.IO_ADDR_R);
+}
+
+static void upm_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+   struct upm_data *ud = to_upm_data(mtd);
+   int i;
+
+   for (i = 0; i < len; i++) {
+   out_8(ud->chip.IO_ADDR_W, buf[i]);
+   if (ud->wait_write)
+   upm_wait_rnb(ud);
+   }
+}
+
+static int __devinit upm_chip_init(struct upm_data *ud)
+{
+   int ret;
+#ifdef CONFIG_MTD_PARTITIONS
+   static const char *part_types[] = { "cmdlinepart", NULL, };
+#endif
+
+