All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3 v2][MTD] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
@ 2010-09-09 10:20 ` Roy Zang
  0 siblings, 0 replies; 40+ messages in thread
From: Roy Zang @ 2010-09-09 10:20 UTC (permalink / raw)
  To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780

From: Lan Chunhe-B25806 <b25806@freescale.com>

Move Freescale elbc interrupt from nand dirver to elbc driver.
Then all elbc devices can use the interrupt instead of ONLY nand.

Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
Comparing with v1, according to the feedback, add some decorations.

 arch/powerpc/Kconfig               |    7 +-
 arch/powerpc/include/asm/fsl_lbc.h |   34 +++++-
 arch/powerpc/sysdev/fsl_lbc.c      |  248 ++++++++++++++++++++++++++++++------
 3 files changed, 247 insertions(+), 42 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 631e5a0..44df1ba 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -687,9 +687,12 @@ config 4xx_SOC
 	bool
 
 config FSL_LBC
-	bool
+	bool "Freescale Local Bus support"
+	depends on FSL_SOC
 	help
-	  Freescale Localbus support
+	  Enables reporting of errors from the Freescale local bus
+	  controller.  Also contains some common code used by
+	  drivers for specific local bus peripherals.
 
 config FSL_GTM
 	bool
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 1b5a210..9b95eab 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -1,9 +1,10 @@
 /* Freescale Local Bus Controller
  *
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
  *
  * Authors: Nick Spence <nick.spence@freescale.com>,
  *          Scott Wood <scottwood@freescale.com>
+ *          Jack Lan <jack.lan@freescale.com>
  *
  * 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
@@ -27,6 +28,9 @@
 #include <linux/types.h>
 #include <linux/io.h>
 
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+
 struct fsl_lbc_bank {
 	__be32 br;             /**< Base Register  */
 #define BR_BA           0xFFFF8000
@@ -125,13 +129,23 @@ struct fsl_lbc_regs {
 #define LTESR_ATMW 0x00800000
 #define LTESR_ATMR 0x00400000
 #define LTESR_CS   0x00080000
+#define LTESR_UPM  0x00000002
 #define LTESR_CC   0x00000001
 #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+#define LTESR_MASK      (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
+			 | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
+			 | LTESR_CC)
+#define LTESR_CLEAR	0xFFFFFFFF
+#define LTECCR_CLEAR	0xFFFFFFFF
+#define LTESR_STATUS	LTESR_MASK
+#define LTEIR_ENABLE	LTESR_MASK
+#define LTEDR_ENABLE	0x00000000
 	__be32 ltedr;           /**< Transfer Error Disable Register */
 	__be32 lteir;           /**< Transfer Error Interrupt Register */
 	__be32 lteatr;          /**< Transfer Error Attributes Register */
 	__be32 ltear;           /**< Transfer Error Address Register */
-	u8 res6[0xC];
+	__be32 lteccr;          /**< Transfer Error ECC Register */
+	u8 res6[0x8];
 	__be32 lbcr;            /**< Configuration Register */
 #define LBCR_LDIS  0x80000000
 #define LBCR_LDIS_SHIFT    31
@@ -265,7 +279,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
 		cpu_relax();
 }
 
+/* overview of the fsl lbc controller */
+
+struct fsl_lbc_ctrl {
+	/* device info */
+	struct device			*dev;
+	struct fsl_lbc_regs __iomem	*regs;
+	int				irq;
+	wait_queue_head_t		irq_wait;
+	spinlock_t			lock;
+	void				*nand;
+
+	/* status read from LTESR by irq handler */
+	unsigned int			irq_status;
+};
+
 extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
 			       u32 mar);
+extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
 
 #endif /* __ASM_FSL_LBC_H */
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index dceb8d1..f4eca8d 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -2,8 +2,11 @@
  * Freescale LBC and UPM routines.
  *
  * Copyright (c) 2007-2008  MontaVista Software, Inc.
+ * Copyright (c) 2010 Freescale Semiconductor
  *
  * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ * Author: Jack Lan <Jack.Lan@freescale.com>
+ * Author: Roy Zang <tie-fei.zang@freescale.com>
  *
  * 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
@@ -21,37 +24,11 @@
 #include <linux/of.h>
 #include <asm/prom.h>
 #include <asm/fsl_lbc.h>
+#include <linux/slab.h>
 
 static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
-static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
-
-static char __initdata *compat_lbc[] = {
-	"fsl,pq2-localbus",
-	"fsl,pq2pro-localbus",
-	"fsl,pq3-localbus",
-	"fsl,elbc",
-};
-
-static int __init fsl_lbc_init(void)
-{
-	struct device_node *lbus;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
-		lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
-		if (lbus)
-			goto found;
-	}
-	return -ENODEV;
-
-found:
-	fsl_lbc_regs = of_iomap(lbus, 0);
-	of_node_put(lbus);
-	if (!fsl_lbc_regs)
-		return -ENOMEM;
-	return 0;
-}
-arch_initcall(fsl_lbc_init);
+struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
+EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
 
 /**
  * fsl_lbc_find - find Localbus bank
@@ -65,13 +42,15 @@ arch_initcall(fsl_lbc_init);
 int fsl_lbc_find(phys_addr_t addr_base)
 {
 	int i;
+	struct fsl_lbc_regs __iomem *lbc;
 
-	if (!fsl_lbc_regs)
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
 		return -ENODEV;
 
-	for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
-		__be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
-		__be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
+	lbc = fsl_lbc_ctrl_dev->regs;
+	for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
+		__be32 br = in_be32(&lbc->bank[i].br);
+		__be32 or = in_be32(&lbc->bank[i].or);
 
 		if (br & BR_V && (br & or & BR_BA) == addr_base)
 			return i;
@@ -94,22 +73,26 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
 {
 	int bank;
 	__be32 br;
+	struct fsl_lbc_regs __iomem *lbc;
 
 	bank = fsl_lbc_find(addr_base);
 	if (bank < 0)
 		return bank;
 
-	br = in_be32(&fsl_lbc_regs->bank[bank].br);
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+		return -ENODEV;
+	lbc = fsl_lbc_ctrl_dev->regs;
+	br = in_be32(&lbc->bank[bank].br);
 
 	switch (br & BR_MSEL) {
 	case BR_MS_UPMA:
-		upm->mxmr = &fsl_lbc_regs->mamr;
+		upm->mxmr = &lbc->mamr;
 		break;
 	case BR_MS_UPMB:
-		upm->mxmr = &fsl_lbc_regs->mbmr;
+		upm->mxmr = &lbc->mbmr;
 		break;
 	case BR_MS_UPMC:
-		upm->mxmr = &fsl_lbc_regs->mcmr;
+		upm->mxmr = &lbc->mcmr;
 		break;
 	default:
 		return -EINVAL;
@@ -143,14 +126,18 @@ EXPORT_SYMBOL(fsl_upm_find);
  * thus UPM pattern actually executed. Note that mar usage depends on the
  * pre-programmed AMX bits in the UPM RAM.
  */
+
 int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
 {
 	int ret = 0;
 	unsigned long flags;
 
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+		return -ENODEV;
+
 	spin_lock_irqsave(&fsl_lbc_lock, flags);
 
-	out_be32(&fsl_lbc_regs->mar, mar);
+	out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
 
 	switch (upm->width) {
 	case 8:
@@ -172,3 +159,188 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
 	return ret;
 }
 EXPORT_SYMBOL(fsl_upm_run_pattern);
+
+static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
+{
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+	/* clear event registers */
+	setbits32(&lbc->ltesr, LTESR_CLEAR);
+	out_be32(&lbc->lteatr, 0);
+	out_be32(&lbc->ltear, 0);
+	out_be32(&lbc->lteccr, LTECCR_CLEAR);
+	out_be32(&lbc->ltedr, LTEDR_ENABLE);
+
+	/* Enable interrupts for any detected events */
+	out_be32(&lbc->lteir, LTEIR_ENABLE);
+
+	return 0;
+}
+
+static int __devexit fsl_lbc_ctrl_remove(struct platform_device *ofdev)
+{
+	struct fsl_lbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
+
+	if (ctrl->irq)
+		free_irq(ctrl->irq, ctrl);
+
+	if (ctrl->regs)
+		iounmap(ctrl->regs);
+
+	dev_set_drvdata(&ofdev->dev, NULL);
+
+	kfree(ctrl);
+
+	return 0;
+}
+
+/*
+ * NOTE: This interrupt is used to report localbus events of various kinds,
+ * such as transaction errors on the chipselects.
+ */
+
+static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
+{
+	struct fsl_lbc_ctrl *ctrl = data;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	u32 status;
+
+	status = in_be32(&lbc->ltesr);
+
+	if (status) {
+		out_be32(&lbc->ltesr, LTESR_CLEAR);
+		out_be32(&lbc->lteatr, 0);
+		out_be32(&lbc->ltear, 0);
+		ctrl->irq_status = status;
+
+		if (status & LTESR_BM)
+			dev_err(ctrl->dev, "Local bus monitor time-out: "
+				"LTESR 0x%08X\n", status);
+		if (status & LTESR_WP)
+			dev_err(ctrl->dev, "Write protect error: "
+				"LTESR 0x%08X\n", status);
+		if (status & LTESR_ATMW)
+			dev_err(ctrl->dev, "Atomic write error: "
+				"LTESR 0x%08X\n", status);
+		if (status & LTESR_ATMR)
+			dev_err(ctrl->dev, "Atomic read error: "
+				"LTESR 0x%08X\n", status);
+		if (status & LTESR_CS)
+			dev_err(ctrl->dev, "Chip select error: "
+				"LTESR 0x%08X\n", status);
+		if (status & LTESR_UPM)
+			;
+		if (status & LTESR_FCT) {
+			dev_err(ctrl->dev, "FCM command time-out: "
+				"LTESR 0x%08X\n", status);
+			smp_wmb();
+			wake_up(&ctrl->irq_wait);
+		}
+		if (status & LTESR_PAR) {
+			dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
+				"LTESR 0x%08X\n", status);
+			smp_wmb();
+			wake_up(&ctrl->irq_wait);
+		}
+		if (status & LTESR_CC) {
+			smp_wmb();
+			wake_up(&ctrl->irq_wait);
+		}
+		if (status & ~LTESR_MASK)
+			dev_err(ctrl->dev, "Unknown error: "
+				"LTESR 0x%08X\n", status);
+
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+/*
+ * fsl_lbc_ctrl_probe
+ *
+ * called by device layer when it finds a device matching
+ * one our driver can handled. This code allocates all of
+ * the resources needed for the controller only.  The
+ * resources for the NAND banks themselves are allocated
+ * in the chip probe function.
+*/
+
+static int __devinit fsl_lbc_ctrl_probe(struct platform_device *ofdev,
+					 const struct of_device_id *match)
+{
+	int ret;
+
+	if (!ofdev->dev.of_node) {
+		dev_err(&ofdev->dev, "Device OF-Node is NULL");
+		return -EFAULT;
+	}
+	fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
+	if (!fsl_lbc_ctrl_dev)
+		return -ENOMEM;
+
+	dev_set_drvdata(&ofdev->dev, fsl_lbc_ctrl_dev);
+
+	spin_lock_init(&fsl_lbc_ctrl_dev->lock);
+	init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
+
+	fsl_lbc_ctrl_dev->regs = of_iomap(ofdev->dev.of_node, 0);
+	if (!fsl_lbc_ctrl_dev->regs) {
+		dev_err(&ofdev->dev, "failed to get memory region\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+	if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
+		dev_err(&ofdev->dev, "failed to get irq resource\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	fsl_lbc_ctrl_dev->dev = &ofdev->dev;
+
+	ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
+	if (ret < 0)
+		goto err;
+
+	ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
+				"fsl-lbc", fsl_lbc_ctrl_dev);
+	if (ret != 0) {
+		dev_err(&ofdev->dev, "failed to install irq (%d)\n",
+			fsl_lbc_ctrl_dev->irq);
+		ret = fsl_lbc_ctrl_dev->irq;
+		goto err;
+	}
+
+	return 0;
+
+err:
+	iounmap(fsl_lbc_ctrl_dev->regs);
+	kfree(fsl_lbc_ctrl_dev);
+	return ret;
+}
+
+static const struct of_device_id fsl_lbc_match[] = {
+	{ .compatible = "fsl,elbc", },
+	{ .compatible = "fsl,pq3-localbus", },
+	{ .compatible = "fsl,pq2-localbus", },
+	{ .compatible = "fsl,pq2pro-localbus", },
+	{},
+};
+
+static struct of_platform_driver fsl_lbc_ctrl_driver = {
+	.driver = {
+		.name = "fsl-lbc",
+		.of_match_table = fsl_lbc_match,
+	},
+	.probe = fsl_lbc_ctrl_probe,
+};
+
+static int __init fsl_lbc_init(void)
+{
+	return of_register_platform_driver(&fsl_lbc_ctrl_driver);
+}
+
+module_init(fsl_lbc_init);
+
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 1/3 v2][MTD] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
@ 2010-09-09 10:20 ` Roy Zang
  0 siblings, 0 replies; 40+ messages in thread
From: Roy Zang @ 2010-09-09 10:20 UTC (permalink / raw)
  To: linux-mtd
  Cc: B07421, dedekind1, B25806, linuxppc-dev, cbouatmailru, akpm,
	dwmw2, B11780

From: Lan Chunhe-B25806 <b25806@freescale.com>

Move Freescale elbc interrupt from nand dirver to elbc driver.
Then all elbc devices can use the interrupt instead of ONLY nand.

Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
Comparing with v1, according to the feedback, add some decorations.

 arch/powerpc/Kconfig               |    7 +-
 arch/powerpc/include/asm/fsl_lbc.h |   34 +++++-
 arch/powerpc/sysdev/fsl_lbc.c      |  248 ++++++++++++++++++++++++++++++------
 3 files changed, 247 insertions(+), 42 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 631e5a0..44df1ba 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -687,9 +687,12 @@ config 4xx_SOC
 	bool
 
 config FSL_LBC
-	bool
+	bool "Freescale Local Bus support"
+	depends on FSL_SOC
 	help
-	  Freescale Localbus support
+	  Enables reporting of errors from the Freescale local bus
+	  controller.  Also contains some common code used by
+	  drivers for specific local bus peripherals.
 
 config FSL_GTM
 	bool
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 1b5a210..9b95eab 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -1,9 +1,10 @@
 /* Freescale Local Bus Controller
  *
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
  *
  * Authors: Nick Spence <nick.spence@freescale.com>,
  *          Scott Wood <scottwood@freescale.com>
+ *          Jack Lan <jack.lan@freescale.com>
  *
  * 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
@@ -27,6 +28,9 @@
 #include <linux/types.h>
 #include <linux/io.h>
 
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+
 struct fsl_lbc_bank {
 	__be32 br;             /**< Base Register  */
 #define BR_BA           0xFFFF8000
@@ -125,13 +129,23 @@ struct fsl_lbc_regs {
 #define LTESR_ATMW 0x00800000
 #define LTESR_ATMR 0x00400000
 #define LTESR_CS   0x00080000
+#define LTESR_UPM  0x00000002
 #define LTESR_CC   0x00000001
 #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+#define LTESR_MASK      (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
+			 | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
+			 | LTESR_CC)
+#define LTESR_CLEAR	0xFFFFFFFF
+#define LTECCR_CLEAR	0xFFFFFFFF
+#define LTESR_STATUS	LTESR_MASK
+#define LTEIR_ENABLE	LTESR_MASK
+#define LTEDR_ENABLE	0x00000000
 	__be32 ltedr;           /**< Transfer Error Disable Register */
 	__be32 lteir;           /**< Transfer Error Interrupt Register */
 	__be32 lteatr;          /**< Transfer Error Attributes Register */
 	__be32 ltear;           /**< Transfer Error Address Register */
-	u8 res6[0xC];
+	__be32 lteccr;          /**< Transfer Error ECC Register */
+	u8 res6[0x8];
 	__be32 lbcr;            /**< Configuration Register */
 #define LBCR_LDIS  0x80000000
 #define LBCR_LDIS_SHIFT    31
@@ -265,7 +279,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
 		cpu_relax();
 }
 
+/* overview of the fsl lbc controller */
+
+struct fsl_lbc_ctrl {
+	/* device info */
+	struct device			*dev;
+	struct fsl_lbc_regs __iomem	*regs;
+	int				irq;
+	wait_queue_head_t		irq_wait;
+	spinlock_t			lock;
+	void				*nand;
+
+	/* status read from LTESR by irq handler */
+	unsigned int			irq_status;
+};
+
 extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
 			       u32 mar);
+extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
 
 #endif /* __ASM_FSL_LBC_H */
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index dceb8d1..f4eca8d 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -2,8 +2,11 @@
  * Freescale LBC and UPM routines.
  *
  * Copyright (c) 2007-2008  MontaVista Software, Inc.
+ * Copyright (c) 2010 Freescale Semiconductor
  *
  * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ * Author: Jack Lan <Jack.Lan@freescale.com>
+ * Author: Roy Zang <tie-fei.zang@freescale.com>
  *
  * 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
@@ -21,37 +24,11 @@
 #include <linux/of.h>
 #include <asm/prom.h>
 #include <asm/fsl_lbc.h>
+#include <linux/slab.h>
 
 static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
-static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
-
-static char __initdata *compat_lbc[] = {
-	"fsl,pq2-localbus",
-	"fsl,pq2pro-localbus",
-	"fsl,pq3-localbus",
-	"fsl,elbc",
-};
-
-static int __init fsl_lbc_init(void)
-{
-	struct device_node *lbus;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
-		lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
-		if (lbus)
-			goto found;
-	}
-	return -ENODEV;
-
-found:
-	fsl_lbc_regs = of_iomap(lbus, 0);
-	of_node_put(lbus);
-	if (!fsl_lbc_regs)
-		return -ENOMEM;
-	return 0;
-}
-arch_initcall(fsl_lbc_init);
+struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
+EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
 
 /**
  * fsl_lbc_find - find Localbus bank
@@ -65,13 +42,15 @@ arch_initcall(fsl_lbc_init);
 int fsl_lbc_find(phys_addr_t addr_base)
 {
 	int i;
+	struct fsl_lbc_regs __iomem *lbc;
 
-	if (!fsl_lbc_regs)
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
 		return -ENODEV;
 
-	for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
-		__be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
-		__be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
+	lbc = fsl_lbc_ctrl_dev->regs;
+	for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
+		__be32 br = in_be32(&lbc->bank[i].br);
+		__be32 or = in_be32(&lbc->bank[i].or);
 
 		if (br & BR_V && (br & or & BR_BA) == addr_base)
 			return i;
@@ -94,22 +73,26 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
 {
 	int bank;
 	__be32 br;
+	struct fsl_lbc_regs __iomem *lbc;
 
 	bank = fsl_lbc_find(addr_base);
 	if (bank < 0)
 		return bank;
 
-	br = in_be32(&fsl_lbc_regs->bank[bank].br);
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+		return -ENODEV;
+	lbc = fsl_lbc_ctrl_dev->regs;
+	br = in_be32(&lbc->bank[bank].br);
 
 	switch (br & BR_MSEL) {
 	case BR_MS_UPMA:
-		upm->mxmr = &fsl_lbc_regs->mamr;
+		upm->mxmr = &lbc->mamr;
 		break;
 	case BR_MS_UPMB:
-		upm->mxmr = &fsl_lbc_regs->mbmr;
+		upm->mxmr = &lbc->mbmr;
 		break;
 	case BR_MS_UPMC:
-		upm->mxmr = &fsl_lbc_regs->mcmr;
+		upm->mxmr = &lbc->mcmr;
 		break;
 	default:
 		return -EINVAL;
@@ -143,14 +126,18 @@ EXPORT_SYMBOL(fsl_upm_find);
  * thus UPM pattern actually executed. Note that mar usage depends on the
  * pre-programmed AMX bits in the UPM RAM.
  */
+
 int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
 {
 	int ret = 0;
 	unsigned long flags;
 
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+		return -ENODEV;
+
 	spin_lock_irqsave(&fsl_lbc_lock, flags);
 
-	out_be32(&fsl_lbc_regs->mar, mar);
+	out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
 
 	switch (upm->width) {
 	case 8:
@@ -172,3 +159,188 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
 	return ret;
 }
 EXPORT_SYMBOL(fsl_upm_run_pattern);
+
+static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
+{
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+	/* clear event registers */
+	setbits32(&lbc->ltesr, LTESR_CLEAR);
+	out_be32(&lbc->lteatr, 0);
+	out_be32(&lbc->ltear, 0);
+	out_be32(&lbc->lteccr, LTECCR_CLEAR);
+	out_be32(&lbc->ltedr, LTEDR_ENABLE);
+
+	/* Enable interrupts for any detected events */
+	out_be32(&lbc->lteir, LTEIR_ENABLE);
+
+	return 0;
+}
+
+static int __devexit fsl_lbc_ctrl_remove(struct platform_device *ofdev)
+{
+	struct fsl_lbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
+
+	if (ctrl->irq)
+		free_irq(ctrl->irq, ctrl);
+
+	if (ctrl->regs)
+		iounmap(ctrl->regs);
+
+	dev_set_drvdata(&ofdev->dev, NULL);
+
+	kfree(ctrl);
+
+	return 0;
+}
+
+/*
+ * NOTE: This interrupt is used to report localbus events of various kinds,
+ * such as transaction errors on the chipselects.
+ */
+
+static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
+{
+	struct fsl_lbc_ctrl *ctrl = data;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	u32 status;
+
+	status = in_be32(&lbc->ltesr);
+
+	if (status) {
+		out_be32(&lbc->ltesr, LTESR_CLEAR);
+		out_be32(&lbc->lteatr, 0);
+		out_be32(&lbc->ltear, 0);
+		ctrl->irq_status = status;
+
+		if (status & LTESR_BM)
+			dev_err(ctrl->dev, "Local bus monitor time-out: "
+				"LTESR 0x%08X\n", status);
+		if (status & LTESR_WP)
+			dev_err(ctrl->dev, "Write protect error: "
+				"LTESR 0x%08X\n", status);
+		if (status & LTESR_ATMW)
+			dev_err(ctrl->dev, "Atomic write error: "
+				"LTESR 0x%08X\n", status);
+		if (status & LTESR_ATMR)
+			dev_err(ctrl->dev, "Atomic read error: "
+				"LTESR 0x%08X\n", status);
+		if (status & LTESR_CS)
+			dev_err(ctrl->dev, "Chip select error: "
+				"LTESR 0x%08X\n", status);
+		if (status & LTESR_UPM)
+			;
+		if (status & LTESR_FCT) {
+			dev_err(ctrl->dev, "FCM command time-out: "
+				"LTESR 0x%08X\n", status);
+			smp_wmb();
+			wake_up(&ctrl->irq_wait);
+		}
+		if (status & LTESR_PAR) {
+			dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
+				"LTESR 0x%08X\n", status);
+			smp_wmb();
+			wake_up(&ctrl->irq_wait);
+		}
+		if (status & LTESR_CC) {
+			smp_wmb();
+			wake_up(&ctrl->irq_wait);
+		}
+		if (status & ~LTESR_MASK)
+			dev_err(ctrl->dev, "Unknown error: "
+				"LTESR 0x%08X\n", status);
+
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+/*
+ * fsl_lbc_ctrl_probe
+ *
+ * called by device layer when it finds a device matching
+ * one our driver can handled. This code allocates all of
+ * the resources needed for the controller only.  The
+ * resources for the NAND banks themselves are allocated
+ * in the chip probe function.
+*/
+
+static int __devinit fsl_lbc_ctrl_probe(struct platform_device *ofdev,
+					 const struct of_device_id *match)
+{
+	int ret;
+
+	if (!ofdev->dev.of_node) {
+		dev_err(&ofdev->dev, "Device OF-Node is NULL");
+		return -EFAULT;
+	}
+	fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
+	if (!fsl_lbc_ctrl_dev)
+		return -ENOMEM;
+
+	dev_set_drvdata(&ofdev->dev, fsl_lbc_ctrl_dev);
+
+	spin_lock_init(&fsl_lbc_ctrl_dev->lock);
+	init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
+
+	fsl_lbc_ctrl_dev->regs = of_iomap(ofdev->dev.of_node, 0);
+	if (!fsl_lbc_ctrl_dev->regs) {
+		dev_err(&ofdev->dev, "failed to get memory region\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+	if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
+		dev_err(&ofdev->dev, "failed to get irq resource\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	fsl_lbc_ctrl_dev->dev = &ofdev->dev;
+
+	ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
+	if (ret < 0)
+		goto err;
+
+	ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
+				"fsl-lbc", fsl_lbc_ctrl_dev);
+	if (ret != 0) {
+		dev_err(&ofdev->dev, "failed to install irq (%d)\n",
+			fsl_lbc_ctrl_dev->irq);
+		ret = fsl_lbc_ctrl_dev->irq;
+		goto err;
+	}
+
+	return 0;
+
+err:
+	iounmap(fsl_lbc_ctrl_dev->regs);
+	kfree(fsl_lbc_ctrl_dev);
+	return ret;
+}
+
+static const struct of_device_id fsl_lbc_match[] = {
+	{ .compatible = "fsl,elbc", },
+	{ .compatible = "fsl,pq3-localbus", },
+	{ .compatible = "fsl,pq2-localbus", },
+	{ .compatible = "fsl,pq2pro-localbus", },
+	{},
+};
+
+static struct of_platform_driver fsl_lbc_ctrl_driver = {
+	.driver = {
+		.name = "fsl-lbc",
+		.of_match_table = fsl_lbc_match,
+	},
+	.probe = fsl_lbc_ctrl_probe,
+};
+
+static int __init fsl_lbc_init(void)
+{
+	return of_register_platform_driver(&fsl_lbc_ctrl_driver);
+}
+
+module_init(fsl_lbc_init);
+
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 2/3 v2][MTD] P4080/mtd: Only make elbc nand driver detect nand flash partitions
  2010-09-09 10:20 ` Roy Zang
@ 2010-09-09 10:20   ` Roy Zang
  -1 siblings, 0 replies; 40+ messages in thread
From: Roy Zang @ 2010-09-09 10:20 UTC (permalink / raw)
  To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780

From: Jack Lan <jack.lan@freescale.com>

The former driver had the two functions:

1. detecting nand flash partitions;
2. registering elbc interrupt.

Now, second function is removed to fsl_lbc.c.

Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
Comparing with v1, according to the feedback, remove global variables.

 drivers/mtd/nand/Kconfig         |    1 +
 drivers/mtd/nand/fsl_elbc_nand.c |  476 +++++++++++++++-----------------------
 2 files changed, 183 insertions(+), 294 deletions(-)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8b4b67c..4132c46 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -458,6 +458,7 @@ config MTD_NAND_ORION
 config MTD_NAND_FSL_ELBC
 	tristate "NAND support for Freescale eLBC controllers"
 	depends on PPC_OF
+	select FSL_LBC
 	help
 	  Various Freescale chips, including the 8313, include a NAND Flash
 	  Controller Module with built-in hardware ECC capabilities.
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 80de0bf..64c840f 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -1,9 +1,10 @@
 /* Freescale Enhanced Local Bus Controller NAND driver
  *
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
  *
  * Authors: Nick Spence <nick.spence@freescale.com>,
  *          Scott Wood <scottwood@freescale.com>
+ *          Jack Lan <jack.lan@freescale.com>
  *
  * 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
@@ -24,32 +25,22 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/of_platform.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
 
-#include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
 #include <asm/fsl_lbc.h>
+#include <linux/slab.h>
 
 #define MAX_BANKS 8
 #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
 #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
 
-struct fsl_elbc_ctrl;
-
 /* mtd information per set */
 
 struct fsl_elbc_mtd {
 	struct mtd_info mtd;
 	struct nand_chip chip;
-	struct fsl_elbc_ctrl *ctrl;
+	struct fsl_lbc_ctrl *ctrl;
 
 	struct device *dev;
 	int bank;               /* Chip select bank number           */
@@ -58,18 +49,12 @@ struct fsl_elbc_mtd {
 	unsigned int fmr;       /* FCM Flash Mode Register value     */
 };
 
-/* overview of the fsl elbc controller */
+/* Freescale eLBC FCM controller infomation */
 
-struct fsl_elbc_ctrl {
+struct fsl_elbc_fcm_ctrl {
 	struct nand_hw_control controller;
 	struct fsl_elbc_mtd *chips[MAX_BANKS];
 
-	/* device info */
-	struct device *dev;
-	struct fsl_lbc_regs __iomem *regs;
-	int irq;
-	wait_queue_head_t irq_wait;
-	unsigned int irq_status; /* status read from LTESR by irq handler */
 	u8 __iomem *addr;        /* Address of assigned FCM buffer        */
 	unsigned int page;       /* Last page written to / read from      */
 	unsigned int read_bytes; /* Number of bytes read during command   */
@@ -164,11 +149,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	int buf_num;
 
-	ctrl->page = page_addr;
+	elbc_fcm_ctrl->page = page_addr;
 
 	out_be32(&lbc->fbar,
 	         page_addr >> (chip->phys_erase_shift - chip->page_shift));
@@ -185,16 +171,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 		buf_num = page_addr & 7;
 	}
 
-	ctrl->addr = priv->vbase + buf_num * 1024;
-	ctrl->index = column;
+	elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
+	elbc_fcm_ctrl->index = column;
 
 	/* for OOB data point to the second half of the buffer */
 	if (oob)
-		ctrl->index += priv->page_size ? 2048 : 512;
+		elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
 
-	dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
+	dev_vdbg(priv->dev, "set_addr: bank=%d, "
+			    "elbc_fcm_ctrl->addr=0x%p (0x%p), "
 	                    "index %x, pes %d ps %d\n",
-	         buf_num, ctrl->addr, priv->vbase, ctrl->index,
+		 buf_num, elbc_fcm_ctrl->addr, priv->vbase,
+		 elbc_fcm_ctrl->index,
 	         chip->phys_erase_shift, chip->page_shift);
 }
 
@@ -205,18 +193,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	/* Setup the FMR[OP] to execute without write protection */
 	out_be32(&lbc->fmr, priv->fmr | 3);
-	if (ctrl->use_mdr)
-		out_be32(&lbc->mdr, ctrl->mdr);
+	if (elbc_fcm_ctrl->use_mdr)
+		out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
 
-	dev_vdbg(ctrl->dev,
+	dev_vdbg(priv->dev,
 	         "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
 	         in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
-	dev_vdbg(ctrl->dev,
+	dev_vdbg(priv->dev,
 	         "fsl_elbc_run_command: fbar=%08x fpar=%08x "
 	         "fbcr=%08x bank=%d\n",
 	         in_be32(&lbc->fbar), in_be32(&lbc->fpar),
@@ -229,19 +218,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 	/* wait for FCM complete flag or timeout */
 	wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
 	                   FCM_TIMEOUT_MSECS * HZ/1000);
-	ctrl->status = ctrl->irq_status;
-
+	elbc_fcm_ctrl->status = ctrl->irq_status;
 	/* store mdr value in case it was needed */
-	if (ctrl->use_mdr)
-		ctrl->mdr = in_be32(&lbc->mdr);
+	if (elbc_fcm_ctrl->use_mdr)
+		elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
 
-	ctrl->use_mdr = 0;
+	elbc_fcm_ctrl->use_mdr = 0;
 
-	if (ctrl->status != LTESR_CC) {
-		dev_info(ctrl->dev,
+	if (elbc_fcm_ctrl->status != LTESR_CC) {
+		dev_info(priv->dev,
 		         "command failed: fir %x fcr %x status %x mdr %x\n",
 		         in_be32(&lbc->fir), in_be32(&lbc->fcr),
-		         ctrl->status, ctrl->mdr);
+			 elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
 		return -EIO;
 	}
 
@@ -251,7 +239,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	if (priv->page_size) {
@@ -284,15 +272,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
-	ctrl->use_mdr = 0;
+	elbc_fcm_ctrl->use_mdr = 0;
 
 	/* clear the read buffer */
-	ctrl->read_bytes = 0;
+	elbc_fcm_ctrl->read_bytes = 0;
 	if (command != NAND_CMD_PAGEPROG)
-		ctrl->index = 0;
+		elbc_fcm_ctrl->index = 0;
 
 	switch (command) {
 	/* READ0 and READ1 read the entire buffer to use hardware ECC. */
@@ -301,7 +290,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* fall-through */
 	case NAND_CMD_READ0:
-		dev_dbg(ctrl->dev,
+		dev_dbg(priv->dev,
 		        "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
 		        " 0x%x, column: 0x%x.\n", page_addr, column);
 
@@ -309,8 +298,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
 		set_addr(mtd, 0, page_addr, 0);
 
-		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
-		ctrl->index += column;
+		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		elbc_fcm_ctrl->index += column;
 
 		fsl_elbc_do_read(chip, 0);
 		fsl_elbc_run_command(mtd);
@@ -318,14 +307,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* READOOB reads only the OOB because no ECC is performed. */
 	case NAND_CMD_READOOB:
-		dev_vdbg(ctrl->dev,
+		dev_vdbg(priv->dev,
 		         "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
 			 " 0x%x, column: 0x%x.\n", page_addr, column);
 
 		out_be32(&lbc->fbcr, mtd->oobsize - column);
 		set_addr(mtd, column, page_addr, 1);
 
-		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
 
 		fsl_elbc_do_read(chip, 1);
 		fsl_elbc_run_command(mtd);
@@ -333,7 +322,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* READID must read all 5 possible bytes while CEB is active */
 	case NAND_CMD_READID:
-		dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
+		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
 
 		out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
 		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
@@ -341,9 +330,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
 		/* 5 bytes for manuf, device and exts */
 		out_be32(&lbc->fbcr, 5);
-		ctrl->read_bytes = 5;
-		ctrl->use_mdr = 1;
-		ctrl->mdr = 0;
+		elbc_fcm_ctrl->read_bytes = 5;
+		elbc_fcm_ctrl->use_mdr = 1;
+		elbc_fcm_ctrl->mdr = 0;
 
 		set_addr(mtd, 0, 0, 0);
 		fsl_elbc_run_command(mtd);
@@ -351,7 +340,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* ERASE1 stores the block and page address */
 	case NAND_CMD_ERASE1:
-		dev_vdbg(ctrl->dev,
+		dev_vdbg(priv->dev,
 		         "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
 		         "page_addr: 0x%x.\n", page_addr);
 		set_addr(mtd, 0, page_addr, 0);
@@ -359,7 +348,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* ERASE2 uses the block and page address from ERASE1 */
 	case NAND_CMD_ERASE2:
-		dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
+		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
 
 		out_be32(&lbc->fir,
 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
@@ -374,8 +363,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		         (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
 
 		out_be32(&lbc->fbcr, 0);
-		ctrl->read_bytes = 0;
-		ctrl->use_mdr = 1;
+		elbc_fcm_ctrl->read_bytes = 0;
+		elbc_fcm_ctrl->use_mdr = 1;
 
 		fsl_elbc_run_command(mtd);
 		return;
@@ -383,14 +372,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 	/* SEQIN sets up the addr buffer and all registers except the length */
 	case NAND_CMD_SEQIN: {
 		__be32 fcr;
-		dev_vdbg(ctrl->dev,
-		         "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
+		dev_vdbg(priv->dev,
+			 "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
 		         "page_addr: 0x%x, column: 0x%x.\n",
 		         page_addr, column);
 
-		ctrl->column = column;
-		ctrl->oob = 0;
-		ctrl->use_mdr = 1;
+		elbc_fcm_ctrl->use_mdr = 1;
 
 		fcr = (NAND_CMD_STATUS   << FCR_CMD1_SHIFT) |
 		      (NAND_CMD_SEQIN    << FCR_CMD2_SHIFT) |
@@ -420,7 +407,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 				/* OOB area --> READOOB */
 				column -= mtd->writesize;
 				fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
-				ctrl->oob = 1;
+				elbc_fcm_ctrl->oob = 1;
 			} else {
 				WARN_ON(column != 0);
 				/* First 256 bytes --> READ0 */
@@ -429,24 +416,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		}
 
 		out_be32(&lbc->fcr, fcr);
-		set_addr(mtd, column, page_addr, ctrl->oob);
+		set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
 		return;
 	}
 
 	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
 	case NAND_CMD_PAGEPROG: {
 		int full_page;
-		dev_vdbg(ctrl->dev,
+		dev_vdbg(priv->dev,
 		         "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
-		         "writing %d bytes.\n", ctrl->index);
+			 "writing %d bytes.\n", elbc_fcm_ctrl->index);
 
 		/* if the write did not start at 0 or is not a full page
 		 * then set the exact length, otherwise use a full page
 		 * write so the HW generates the ECC.
 		 */
-		if (ctrl->oob || ctrl->column != 0 ||
-		    ctrl->index != mtd->writesize + mtd->oobsize) {
-			out_be32(&lbc->fbcr, ctrl->index);
+		if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
+		    elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
+			out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
 			full_page = 0;
 		} else {
 			out_be32(&lbc->fbcr, 0);
@@ -458,21 +445,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		/* Read back the page in order to fill in the ECC for the
 		 * caller.  Is this really needed?
 		 */
-		if (full_page && ctrl->oob_poi) {
+		if (full_page && elbc_fcm_ctrl->oob_poi) {
 			out_be32(&lbc->fbcr, 3);
 			set_addr(mtd, 6, page_addr, 1);
 
-			ctrl->read_bytes = mtd->writesize + 9;
+			elbc_fcm_ctrl->read_bytes = mtd->writesize + 9;
 
 			fsl_elbc_do_read(chip, 1);
 			fsl_elbc_run_command(mtd);
 
-			memcpy_fromio(ctrl->oob_poi + 6,
-			              &ctrl->addr[ctrl->index], 3);
-			ctrl->index += 3;
+			memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6,
+				&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3);
+			elbc_fcm_ctrl->index += 3;
 		}
 
-		ctrl->oob_poi = NULL;
+		elbc_fcm_ctrl->oob_poi = NULL;
 		return;
 	}
 
@@ -485,26 +472,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
 		out_be32(&lbc->fbcr, 1);
 		set_addr(mtd, 0, 0, 0);
-		ctrl->read_bytes = 1;
+		elbc_fcm_ctrl->read_bytes = 1;
 
 		fsl_elbc_run_command(mtd);
 
 		/* The chip always seems to report that it is
 		 * write-protected, even when it is not.
 		 */
-		setbits8(ctrl->addr, NAND_STATUS_WP);
+		setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
 		return;
 
 	/* RESET without waiting for the ready line */
 	case NAND_CMD_RESET:
-		dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
+		dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
 		out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
 		out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
 		fsl_elbc_run_command(mtd);
 		return;
 
 	default:
-		dev_err(ctrl->dev,
+		dev_err(priv->dev,
 		        "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
 		        command);
 	}
@@ -524,24 +511,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	unsigned int bufsize = mtd->writesize + mtd->oobsize;
 
 	if (len <= 0) {
-		dev_err(ctrl->dev, "write_buf of %d bytes", len);
-		ctrl->status = 0;
+		dev_err(priv->dev, "write_buf of %d bytes", len);
+		elbc_fcm_ctrl->status = 0;
 		return;
 	}
 
-	if ((unsigned int)len > bufsize - ctrl->index) {
-		dev_err(ctrl->dev,
+	if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
+		dev_err(priv->dev,
 		        "write_buf beyond end of buffer "
 		        "(%d requested, %u available)\n",
-		        len, bufsize - ctrl->index);
-		len = bufsize - ctrl->index;
+			len, bufsize - elbc_fcm_ctrl->index);
+		len = bufsize - elbc_fcm_ctrl->index;
 	}
 
-	memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+	memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
 	/*
 	 * This is workaround for the weird elbc hangs during nand write,
 	 * Scott Wood says: "...perhaps difference in how long it takes a
@@ -549,9 +536,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 	 * is causing problems, and sync isn't helping for some reason."
 	 * Reading back the last byte helps though.
 	 */
-	in_8(&ctrl->addr[ctrl->index] + len - 1);
+	in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
 
-	ctrl->index += len;
+	elbc_fcm_ctrl->index += len;
 }
 
 /*
@@ -562,13 +549,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 
 	/* If there are still bytes in the FCM, then use the next byte. */
-	if (ctrl->index < ctrl->read_bytes)
-		return in_8(&ctrl->addr[ctrl->index++]);
+	if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
+		return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
 
-	dev_err(ctrl->dev, "read_byte beyond end of buffer\n");
+	dev_err(priv->dev, "read_byte beyond end of buffer\n");
 	return ERR_BYTE;
 }
 
@@ -579,18 +566,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	int avail;
 
 	if (len < 0)
 		return;
 
-	avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
-	memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
-	ctrl->index += avail;
+	avail = min((unsigned int)len,
+			elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
+	memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
+	elbc_fcm_ctrl->index += avail;
 
 	if (len > avail)
-		dev_err(ctrl->dev,
+		dev_err(priv->dev,
 		        "read_buf beyond end of buffer "
 		        "(%d requested, %d available)\n",
 		        len, avail);
@@ -603,30 +591,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	int i;
 
 	if (len < 0) {
-		dev_err(ctrl->dev, "write_buf of %d bytes", len);
+		dev_err(priv->dev, "write_buf of %d bytes", len);
 		return -EINVAL;
 	}
 
-	if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
-		dev_err(ctrl->dev,
-		        "verify_buf beyond end of buffer "
-		        "(%d requested, %u available)\n",
-		        len, ctrl->read_bytes - ctrl->index);
+	if ((unsigned int)len >
+			elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) {
+		dev_err(priv->dev,
+			"verify_buf beyond end of buffer "
+			"(%d requested, %u available)\n",
+			len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
 
-		ctrl->index = ctrl->read_bytes;
+		elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes;
 		return -EINVAL;
 	}
 
 	for (i = 0; i < len; i++)
-		if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
+		if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
+				!= buf[i])
 			break;
 
-	ctrl->index += len;
-	return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
+	elbc_fcm_ctrl->index += len;
+	return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO;
 }
 
 /* This function is called after Program and Erase Operations to
@@ -635,22 +625,21 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
-	if (ctrl->status != LTESR_CC)
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
+	if (elbc_fcm_ctrl->status != LTESR_CC)
 		return NAND_STATUS_FAIL;
 
 	/* The chip always seems to report that it is
 	 * write-protected, even when it is not.
 	 */
-	return (ctrl->mdr & 0xff) | NAND_STATUS_WP;
+	return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
 }
 
 static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	unsigned int al;
 
@@ -665,41 +654,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 	priv->fmr |= (12 << FMR_CWTO_SHIFT) |  /* Timeout > 12 ms */
 	             (al << FMR_AL_SHIFT);
 
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
 	        chip->numchips);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
 	        chip->chipsize);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
 	        chip->pagemask);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
 	        chip->chip_delay);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
 	        chip->badblockpos);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
 	        chip->chip_shift);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
 	        chip->page_shift);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
 	        chip->phys_erase_shift);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
 	        chip->ecclayout);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
 	        chip->ecc.mode);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
 	        chip->ecc.steps);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
 	        chip->ecc.bytes);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
 	        chip->ecc.total);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
 	        chip->ecc.layout);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
 	        mtd->erasesize);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
 	        mtd->writesize);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
 	        mtd->oobsize);
 
 	/* adjust Option Register and ECC to match Flash page size */
@@ -719,7 +708,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 			chip->badblock_pattern = &largepage_memorybased;
 		}
 	} else {
-		dev_err(ctrl->dev,
+		dev_err(priv->dev,
 		        "fsl_elbc_init: page size %d is not supported\n",
 		        mtd->writesize);
 		return -1;
@@ -750,18 +739,18 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
                                 const uint8_t *buf)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
 	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
 
-	ctrl->oob_poi = chip->oob_poi;
+	elbc_fcm_ctrl->oob_poi = chip->oob_poi;
 }
 
 static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 {
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct nand_chip *chip = &priv->chip;
 
 	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
@@ -790,7 +779,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 	chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
 			NAND_USE_FLASH_BBT;
 
-	chip->controller = &ctrl->controller;
+	chip->controller = &elbc_fcm_ctrl->controller;
 	chip->priv = priv;
 
 	chip->ecc.read_page = fsl_elbc_read_page;
@@ -815,8 +804,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 
 static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 {
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	nand_release(&priv->mtd);
 
 	kfree(priv->mtd.name);
@@ -824,18 +812,19 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 	if (priv->vbase)
 		iounmap(priv->vbase);
 
-	ctrl->chips[priv->bank] = NULL;
+	elbc_fcm_ctrl->chips[priv->bank] = NULL;
 	kfree(priv);
-
+	kfree(elbc_fcm_ctrl);
 	return 0;
 }
 
-static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
-					 struct device_node *node)
+static int __devinit fsl_elbc_nand_probe(struct platform_device *dev,
+					 const struct of_device_id *match)
 {
-	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc;
 	struct fsl_elbc_mtd *priv;
 	struct resource res;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
 #ifdef CONFIG_MTD_PARTITIONS
 	static const char *part_probe_types[]
 		= { "cmdlinepart", "RedBoot", NULL };
@@ -843,11 +832,16 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
 #endif
 	int ret;
 	int bank;
+	struct device_node *node = dev->dev.of_node;
+
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+		return -ENODEV;
+	lbc = fsl_lbc_ctrl_dev->regs;
 
 	/* get, allocate and map the memory resource */
 	ret = of_address_to_resource(node, 0, &res);
 	if (ret) {
-		dev_err(ctrl->dev, "failed to get resource\n");
+		dev_err(fsl_lbc_ctrl_dev->dev, "failed to get resource\n");
 		return ret;
 	}
 
@@ -861,7 +855,8 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
 			break;
 
 	if (bank >= MAX_BANKS) {
-		dev_err(ctrl->dev, "address did not match any chip selects\n");
+		dev_err(fsl_lbc_ctrl_dev->dev, "address did not match any "
+			"chip selects\n");
 		return -ENODEV;
 	}
 
@@ -869,14 +864,28 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
 	if (!priv)
 		return -ENOMEM;
 
-	ctrl->chips[bank] = priv;
+	if (fsl_lbc_ctrl_dev->nand == NULL) {
+		elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
+		if (!elbc_fcm_ctrl)
+			return -ENOMEM;
+
+		elbc_fcm_ctrl->read_bytes = 0;
+		elbc_fcm_ctrl->index = 0;
+		elbc_fcm_ctrl->addr = NULL;
+
+		spin_lock_init(&elbc_fcm_ctrl->controller.lock);
+		init_waitqueue_head(&elbc_fcm_ctrl->controller.wq);
+		fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
+	}
+
+	elbc_fcm_ctrl->chips[bank] = priv;
 	priv->bank = bank;
-	priv->ctrl = ctrl;
-	priv->dev = ctrl->dev;
+	priv->ctrl = fsl_lbc_ctrl_dev;
+	priv->dev = fsl_lbc_ctrl_dev->dev;
 
 	priv->vbase = ioremap(res.start, resource_size(&res));
 	if (!priv->vbase) {
-		dev_err(ctrl->dev, "failed to map chip region\n");
+		dev_err(fsl_lbc_ctrl_dev->dev, "failed to map chip region\n");
 		ret = -ENOMEM;
 		goto err;
 	}
@@ -933,171 +942,50 @@ err:
 	return ret;
 }
 
-static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
+static int fsl_elbc_nand_remove(struct platform_device *ofdev)
 {
-	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-
-	/*
-	 * NAND transactions can tie up the bus for a long time, so set the
-	 * bus timeout to max by clearing LBCR[BMT] (highest base counter
-	 * value) and setting LBCR[BMTPS] to the highest prescaler value.
-	 */
-	clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
-
-	/* clear event registers */
-	setbits32(&lbc->ltesr, LTESR_NAND_MASK);
-	out_be32(&lbc->lteatr, 0);
-
-	/* Enable interrupts for any detected events */
-	out_be32(&lbc->lteir, LTESR_NAND_MASK);
-
-	ctrl->read_bytes = 0;
-	ctrl->index = 0;
-	ctrl->addr = NULL;
-
-	return 0;
-}
-
-static int fsl_elbc_ctrl_remove(struct platform_device *ofdev)
-{
-	struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
 	int i;
-
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
 	for (i = 0; i < MAX_BANKS; i++)
-		if (ctrl->chips[i])
-			fsl_elbc_chip_remove(ctrl->chips[i]);
-
-	if (ctrl->irq)
-		free_irq(ctrl->irq, ctrl);
-
-	if (ctrl->regs)
-		iounmap(ctrl->regs);
-
-	dev_set_drvdata(&ofdev->dev, NULL);
-	kfree(ctrl);
-	return 0;
-}
-
-/* NOTE: This interrupt is also used to report other localbus events,
- * such as transaction errors on other chipselects.  If we want to
- * capture those, we'll need to move the IRQ code into a shared
- * LBC driver.
- */
-
-static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
-{
-	struct fsl_elbc_ctrl *ctrl = data;
-	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-	__be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
-
-	if (status) {
-		out_be32(&lbc->ltesr, status);
-		out_be32(&lbc->lteatr, 0);
-
-		ctrl->irq_status = status;
-		smp_wmb();
-		wake_up(&ctrl->irq_wait);
-
-		return IRQ_HANDLED;
-	}
-
-	return IRQ_NONE;
-}
-
-/* fsl_elbc_ctrl_probe
- *
- * called by device layer when it finds a device matching
- * one our driver can handled. This code allocates all of
- * the resources needed for the controller only.  The
- * resources for the NAND banks themselves are allocated
- * in the chip probe function.
-*/
-
-static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev,
-                                         const struct of_device_id *match)
-{
-	struct device_node *child;
-	struct fsl_elbc_ctrl *ctrl;
-	int ret;
-
-	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
-	if (!ctrl)
-		return -ENOMEM;
+		if (elbc_fcm_ctrl->chips[i])
+			fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]);
 
-	dev_set_drvdata(&ofdev->dev, ctrl);
-
-	spin_lock_init(&ctrl->controller.lock);
-	init_waitqueue_head(&ctrl->controller.wq);
-	init_waitqueue_head(&ctrl->irq_wait);
-
-	ctrl->regs = of_iomap(ofdev->dev.of_node, 0);
-	if (!ctrl->regs) {
-		dev_err(&ofdev->dev, "failed to get memory region\n");
-		ret = -ENODEV;
-		goto err;
-	}
-
-	ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
-	if (ctrl->irq == NO_IRQ) {
-		dev_err(&ofdev->dev, "failed to get irq resource\n");
-		ret = -ENODEV;
-		goto err;
-	}
-
-	ctrl->dev = &ofdev->dev;
-
-	ret = fsl_elbc_ctrl_init(ctrl);
-	if (ret < 0)
-		goto err;
-
-	ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl);
-	if (ret != 0) {
-		dev_err(&ofdev->dev, "failed to install irq (%d)\n",
-		        ctrl->irq);
-		ret = ctrl->irq;
-		goto err;
-	}
-
-	for_each_child_of_node(ofdev->dev.of_node, child)
-		if (of_device_is_compatible(child, "fsl,elbc-fcm-nand"))
-			fsl_elbc_chip_probe(ctrl, child);
+	fsl_lbc_ctrl_dev->nand = NULL;
+	kfree(elbc_fcm_ctrl);
 
 	return 0;
 
-err:
-	fsl_elbc_ctrl_remove(ofdev);
-	return ret;
 }
 
-static const struct of_device_id fsl_elbc_match[] = {
+static const struct of_device_id fsl_elbc_nand_match[] = {
 	{
-		.compatible = "fsl,elbc",
+		.compatible = "fsl,elbc-fcm-nand",
 	},
 	{}
 };
 
-static struct of_platform_driver fsl_elbc_ctrl_driver = {
+static struct of_platform_driver fsl_elbc_nand_driver = {
 	.driver = {
-		.name = "fsl-elbc",
+		.name = "fsl,elbc-fcm-nand",
 		.owner = THIS_MODULE,
-		.of_match_table = fsl_elbc_match,
+		.of_match_table = fsl_elbc_nand_match,
 	},
-	.probe = fsl_elbc_ctrl_probe,
-	.remove = fsl_elbc_ctrl_remove,
+	.probe = fsl_elbc_nand_probe,
+	.remove = fsl_elbc_nand_remove,
 };
 
-static int __init fsl_elbc_init(void)
+static int __init fsl_elbc_nand_init(void)
 {
-	return of_register_platform_driver(&fsl_elbc_ctrl_driver);
+	return of_register_platform_driver(&fsl_elbc_nand_driver);
 }
 
-static void __exit fsl_elbc_exit(void)
+static void __exit fsl_elbc_nand_exit(void)
 {
-	of_unregister_platform_driver(&fsl_elbc_ctrl_driver);
+	of_unregister_platform_driver(&fsl_elbc_nand_driver);
 }
 
-module_init(fsl_elbc_init);
-module_exit(fsl_elbc_exit);
+module_init(fsl_elbc_nand_init);
+module_exit(fsl_elbc_nand_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Freescale");
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 2/3 v2][MTD] P4080/mtd: Only make elbc nand driver detect nand flash partitions
@ 2010-09-09 10:20   ` Roy Zang
  0 siblings, 0 replies; 40+ messages in thread
From: Roy Zang @ 2010-09-09 10:20 UTC (permalink / raw)
  To: linux-mtd
  Cc: B07421, dedekind1, B25806, linuxppc-dev, cbouatmailru, akpm,
	dwmw2, B11780

From: Jack Lan <jack.lan@freescale.com>

The former driver had the two functions:

1. detecting nand flash partitions;
2. registering elbc interrupt.

Now, second function is removed to fsl_lbc.c.

Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
Comparing with v1, according to the feedback, remove global variables.

 drivers/mtd/nand/Kconfig         |    1 +
 drivers/mtd/nand/fsl_elbc_nand.c |  476 +++++++++++++++-----------------------
 2 files changed, 183 insertions(+), 294 deletions(-)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8b4b67c..4132c46 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -458,6 +458,7 @@ config MTD_NAND_ORION
 config MTD_NAND_FSL_ELBC
 	tristate "NAND support for Freescale eLBC controllers"
 	depends on PPC_OF
+	select FSL_LBC
 	help
 	  Various Freescale chips, including the 8313, include a NAND Flash
 	  Controller Module with built-in hardware ECC capabilities.
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 80de0bf..64c840f 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -1,9 +1,10 @@
 /* Freescale Enhanced Local Bus Controller NAND driver
  *
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
  *
  * Authors: Nick Spence <nick.spence@freescale.com>,
  *          Scott Wood <scottwood@freescale.com>
+ *          Jack Lan <jack.lan@freescale.com>
  *
  * 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
@@ -24,32 +25,22 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/of_platform.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
 
-#include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
 #include <asm/fsl_lbc.h>
+#include <linux/slab.h>
 
 #define MAX_BANKS 8
 #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
 #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
 
-struct fsl_elbc_ctrl;
-
 /* mtd information per set */
 
 struct fsl_elbc_mtd {
 	struct mtd_info mtd;
 	struct nand_chip chip;
-	struct fsl_elbc_ctrl *ctrl;
+	struct fsl_lbc_ctrl *ctrl;
 
 	struct device *dev;
 	int bank;               /* Chip select bank number           */
@@ -58,18 +49,12 @@ struct fsl_elbc_mtd {
 	unsigned int fmr;       /* FCM Flash Mode Register value     */
 };
 
-/* overview of the fsl elbc controller */
+/* Freescale eLBC FCM controller infomation */
 
-struct fsl_elbc_ctrl {
+struct fsl_elbc_fcm_ctrl {
 	struct nand_hw_control controller;
 	struct fsl_elbc_mtd *chips[MAX_BANKS];
 
-	/* device info */
-	struct device *dev;
-	struct fsl_lbc_regs __iomem *regs;
-	int irq;
-	wait_queue_head_t irq_wait;
-	unsigned int irq_status; /* status read from LTESR by irq handler */
 	u8 __iomem *addr;        /* Address of assigned FCM buffer        */
 	unsigned int page;       /* Last page written to / read from      */
 	unsigned int read_bytes; /* Number of bytes read during command   */
@@ -164,11 +149,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	int buf_num;
 
-	ctrl->page = page_addr;
+	elbc_fcm_ctrl->page = page_addr;
 
 	out_be32(&lbc->fbar,
 	         page_addr >> (chip->phys_erase_shift - chip->page_shift));
@@ -185,16 +171,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 		buf_num = page_addr & 7;
 	}
 
-	ctrl->addr = priv->vbase + buf_num * 1024;
-	ctrl->index = column;
+	elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
+	elbc_fcm_ctrl->index = column;
 
 	/* for OOB data point to the second half of the buffer */
 	if (oob)
-		ctrl->index += priv->page_size ? 2048 : 512;
+		elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
 
-	dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
+	dev_vdbg(priv->dev, "set_addr: bank=%d, "
+			    "elbc_fcm_ctrl->addr=0x%p (0x%p), "
 	                    "index %x, pes %d ps %d\n",
-	         buf_num, ctrl->addr, priv->vbase, ctrl->index,
+		 buf_num, elbc_fcm_ctrl->addr, priv->vbase,
+		 elbc_fcm_ctrl->index,
 	         chip->phys_erase_shift, chip->page_shift);
 }
 
@@ -205,18 +193,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	/* Setup the FMR[OP] to execute without write protection */
 	out_be32(&lbc->fmr, priv->fmr | 3);
-	if (ctrl->use_mdr)
-		out_be32(&lbc->mdr, ctrl->mdr);
+	if (elbc_fcm_ctrl->use_mdr)
+		out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
 
-	dev_vdbg(ctrl->dev,
+	dev_vdbg(priv->dev,
 	         "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
 	         in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
-	dev_vdbg(ctrl->dev,
+	dev_vdbg(priv->dev,
 	         "fsl_elbc_run_command: fbar=%08x fpar=%08x "
 	         "fbcr=%08x bank=%d\n",
 	         in_be32(&lbc->fbar), in_be32(&lbc->fpar),
@@ -229,19 +218,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 	/* wait for FCM complete flag or timeout */
 	wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
 	                   FCM_TIMEOUT_MSECS * HZ/1000);
-	ctrl->status = ctrl->irq_status;
-
+	elbc_fcm_ctrl->status = ctrl->irq_status;
 	/* store mdr value in case it was needed */
-	if (ctrl->use_mdr)
-		ctrl->mdr = in_be32(&lbc->mdr);
+	if (elbc_fcm_ctrl->use_mdr)
+		elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
 
-	ctrl->use_mdr = 0;
+	elbc_fcm_ctrl->use_mdr = 0;
 
-	if (ctrl->status != LTESR_CC) {
-		dev_info(ctrl->dev,
+	if (elbc_fcm_ctrl->status != LTESR_CC) {
+		dev_info(priv->dev,
 		         "command failed: fir %x fcr %x status %x mdr %x\n",
 		         in_be32(&lbc->fir), in_be32(&lbc->fcr),
-		         ctrl->status, ctrl->mdr);
+			 elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
 		return -EIO;
 	}
 
@@ -251,7 +239,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	if (priv->page_size) {
@@ -284,15 +272,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
-	ctrl->use_mdr = 0;
+	elbc_fcm_ctrl->use_mdr = 0;
 
 	/* clear the read buffer */
-	ctrl->read_bytes = 0;
+	elbc_fcm_ctrl->read_bytes = 0;
 	if (command != NAND_CMD_PAGEPROG)
-		ctrl->index = 0;
+		elbc_fcm_ctrl->index = 0;
 
 	switch (command) {
 	/* READ0 and READ1 read the entire buffer to use hardware ECC. */
@@ -301,7 +290,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* fall-through */
 	case NAND_CMD_READ0:
-		dev_dbg(ctrl->dev,
+		dev_dbg(priv->dev,
 		        "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
 		        " 0x%x, column: 0x%x.\n", page_addr, column);
 
@@ -309,8 +298,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
 		set_addr(mtd, 0, page_addr, 0);
 
-		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
-		ctrl->index += column;
+		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		elbc_fcm_ctrl->index += column;
 
 		fsl_elbc_do_read(chip, 0);
 		fsl_elbc_run_command(mtd);
@@ -318,14 +307,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* READOOB reads only the OOB because no ECC is performed. */
 	case NAND_CMD_READOOB:
-		dev_vdbg(ctrl->dev,
+		dev_vdbg(priv->dev,
 		         "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
 			 " 0x%x, column: 0x%x.\n", page_addr, column);
 
 		out_be32(&lbc->fbcr, mtd->oobsize - column);
 		set_addr(mtd, column, page_addr, 1);
 
-		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
 
 		fsl_elbc_do_read(chip, 1);
 		fsl_elbc_run_command(mtd);
@@ -333,7 +322,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* READID must read all 5 possible bytes while CEB is active */
 	case NAND_CMD_READID:
-		dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
+		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
 
 		out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
 		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
@@ -341,9 +330,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
 		/* 5 bytes for manuf, device and exts */
 		out_be32(&lbc->fbcr, 5);
-		ctrl->read_bytes = 5;
-		ctrl->use_mdr = 1;
-		ctrl->mdr = 0;
+		elbc_fcm_ctrl->read_bytes = 5;
+		elbc_fcm_ctrl->use_mdr = 1;
+		elbc_fcm_ctrl->mdr = 0;
 
 		set_addr(mtd, 0, 0, 0);
 		fsl_elbc_run_command(mtd);
@@ -351,7 +340,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* ERASE1 stores the block and page address */
 	case NAND_CMD_ERASE1:
-		dev_vdbg(ctrl->dev,
+		dev_vdbg(priv->dev,
 		         "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
 		         "page_addr: 0x%x.\n", page_addr);
 		set_addr(mtd, 0, page_addr, 0);
@@ -359,7 +348,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* ERASE2 uses the block and page address from ERASE1 */
 	case NAND_CMD_ERASE2:
-		dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
+		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
 
 		out_be32(&lbc->fir,
 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
@@ -374,8 +363,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		         (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
 
 		out_be32(&lbc->fbcr, 0);
-		ctrl->read_bytes = 0;
-		ctrl->use_mdr = 1;
+		elbc_fcm_ctrl->read_bytes = 0;
+		elbc_fcm_ctrl->use_mdr = 1;
 
 		fsl_elbc_run_command(mtd);
 		return;
@@ -383,14 +372,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 	/* SEQIN sets up the addr buffer and all registers except the length */
 	case NAND_CMD_SEQIN: {
 		__be32 fcr;
-		dev_vdbg(ctrl->dev,
-		         "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
+		dev_vdbg(priv->dev,
+			 "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
 		         "page_addr: 0x%x, column: 0x%x.\n",
 		         page_addr, column);
 
-		ctrl->column = column;
-		ctrl->oob = 0;
-		ctrl->use_mdr = 1;
+		elbc_fcm_ctrl->use_mdr = 1;
 
 		fcr = (NAND_CMD_STATUS   << FCR_CMD1_SHIFT) |
 		      (NAND_CMD_SEQIN    << FCR_CMD2_SHIFT) |
@@ -420,7 +407,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 				/* OOB area --> READOOB */
 				column -= mtd->writesize;
 				fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
-				ctrl->oob = 1;
+				elbc_fcm_ctrl->oob = 1;
 			} else {
 				WARN_ON(column != 0);
 				/* First 256 bytes --> READ0 */
@@ -429,24 +416,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		}
 
 		out_be32(&lbc->fcr, fcr);
-		set_addr(mtd, column, page_addr, ctrl->oob);
+		set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
 		return;
 	}
 
 	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
 	case NAND_CMD_PAGEPROG: {
 		int full_page;
-		dev_vdbg(ctrl->dev,
+		dev_vdbg(priv->dev,
 		         "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
-		         "writing %d bytes.\n", ctrl->index);
+			 "writing %d bytes.\n", elbc_fcm_ctrl->index);
 
 		/* if the write did not start at 0 or is not a full page
 		 * then set the exact length, otherwise use a full page
 		 * write so the HW generates the ECC.
 		 */
-		if (ctrl->oob || ctrl->column != 0 ||
-		    ctrl->index != mtd->writesize + mtd->oobsize) {
-			out_be32(&lbc->fbcr, ctrl->index);
+		if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
+		    elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
+			out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
 			full_page = 0;
 		} else {
 			out_be32(&lbc->fbcr, 0);
@@ -458,21 +445,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		/* Read back the page in order to fill in the ECC for the
 		 * caller.  Is this really needed?
 		 */
-		if (full_page && ctrl->oob_poi) {
+		if (full_page && elbc_fcm_ctrl->oob_poi) {
 			out_be32(&lbc->fbcr, 3);
 			set_addr(mtd, 6, page_addr, 1);
 
-			ctrl->read_bytes = mtd->writesize + 9;
+			elbc_fcm_ctrl->read_bytes = mtd->writesize + 9;
 
 			fsl_elbc_do_read(chip, 1);
 			fsl_elbc_run_command(mtd);
 
-			memcpy_fromio(ctrl->oob_poi + 6,
-			              &ctrl->addr[ctrl->index], 3);
-			ctrl->index += 3;
+			memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6,
+				&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3);
+			elbc_fcm_ctrl->index += 3;
 		}
 
-		ctrl->oob_poi = NULL;
+		elbc_fcm_ctrl->oob_poi = NULL;
 		return;
 	}
 
@@ -485,26 +472,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
 		out_be32(&lbc->fbcr, 1);
 		set_addr(mtd, 0, 0, 0);
-		ctrl->read_bytes = 1;
+		elbc_fcm_ctrl->read_bytes = 1;
 
 		fsl_elbc_run_command(mtd);
 
 		/* The chip always seems to report that it is
 		 * write-protected, even when it is not.
 		 */
-		setbits8(ctrl->addr, NAND_STATUS_WP);
+		setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
 		return;
 
 	/* RESET without waiting for the ready line */
 	case NAND_CMD_RESET:
-		dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
+		dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
 		out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
 		out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
 		fsl_elbc_run_command(mtd);
 		return;
 
 	default:
-		dev_err(ctrl->dev,
+		dev_err(priv->dev,
 		        "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
 		        command);
 	}
@@ -524,24 +511,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	unsigned int bufsize = mtd->writesize + mtd->oobsize;
 
 	if (len <= 0) {
-		dev_err(ctrl->dev, "write_buf of %d bytes", len);
-		ctrl->status = 0;
+		dev_err(priv->dev, "write_buf of %d bytes", len);
+		elbc_fcm_ctrl->status = 0;
 		return;
 	}
 
-	if ((unsigned int)len > bufsize - ctrl->index) {
-		dev_err(ctrl->dev,
+	if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
+		dev_err(priv->dev,
 		        "write_buf beyond end of buffer "
 		        "(%d requested, %u available)\n",
-		        len, bufsize - ctrl->index);
-		len = bufsize - ctrl->index;
+			len, bufsize - elbc_fcm_ctrl->index);
+		len = bufsize - elbc_fcm_ctrl->index;
 	}
 
-	memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+	memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
 	/*
 	 * This is workaround for the weird elbc hangs during nand write,
 	 * Scott Wood says: "...perhaps difference in how long it takes a
@@ -549,9 +536,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 	 * is causing problems, and sync isn't helping for some reason."
 	 * Reading back the last byte helps though.
 	 */
-	in_8(&ctrl->addr[ctrl->index] + len - 1);
+	in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
 
-	ctrl->index += len;
+	elbc_fcm_ctrl->index += len;
 }
 
 /*
@@ -562,13 +549,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 
 	/* If there are still bytes in the FCM, then use the next byte. */
-	if (ctrl->index < ctrl->read_bytes)
-		return in_8(&ctrl->addr[ctrl->index++]);
+	if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
+		return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
 
-	dev_err(ctrl->dev, "read_byte beyond end of buffer\n");
+	dev_err(priv->dev, "read_byte beyond end of buffer\n");
 	return ERR_BYTE;
 }
 
@@ -579,18 +566,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	int avail;
 
 	if (len < 0)
 		return;
 
-	avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
-	memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
-	ctrl->index += avail;
+	avail = min((unsigned int)len,
+			elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
+	memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
+	elbc_fcm_ctrl->index += avail;
 
 	if (len > avail)
-		dev_err(ctrl->dev,
+		dev_err(priv->dev,
 		        "read_buf beyond end of buffer "
 		        "(%d requested, %d available)\n",
 		        len, avail);
@@ -603,30 +591,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	int i;
 
 	if (len < 0) {
-		dev_err(ctrl->dev, "write_buf of %d bytes", len);
+		dev_err(priv->dev, "write_buf of %d bytes", len);
 		return -EINVAL;
 	}
 
-	if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
-		dev_err(ctrl->dev,
-		        "verify_buf beyond end of buffer "
-		        "(%d requested, %u available)\n",
-		        len, ctrl->read_bytes - ctrl->index);
+	if ((unsigned int)len >
+			elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) {
+		dev_err(priv->dev,
+			"verify_buf beyond end of buffer "
+			"(%d requested, %u available)\n",
+			len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
 
-		ctrl->index = ctrl->read_bytes;
+		elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes;
 		return -EINVAL;
 	}
 
 	for (i = 0; i < len; i++)
-		if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
+		if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
+				!= buf[i])
 			break;
 
-	ctrl->index += len;
-	return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
+	elbc_fcm_ctrl->index += len;
+	return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO;
 }
 
 /* This function is called after Program and Erase Operations to
@@ -635,22 +625,21 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
-	if (ctrl->status != LTESR_CC)
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
+	if (elbc_fcm_ctrl->status != LTESR_CC)
 		return NAND_STATUS_FAIL;
 
 	/* The chip always seems to report that it is
 	 * write-protected, even when it is not.
 	 */
-	return (ctrl->mdr & 0xff) | NAND_STATUS_WP;
+	return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
 }
 
 static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	unsigned int al;
 
@@ -665,41 +654,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 	priv->fmr |= (12 << FMR_CWTO_SHIFT) |  /* Timeout > 12 ms */
 	             (al << FMR_AL_SHIFT);
 
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
 	        chip->numchips);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
 	        chip->chipsize);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
 	        chip->pagemask);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
 	        chip->chip_delay);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
 	        chip->badblockpos);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
 	        chip->chip_shift);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
 	        chip->page_shift);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
 	        chip->phys_erase_shift);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
 	        chip->ecclayout);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
 	        chip->ecc.mode);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
 	        chip->ecc.steps);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
 	        chip->ecc.bytes);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
 	        chip->ecc.total);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
 	        chip->ecc.layout);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
 	        mtd->erasesize);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
 	        mtd->writesize);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
 	        mtd->oobsize);
 
 	/* adjust Option Register and ECC to match Flash page size */
@@ -719,7 +708,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 			chip->badblock_pattern = &largepage_memorybased;
 		}
 	} else {
-		dev_err(ctrl->dev,
+		dev_err(priv->dev,
 		        "fsl_elbc_init: page size %d is not supported\n",
 		        mtd->writesize);
 		return -1;
@@ -750,18 +739,18 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
                                 const uint8_t *buf)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
 	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
 
-	ctrl->oob_poi = chip->oob_poi;
+	elbc_fcm_ctrl->oob_poi = chip->oob_poi;
 }
 
 static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 {
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct nand_chip *chip = &priv->chip;
 
 	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
@@ -790,7 +779,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 	chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
 			NAND_USE_FLASH_BBT;
 
-	chip->controller = &ctrl->controller;
+	chip->controller = &elbc_fcm_ctrl->controller;
 	chip->priv = priv;
 
 	chip->ecc.read_page = fsl_elbc_read_page;
@@ -815,8 +804,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 
 static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 {
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	nand_release(&priv->mtd);
 
 	kfree(priv->mtd.name);
@@ -824,18 +812,19 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 	if (priv->vbase)
 		iounmap(priv->vbase);
 
-	ctrl->chips[priv->bank] = NULL;
+	elbc_fcm_ctrl->chips[priv->bank] = NULL;
 	kfree(priv);
-
+	kfree(elbc_fcm_ctrl);
 	return 0;
 }
 
-static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
-					 struct device_node *node)
+static int __devinit fsl_elbc_nand_probe(struct platform_device *dev,
+					 const struct of_device_id *match)
 {
-	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc;
 	struct fsl_elbc_mtd *priv;
 	struct resource res;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
 #ifdef CONFIG_MTD_PARTITIONS
 	static const char *part_probe_types[]
 		= { "cmdlinepart", "RedBoot", NULL };
@@ -843,11 +832,16 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
 #endif
 	int ret;
 	int bank;
+	struct device_node *node = dev->dev.of_node;
+
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+		return -ENODEV;
+	lbc = fsl_lbc_ctrl_dev->regs;
 
 	/* get, allocate and map the memory resource */
 	ret = of_address_to_resource(node, 0, &res);
 	if (ret) {
-		dev_err(ctrl->dev, "failed to get resource\n");
+		dev_err(fsl_lbc_ctrl_dev->dev, "failed to get resource\n");
 		return ret;
 	}
 
@@ -861,7 +855,8 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
 			break;
 
 	if (bank >= MAX_BANKS) {
-		dev_err(ctrl->dev, "address did not match any chip selects\n");
+		dev_err(fsl_lbc_ctrl_dev->dev, "address did not match any "
+			"chip selects\n");
 		return -ENODEV;
 	}
 
@@ -869,14 +864,28 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
 	if (!priv)
 		return -ENOMEM;
 
-	ctrl->chips[bank] = priv;
+	if (fsl_lbc_ctrl_dev->nand == NULL) {
+		elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
+		if (!elbc_fcm_ctrl)
+			return -ENOMEM;
+
+		elbc_fcm_ctrl->read_bytes = 0;
+		elbc_fcm_ctrl->index = 0;
+		elbc_fcm_ctrl->addr = NULL;
+
+		spin_lock_init(&elbc_fcm_ctrl->controller.lock);
+		init_waitqueue_head(&elbc_fcm_ctrl->controller.wq);
+		fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
+	}
+
+	elbc_fcm_ctrl->chips[bank] = priv;
 	priv->bank = bank;
-	priv->ctrl = ctrl;
-	priv->dev = ctrl->dev;
+	priv->ctrl = fsl_lbc_ctrl_dev;
+	priv->dev = fsl_lbc_ctrl_dev->dev;
 
 	priv->vbase = ioremap(res.start, resource_size(&res));
 	if (!priv->vbase) {
-		dev_err(ctrl->dev, "failed to map chip region\n");
+		dev_err(fsl_lbc_ctrl_dev->dev, "failed to map chip region\n");
 		ret = -ENOMEM;
 		goto err;
 	}
@@ -933,171 +942,50 @@ err:
 	return ret;
 }
 
-static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
+static int fsl_elbc_nand_remove(struct platform_device *ofdev)
 {
-	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-
-	/*
-	 * NAND transactions can tie up the bus for a long time, so set the
-	 * bus timeout to max by clearing LBCR[BMT] (highest base counter
-	 * value) and setting LBCR[BMTPS] to the highest prescaler value.
-	 */
-	clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
-
-	/* clear event registers */
-	setbits32(&lbc->ltesr, LTESR_NAND_MASK);
-	out_be32(&lbc->lteatr, 0);
-
-	/* Enable interrupts for any detected events */
-	out_be32(&lbc->lteir, LTESR_NAND_MASK);
-
-	ctrl->read_bytes = 0;
-	ctrl->index = 0;
-	ctrl->addr = NULL;
-
-	return 0;
-}
-
-static int fsl_elbc_ctrl_remove(struct platform_device *ofdev)
-{
-	struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
 	int i;
-
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
 	for (i = 0; i < MAX_BANKS; i++)
-		if (ctrl->chips[i])
-			fsl_elbc_chip_remove(ctrl->chips[i]);
-
-	if (ctrl->irq)
-		free_irq(ctrl->irq, ctrl);
-
-	if (ctrl->regs)
-		iounmap(ctrl->regs);
-
-	dev_set_drvdata(&ofdev->dev, NULL);
-	kfree(ctrl);
-	return 0;
-}
-
-/* NOTE: This interrupt is also used to report other localbus events,
- * such as transaction errors on other chipselects.  If we want to
- * capture those, we'll need to move the IRQ code into a shared
- * LBC driver.
- */
-
-static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
-{
-	struct fsl_elbc_ctrl *ctrl = data;
-	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-	__be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
-
-	if (status) {
-		out_be32(&lbc->ltesr, status);
-		out_be32(&lbc->lteatr, 0);
-
-		ctrl->irq_status = status;
-		smp_wmb();
-		wake_up(&ctrl->irq_wait);
-
-		return IRQ_HANDLED;
-	}
-
-	return IRQ_NONE;
-}
-
-/* fsl_elbc_ctrl_probe
- *
- * called by device layer when it finds a device matching
- * one our driver can handled. This code allocates all of
- * the resources needed for the controller only.  The
- * resources for the NAND banks themselves are allocated
- * in the chip probe function.
-*/
-
-static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev,
-                                         const struct of_device_id *match)
-{
-	struct device_node *child;
-	struct fsl_elbc_ctrl *ctrl;
-	int ret;
-
-	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
-	if (!ctrl)
-		return -ENOMEM;
+		if (elbc_fcm_ctrl->chips[i])
+			fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]);
 
-	dev_set_drvdata(&ofdev->dev, ctrl);
-
-	spin_lock_init(&ctrl->controller.lock);
-	init_waitqueue_head(&ctrl->controller.wq);
-	init_waitqueue_head(&ctrl->irq_wait);
-
-	ctrl->regs = of_iomap(ofdev->dev.of_node, 0);
-	if (!ctrl->regs) {
-		dev_err(&ofdev->dev, "failed to get memory region\n");
-		ret = -ENODEV;
-		goto err;
-	}
-
-	ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
-	if (ctrl->irq == NO_IRQ) {
-		dev_err(&ofdev->dev, "failed to get irq resource\n");
-		ret = -ENODEV;
-		goto err;
-	}
-
-	ctrl->dev = &ofdev->dev;
-
-	ret = fsl_elbc_ctrl_init(ctrl);
-	if (ret < 0)
-		goto err;
-
-	ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl);
-	if (ret != 0) {
-		dev_err(&ofdev->dev, "failed to install irq (%d)\n",
-		        ctrl->irq);
-		ret = ctrl->irq;
-		goto err;
-	}
-
-	for_each_child_of_node(ofdev->dev.of_node, child)
-		if (of_device_is_compatible(child, "fsl,elbc-fcm-nand"))
-			fsl_elbc_chip_probe(ctrl, child);
+	fsl_lbc_ctrl_dev->nand = NULL;
+	kfree(elbc_fcm_ctrl);
 
 	return 0;
 
-err:
-	fsl_elbc_ctrl_remove(ofdev);
-	return ret;
 }
 
-static const struct of_device_id fsl_elbc_match[] = {
+static const struct of_device_id fsl_elbc_nand_match[] = {
 	{
-		.compatible = "fsl,elbc",
+		.compatible = "fsl,elbc-fcm-nand",
 	},
 	{}
 };
 
-static struct of_platform_driver fsl_elbc_ctrl_driver = {
+static struct of_platform_driver fsl_elbc_nand_driver = {
 	.driver = {
-		.name = "fsl-elbc",
+		.name = "fsl,elbc-fcm-nand",
 		.owner = THIS_MODULE,
-		.of_match_table = fsl_elbc_match,
+		.of_match_table = fsl_elbc_nand_match,
 	},
-	.probe = fsl_elbc_ctrl_probe,
-	.remove = fsl_elbc_ctrl_remove,
+	.probe = fsl_elbc_nand_probe,
+	.remove = fsl_elbc_nand_remove,
 };
 
-static int __init fsl_elbc_init(void)
+static int __init fsl_elbc_nand_init(void)
 {
-	return of_register_platform_driver(&fsl_elbc_ctrl_driver);
+	return of_register_platform_driver(&fsl_elbc_nand_driver);
 }
 
-static void __exit fsl_elbc_exit(void)
+static void __exit fsl_elbc_nand_exit(void)
 {
-	of_unregister_platform_driver(&fsl_elbc_ctrl_driver);
+	of_unregister_platform_driver(&fsl_elbc_nand_driver);
 }
 
-module_init(fsl_elbc_init);
-module_exit(fsl_elbc_exit);
+module_init(fsl_elbc_nand_init);
+module_exit(fsl_elbc_nand_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Freescale");
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-09 10:20   ` Roy Zang
@ 2010-09-09 10:20     ` Roy Zang
  -1 siblings, 0 replies; 40+ messages in thread
From: Roy Zang @ 2010-09-09 10:20 UTC (permalink / raw)
  To: linux-mtd; +Cc: B07421, dedekind1, B25806, linuxppc-dev, akpm, dwmw2, B11780

From: Lan Chunhe-B25806 <b25806@freescale.com>

When system uses 36bit physical address, res.start is 36bit
physical address. But the function of in_be32 returns 32bit
physical address. Then both of them compared each other is
wrong. So by converting the address of res.start into
the right format fixes this issue.

Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
Comparing with v1, according to the feedback, add some decorations.
 arch/powerpc/include/asm/fsl_lbc.h |    1 +
 arch/powerpc/sysdev/fsl_lbc.c      |   26 +++++++++++++++++++++++++-
 drivers/mtd/nand/fsl_elbc_nand.c   |    2 +-
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 9b95eab..bff85c8 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -249,6 +249,7 @@ struct fsl_upm {
 	int width;
 };
 
+extern unsigned int fsl_lbc_addr(phys_addr_t addr_base);
 extern int fsl_lbc_find(phys_addr_t addr_base);
 extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
 
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index f4eca8d..3a09e90 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -31,6 +31,30 @@ struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
 EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
 
 /**
+ * fsl_lbc_addr - convert the base address
+ * @addr_base:	base address of the memory bank
+ *
+ * This function converts a base address of lbc into the right format for the BR
+ * registers. If the SOC has eLBC then it returns 32bit physical address else
+ * it returns 34bit physical address for local bus(Example: MPC8641).
+ */
+unsigned int fsl_lbc_addr(phys_addr_t addr_base)
+{
+	void *dev;
+	int compatible;
+
+	dev = fsl_lbc_ctrl_dev->dev->of_node;
+	compatible = of_device_is_compatible(dev, "fsl,elbc");
+
+	if (compatible)
+		return addr_base & 0xffff8000;
+	else
+		return (addr_base & 0x0ffff8000ull)
+			| ((addr_base & 0x300000000ull) >> 19);
+}
+EXPORT_SYMBOL(fsl_lbc_addr);
+
+/**
  * fsl_lbc_find - find Localbus bank
  * @addr_base:	base address of the memory bank
  *
@@ -52,7 +76,7 @@ int fsl_lbc_find(phys_addr_t addr_base)
 		__be32 br = in_be32(&lbc->bank[i].br);
 		__be32 or = in_be32(&lbc->bank[i].or);
 
-		if (br & BR_V && (br & or & BR_BA) == addr_base)
+		if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
 			return i;
 	}
 
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 64c840f..6dec268 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -851,7 +851,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *dev,
 		    (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
 		    (in_be32(&lbc->bank[bank].br) &
 		     in_be32(&lbc->bank[bank].or) & BR_BA)
-		     == res.start)
+		     == fsl_lbc_addr(res.start))
 			break;
 
 	if (bank >= MAX_BANKS) {
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-09 10:20     ` Roy Zang
  0 siblings, 0 replies; 40+ messages in thread
From: Roy Zang @ 2010-09-09 10:20 UTC (permalink / raw)
  To: linux-mtd
  Cc: B07421, dedekind1, B25806, linuxppc-dev, cbouatmailru, akpm,
	dwmw2, B11780

From: Lan Chunhe-B25806 <b25806@freescale.com>

When system uses 36bit physical address, res.start is 36bit
physical address. But the function of in_be32 returns 32bit
physical address. Then both of them compared each other is
wrong. So by converting the address of res.start into
the right format fixes this issue.

Signed-off-by: Lan Chunhe-B25806 <b25806@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
Comparing with v1, according to the feedback, add some decorations.
 arch/powerpc/include/asm/fsl_lbc.h |    1 +
 arch/powerpc/sysdev/fsl_lbc.c      |   26 +++++++++++++++++++++++++-
 drivers/mtd/nand/fsl_elbc_nand.c   |    2 +-
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 9b95eab..bff85c8 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -249,6 +249,7 @@ struct fsl_upm {
 	int width;
 };
 
+extern unsigned int fsl_lbc_addr(phys_addr_t addr_base);
 extern int fsl_lbc_find(phys_addr_t addr_base);
 extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
 
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index f4eca8d..3a09e90 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -31,6 +31,30 @@ struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
 EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
 
 /**
+ * fsl_lbc_addr - convert the base address
+ * @addr_base:	base address of the memory bank
+ *
+ * This function converts a base address of lbc into the right format for the BR
+ * registers. If the SOC has eLBC then it returns 32bit physical address else
+ * it returns 34bit physical address for local bus(Example: MPC8641).
+ */
+unsigned int fsl_lbc_addr(phys_addr_t addr_base)
+{
+	void *dev;
+	int compatible;
+
+	dev = fsl_lbc_ctrl_dev->dev->of_node;
+	compatible = of_device_is_compatible(dev, "fsl,elbc");
+
+	if (compatible)
+		return addr_base & 0xffff8000;
+	else
+		return (addr_base & 0x0ffff8000ull)
+			| ((addr_base & 0x300000000ull) >> 19);
+}
+EXPORT_SYMBOL(fsl_lbc_addr);
+
+/**
  * fsl_lbc_find - find Localbus bank
  * @addr_base:	base address of the memory bank
  *
@@ -52,7 +76,7 @@ int fsl_lbc_find(phys_addr_t addr_base)
 		__be32 br = in_be32(&lbc->bank[i].br);
 		__be32 or = in_be32(&lbc->bank[i].or);
 
-		if (br & BR_V && (br & or & BR_BA) == addr_base)
+		if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
 			return i;
 	}
 
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 64c840f..6dec268 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -851,7 +851,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *dev,
 		    (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
 		    (in_be32(&lbc->bank[bank].br) &
 		     in_be32(&lbc->bank[bank].or) & BR_BA)
-		     == res.start)
+		     == fsl_lbc_addr(res.start))
 			break;
 
 	if (bank >= MAX_BANKS) {
-- 
1.5.6.5

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-09 10:20     ` Roy Zang
@ 2010-09-09 11:06       ` Geert Uytterhoeven
  -1 siblings, 0 replies; 40+ messages in thread
From: Geert Uytterhoeven @ 2010-09-09 11:06 UTC (permalink / raw)
  To: Roy Zang
  Cc: B07421, dedekind1, B25806, linuxppc-dev, linux-mtd, akpm, dwmw2, B11780

On Thu, Sep 9, 2010 at 12:20, Roy Zang <tie-fei.zang@freescale.com> wrote:
> From: Lan Chunhe-B25806 <b25806@freescale.com>
>
> When system uses 36bit physical address, res.start is 36bit
> physical address. But the function of in_be32 returns 32bit
> physical address. Then both of them compared each other is
> wrong. So by converting the address of res.start into
> the right format fixes this issue.

> =C2=A0/**
> + * fsl_lbc_addr - convert the base address
> + * @addr_base: base address of the memory bank
> + *
> + * This function converts a base address of lbc into the right format fo=
r the BR
> + * registers. If the SOC has eLBC then it returns 32bit physical address=
 else
> + * it returns 34bit physical address for local bus(Example: MPC8641).
> + */
> +unsigned int fsl_lbc_addr(phys_addr_t addr_base)
    ^^^^^^^^^^^^
Shouldn't this be u32 or __be32, for consistency with the actual
comparisons below?

> @@ -52,7 +76,7 @@ int fsl_lbc_find(phys_addr_t addr_base)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0__be32 br =3D in_b=
e32(&lbc->bank[i].br);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0__be32 or =3D in_b=
e32(&lbc->bank[i].or);
>
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (br & BR_V && (br &=
 or & BR_BA) =3D=3D addr_base)
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (br & BR_V && (br &=
 or & BR_BA) =3D=3D fsl_lbc_addr(addr_base))
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0return i;

> @@ -851,7 +851,7 @@ static int __devinit fsl_elbc_nand_probe(struct platf=
orm_device *dev,
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(in_=
be32(&lbc->bank[bank].br) & BR_MSEL) =3D=3D BR_MS_FCM &&
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(in_=
be32(&lbc->bank[bank].br) &
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 in_=
be32(&lbc->bank[bank].or) & BR_BA)
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
=3D=3D res.start)
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
=3D=3D fsl_lbc_addr(res.start))
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0break;

Gr{oetje,eeting}s,

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org

In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 -- Linus Torvalds

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-09 11:06       ` Geert Uytterhoeven
  0 siblings, 0 replies; 40+ messages in thread
From: Geert Uytterhoeven @ 2010-09-09 11:06 UTC (permalink / raw)
  To: Roy Zang
  Cc: B07421, dedekind1, B25806, linuxppc-dev, linux-mtd, akpm, dwmw2, B11780

On Thu, Sep 9, 2010 at 12:20, Roy Zang <tie-fei.zang@freescale.com> wrote:
> From: Lan Chunhe-B25806 <b25806@freescale.com>
>
> When system uses 36bit physical address, res.start is 36bit
> physical address. But the function of in_be32 returns 32bit
> physical address. Then both of them compared each other is
> wrong. So by converting the address of res.start into
> the right format fixes this issue.

>  /**
> + * fsl_lbc_addr - convert the base address
> + * @addr_base: base address of the memory bank
> + *
> + * This function converts a base address of lbc into the right format for the BR
> + * registers. If the SOC has eLBC then it returns 32bit physical address else
> + * it returns 34bit physical address for local bus(Example: MPC8641).
> + */
> +unsigned int fsl_lbc_addr(phys_addr_t addr_base)
    ^^^^^^^^^^^^
Shouldn't this be u32 or __be32, for consistency with the actual
comparisons below?

> @@ -52,7 +76,7 @@ int fsl_lbc_find(phys_addr_t addr_base)
>                __be32 br = in_be32(&lbc->bank[i].br);
>                __be32 or = in_be32(&lbc->bank[i].or);
>
> -               if (br & BR_V && (br & or & BR_BA) == addr_base)
> +               if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
>                        return i;

> @@ -851,7 +851,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *dev,
>                    (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
>                    (in_be32(&lbc->bank[bank].br) &
>                     in_be32(&lbc->bank[bank].or) & BR_BA)
> -                    == res.start)
> +                    == fsl_lbc_addr(res.start))
>                        break;

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 2/3 v2][MTD] P4080/mtd: Only make elbc nand driver detect nand flash partitions
  2010-09-09 10:20   ` Roy Zang
  (?)
  (?)
@ 2010-09-09 11:23   ` Anton Vorontsov
  -1 siblings, 0 replies; 40+ messages in thread
From: Anton Vorontsov @ 2010-09-09 11:23 UTC (permalink / raw)
  To: Roy Zang
  Cc: B07421, dedekind1, B25806, linuxppc-dev, linux-mtd, akpm, dwmw2, B11780

On Thu, Sep 09, 2010 at 06:20:31PM +0800, Roy Zang wrote:
[...]
>  #include <linux/types.h>
>  #include <linux/init.h>
>  #include <linux/kernel.h>
> -#include <linux/string.h>
> -#include <linux/ioport.h>
> -#include <linux/of_platform.h>
> -#include <linux/slab.h>
> -#include <linux/interrupt.h>
>  
> -#include <linux/mtd/mtd.h>
>  #include <linux/mtd/nand.h>
> -#include <linux/mtd/nand_ecc.h>
>  #include <linux/mtd/partitions.h>
> -
> -#include <asm/io.h>
>  #include <asm/fsl_lbc.h>
> +#include <linux/slab.h>

Why move slab.h?

[...]
>  	for (i = 0; i < len; i++)
> -		if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
> +		if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
> +				!= buf[i])
>  			break;
>  
> -	ctrl->index += len;
> -	return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
> +	elbc_fcm_ctrl->index += len;
> +	return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO;
>  }
>  
>  /* This function is called after Program and Erase Operations to
> @@ -635,22 +625,21 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
>  {
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> -

Please keep the empty line between variables declaration and the code.

> -	if (ctrl->status != LTESR_CC)
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
> +	if (elbc_fcm_ctrl->status != LTESR_CC)
>  		return NAND_STATUS_FAIL;
[...]
> @@ -750,18 +739,18 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
>                                  const uint8_t *buf)
>  {
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> -
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;

Ditto.

>  	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
>  	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
>  
> -	ctrl->oob_poi = chip->oob_poi;
> +	elbc_fcm_ctrl->oob_poi = chip->oob_poi;
>  }

[...]
> -static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
> -					 struct device_node *node)
> +static int __devinit fsl_elbc_nand_probe(struct platform_device *dev,
> +					 const struct of_device_id *match)
>  {
> -	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> +	struct fsl_lbc_regs __iomem *lbc;
>  	struct fsl_elbc_mtd *priv;
>  	struct resource res;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;

(***1)

>  #ifdef CONFIG_MTD_PARTITIONS
>  	static const char *part_probe_types[]
>  		= { "cmdlinepart", "RedBoot", NULL };
> @@ -843,11 +832,16 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
>  #endif
>  	int ret;
>  	int bank;
> +	struct device_node *node = dev->dev.of_node;
> +
> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
> +		return -ENODEV;
> +	lbc = fsl_lbc_ctrl_dev->regs;
>  
>  	/* get, allocate and map the memory resource */
>  	ret = of_address_to_resource(node, 0, &res);
>  	if (ret) {
> -		dev_err(ctrl->dev, "failed to get resource\n");
> +		dev_err(fsl_lbc_ctrl_dev->dev, "failed to get resource\n");
>  		return ret;
>  	}
>  
> @@ -861,7 +855,8 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
>  			break;
>  
>  	if (bank >= MAX_BANKS) {
> -		dev_err(ctrl->dev, "address did not match any chip selects\n");
> +		dev_err(fsl_lbc_ctrl_dev->dev, "address did not match any "
> +			"chip selects\n");
>  		return -ENODEV;
>  	}
>  
> @@ -869,14 +864,28 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
>  	if (!priv)
>  		return -ENOMEM;
>  
> -	ctrl->chips[bank] = priv;
> +	if (fsl_lbc_ctrl_dev->nand == NULL) {
> +		elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
> +		if (!elbc_fcm_ctrl)
> +			return -ENOMEM;

'priv' leaked.

> +
> +		elbc_fcm_ctrl->read_bytes = 0;
> +		elbc_fcm_ctrl->index = 0;
> +		elbc_fcm_ctrl->addr = NULL;
> +
> +		spin_lock_init(&elbc_fcm_ctrl->controller.lock);
> +		init_waitqueue_head(&elbc_fcm_ctrl->controller.wq);
> +		fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
> +	}
> +
> +	elbc_fcm_ctrl->chips[bank] = priv;

The driver will oops on the second probe.

You probably meant

  struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;

at (***1).

Also, nowadays the kernel may probe devices in parallel, which
means that you probably need a mutex for fsl_lbc_ctrl_dev->nand.

[...]
> -static const struct of_device_id fsl_elbc_match[] = {
> +static const struct of_device_id fsl_elbc_nand_match[] = {

linux/mod_devicetable.h is needed for this.

>  	{
> -		.compatible = "fsl,elbc",
> +		.compatible = "fsl,elbc-fcm-nand",
>  	},
>  	{}
>  };
>  
> -static struct of_platform_driver fsl_elbc_ctrl_driver = {
> +static struct of_platform_driver fsl_elbc_nand_driver = {

If you write of_platform_driver, you need linux/of_platform.h (which
you removed in this patch).

But I think that you need just 'struct platform_driver' here, and
include linux/platform_device.h.

>  	.driver = {
> -		.name = "fsl-elbc",
> +		.name = "fsl,elbc-fcm-nand",
>  		.owner = THIS_MODULE,
> -		.of_match_table = fsl_elbc_match,
> +		.of_match_table = fsl_elbc_nand_match,
>  	},
> -	.probe = fsl_elbc_ctrl_probe,
> -	.remove = fsl_elbc_ctrl_remove,
> +	.probe = fsl_elbc_nand_probe,
> +	.remove = fsl_elbc_nand_remove,
>  };

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-09 10:20     ` Roy Zang
  (?)
  (?)
@ 2010-09-09 11:41     ` Anton Vorontsov
  2010-09-13  7:30         ` Zang Roy-R61911
  -1 siblings, 1 reply; 40+ messages in thread
From: Anton Vorontsov @ 2010-09-09 11:41 UTC (permalink / raw)
  To: Roy Zang
  Cc: B07421, dedekind1, B25806, linuxppc-dev, linux-mtd, akpm, dwmw2, B11780

On Thu, Sep 09, 2010 at 06:20:32PM +0800, Roy Zang wrote:
[...]
>  /**
> + * fsl_lbc_addr - convert the base address
> + * @addr_base:	base address of the memory bank
> + *
> + * This function converts a base address of lbc into the right format for the BR
> + * registers. If the SOC has eLBC then it returns 32bit physical address else
> + * it returns 34bit physical address for local bus(Example: MPC8641).
> + */

It returns 34bit physical address encoded in a 32 bit word,
right? Because, IIRC, 'unsigned int' is always 32 bit.

Worth mentioning this fact.

> +unsigned int fsl_lbc_addr(phys_addr_t addr_base)
> +{
> +	void *dev;

struct device_node *np;

> +	int compatible;
> +
> +	dev = fsl_lbc_ctrl_dev->dev->of_node;
> +	compatible = of_device_is_compatible(dev, "fsl,elbc");
> +
> +	if (compatible)
> +		return addr_base & 0xffff8000;
> +	else
> +		return (addr_base & 0x0ffff8000ull)
> +			| ((addr_base & 0x300000000ull) >> 19);
> +}
> +EXPORT_SYMBOL(fsl_lbc_addr);

Almost perfect. I'm not sure if 'unsigned int' is technically
correct return type for this function though. I guess it should
be u32.

Also, the function may be a bit more understandable and shorter:

u32 fsl_lbc_addr(phys_addr_t addr)
{
	struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node;
	u32 addrl = addr & 0xffff8000;

	if (of_device_is_compatible(np, "fsl,elbc"))
		return addrl;

	return addrl | ((addr & 0x300000000ull) >> 19);
}
EXPORT_SYMBOL(fsl_lbc_addr);

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 1/3 v2][MTD] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
  2010-09-09 10:20 ` Roy Zang
  (?)
  (?)
@ 2010-09-09 11:53 ` Anton Vorontsov
  2010-09-10  6:58     ` Zang Roy-R61911
  -1 siblings, 1 reply; 40+ messages in thread
From: Anton Vorontsov @ 2010-09-09 11:53 UTC (permalink / raw)
  To: Roy Zang
  Cc: B07421, dedekind1, B25806, linuxppc-dev, linux-mtd, akpm, dwmw2, B11780

Just a few cosmetic nits for this patch...

On Thu, Sep 09, 2010 at 06:20:30PM +0800, Roy Zang wrote:
[...]
> @@ -94,22 +73,26 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
>  {
>  	int bank;
>  	__be32 br;
> +	struct fsl_lbc_regs __iomem *lbc;
>  
>  	bank = fsl_lbc_find(addr_base);
>  	if (bank < 0)
>  		return bank;
>  
> -	br = in_be32(&fsl_lbc_regs->bank[bank].br);
> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
> +		return -ENODEV;

I'd add an empty line here.

> +	lbc = fsl_lbc_ctrl_dev->regs;
> +	br = in_be32(&lbc->bank[bank].br);
>  
>  	switch (br & BR_MSEL) {
>  	case BR_MS_UPMA:
> -		upm->mxmr = &fsl_lbc_regs->mamr;
> +		upm->mxmr = &lbc->mamr;
>  		break;
>  	case BR_MS_UPMB:
> -		upm->mxmr = &fsl_lbc_regs->mbmr;
> +		upm->mxmr = &lbc->mbmr;
>  		break;
>  	case BR_MS_UPMC:
> -		upm->mxmr = &fsl_lbc_regs->mcmr;
> +		upm->mxmr = &lbc->mcmr;
>  		break;
>  	default:
>  		return -EINVAL;
> @@ -143,14 +126,18 @@ EXPORT_SYMBOL(fsl_upm_find);
>   * thus UPM pattern actually executed. Note that mar usage depends on the
>   * pre-programmed AMX bits in the UPM RAM.
>   */
> +
>  int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
>  {
>  	int ret = 0;
>  	unsigned long flags;
>  
> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
> +		return -ENODEV;
> +
>  	spin_lock_irqsave(&fsl_lbc_lock, flags);
>  
> -	out_be32(&fsl_lbc_regs->mar, mar);
> +	out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
>  
>  	switch (upm->width) {
>  	case 8:
> @@ -172,3 +159,188 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
>  	return ret;
>  }
>  EXPORT_SYMBOL(fsl_upm_run_pattern);
> +
> +static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
> +{
> +	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> +
> +	/* clear event registers */
> +	setbits32(&lbc->ltesr, LTESR_CLEAR);
> +	out_be32(&lbc->lteatr, 0);
> +	out_be32(&lbc->ltear, 0);
> +	out_be32(&lbc->lteccr, LTECCR_CLEAR);
> +	out_be32(&lbc->ltedr, LTEDR_ENABLE);
> +
> +	/* Enable interrupts for any detected events */
> +	out_be32(&lbc->lteir, LTEIR_ENABLE);
> +
> +	return 0;
> +}
> +
> +static int __devexit fsl_lbc_ctrl_remove(struct platform_device *ofdev)
> +{
> +	struct fsl_lbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
> +
> +	if (ctrl->irq)
> +		free_irq(ctrl->irq, ctrl);
> +
> +	if (ctrl->regs)
> +		iounmap(ctrl->regs);
> +
> +	dev_set_drvdata(&ofdev->dev, NULL);
> +
> +	kfree(ctrl);
> +
> +	return 0;
> +}
> +
> +/*
> + * NOTE: This interrupt is used to report localbus events of various kinds,
> + * such as transaction errors on the chipselects.
> + */
> +
> +static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
> +{
> +	struct fsl_lbc_ctrl *ctrl = data;
> +	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> +	u32 status;
> +
> +	status = in_be32(&lbc->ltesr);
> +
> +	if (status) {

You could save indentation and improve readability by writing

status = in_be32(&lbc->ltesr);
if (!status)
	return IRQ_NONE;

...the rest of the function...

I understand that you just move the code around though.

> +		out_be32(&lbc->ltesr, LTESR_CLEAR);
> +		out_be32(&lbc->lteatr, 0);
> +		out_be32(&lbc->ltear, 0);
> +		ctrl->irq_status = status;
> +
> +		if (status & LTESR_BM)
> +			dev_err(ctrl->dev, "Local bus monitor time-out: "
> +				"LTESR 0x%08X\n", status);
> +		if (status & LTESR_WP)
> +			dev_err(ctrl->dev, "Write protect error: "
> +				"LTESR 0x%08X\n", status);
> +		if (status & LTESR_ATMW)
> +			dev_err(ctrl->dev, "Atomic write error: "
> +				"LTESR 0x%08X\n", status);
> +		if (status & LTESR_ATMR)
> +			dev_err(ctrl->dev, "Atomic read error: "
> +				"LTESR 0x%08X\n", status);
> +		if (status & LTESR_CS)
> +			dev_err(ctrl->dev, "Chip select error: "
> +				"LTESR 0x%08X\n", status);
> +		if (status & LTESR_UPM)
> +			;
> +		if (status & LTESR_FCT) {
> +			dev_err(ctrl->dev, "FCM command time-out: "
> +				"LTESR 0x%08X\n", status);
> +			smp_wmb();
> +			wake_up(&ctrl->irq_wait);
> +		}
> +		if (status & LTESR_PAR) {
> +			dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
> +				"LTESR 0x%08X\n", status);
> +			smp_wmb();
> +			wake_up(&ctrl->irq_wait);
> +		}
> +		if (status & LTESR_CC) {
> +			smp_wmb();
> +			wake_up(&ctrl->irq_wait);
> +		}
> +		if (status & ~LTESR_MASK)
> +			dev_err(ctrl->dev, "Unknown error: "
> +				"LTESR 0x%08X\n", status);
> +
> +		return IRQ_HANDLED;
> +	}
> +
> +	return IRQ_NONE;
> +}
> +
> +/*
> + * fsl_lbc_ctrl_probe
> + *
> + * called by device layer when it finds a device matching
> + * one our driver can handled. This code allocates all of
> + * the resources needed for the controller only.  The
> + * resources for the NAND banks themselves are allocated
> + * in the chip probe function.
> +*/
> +
> +static int __devinit fsl_lbc_ctrl_probe(struct platform_device *ofdev,
> +					 const struct of_device_id *match)
> +{
> +	int ret;
> +
> +	if (!ofdev->dev.of_node) {
> +		dev_err(&ofdev->dev, "Device OF-Node is NULL");
> +		return -EFAULT;
> +	}
> +	fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
> +	if (!fsl_lbc_ctrl_dev)
> +		return -ENOMEM;
> +
> +	dev_set_drvdata(&ofdev->dev, fsl_lbc_ctrl_dev);
> +
> +	spin_lock_init(&fsl_lbc_ctrl_dev->lock);
> +	init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
> +
> +	fsl_lbc_ctrl_dev->regs = of_iomap(ofdev->dev.of_node, 0);
> +	if (!fsl_lbc_ctrl_dev->regs) {
> +		dev_err(&ofdev->dev, "failed to get memory region\n");
> +		ret = -ENODEV;
> +		goto err;
> +	}
> +
> +	fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
> +	if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
> +		dev_err(&ofdev->dev, "failed to get irq resource\n");
> +		ret = -ENODEV;
> +		goto err;
> +	}
> +
> +	fsl_lbc_ctrl_dev->dev = &ofdev->dev;
> +
> +	ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
> +	if (ret < 0)
> +		goto err;
> +
> +	ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
> +				"fsl-lbc", fsl_lbc_ctrl_dev);
> +	if (ret != 0) {
> +		dev_err(&ofdev->dev, "failed to install irq (%d)\n",
> +			fsl_lbc_ctrl_dev->irq);
> +		ret = fsl_lbc_ctrl_dev->irq;
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	iounmap(fsl_lbc_ctrl_dev->regs);
> +	kfree(fsl_lbc_ctrl_dev);
> +	return ret;
> +}
> +
> +static const struct of_device_id fsl_lbc_match[] = {
> +	{ .compatible = "fsl,elbc", },
> +	{ .compatible = "fsl,pq3-localbus", },
> +	{ .compatible = "fsl,pq2-localbus", },
> +	{ .compatible = "fsl,pq2pro-localbus", },
> +	{},
> +};

You need linux/mod_devicetable.h for this.

> +
> +static struct of_platform_driver fsl_lbc_ctrl_driver = {

Need linux/of_platform.h for this.

But you actually don't need of_platform_driver, as for the
new code you can use platform_driver (and thus
linux/platform_device.h).

> +	.driver = {
> +		.name = "fsl-lbc",
> +		.of_match_table = fsl_lbc_match,
> +	},
> +	.probe = fsl_lbc_ctrl_probe,
> +};
> +
> +static int __init fsl_lbc_init(void)
> +{
> +	return of_register_platform_driver(&fsl_lbc_ctrl_driver);
> +}
> +

No need for this empty line.

> +module_init(fsl_lbc_init);

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH 1/3 v2][MTD] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
  2010-09-09 11:53 ` [PATCH 1/3 v2][MTD] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices Anton Vorontsov
@ 2010-09-10  6:58     ` Zang Roy-R61911
  0 siblings, 0 replies; 40+ messages in thread
From: Zang Roy-R61911 @ 2010-09-10  6:58 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, akpm, dwmw2, Gala Kumar-B11780

DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQW50b24gVm9yb250c292
IFttYWlsdG86Y2JvdWF0bWFpbHJ1QGdtYWlsLmNvbV0NCj4gU2VudDogVGh1cnNkYXksIFNlcHRl
bWJlciAwOSwgMjAxMCAxOTo1NCBQTQ0KPiBUbzogWmFuZyBSb3ktUjYxOTExDQo+IENjOiBsaW51
eC1tdGRAbGlzdHMuaW5mcmFkZWFkLm9yZzsgZHdtdzJAaW5mcmFkZWFkLm9yZzsgZGVkZWtpbmQx
QGdtYWlsLmNvbTsNCj4gYWtwbUBsaW51eC1mb3VuZGF0aW9uLm9yZzsgTGFuIENodW5oZS1CMjU4
MDY7IFdvb2QgU2NvdHQtQjA3NDIxOyBHYWxhIEt1bWFyLQ0KPiBCMTE3ODA7IGxpbnV4cHBjLWRl
dkBvemxhYnMub3JnDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggMS8zIHYyXVtNVERdIFA0MDgwL2VM
QkM6IE1ha2UgRnJlZXNjYWxlIGVsYmMgaW50ZXJydXB0DQo+IGNvbW1vbiB0byBlbGJjIGRldmlj
ZXMNCj4gDQo+IEp1c3QgYSBmZXcgY29zbWV0aWMgbml0cyBmb3IgdGhpcyBwYXRjaC4uLg0KPiAN
Cj4gT24gVGh1LCBTZXAgMDksIDIwMTAgYXQgMDY6MjA6MzBQTSArMDgwMCwgUm95IFphbmcgd3Jv
dGU6DQo+IFsuLi5dDQpbc25pcF0NCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2Vf
aWQgZnNsX2xiY19tYXRjaFtdID0gew0KPiA+ICsJeyAuY29tcGF0aWJsZSA9ICJmc2wsZWxiYyIs
IH0sDQo+ID4gKwl7IC5jb21wYXRpYmxlID0gImZzbCxwcTMtbG9jYWxidXMiLCB9LA0KPiA+ICsJ
eyAuY29tcGF0aWJsZSA9ICJmc2wscHEyLWxvY2FsYnVzIiwgfSwNCj4gPiArCXsgLmNvbXBhdGli
bGUgPSAiZnNsLHBxMnByby1sb2NhbGJ1cyIsIH0sDQo+ID4gKwl7fSwNCj4gPiArfTsNCj4gDQo+
IFlvdSBuZWVkIGxpbnV4L21vZF9kZXZpY2V0YWJsZS5oIGZvciB0aGlzLg0KSXQgaGFzIGJlZW4g
aW5jbHVkZSBpbiBsaW51eC9vZi5oLg0KDQo+IA0KPiA+ICsNCj4gPiArc3RhdGljIHN0cnVjdCBv
Zl9wbGF0Zm9ybV9kcml2ZXIgZnNsX2xiY19jdHJsX2RyaXZlciA9IHsNCj4gDQo+IE5lZWQgbGlu
dXgvb2ZfcGxhdGZvcm0uaCBmb3IgdGhpcy4NCkl0IGhhcyBiZWVuIGluY2x1ZGUgYnkNCmZzbF9s
YmMuaC0+bGludXgvb2ZfcGxhdGZvcm0uaC0+IGxpbnV4L3BsYXRmb3JtX2RldmljZS5oDQpCZWZv
cmUgc3VibWl0dGluZyB0aGUgcGF0Y2gsIEkgaGF2ZSBidWlsdCBhbmQgdGVzdGVkIGl0Lg0KDQpE
byB5b3UgdGhpbmsgSSBkbyBub3QgYnVpbGQgdGhlIHRyZWUgYmVmb3JlIEkgc2VuZCBvdXQgdGhl
IHBhdGNoPw0KPiANCj4gPiArDQo+ID4gK3N0YXRpYyBzdHJ1Y3Qgb2ZfcGxhdGZvcm1fZHJpdmVy
IGZzbF9sYmNfY3RybF9kcml2ZXIgPSB7DQo+IA0KPiBOZWVkIGxpbnV4L29mX3BsYXRmb3JtLmgg
Zm9yIHRoaXMuDQo+IA0KPiBCdXQgeW91IGFjdHVhbGx5IGRvbid0IG5lZWQgb2ZfcGxhdGZvcm1f
ZHJpdmVyLCBhcyBmb3IgdGhlDQo+IG5ldyBjb2RlIHlvdSBjYW4gdXNlIHBsYXRmb3JtX2RyaXZl
ciAoYW5kIHRodXMNCj4gbGludXgvcGxhdGZvcm1fZGV2aWNlLmgpLg0KSSdkIHByZWZlciB1c2lu
ZyBvZl9wbGF0Zm9ybV9kcml2ZXIgaGVyZSBmb3Igc2ltcGxpZmllZCBjb2RlLg0KQW55IHNwZWNp
YWwgcmVhc29uIHRvIHVzZSBwbGF0Zm9ybV9kZXZpY2UgaGVyZT8NClRoYW5rcy4NClJveQ0K

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH 1/3 v2][MTD] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
@ 2010-09-10  6:58     ` Zang Roy-R61911
  0 siblings, 0 replies; 40+ messages in thread
From: Zang Roy-R61911 @ 2010-09-10  6:58 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, akpm, dwmw2, Gala Kumar-B11780



> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru@gmail.com]
> Sent: Thursday, September 09, 2010 19:54 PM
> To: Zang Roy-R61911
> Cc: linux-mtd@lists.infradead.org; dwmw2@infradead.org; dedekind1@gmail.com;
> akpm@linux-foundation.org; Lan Chunhe-B25806; Wood Scott-B07421; Gala Kumar-
> B11780; linuxppc-dev@ozlabs.org
> Subject: Re: [PATCH 1/3 v2][MTD] P4080/eLBC: Make Freescale elbc interrupt
> common to elbc devices
> 
> Just a few cosmetic nits for this patch...
> 
> On Thu, Sep 09, 2010 at 06:20:30PM +0800, Roy Zang wrote:
> [...]
[snip]
> > +static const struct of_device_id fsl_lbc_match[] = {
> > +	{ .compatible = "fsl,elbc", },
> > +	{ .compatible = "fsl,pq3-localbus", },
> > +	{ .compatible = "fsl,pq2-localbus", },
> > +	{ .compatible = "fsl,pq2pro-localbus", },
> > +	{},
> > +};
> 
> You need linux/mod_devicetable.h for this.
It has been include in linux/of.h.

> 
> > +
> > +static struct of_platform_driver fsl_lbc_ctrl_driver = {
> 
> Need linux/of_platform.h for this.
It has been include by
fsl_lbc.h->linux/of_platform.h-> linux/platform_device.h
Before submitting the patch, I have built and tested it.

Do you think I do not build the tree before I send out the patch?
> 
> > +
> > +static struct of_platform_driver fsl_lbc_ctrl_driver = {
> 
> Need linux/of_platform.h for this.
> 
> But you actually don't need of_platform_driver, as for the
> new code you can use platform_driver (and thus
> linux/platform_device.h).
I'd prefer using of_platform_driver here for simplified code.
Any special reason to use platform_device here?
Thanks.
Roy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 1/3 v2][MTD] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
  2010-09-10  6:58     ` Zang Roy-R61911
  (?)
@ 2010-09-10  9:31     ` Anton Vorontsov
  -1 siblings, 0 replies; 40+ messages in thread
From: Anton Vorontsov @ 2010-09-10  9:31 UTC (permalink / raw)
  To: Zang Roy-R61911
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, akpm, dwmw2, Gala Kumar-B11780

On Fri, Sep 10, 2010 at 02:58:15PM +0800, Zang Roy-R61911 wrote:
[...]
> > > +static struct of_platform_driver fsl_lbc_ctrl_driver = {
> > 
> > Need linux/of_platform.h for this.
> It has been include by
> fsl_lbc.h->linux/of_platform.h-> linux/platform_device.h
> Before submitting the patch, I have built and tested it.

In Linux we try to include all the headers explicitly (except
for asm/* if the same header name exists in linux/).

That's to avoid problems if for some reason fsl_lbc.h will stop
including of_plaform.h some day.

Oh, and by the way, there is absolutely no reason to add
linux/of_platform.h and interrupts.h into fsl_lbc.h, they're
is simply not needed in fsl_lbc.h.

> Do you think I do not build the tree before I send out the patch?

Nope, that's not what I think. I didn't say that the file
won't build w/o these fixes, but they're still needed.

> > > +
> > > +static struct of_platform_driver fsl_lbc_ctrl_driver = {
> > 
> > Need linux/of_platform.h for this.
> > 
> > But you actually don't need of_platform_driver, as for the
> > new code you can use platform_driver (and thus
> > linux/platform_device.h).
> I'd prefer using of_platform_driver here for simplified code.
> Any special reason to use platform_device here?

In the new kernels, of_platform_driver is almost a synonym of
platform_driver, and 'of_platform_driver' stuff is soon to be
deleted. You can use platform_driver just like
of_platform_driver nowadays.

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-09 11:06       ` Geert Uytterhoeven
@ 2010-09-13  7:22         ` Zang Roy-R61911
  -1 siblings, 0 replies; 40+ messages in thread
From: Zang Roy-R61911 @ 2010-09-13  7:22 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, akpm, dwmw2, Gala Kumar-B11780

DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogZ2VlcnQudXl0dGVyaG9l
dmVuQGdtYWlsLmNvbSBbbWFpbHRvOmdlZXJ0LnV5dHRlcmhvZXZlbkBnbWFpbC5jb21dIE9uDQo+
IEJlaGFsZiBPZiBHZWVydCBVeXR0ZXJob2V2ZW4NCj4gU2VudDogVGh1cnNkYXksIFNlcHRlbWJl
ciAwOSwgMjAxMCAxOTowNiBQTQ0KPiBUbzogWmFuZyBSb3ktUjYxOTExDQo+IENjOiBsaW51eC1t
dGRAbGlzdHMuaW5mcmFkZWFkLm9yZzsgV29vZCBTY290dC1CMDc0MjE7IGRlZGVraW5kMUBnbWFp
bC5jb207IExhbg0KPiBDaHVuaGUtQjI1ODA2OyBsaW51eHBwYy1kZXZAb3psYWJzLm9yZzsgYWtw
bUBsaW51eC1mb3VuZGF0aW9uLm9yZzsNCj4gZHdtdzJAaW5mcmFkZWFkLm9yZzsgR2FsYSBLdW1h
ci1CMTE3ODANCj4gU3ViamVjdDogUmU6IFtQQVRDSCB2MiAzLzNdW01URF0gUDQwODAvbXRkOiBG
aXggdGhlIGZyZWVzY2FsZSBsYmMgaXNzdWUgd2l0aA0KPiAzNmJpdCBtb2RlDQo+IA0KPiBPbiBU
aHUsIFNlcCA5LCAyMDEwIGF0IDEyOjIwLCBSb3kgWmFuZyA8dGllLWZlaS56YW5nQGZyZWVzY2Fs
ZS5jb20+IHdyb3RlOg0KPiA+IEZyb206IExhbiBDaHVuaGUtQjI1ODA2IDxiMjU4MDZAZnJlZXNj
YWxlLmNvbT4NCj4gPg0KPiA+IFdoZW4gc3lzdGVtIHVzZXMgMzZiaXQgcGh5c2ljYWwgYWRkcmVz
cywgcmVzLnN0YXJ0IGlzIDM2Yml0DQo+ID4gcGh5c2ljYWwgYWRkcmVzcy4gQnV0IHRoZSBmdW5j
dGlvbiBvZiBpbl9iZTMyIHJldHVybnMgMzJiaXQNCj4gPiBwaHlzaWNhbCBhZGRyZXNzLiBUaGVu
IGJvdGggb2YgdGhlbSBjb21wYXJlZCBlYWNoIG90aGVyIGlzDQo+ID4gd3JvbmcuIFNvIGJ5IGNv
bnZlcnRpbmcgdGhlIGFkZHJlc3Mgb2YgcmVzLnN0YXJ0IGludG8NCj4gPiB0aGUgcmlnaHQgZm9y
bWF0IGZpeGVzIHRoaXMgaXNzdWUuDQo+IA0KPiA+IMKgLyoqDQo+ID4gKyAqIGZzbF9sYmNfYWRk
ciAtIGNvbnZlcnQgdGhlIGJhc2UgYWRkcmVzcw0KPiA+ICsgKiBAYWRkcl9iYXNlOiBiYXNlIGFk
ZHJlc3Mgb2YgdGhlIG1lbW9yeSBiYW5rDQo+ID4gKyAqDQo+ID4gKyAqIFRoaXMgZnVuY3Rpb24g
Y29udmVydHMgYSBiYXNlIGFkZHJlc3Mgb2YgbGJjIGludG8gdGhlIHJpZ2h0IGZvcm1hdCBmb3IN
Cj4gdGhlIEJSDQo+ID4gKyAqIHJlZ2lzdGVycy4gSWYgdGhlIFNPQyBoYXMgZUxCQyB0aGVuIGl0
IHJldHVybnMgMzJiaXQgcGh5c2ljYWwgYWRkcmVzcw0KPiBlbHNlDQo+ID4gKyAqIGl0IHJldHVy
bnMgMzRiaXQgcGh5c2ljYWwgYWRkcmVzcyBmb3IgbG9jYWwgYnVzKEV4YW1wbGU6IE1QQzg2NDEp
Lg0KPiA+ICsgKi8NCj4gPiArdW5zaWduZWQgaW50IGZzbF9sYmNfYWRkcihwaHlzX2FkZHJfdCBh
ZGRyX2Jhc2UpDQo+ICAgICBeXl5eXl5eXl5eXl4NCj4gU2hvdWxkbid0IHRoaXMgYmUgdTMyIG9y
IF9fYmUzMiwgZm9yIGNvbnNpc3RlbmN5IHdpdGggdGhlIGFjdHVhbA0KPiBjb21wYXJpc29ucyBi
ZWxvdz8NCl9fYmUzMiBpcyBiZXR0ZXIuDQpUaGFua3MuDQpSb3kNCg==

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-13  7:22         ` Zang Roy-R61911
  0 siblings, 0 replies; 40+ messages in thread
From: Zang Roy-R61911 @ 2010-09-13  7:22 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, akpm, dwmw2, Gala Kumar-B11780



> -----Original Message-----
> From: geert.uytterhoeven@gmail.com [mailto:geert.uytterhoeven@gmail.com] On
> Behalf Of Geert Uytterhoeven
> Sent: Thursday, September 09, 2010 19:06 PM
> To: Zang Roy-R61911
> Cc: linux-mtd@lists.infradead.org; Wood Scott-B07421; dedekind1@gmail.com; Lan
> Chunhe-B25806; linuxppc-dev@ozlabs.org; akpm@linux-foundation.org;
> dwmw2@infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with
> 36bit mode
> 
> On Thu, Sep 9, 2010 at 12:20, Roy Zang <tie-fei.zang@freescale.com> wrote:
> > From: Lan Chunhe-B25806 <b25806@freescale.com>
> >
> > When system uses 36bit physical address, res.start is 36bit
> > physical address. But the function of in_be32 returns 32bit
> > physical address. Then both of them compared each other is
> > wrong. So by converting the address of res.start into
> > the right format fixes this issue.
> 
> >  /**
> > + * fsl_lbc_addr - convert the base address
> > + * @addr_base: base address of the memory bank
> > + *
> > + * This function converts a base address of lbc into the right format for
> the BR
> > + * registers. If the SOC has eLBC then it returns 32bit physical address
> else
> > + * it returns 34bit physical address for local bus(Example: MPC8641).
> > + */
> > +unsigned int fsl_lbc_addr(phys_addr_t addr_base)
>     ^^^^^^^^^^^^
> Shouldn't this be u32 or __be32, for consistency with the actual
> comparisons below?
__be32 is better.
Thanks.
Roy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-09 11:41     ` Anton Vorontsov
@ 2010-09-13  7:30         ` Zang Roy-R61911
  0 siblings, 0 replies; 40+ messages in thread
From: Zang Roy-R61911 @ 2010-09-13  7:30 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, akpm, dwmw2, Gala Kumar-B11780

DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQW50b24gVm9yb250c292
IFttYWlsdG86Y2JvdWF0bWFpbHJ1QGdtYWlsLmNvbV0NCj4gU2VudDogVGh1cnNkYXksIFNlcHRl
bWJlciAwOSwgMjAxMCAxOTo0MiBQTQ0KPiBUbzogWmFuZyBSb3ktUjYxOTExDQo+IENjOiBsaW51
eC1tdGRAbGlzdHMuaW5mcmFkZWFkLm9yZzsgZHdtdzJAaW5mcmFkZWFkLm9yZzsgZGVkZWtpbmQx
QGdtYWlsLmNvbTsNCj4gYWtwbUBsaW51eC1mb3VuZGF0aW9uLm9yZzsgTGFuIENodW5oZS1CMjU4
MDY7IFdvb2QgU2NvdHQtQjA3NDIxOyBHYWxhIEt1bWFyLQ0KPiBCMTE3ODA7IGxpbnV4cHBjLWRl
dkBvemxhYnMub3JnDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggdjIgMy8zXVtNVERdIFA0MDgwL210
ZDogRml4IHRoZSBmcmVlc2NhbGUgbGJjIGlzc3VlIHdpdGgNCj4gMzZiaXQgbW9kZQ0KPiANCj4g
T24gVGh1LCBTZXAgMDksIDIwMTAgYXQgMDY6MjA6MzJQTSArMDgwMCwgUm95IFphbmcgd3JvdGU6
DQo+IFsuLi5dDQo+ID4gIC8qKg0KPiA+ICsgKiBmc2xfbGJjX2FkZHIgLSBjb252ZXJ0IHRoZSBi
YXNlIGFkZHJlc3MNCj4gPiArICogQGFkZHJfYmFzZToJYmFzZSBhZGRyZXNzIG9mIHRoZSBtZW1v
cnkgYmFuaw0KPiA+ICsgKg0KPiA+ICsgKiBUaGlzIGZ1bmN0aW9uIGNvbnZlcnRzIGEgYmFzZSBh
ZGRyZXNzIG9mIGxiYyBpbnRvIHRoZSByaWdodCBmb3JtYXQgZm9yDQo+IHRoZSBCUg0KPiA+ICsg
KiByZWdpc3RlcnMuIElmIHRoZSBTT0MgaGFzIGVMQkMgdGhlbiBpdCByZXR1cm5zIDMyYml0IHBo
eXNpY2FsIGFkZHJlc3MNCj4gZWxzZQ0KPiA+ICsgKiBpdCByZXR1cm5zIDM0Yml0IHBoeXNpY2Fs
IGFkZHJlc3MgZm9yIGxvY2FsIGJ1cyhFeGFtcGxlOiBNUEM4NjQxKS4NCj4gPiArICovDQo+IA0K
PiBJdCByZXR1cm5zIDM0Yml0IHBoeXNpY2FsIGFkZHJlc3MgZW5jb2RlZCBpbiBhIDMyIGJpdCB3
b3JkLA0KPiByaWdodD8gDQpZZXMuDQoNCj5CZWNhdXNlLCBJSVJDLCAndW5zaWduZWQgaW50JyBp
cyBhbHdheXMgMzIgYml0Lg0KPiANCj4gV29ydGggbWVudGlvbmluZyB0aGlzIGZhY3QuDQpBZ3Jl
ZS4NClRoZSBjb21tZW50IGlzIGEgbGl0dGxlIGJpdCBjb25mdXNpbmcuIFdpbGwgdXBkYXRlLg0K
DQoNCj4gDQo+ID4gK3Vuc2lnbmVkIGludCBmc2xfbGJjX2FkZHIocGh5c19hZGRyX3QgYWRkcl9i
YXNlKQ0KPiA+ICt7DQo+ID4gKwl2b2lkICpkZXY7DQo+IA0KPiBzdHJ1Y3QgZGV2aWNlX25vZGUg
Km5wOw0KPiANCj4gPiArCWludCBjb21wYXRpYmxlOw0KPiA+ICsNCj4gPiArCWRldiA9IGZzbF9s
YmNfY3RybF9kZXYtPmRldi0+b2Zfbm9kZTsNCj4gPiArCWNvbXBhdGlibGUgPSBvZl9kZXZpY2Vf
aXNfY29tcGF0aWJsZShkZXYsICJmc2wsZWxiYyIpOw0KPiA+ICsNCj4gPiArCWlmIChjb21wYXRp
YmxlKQ0KPiA+ICsJCXJldHVybiBhZGRyX2Jhc2UgJiAweGZmZmY4MDAwOw0KPiA+ICsJZWxzZQ0K
PiA+ICsJCXJldHVybiAoYWRkcl9iYXNlICYgMHgwZmZmZjgwMDB1bGwpDQo+ID4gKwkJCXwgKChh
ZGRyX2Jhc2UgJiAweDMwMDAwMDAwMHVsbCkgPj4gMTkpOw0KPiA+ICt9DQo+ID4gK0VYUE9SVF9T
WU1CT0woZnNsX2xiY19hZGRyKTsNCj4gDQo+IEFsbW9zdCBwZXJmZWN0LiBJJ20gbm90IHN1cmUg
aWYgJ3Vuc2lnbmVkIGludCcgaXMgdGVjaG5pY2FsbHkNCj4gY29ycmVjdCByZXR1cm4gdHlwZSBm
b3IgdGhpcyBmdW5jdGlvbiB0aG91Z2guIEkgZ3Vlc3MgaXQgc2hvdWxkDQo+IGJlIHUzMi4NCj4g
DQpXaGF0IGlzIHRoZSBkaWZmZXJlbnQgZm9yIHVuc2lnbmVkIGludCBhbmQgdTMyPyBJIHRoaW5r
IHRoZXkgYXJlIHNhbWUuDQoNCg0KPiBBbHNvLCB0aGUgZnVuY3Rpb24gbWF5IGJlIGEgYml0IG1v
cmUgdW5kZXJzdGFuZGFibGUgYW5kIHNob3J0ZXI6DQo+IA0KPiB1MzIgZnNsX2xiY19hZGRyKHBo
eXNfYWRkcl90IGFkZHIpDQo+IHsNCj4gCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAgPSBmc2xfbGJj
X2N0cmxfZGV2LT5kZXYtPm9mX25vZGU7DQo+IAl1MzIgYWRkcmwgPSBhZGRyICYgMHhmZmZmODAw
MDsNCmlmIGFkZHIgaXMgMzQgYml0IGxvbmcsIGlzIHRoaXMgY29ycmVjdD8NClRoYW5rcy4NClJv
eQ0K

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-13  7:30         ` Zang Roy-R61911
  0 siblings, 0 replies; 40+ messages in thread
From: Zang Roy-R61911 @ 2010-09-13  7:30 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, akpm, dwmw2, Gala Kumar-B11780



> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru@gmail.com]
> Sent: Thursday, September 09, 2010 19:42 PM
> To: Zang Roy-R61911
> Cc: linux-mtd@lists.infradead.org; dwmw2@infradead.org; dedekind1@gmail.com;
> akpm@linux-foundation.org; Lan Chunhe-B25806; Wood Scott-B07421; Gala Kumar-
> B11780; linuxppc-dev@ozlabs.org
> Subject: Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with
> 36bit mode
> 
> On Thu, Sep 09, 2010 at 06:20:32PM +0800, Roy Zang wrote:
> [...]
> >  /**
> > + * fsl_lbc_addr - convert the base address
> > + * @addr_base:	base address of the memory bank
> > + *
> > + * This function converts a base address of lbc into the right format for
> the BR
> > + * registers. If the SOC has eLBC then it returns 32bit physical address
> else
> > + * it returns 34bit physical address for local bus(Example: MPC8641).
> > + */
> 
> It returns 34bit physical address encoded in a 32 bit word,
> right? 
Yes.

>Because, IIRC, 'unsigned int' is always 32 bit.
> 
> Worth mentioning this fact.
Agree.
The comment is a little bit confusing. Will update.


> 
> > +unsigned int fsl_lbc_addr(phys_addr_t addr_base)
> > +{
> > +	void *dev;
> 
> struct device_node *np;
> 
> > +	int compatible;
> > +
> > +	dev = fsl_lbc_ctrl_dev->dev->of_node;
> > +	compatible = of_device_is_compatible(dev, "fsl,elbc");
> > +
> > +	if (compatible)
> > +		return addr_base & 0xffff8000;
> > +	else
> > +		return (addr_base & 0x0ffff8000ull)
> > +			| ((addr_base & 0x300000000ull) >> 19);
> > +}
> > +EXPORT_SYMBOL(fsl_lbc_addr);
> 
> Almost perfect. I'm not sure if 'unsigned int' is technically
> correct return type for this function though. I guess it should
> be u32.
> 
What is the different for unsigned int and u32? I think they are same.


> Also, the function may be a bit more understandable and shorter:
> 
> u32 fsl_lbc_addr(phys_addr_t addr)
> {
> 	struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node;
> 	u32 addrl = addr & 0xffff8000;
if addr is 34 bit long, is this correct?
Thanks.
Roy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-13  7:30         ` Zang Roy-R61911
@ 2010-09-13 14:10           ` Timur Tabi
  -1 siblings, 0 replies; 40+ messages in thread
From: Timur Tabi @ 2010-09-13 14:10 UTC (permalink / raw)
  To: Zang Roy-R61911
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, akpm, dwmw2, Gala Kumar-B11780

On Mon, Sep 13, 2010 at 2:30 AM, Zang Roy-R61911 <r61911@freescale.com> wrote:

> What is the different for unsigned int and u32? I think they are same.

Roy, please don't ever write code that assumes that sizeof(int) == 4.
There's a reason why we have unsized integer types (like int, long,
and short) and sized integer types (like u8, u16, u32).  If you want
an integer of a specific size, you should use a sized integer type.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-13 14:10           ` Timur Tabi
  0 siblings, 0 replies; 40+ messages in thread
From: Timur Tabi @ 2010-09-13 14:10 UTC (permalink / raw)
  To: Zang Roy-R61911
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, Anton Vorontsov, akpm, dwmw2, Gala Kumar-B11780

On Mon, Sep 13, 2010 at 2:30 AM, Zang Roy-R61911 <r61911@freescale.com> wrote:

> What is the different for unsigned int and u32? I think they are same.

Roy, please don't ever write code that assumes that sizeof(int) == 4.
There's a reason why we have unsized integer types (like int, long,
and short) and sized integer types (like u8, u16, u32).  If you want
an integer of a specific size, you should use a sized integer type.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-13 14:10           ` Timur Tabi
@ 2010-09-13 14:27             ` Artem Bityutskiy
  -1 siblings, 0 replies; 40+ messages in thread
From: Artem Bityutskiy @ 2010-09-13 14:27 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Wood Scott-B07421, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, akpm, dwmw2, Gala Kumar-B11780

On Mon, 2010-09-13 at 09:10 -0500, Timur Tabi wrote:
> On Mon, Sep 13, 2010 at 2:30 AM, Zang Roy-R61911 <r61911@freescale.com> wrote:
> 
> > What is the different for unsigned int and u32? I think they are same.
> 
> Roy, please don't ever write code that assumes that sizeof(int) == 4.
> There's a reason why we have unsized integer types (like int, long,
> and short) and sized integer types (like u8, u16, u32).  If you want
> an integer of a specific size, you should use a sized integer type.

Yes, sizeof(int) == 4 assumption is not good.

But sizeof(int) >= 4 is perfectly fine.

It is OK to rely on the fact that unsigned int is _at least_ 32-bit, not
less. And if you know 32 bits is enough, and you are fine with more, it
is _better_ to avoid u32. Simply because with unsigned int you do not
limit the compiler and CPU and let them use native integers, rather than
strictly 32-bit. This potentially gives the compiler and CPU more room
for optimization.

I see people use u32 and the friends too much. It is safe and better to
use native types, unless you really have to make the variable to be
strictly u32.

I did not follow this particular conversation and do not judge which
type is better in this case. I am talking in general. :-)

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-13 14:27             ` Artem Bityutskiy
  0 siblings, 0 replies; 40+ messages in thread
From: Artem Bityutskiy @ 2010-09-13 14:27 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Wood Scott-B07421, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, Anton Vorontsov, akpm, dwmw2,
	Gala Kumar-B11780

On Mon, 2010-09-13 at 09:10 -0500, Timur Tabi wrote:
> On Mon, Sep 13, 2010 at 2:30 AM, Zang Roy-R61911 <r61911@freescale.com> wrote:
> 
> > What is the different for unsigned int and u32? I think they are same.
> 
> Roy, please don't ever write code that assumes that sizeof(int) == 4.
> There's a reason why we have unsized integer types (like int, long,
> and short) and sized integer types (like u8, u16, u32).  If you want
> an integer of a specific size, you should use a sized integer type.

Yes, sizeof(int) == 4 assumption is not good.

But sizeof(int) >= 4 is perfectly fine.

It is OK to rely on the fact that unsigned int is _at least_ 32-bit, not
less. And if you know 32 bits is enough, and you are fine with more, it
is _better_ to avoid u32. Simply because with unsigned int you do not
limit the compiler and CPU and let them use native integers, rather than
strictly 32-bit. This potentially gives the compiler and CPU more room
for optimization.

I see people use u32 and the friends too much. It is safe and better to
use native types, unless you really have to make the variable to be
strictly u32.

I did not follow this particular conversation and do not judge which
type is better in this case. I am talking in general. :-)

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-13 14:27             ` Artem Bityutskiy
@ 2010-09-13 14:35               ` Timur Tabi
  -1 siblings, 0 replies; 40+ messages in thread
From: Timur Tabi @ 2010-09-13 14:35 UTC (permalink / raw)
  To: dedekind1
  Cc: Wood Scott-B07421, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, akpm, dwmw2, Gala Kumar-B11780

On Mon, Sep 13, 2010 at 9:27 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:

> Yes, sizeof(int) == 4 assumption is not good.
>
> But sizeof(int) >= 4 is perfectly fine.

I have to disagree.   I don't see how you can say that == is not okay,
but >= is okay.  That just doesn't make any sense.  Obviously, you
have to make some assumptions about sizeof(int), but that assumption
should be nothing more than "it should be big enough for these small
numbers that I'm using".

> I see people use u32 and the friends too much.

I agree with that.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-13 14:35               ` Timur Tabi
  0 siblings, 0 replies; 40+ messages in thread
From: Timur Tabi @ 2010-09-13 14:35 UTC (permalink / raw)
  To: dedekind1
  Cc: Wood Scott-B07421, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, Anton Vorontsov, akpm, dwmw2,
	Gala Kumar-B11780

On Mon, Sep 13, 2010 at 9:27 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:

> Yes, sizeof(int) == 4 assumption is not good.
>
> But sizeof(int) >= 4 is perfectly fine.

I have to disagree.   I don't see how you can say that == is not okay,
but >= is okay.  That just doesn't make any sense.  Obviously, you
have to make some assumptions about sizeof(int), but that assumption
should be nothing more than "it should be big enough for these small
numbers that I'm using".

> I see people use u32 and the friends too much.

I agree with that.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-13  7:22         ` Zang Roy-R61911
@ 2010-09-13 16:27           ` Scott Wood
  -1 siblings, 0 replies; 40+ messages in thread
From: Scott Wood @ 2010-09-13 16:27 UTC (permalink / raw)
  To: Zang Roy-R61911
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, Geert Uytterhoeven, akpm, dwmw2, Gala Kumar-B11780

On Mon, 13 Sep 2010 00:22:10 -0700
"Zang Roy-R61911" <r61911@freescale.com> wrote:

>=20
>=20
> > -----Original Message-----
> > From: geert.uytterhoeven@gmail.com [mailto:geert.uytterhoeven@gmail.com=
] On
> > Behalf Of Geert Uytterhoeven
> > Sent: Thursday, September 09, 2010 19:06 PM
> > To: Zang Roy-R61911
> > Cc: linux-mtd@lists.infradead.org; Wood Scott-B07421; dedekind1@gmail.c=
om; Lan
> > Chunhe-B25806; linuxppc-dev@ozlabs.org; akpm@linux-foundation.org;
> > dwmw2@infradead.org; Gala Kumar-B11780
> > Subject: Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue=
 with
> > 36bit mode
> >=20
> > On Thu, Sep 9, 2010 at 12:20, Roy Zang <tie-fei.zang@freescale.com> wro=
te:
> > > From: Lan Chunhe-B25806 <b25806@freescale.com>
> > >
> > > When system uses 36bit physical address, res.start is 36bit
> > > physical address. But the function of in_be32 returns 32bit
> > > physical address. Then both of them compared each other is
> > > wrong. So by converting the address of res.start into
> > > the right format fixes this issue.
> >=20
> > > =A0/**
> > > + * fsl_lbc_addr - convert the base address
> > > + * @addr_base: base address of the memory bank
> > > + *
> > > + * This function converts a base address of lbc into the right forma=
t for
> > the BR
> > > + * registers. If the SOC has eLBC then it returns 32bit physical add=
ress
> > else
> > > + * it returns 34bit physical address for local bus(Example: MPC8641).
> > > + */
> > > +unsigned int fsl_lbc_addr(phys_addr_t addr_base)
> >     ^^^^^^^^^^^^
> > Shouldn't this be u32 or __be32, for consistency with the actual
> > comparisons below?
> __be32 is better.

I disagree, the return from this function is native-endian.  It should
be u32.

-Scott

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-13 16:27           ` Scott Wood
  0 siblings, 0 replies; 40+ messages in thread
From: Scott Wood @ 2010-09-13 16:27 UTC (permalink / raw)
  To: Zang Roy-R61911
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	linux-mtd, Geert Uytterhoeven, akpm, dwmw2, Gala Kumar-B11780

On Mon, 13 Sep 2010 00:22:10 -0700
"Zang Roy-R61911" <r61911@freescale.com> wrote:

> 
> 
> > -----Original Message-----
> > From: geert.uytterhoeven@gmail.com [mailto:geert.uytterhoeven@gmail.com] On
> > Behalf Of Geert Uytterhoeven
> > Sent: Thursday, September 09, 2010 19:06 PM
> > To: Zang Roy-R61911
> > Cc: linux-mtd@lists.infradead.org; Wood Scott-B07421; dedekind1@gmail.com; Lan
> > Chunhe-B25806; linuxppc-dev@ozlabs.org; akpm@linux-foundation.org;
> > dwmw2@infradead.org; Gala Kumar-B11780
> > Subject: Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with
> > 36bit mode
> > 
> > On Thu, Sep 9, 2010 at 12:20, Roy Zang <tie-fei.zang@freescale.com> wrote:
> > > From: Lan Chunhe-B25806 <b25806@freescale.com>
> > >
> > > When system uses 36bit physical address, res.start is 36bit
> > > physical address. But the function of in_be32 returns 32bit
> > > physical address. Then both of them compared each other is
> > > wrong. So by converting the address of res.start into
> > > the right format fixes this issue.
> > 
> > >  /**
> > > + * fsl_lbc_addr - convert the base address
> > > + * @addr_base: base address of the memory bank
> > > + *
> > > + * This function converts a base address of lbc into the right format for
> > the BR
> > > + * registers. If the SOC has eLBC then it returns 32bit physical address
> > else
> > > + * it returns 34bit physical address for local bus(Example: MPC8641).
> > > + */
> > > +unsigned int fsl_lbc_addr(phys_addr_t addr_base)
> >     ^^^^^^^^^^^^
> > Shouldn't this be u32 or __be32, for consistency with the actual
> > comparisons below?
> __be32 is better.

I disagree, the return from this function is native-endian.  It should
be u32.

-Scott

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-13 14:35               ` Timur Tabi
@ 2010-09-13 16:45                 ` Artem Bityutskiy
  -1 siblings, 0 replies; 40+ messages in thread
From: Artem Bityutskiy @ 2010-09-13 16:45 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Wood Scott-B07421, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, akpm, dwmw2, Gala Kumar-B11780

On Mon, 2010-09-13 at 09:35 -0500, Timur Tabi wrote:
> On Mon, Sep 13, 2010 at 9:27 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> 
> > Yes, sizeof(int) == 4 assumption is not good.
> >
> > But sizeof(int) >= 4 is perfectly fine.
> 
> I have to disagree.   I don't see how you can say that == is not okay,
> but >= is okay.

If I assume that int == 4, which is true for all platform ATM, and will
most probably stay true for very long time, I still make an unnecessary
assumption which C99 does not guarantee. This is just not very clean. So
for things which require exactly 32 bits, u32 or C99 uint32_t should be
used.

On the other hand, if a have a local variable "var" which needs to store
values which I know will always fit 32 bits, and I do not use it in
operations (I/O, etc) which require exactly 32 bits, it is better to use
unsigned int for it. Unsigned int is reliably >= 4 in Linux.

This is wat I meant that sizeof(int) >= 4 is perfectly fine. One
everywhere, of course, but in many cases.

To put it differently, if there is no special reason to limit the
variable by exactly 32 bits, it is better to use int.

-- 
Best Regards,
Artem Bityutskiy (Битюцкий Артём)

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-13 16:45                 ` Artem Bityutskiy
  0 siblings, 0 replies; 40+ messages in thread
From: Artem Bityutskiy @ 2010-09-13 16:45 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Wood Scott-B07421, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, Anton Vorontsov, akpm, dwmw2,
	Gala Kumar-B11780

On Mon, 2010-09-13 at 09:35 -0500, Timur Tabi wrote:
> On Mon, Sep 13, 2010 at 9:27 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> 
> > Yes, sizeof(int) == 4 assumption is not good.
> >
> > But sizeof(int) >= 4 is perfectly fine.
> 
> I have to disagree.   I don't see how you can say that == is not okay,
> but >= is okay.

If I assume that int == 4, which is true for all platform ATM, and will
most probably stay true for very long time, I still make an unnecessary
assumption which C99 does not guarantee. This is just not very clean. So
for things which require exactly 32 bits, u32 or C99 uint32_t should be
used.

On the other hand, if a have a local variable "var" which needs to store
values which I know will always fit 32 bits, and I do not use it in
operations (I/O, etc) which require exactly 32 bits, it is better to use
unsigned int for it. Unsigned int is reliably >= 4 in Linux.

This is wat I meant that sizeof(int) >= 4 is perfectly fine. One
everywhere, of course, but in many cases.

To put it differently, if there is no special reason to limit the
variable by exactly 32 bits, it is better to use int.

-- 
Best Regards,
Artem Bityutskiy (Битюцкий Артём)

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-13 16:45                 ` Artem Bityutskiy
@ 2010-09-13 18:36                   ` Timur Tabi
  -1 siblings, 0 replies; 40+ messages in thread
From: Timur Tabi @ 2010-09-13 18:36 UTC (permalink / raw)
  To: dedekind1
  Cc: Wood Scott-B07421, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, akpm, dwmw2, Gala Kumar-B11780

On Mon, Sep 13, 2010 at 11:45 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> Unsigned int is reliably >= 4 in Linux.

Not exactly.  sizeof(unsigned int) is effectively never greater than 4
in Linux (I think it's still 32 bits even on a 64-bit kernel), so it
makes no sense to say >=.  So since you can't say that sizeof(int) ==
4, and you can't say that sizeof(int) > 4, then you certainly can't
say that sizeof(int) >= 4.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-13 18:36                   ` Timur Tabi
  0 siblings, 0 replies; 40+ messages in thread
From: Timur Tabi @ 2010-09-13 18:36 UTC (permalink / raw)
  To: dedekind1
  Cc: Wood Scott-B07421, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, Anton Vorontsov, akpm, dwmw2,
	Gala Kumar-B11780

On Mon, Sep 13, 2010 at 11:45 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> Unsigned int is reliably >= 4 in Linux.

Not exactly.  sizeof(unsigned int) is effectively never greater than 4
in Linux (I think it's still 32 bits even on a 64-bit kernel), so it
makes no sense to say >=.  So since you can't say that sizeof(int) ==
4, and you can't say that sizeof(int) > 4, then you certainly can't
say that sizeof(int) >= 4.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-13 18:36                   ` Timur Tabi
@ 2010-09-13 18:46                     ` Artem Bityutskiy
  -1 siblings, 0 replies; 40+ messages in thread
From: Artem Bityutskiy @ 2010-09-13 18:46 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Wood Scott-B07421, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, akpm, dwmw2, Gala Kumar-B11780

On Mon, 2010-09-13 at 13:36 -0500, Timur Tabi wrote:
> On Mon, Sep 13, 2010 at 11:45 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> > Unsigned int is reliably >= 4 in Linux.
> 
> Not exactly.  sizeof(unsigned int) is effectively never greater than 4
> in Linux

I know and said the same in the other paragraph which you cut.

>  (I think it's still 32 bits even on a 64-bit kernel)

Yes.

> , so it
> makes no sense to say >=.  So since you can't say that sizeof(int) ==
> 4, and you can't say that sizeof(int) > 4, then you certainly can't
> say that sizeof(int) >= 4.

It also makes no sense to send "makes no sense" answer 2 times in a row
and it makes no sense to not read and not try to understand the e-mail
you are replying (even though the english of the writer is not perfect)
So it makes no sense to continue arguing.

But it makes some sense to go sleep, good night.

-- 
Best Regards,
Artem Bityutskiy (Битюцкий Артём)

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-13 18:46                     ` Artem Bityutskiy
  0 siblings, 0 replies; 40+ messages in thread
From: Artem Bityutskiy @ 2010-09-13 18:46 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Wood Scott-B07421, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, Anton Vorontsov, akpm, dwmw2,
	Gala Kumar-B11780

On Mon, 2010-09-13 at 13:36 -0500, Timur Tabi wrote:
> On Mon, Sep 13, 2010 at 11:45 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> > Unsigned int is reliably >= 4 in Linux.
> 
> Not exactly.  sizeof(unsigned int) is effectively never greater than 4
> in Linux

I know and said the same in the other paragraph which you cut.

>  (I think it's still 32 bits even on a 64-bit kernel)

Yes.

> , so it
> makes no sense to say >=.  So since you can't say that sizeof(int) ==
> 4, and you can't say that sizeof(int) > 4, then you certainly can't
> say that sizeof(int) >= 4.

It also makes no sense to send "makes no sense" answer 2 times in a row
and it makes no sense to not read and not try to understand the e-mail
you are replying (even though the english of the writer is not perfect)
So it makes no sense to continue arguing.

But it makes some sense to go sleep, good night.

-- 
Best Regards,
Artem Bityutskiy (Битюцкий Артём)

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-13 18:36                   ` Timur Tabi
@ 2010-09-13 20:04                     ` Scott Wood
  -1 siblings, 0 replies; 40+ messages in thread
From: Scott Wood @ 2010-09-13 20:04 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Wood Scott-B07421, dedekind1, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, akpm, dwmw2, Gala Kumar-B11780

On Mon, 13 Sep 2010 13:36:45 -0500
Timur Tabi <timur.tabi@gmail.com> wrote:

> On Mon, Sep 13, 2010 at 11:45 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> > Unsigned int is reliably >= 4 in Linux.
> 
> Not exactly.  sizeof(unsigned int) is effectively never greater than 4
> in Linux (I think it's still 32 bits even on a 64-bit kernel), so it
> makes no sense to say >=.  

I think the point is that if a machine/ABI comes along with
sizeof(int) > 4 (e.g. if there's a significant penalty for working
with anything < 64-bit), Linux might consider supporting that.  Whereas
if someone points to their microcontroller or ancient 286 with
sizeof(int) == 2, the answer would be, "Here's a nickel, kid -- get a
real computer".

-Scott

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-13 20:04                     ` Scott Wood
  0 siblings, 0 replies; 40+ messages in thread
From: Scott Wood @ 2010-09-13 20:04 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Wood Scott-B07421, dedekind1, Zang Roy-R61911, Lan Chunhe-B25806,
	linuxppc-dev, linux-mtd, Anton Vorontsov, akpm, dwmw2,
	Gala Kumar-B11780

On Mon, 13 Sep 2010 13:36:45 -0500
Timur Tabi <timur.tabi@gmail.com> wrote:

> On Mon, Sep 13, 2010 at 11:45 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> > Unsigned int is reliably >= 4 in Linux.
> 
> Not exactly.  sizeof(unsigned int) is effectively never greater than 4
> in Linux (I think it's still 32 bits even on a 64-bit kernel), so it
> makes no sense to say >=.  

I think the point is that if a machine/ABI comes along with
sizeof(int) > 4 (e.g. if there's a significant penalty for working
with anything < 64-bit), Linux might consider supporting that.  Whereas
if someone points to their microcontroller or ancient 286 with
sizeof(int) == 2, the answer would be, "Here's a nickel, kid -- get a
real computer".

-Scott

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-13 16:27           ` Scott Wood
@ 2010-09-14  4:09             ` Zang Roy-R61911
  -1 siblings, 0 replies; 40+ messages in thread
From: Zang Roy-R61911 @ 2010-09-14  4:09 UTC (permalink / raw)
  To: Wood Scott-B07421
  Cc: dedekind1, Lan Chunhe-B25806, linuxppc-dev, linux-mtd,
	Geert Uytterhoeven, akpm, dwmw2, Gala Kumar-B11780



> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Tuesday, September 14, 2010 0:28 AM
> To: Zang Roy-R61911
> Cc: Geert Uytterhoeven; linux-mtd@lists.infradead.org; Wood =
Scott-B07421;
> dedekind1@gmail.com; Lan Chunhe-B25806; linuxppc-dev@ozlabs.org; =
akpm@linux-
> foundation.org; dwmw2@infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc =
issue with
> 36bit mode
>=20
> On Mon, 13 Sep 2010 00:22:10 -0700
> "Zang Roy-R61911" <r61911@freescale.com> wrote:
>=20
> >
> >
> > > -----Original Message-----
> > > From: geert.uytterhoeven@gmail.com =
[mailto:geert.uytterhoeven@gmail.com]
> On
> > > Behalf Of Geert Uytterhoeven
> > > Sent: Thursday, September 09, 2010 19:06 PM
> > > To: Zang Roy-R61911
> > > Cc: linux-mtd@lists.infradead.org; Wood Scott-B07421; =
dedekind1@gmail.com;
> Lan
> > > Chunhe-B25806; linuxppc-dev@ozlabs.org; akpm@linux-foundation.org;
> > > dwmw2@infradead.org; Gala Kumar-B11780
> > > Subject: Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc =
issue
> with
> > > 36bit mode
> > >
> > > On Thu, Sep 9, 2010 at 12:20, Roy Zang =
<tie-fei.zang@freescale.com> wrote:
> > > > From: Lan Chunhe-B25806 <b25806@freescale.com>
> > > >
> > > > When system uses 36bit physical address, res.start is 36bit
> > > > physical address. But the function of in_be32 returns 32bit
> > > > physical address. Then both of them compared each other is
> > > > wrong. So by converting the address of res.start into
> > > > the right format fixes this issue.
> > >
> > > > =A0/**
> > > > + * fsl_lbc_addr - convert the base address
> > > > + * @addr_base: base address of the memory bank
> > > > + *
> > > > + * This function converts a base address of lbc into the right =
format
> for
> > > the BR
> > > > + * registers. If the SOC has eLBC then it returns 32bit =
physical
> address
> > > else
> > > > + * it returns 34bit physical address for local bus(Example: =
MPC8641).
> > > > + */
> > > > +unsigned int fsl_lbc_addr(phys_addr_t addr_base)
> > >     ^^^^^^^^^^^^
> > > Shouldn't this be u32 or __be32, for consistency with the actual
> > > comparisons below?
> > __be32 is better.
>=20
> I disagree, the return from this function is native-endian.  It should
> be u32.
But the return of this value is ONLY used for br comparing. It is big =
endia.
Thanks.
Roy=20

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-14  4:09             ` Zang Roy-R61911
  0 siblings, 0 replies; 40+ messages in thread
From: Zang Roy-R61911 @ 2010-09-14  4:09 UTC (permalink / raw)
  To: Wood Scott-B07421
  Cc: dedekind1, Lan Chunhe-B25806, linuxppc-dev, linux-mtd,
	Geert Uytterhoeven, akpm, dwmw2, Gala Kumar-B11780



> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Tuesday, September 14, 2010 0:28 AM
> To: Zang Roy-R61911
> Cc: Geert Uytterhoeven; linux-mtd@lists.infradead.org; Wood Scott-B07421;
> dedekind1@gmail.com; Lan Chunhe-B25806; linuxppc-dev@ozlabs.org; akpm@linux-
> foundation.org; dwmw2@infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with
> 36bit mode
> 
> On Mon, 13 Sep 2010 00:22:10 -0700
> "Zang Roy-R61911" <r61911@freescale.com> wrote:
> 
> >
> >
> > > -----Original Message-----
> > > From: geert.uytterhoeven@gmail.com [mailto:geert.uytterhoeven@gmail.com]
> On
> > > Behalf Of Geert Uytterhoeven
> > > Sent: Thursday, September 09, 2010 19:06 PM
> > > To: Zang Roy-R61911
> > > Cc: linux-mtd@lists.infradead.org; Wood Scott-B07421; dedekind1@gmail.com;
> Lan
> > > Chunhe-B25806; linuxppc-dev@ozlabs.org; akpm@linux-foundation.org;
> > > dwmw2@infradead.org; Gala Kumar-B11780
> > > Subject: Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue
> with
> > > 36bit mode
> > >
> > > On Thu, Sep 9, 2010 at 12:20, Roy Zang <tie-fei.zang@freescale.com> wrote:
> > > > From: Lan Chunhe-B25806 <b25806@freescale.com>
> > > >
> > > > When system uses 36bit physical address, res.start is 36bit
> > > > physical address. But the function of in_be32 returns 32bit
> > > > physical address. Then both of them compared each other is
> > > > wrong. So by converting the address of res.start into
> > > > the right format fixes this issue.
> > >
> > > >  /**
> > > > + * fsl_lbc_addr - convert the base address
> > > > + * @addr_base: base address of the memory bank
> > > > + *
> > > > + * This function converts a base address of lbc into the right format
> for
> > > the BR
> > > > + * registers. If the SOC has eLBC then it returns 32bit physical
> address
> > > else
> > > > + * it returns 34bit physical address for local bus(Example: MPC8641).
> > > > + */
> > > > +unsigned int fsl_lbc_addr(phys_addr_t addr_base)
> > >     ^^^^^^^^^^^^
> > > Shouldn't this be u32 or __be32, for consistency with the actual
> > > comparisons below?
> > __be32 is better.
> 
> I disagree, the return from this function is native-endian.  It should
> be u32.
But the return of this value is ONLY used for br comparing. It is big endia.
Thanks.
Roy 

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-13 14:27             ` Artem Bityutskiy
@ 2010-09-14  6:20               ` Zang Roy-R61911
  -1 siblings, 0 replies; 40+ messages in thread
From: Zang Roy-R61911 @ 2010-09-14  6:20 UTC (permalink / raw)
  To: dedekind1, Timur Tabi
  Cc: Wood Scott-B07421, Lan Chunhe-B25806, linuxppc-dev, linux-mtd,
	akpm, dwmw2, Gala Kumar-B11780

DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogQXJ0ZW0gQml0eXV0c2tp
eSBbbWFpbHRvOmRlZGVraW5kMUBnbWFpbC5jb21dDQo+IFNlbnQ6IE1vbmRheSwgU2VwdGVtYmVy
IDEzLCAyMDEwIDIyOjI4IFBNDQo+IFRvOiBUaW11ciBUYWJpDQo+IENjOiBaYW5nIFJveS1SNjE5
MTE7IEFudG9uIFZvcm9udHNvdjsgV29vZCBTY290dC1CMDc0MjE7IExhbiBDaHVuaGUtQjI1ODA2
Ow0KPiBsaW51eHBwYy1kZXZAb3psYWJzLm9yZzsgbGludXgtbXRkQGxpc3RzLmluZnJhZGVhZC5v
cmc7IGFrcG1AbGludXgtDQo+IGZvdW5kYXRpb24ub3JnOyBkd213MkBpbmZyYWRlYWQub3JnOyBH
YWxhIEt1bWFyLUIxMTc4MA0KPiBTdWJqZWN0OiBSZTogW1BBVENIIHYyIDMvM11bTVREXSBQNDA4
MC9tdGQ6IEZpeCB0aGUgZnJlZXNjYWxlIGxiYyBpc3N1ZSB3aXRoDQo+IDM2Yml0IG1vZGUNCj4g
DQo+IE9uIE1vbiwgMjAxMC0wOS0xMyBhdCAwOToxMCAtMDUwMCwgVGltdXIgVGFiaSB3cm90ZToN
Cj4gPiBPbiBNb24sIFNlcCAxMywgMjAxMCBhdCAyOjMwIEFNLCBaYW5nIFJveS1SNjE5MTEgPHI2
MTkxMUBmcmVlc2NhbGUuY29tPg0KPiB3cm90ZToNCj4gPg0KPiA+ID4gV2hhdCBpcyB0aGUgZGlm
ZmVyZW50IGZvciB1bnNpZ25lZCBpbnQgYW5kIHUzMj8gSSB0aGluayB0aGV5IGFyZSBzYW1lLg0K
PiA+DQo+ID4gUm95LCBwbGVhc2UgZG9uJ3QgZXZlciB3cml0ZSBjb2RlIHRoYXQgYXNzdW1lcyB0
aGF0IHNpemVvZihpbnQpID09IDQuDQo+ID4gVGhlcmUncyBhIHJlYXNvbiB3aHkgd2UgaGF2ZSB1
bnNpemVkIGludGVnZXIgdHlwZXMgKGxpa2UgaW50LCBsb25nLA0KPiA+IGFuZCBzaG9ydCkgYW5k
IHNpemVkIGludGVnZXIgdHlwZXMgKGxpa2UgdTgsIHUxNiwgdTMyKS4gIElmIHlvdSB3YW50DQo+
ID4gYW4gaW50ZWdlciBvZiBhIHNwZWNpZmljIHNpemUsIHlvdSBzaG91bGQgdXNlIGEgc2l6ZWQg
aW50ZWdlciB0eXBlLg0KPiANCj4gWWVzLCBzaXplb2YoaW50KSA9PSA0IGFzc3VtcHRpb24gaXMg
bm90IGdvb2QuDQo+IA0KPiBCdXQgc2l6ZW9mKGludCkgPj0gNCBpcyBwZXJmZWN0bHkgZmluZS4N
Cj4gDQo+IEl0IGlzIE9LIHRvIHJlbHkgb24gdGhlIGZhY3QgdGhhdCB1bnNpZ25lZCBpbnQgaXMg
X2F0IGxlYXN0XyAzMi1iaXQsIG5vdA0KPiBsZXNzLiBBbmQgaWYgeW91IGtub3cgMzIgYml0cyBp
cyBlbm91Z2gsIGFuZCB5b3UgYXJlIGZpbmUgd2l0aCBtb3JlLCBpdA0KPiBpcyBfYmV0dGVyXyB0
byBhdm9pZCB1MzIuIFNpbXBseSBiZWNhdXNlIHdpdGggdW5zaWduZWQgaW50IHlvdSBkbyBub3QN
Cj4gbGltaXQgdGhlIGNvbXBpbGVyIGFuZCBDUFUgYW5kIGxldCB0aGVtIHVzZSBuYXRpdmUgaW50
ZWdlcnMsIHJhdGhlciB0aGFuDQo+IHN0cmljdGx5IDMyLWJpdC4gVGhpcyBwb3RlbnRpYWxseSBn
aXZlcyB0aGUgY29tcGlsZXIgYW5kIENQVSBtb3JlIHJvb20NCj4gZm9yIG9wdGltaXphdGlvbi4N
Cj4gDQo+IEkgc2VlIHBlb3BsZSB1c2UgdTMyIGFuZCB0aGUgZnJpZW5kcyB0b28gbXVjaC4gSXQg
aXMgc2FmZSBhbmQgYmV0dGVyIHRvDQo+IHVzZSBuYXRpdmUgdHlwZXMsIHVubGVzcyB5b3UgcmVh
bGx5IGhhdmUgdG8gbWFrZSB0aGUgdmFyaWFibGUgdG8gYmUNCj4gc3RyaWN0bHkgdTMyLg0KPiAN
Cj4gSSBkaWQgbm90IGZvbGxvdyB0aGlzIHBhcnRpY3VsYXIgY29udmVyc2F0aW9uIGFuZCBkbyBu
b3QganVkZ2Ugd2hpY2gNCj4gdHlwZSBpcyBiZXR0ZXIgaW4gdGhpcyBjYXNlLiBJIGFtIHRhbGtp
bmcgaW4gZ2VuZXJhbC4gOi0pDQoNClRoZSBmdW5jdGlvbiB3aWxsIHJldHVybiBmaXhlZCAzMmJp
dC4gc28gdTMyIHNob3VsZCBiZSBPSy4NClRoYW5rcy4NClJveQ0K

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-14  6:20               ` Zang Roy-R61911
  0 siblings, 0 replies; 40+ messages in thread
From: Zang Roy-R61911 @ 2010-09-14  6:20 UTC (permalink / raw)
  To: dedekind1, Timur Tabi
  Cc: Wood Scott-B07421, Lan Chunhe-B25806, linuxppc-dev, linux-mtd,
	Anton Vorontsov, akpm, dwmw2, Gala Kumar-B11780



> -----Original Message-----
> From: Artem Bityutskiy [mailto:dedekind1@gmail.com]
> Sent: Monday, September 13, 2010 22:28 PM
> To: Timur Tabi
> Cc: Zang Roy-R61911; Anton Vorontsov; Wood Scott-B07421; Lan Chunhe-B25806;
> linuxppc-dev@ozlabs.org; linux-mtd@lists.infradead.org; akpm@linux-
> foundation.org; dwmw2@infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with
> 36bit mode
> 
> On Mon, 2010-09-13 at 09:10 -0500, Timur Tabi wrote:
> > On Mon, Sep 13, 2010 at 2:30 AM, Zang Roy-R61911 <r61911@freescale.com>
> wrote:
> >
> > > What is the different for unsigned int and u32? I think they are same.
> >
> > Roy, please don't ever write code that assumes that sizeof(int) == 4.
> > There's a reason why we have unsized integer types (like int, long,
> > and short) and sized integer types (like u8, u16, u32).  If you want
> > an integer of a specific size, you should use a sized integer type.
> 
> Yes, sizeof(int) == 4 assumption is not good.
> 
> But sizeof(int) >= 4 is perfectly fine.
> 
> It is OK to rely on the fact that unsigned int is _at least_ 32-bit, not
> less. And if you know 32 bits is enough, and you are fine with more, it
> is _better_ to avoid u32. Simply because with unsigned int you do not
> limit the compiler and CPU and let them use native integers, rather than
> strictly 32-bit. This potentially gives the compiler and CPU more room
> for optimization.
> 
> I see people use u32 and the friends too much. It is safe and better to
> use native types, unless you really have to make the variable to be
> strictly u32.
> 
> I did not follow this particular conversation and do not judge which
> type is better in this case. I am talking in general. :-)

The function will return fixed 32bit. so u32 should be OK.
Thanks.
Roy

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
  2010-09-14  4:09             ` Zang Roy-R61911
@ 2010-09-14 11:56               ` Timur Tabi
  -1 siblings, 0 replies; 40+ messages in thread
From: Timur Tabi @ 2010-09-14 11:56 UTC (permalink / raw)
  To: Zang Roy-R61911
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	Geert Uytterhoeven, linux-mtd, akpm, dwmw2, Gala Kumar-B11780

On Mon, Sep 13, 2010 at 11:09 PM, Zang Roy-R61911 <r61911@freescale.com> wr=
ote:

>> > > Shouldn't this be u32 or __be32, for consistency with the actual
>> > > comparisons below?
>> > __be32 is better.
>>
>> I disagree, the return from this function is native-endian. =A0It should
>> be u32.
> But the return of this value is ONLY used for br comparing. It is big end=
ia.
> Thanks.

No, Scott is right.  The return value is native-endian (NE).  You've
converted it from BE to NE already.

--=20
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode
@ 2010-09-14 11:56               ` Timur Tabi
  0 siblings, 0 replies; 40+ messages in thread
From: Timur Tabi @ 2010-09-14 11:56 UTC (permalink / raw)
  To: Zang Roy-R61911
  Cc: Wood Scott-B07421, dedekind1, Lan Chunhe-B25806, linuxppc-dev,
	Geert Uytterhoeven, linux-mtd, akpm, dwmw2, Gala Kumar-B11780

On Mon, Sep 13, 2010 at 11:09 PM, Zang Roy-R61911 <r61911@freescale.com> wrote:

>> > > Shouldn't this be u32 or __be32, for consistency with the actual
>> > > comparisons below?
>> > __be32 is better.
>>
>> I disagree, the return from this function is native-endian.  It should
>> be u32.
> But the return of this value is ONLY used for br comparing. It is big endia.
> Thanks.

No, Scott is right.  The return value is native-endian (NE).  You've
converted it from BE to NE already.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2010-09-14 11:57 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-09 10:20 [PATCH 1/3 v2][MTD] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices Roy Zang
2010-09-09 10:20 ` Roy Zang
2010-09-09 10:20 ` [PATCH 2/3 v2][MTD] P4080/mtd: Only make elbc nand driver detect nand flash partitions Roy Zang
2010-09-09 10:20   ` Roy Zang
2010-09-09 10:20   ` [PATCH v2 3/3][MTD] P4080/mtd: Fix the freescale lbc issue with 36bit mode Roy Zang
2010-09-09 10:20     ` Roy Zang
2010-09-09 11:06     ` Geert Uytterhoeven
2010-09-09 11:06       ` Geert Uytterhoeven
2010-09-13  7:22       ` Zang Roy-R61911
2010-09-13  7:22         ` Zang Roy-R61911
2010-09-13 16:27         ` Scott Wood
2010-09-13 16:27           ` Scott Wood
2010-09-14  4:09           ` Zang Roy-R61911
2010-09-14  4:09             ` Zang Roy-R61911
2010-09-14 11:56             ` Timur Tabi
2010-09-14 11:56               ` Timur Tabi
2010-09-09 11:41     ` Anton Vorontsov
2010-09-13  7:30       ` Zang Roy-R61911
2010-09-13  7:30         ` Zang Roy-R61911
2010-09-13 14:10         ` Timur Tabi
2010-09-13 14:10           ` Timur Tabi
2010-09-13 14:27           ` Artem Bityutskiy
2010-09-13 14:27             ` Artem Bityutskiy
2010-09-13 14:35             ` Timur Tabi
2010-09-13 14:35               ` Timur Tabi
2010-09-13 16:45               ` Artem Bityutskiy
2010-09-13 16:45                 ` Artem Bityutskiy
2010-09-13 18:36                 ` Timur Tabi
2010-09-13 18:36                   ` Timur Tabi
2010-09-13 18:46                   ` Artem Bityutskiy
2010-09-13 18:46                     ` Artem Bityutskiy
2010-09-13 20:04                   ` Scott Wood
2010-09-13 20:04                     ` Scott Wood
2010-09-14  6:20             ` Zang Roy-R61911
2010-09-14  6:20               ` Zang Roy-R61911
2010-09-09 11:23   ` [PATCH 2/3 v2][MTD] P4080/mtd: Only make elbc nand driver detect nand flash partitions Anton Vorontsov
2010-09-09 11:53 ` [PATCH 1/3 v2][MTD] P4080/eLBC: Make Freescale elbc interrupt common to elbc devices Anton Vorontsov
2010-09-10  6:58   ` Zang Roy-R61911
2010-09-10  6:58     ` Zang Roy-R61911
2010-09-10  9:31     ` Anton Vorontsov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.