* [PATCH] ndfc driver
@ 2008-10-30 6:08 Sean MacLennan
0 siblings, 0 replies; 28+ messages in thread
From: Sean MacLennan @ 2008-10-30 6:08 UTC (permalink / raw)
To: linux-mtd; +Cc: linuxppc-dev, dwmw2
The current ndfc driver only compiles under arch/ppc. This arch was
merged with arch/powerpc and then removed from the kernel. I notice the
entry for the ndfc in Kconfig has been removed in 2.6.28.
This patch converts the ndfc to a proper OF (OpenFirmware) driver. I
can give a working example of the DTS if needed.
The patch has been in production use on the PIKA Warp Appliance. The
Warp basically boots from NAND, so the ndfc driver is very important to
us.
Cheers,
Sean MacLennan
Port of the ndfc driver to an of platform driver.
Signed-off-by: Sean MacLennan <smaclennan@pikatech.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1c2e945..5705f85 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -163,6 +163,13 @@ config MTD_NAND_S3C2410_HWECC
incorrect ECC generation, and if using these, the default of
software ECC is preferable.
+config MTD_NAND_NDFC
+ tristate "NDFC NanD Flash Controller"
+ depends on 4xx
+ select MTD_NAND_ECC_SMC
+ help
+ NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
+
config MTD_NAND_S3C2410_CLKSTOP
bool "S3C2410 NAND IDLE clock stop"
depends on MTD_NAND_S3C2410
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 955959e..0352d5c 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -5,9 +5,13 @@
* Platform independend driver for NDFC (NanD Flash Controller)
* integrated into EP440 cores
*
+ * Ported to an OF platform driver by Sean MacLennan
+ *
* Author: Thomas Gleixner
*
* Copyright 2006 IBM
+ * Copyright 2008 PIKA Technologies
+ * Sean MacLennan <smaclennan@pikatech.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 the
@@ -21,27 +25,17 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/ndfc.h>
#include <linux/mtd/mtd.h>
-#include <linux/platform_device.h>
-
+#include <linux/of_platform.h>
#include <asm/io.h>
-#ifdef CONFIG_40x
-#include <asm/ibm405.h>
-#else
-#include <asm/ibm44x.h>
-#endif
-
-struct ndfc_nand_mtd {
- struct mtd_info mtd;
- struct nand_chip chip;
- struct platform_nand_chip *pl_chip;
-};
-static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS];
struct ndfc_controller {
- void __iomem *ndfcbase;
- struct nand_hw_control ndfc_control;
- atomic_t childs_active;
+ struct of_device *ofdev;
+ void __iomem *ndfcbase;
+ struct mtd_info mtd;
+ struct nand_chip chip;
+ int chip_select;
+ struct nand_hw_control ndfc_control;
};
static struct ndfc_controller ndfc_ctrl;
@@ -50,17 +44,14 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
{
uint32_t ccr;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct nand_chip *nandchip = mtd->priv;
- struct ndfc_nand_mtd *nandmtd = nandchip->priv;
- struct platform_nand_chip *pchip = nandmtd->pl_chip;
- ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+ ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
if (chip >= 0) {
ccr &= ~NDFC_CCR_BS_MASK;
- ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
+ ccr |= NDFC_CCR_BS(chip + ndfc->chip_select);
} else
ccr |= NDFC_CCR_RESET_CE;
- __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
}
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
@@ -80,7 +71,7 @@ static int ndfc_ready(struct mtd_info *mtd)
{
struct ndfc_controller *ndfc = &ndfc_ctrl;
- return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
+ return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
}
static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
@@ -88,9 +79,9 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
uint32_t ccr;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+ ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
ccr |= NDFC_CCR_RESET_ECC;
- __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
wmb();
}
@@ -102,9 +93,10 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
uint8_t *p = (uint8_t *)&ecc;
wmb();
- ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC);
- ecc_code[0] = p[1];
- ecc_code[1] = p[2];
+ ecc = in_be32(ndfc->ndfcbase + NDFC_ECC);
+ /* The NDFC uses Smart Media (SMC) bytes order */
+ ecc_code[0] = p[2];
+ ecc_code[1] = p[1];
ecc_code[2] = p[3];
return 0;
@@ -123,7 +115,7 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA);
+ *p++ = in_be32(ndfc->ndfcbase + NDFC_DATA);
}
static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
@@ -132,7 +124,7 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA);
+ out_be32(ndfc->ndfcbase + NDFC_DATA, *p++);
}
static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
@@ -141,7 +133,7 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA))
+ if (*p++ != in_be32(ndfc->ndfcbase + NDFC_DATA))
return -EFAULT;
return 0;
}
@@ -149,10 +141,19 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
/*
* Initialize chip structure
*/
-static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
+static int ndfc_chip_init(struct ndfc_controller *ndfc,
+ struct device_node *node)
{
- struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct nand_chip *chip = &mtd->chip;
+#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ static const char *part_types[] = { "cmdlinepart", NULL };
+#else
+ static const char *part_types[] = { NULL };
+#endif
+ struct mtd_partition *parts;
+#endif
+ struct nand_chip *chip = &ndfc->chip;
+ int ret;
chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
@@ -160,8 +161,6 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip->dev_ready = ndfc_ready;
chip->select_chip = ndfc_select_chip;
chip->chip_delay = 50;
- chip->priv = mtd;
- chip->options = mtd->pl_chip->options;
chip->controller = &ndfc->ndfc_control;
chip->read_buf = ndfc_read_buf;
chip->write_buf = ndfc_write_buf;
@@ -172,143 +171,120 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = 256;
chip->ecc.bytes = 3;
- chip->ecclayout = chip->ecc.layout = mtd->pl_chip->ecclayout;
- mtd->mtd.priv = chip;
- mtd->mtd.owner = THIS_MODULE;
-}
-
-static int ndfc_chip_probe(struct platform_device *pdev)
-{
- struct platform_nand_chip *nc = pdev->dev.platform_data;
- struct ndfc_chip_settings *settings = nc->priv;
- struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct ndfc_nand_mtd *nandmtd;
-
- if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS)
- return -EINVAL;
- /* Set the bank settings */
- __raw_writel(settings->bank_settings,
- ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2));
+ ndfc->mtd.priv = chip;
+ ndfc->mtd.owner = THIS_MODULE;
- nandmtd = &ndfc_mtd[pdev->id];
- if (nandmtd->pl_chip)
- return -EBUSY;
+ ret = nand_scan(&ndfc->mtd, 1);
+ if (ret)
+ return ret;
- nandmtd->pl_chip = nc;
- ndfc_chip_init(nandmtd);
-
- /* Scan for chips */
- if (nand_scan(&nandmtd->mtd, nc->nr_chips)) {
- nandmtd->pl_chip = NULL;
- return -ENODEV;
- }
+ ndfc->mtd.name = ndfc->ofdev->dev.bus_id;
#ifdef CONFIG_MTD_PARTITIONS
- printk("Number of partitions %d\n", nc->nr_partitions);
- if (nc->nr_partitions) {
- /* Add the full device, so complete dumps can be made */
- add_mtd_device(&nandmtd->mtd);
- add_mtd_partitions(&nandmtd->mtd, nc->partitions,
- nc->nr_partitions);
-
- } else
-#else
- add_mtd_device(&nandmtd->mtd);
+ ret = parse_mtd_partitions(&ndfc->mtd, part_types, &parts, 0);
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_MTD_OF_PARTS
+ if (ret == 0) {
+ ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, node, &parts);
+ if (ret < 0)
+ return ret;
+ }
#endif
- atomic_inc(&ndfc->childs_active);
- return 0;
-}
+ if (ret > 0)
+ return add_mtd_partitions(&ndfc->mtd, parts, ret);
+#endif
-static int ndfc_chip_remove(struct platform_device *pdev)
-{
- return 0;
+ return add_mtd_device(&ndfc->mtd);
}
-static int ndfc_nand_probe(struct platform_device *pdev)
+static int __devinit ndfc_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
{
- struct platform_nand_ctrl *nc = pdev->dev.platform_data;
- struct ndfc_controller_settings *settings = nc->priv;
- struct resource *res = pdev->resource;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- unsigned long long phys = settings->ndfc_erpn | res->start;
+ const u32 *reg;
+ u32 ccr;
+ int err, len;
-#ifndef CONFIG_PHYS_64BIT
- ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
-#else
- ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
-#endif
+ spin_lock_init(&ndfc->ndfc_control.lock);
+ init_waitqueue_head(&ndfc->ndfc_control.wq);
+ ndfc->ofdev = ofdev;
+ dev_set_drvdata(&ofdev->dev, ndfc);
+
+ /* Read the reg property to get the chip select */
+ reg = of_get_property(ofdev->node, "reg", &len);
+ if (reg == NULL || len != 12) {
+ dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
+ return -ENOENT;
+ }
+ ndfc->chip_select = reg[0];
+
+ ndfc->ndfcbase = of_iomap(ofdev->node, 0);
if (!ndfc->ndfcbase) {
- printk(KERN_ERR "NDFC: ioremap failed\n");
+ dev_err(&ofdev->dev, "failed to get memory\n");
return -EIO;
}
- __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR);
+ ccr = NDFC_CCR_BS(ndfc->chip_select);
- spin_lock_init(&ndfc->ndfc_control.lock);
- init_waitqueue_head(&ndfc->ndfc_control.wq);
+ /* It is ok if ccr does not exist - just default to 0 */
+ reg = of_get_property(ofdev->node, "ccr", NULL);
+ if (reg)
+ ccr |= *reg;
+
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
- platform_set_drvdata(pdev, ndfc);
+ /* Set the bank settings if given */
+ reg = of_get_property(ofdev->node, "bank-settings", NULL);
+ if (reg) {
+ int offset = NDFC_BCFG0 + (ndfc->chip_select << 2);
+ out_be32(ndfc->ndfcbase + offset, *reg);
+ }
- printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n",
- __raw_readl(ndfc->ndfcbase + NDFC_REVID));
+ err = ndfc_chip_init(ndfc, ofdev->node);
+ if (err) {
+ iounmap(ndfc->ndfcbase);
+ return err;
+ }
return 0;
}
-static int ndfc_nand_remove(struct platform_device *pdev)
+static int __devexit ndfc_remove(struct of_device *ofdev)
{
- struct ndfc_controller *ndfc = platform_get_drvdata(pdev);
+ struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
- if (atomic_read(&ndfc->childs_active))
- return -EBUSY;
+ nand_release(&ndfc->mtd);
- if (ndfc) {
- platform_set_drvdata(pdev, NULL);
- iounmap(ndfc_ctrl.ndfcbase);
- ndfc_ctrl.ndfcbase = NULL;
- }
return 0;
}
-/* driver device registration */
-
-static struct platform_driver ndfc_chip_driver = {
- .probe = ndfc_chip_probe,
- .remove = ndfc_chip_remove,
- .driver = {
- .name = "ndfc-chip",
- .owner = THIS_MODULE,
- },
+static const struct of_device_id ndfc_match[] = {
+ { .compatible = "amcc,ndfc", },
+ {}
};
+MODULE_DEVICE_TABLE(of, ndfc_match);
-static struct platform_driver ndfc_nand_driver = {
- .probe = ndfc_nand_probe,
- .remove = ndfc_nand_remove,
- .driver = {
- .name = "ndfc-nand",
- .owner = THIS_MODULE,
+static struct of_platform_driver ndfc_driver = {
+ .driver = {
+ .name = "ndfc",
},
+ .match_table = ndfc_match,
+ .probe = ndfc_probe,
+ .remove = __devexit_p(ndfc_remove),
};
static int __init ndfc_nand_init(void)
{
- int ret;
-
- spin_lock_init(&ndfc_ctrl.ndfc_control.lock);
- init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq);
-
- ret = platform_driver_register(&ndfc_nand_driver);
- if (!ret)
- ret = platform_driver_register(&ndfc_chip_driver);
- return ret;
+ return of_register_platform_driver(&ndfc_driver);
}
static void __exit ndfc_nand_exit(void)
{
- platform_driver_unregister(&ndfc_chip_driver);
- platform_driver_unregister(&ndfc_nand_driver);
+ of_unregister_platform_driver(&ndfc_driver);
}
module_init(ndfc_nand_init);
@@ -316,6 +292,4 @@ module_exit(ndfc_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION("Platform driver for NDFC");
-MODULE_ALIAS("platform:ndfc-chip");
-MODULE_ALIAS("platform:ndfc-nand");
+MODULE_DESCRIPTION("OF Platform driver for NDFC");
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH] ndfc driver
@ 2008-12-04 3:28 Sean MacLennan
2008-12-04 14:01 ` Josh Boyer
0 siblings, 1 reply; 28+ messages in thread
From: Sean MacLennan @ 2008-12-04 3:28 UTC (permalink / raw)
To: linux-mtd
The current ndfc driver only compiles under arch/ppc. This arch was
removed from the kernel. I notice the event entry for the ndfc in
Kconfig has been removed in 2.6.28.
This patch converts the ndfc to a proper OF (OpenFirmware) driver. I
can give a working example of the DTS if needed.
The patch has been in production use on the PIKA Warp Appliance and is
in use by others. The Warp basically boots from NAND, so the ndfc driver
is very important to us.
This is a bi-monthly posting ;)
Cheers,
Sean MacLennan
Port of the ndfc driver to an of platform driver.
Signed-off-by: Sean MacLennan <smaclennan@pikatech.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1c2e945..5705f85 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -163,6 +163,13 @@ config MTD_NAND_S3C2410_HWECC
incorrect ECC generation, and if using these, the default of
software ECC is preferable.
+config MTD_NAND_NDFC
+ tristate "NDFC NanD Flash Controller"
+ depends on 4xx
+ select MTD_NAND_ECC_SMC
+ help
+ NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
+
config MTD_NAND_S3C2410_CLKSTOP
bool "S3C2410 NAND IDLE clock stop"
depends on MTD_NAND_S3C2410
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 955959e..0352d5c 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -5,9 +5,13 @@
* Platform independend driver for NDFC (NanD Flash Controller)
* integrated into EP440 cores
*
+ * Ported to an OF platform driver by Sean MacLennan
+ *
* Author: Thomas Gleixner
*
* Copyright 2006 IBM
+ * Copyright 2008 PIKA Technologies
+ * Sean MacLennan <smaclennan@pikatech.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 the
@@ -21,27 +25,17 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/ndfc.h>
#include <linux/mtd/mtd.h>
-#include <linux/platform_device.h>
-
+#include <linux/of_platform.h>
#include <asm/io.h>
-#ifdef CONFIG_40x
-#include <asm/ibm405.h>
-#else
-#include <asm/ibm44x.h>
-#endif
-
-struct ndfc_nand_mtd {
- struct mtd_info mtd;
- struct nand_chip chip;
- struct platform_nand_chip *pl_chip;
-};
-static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS];
struct ndfc_controller {
- void __iomem *ndfcbase;
- struct nand_hw_control ndfc_control;
- atomic_t childs_active;
+ struct of_device *ofdev;
+ void __iomem *ndfcbase;
+ struct mtd_info mtd;
+ struct nand_chip chip;
+ int chip_select;
+ struct nand_hw_control ndfc_control;
};
static struct ndfc_controller ndfc_ctrl;
@@ -50,17 +44,14 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
{
uint32_t ccr;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct nand_chip *nandchip = mtd->priv;
- struct ndfc_nand_mtd *nandmtd = nandchip->priv;
- struct platform_nand_chip *pchip = nandmtd->pl_chip;
- ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+ ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
if (chip >= 0) {
ccr &= ~NDFC_CCR_BS_MASK;
- ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
+ ccr |= NDFC_CCR_BS(chip + ndfc->chip_select);
} else
ccr |= NDFC_CCR_RESET_CE;
- __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
}
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
@@ -80,7 +71,7 @@ static int ndfc_ready(struct mtd_info *mtd)
{
struct ndfc_controller *ndfc = &ndfc_ctrl;
- return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
+ return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
}
static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
@@ -88,9 +79,9 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
uint32_t ccr;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+ ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
ccr |= NDFC_CCR_RESET_ECC;
- __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
wmb();
}
@@ -102,9 +93,10 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
uint8_t *p = (uint8_t *)&ecc;
wmb();
- ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC);
- ecc_code[0] = p[1];
- ecc_code[1] = p[2];
+ ecc = in_be32(ndfc->ndfcbase + NDFC_ECC);
+ /* The NDFC uses Smart Media (SMC) bytes order */
+ ecc_code[0] = p[2];
+ ecc_code[1] = p[1];
ecc_code[2] = p[3];
return 0;
@@ -123,7 +115,7 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA);
+ *p++ = in_be32(ndfc->ndfcbase + NDFC_DATA);
}
static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
@@ -132,7 +124,7 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA);
+ out_be32(ndfc->ndfcbase + NDFC_DATA, *p++);
}
static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
@@ -141,7 +133,7 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA))
+ if (*p++ != in_be32(ndfc->ndfcbase + NDFC_DATA))
return -EFAULT;
return 0;
}
@@ -149,10 +141,19 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
/*
* Initialize chip structure
*/
-static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
+static int ndfc_chip_init(struct ndfc_controller *ndfc,
+ struct device_node *node)
{
- struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct nand_chip *chip = &mtd->chip;
+#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ static const char *part_types[] = { "cmdlinepart", NULL };
+#else
+ static const char *part_types[] = { NULL };
+#endif
+ struct mtd_partition *parts;
+#endif
+ struct nand_chip *chip = &ndfc->chip;
+ int ret;
chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
@@ -160,8 +161,6 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip->dev_ready = ndfc_ready;
chip->select_chip = ndfc_select_chip;
chip->chip_delay = 50;
- chip->priv = mtd;
- chip->options = mtd->pl_chip->options;
chip->controller = &ndfc->ndfc_control;
chip->read_buf = ndfc_read_buf;
chip->write_buf = ndfc_write_buf;
@@ -172,143 +171,120 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = 256;
chip->ecc.bytes = 3;
- chip->ecclayout = chip->ecc.layout = mtd->pl_chip->ecclayout;
- mtd->mtd.priv = chip;
- mtd->mtd.owner = THIS_MODULE;
-}
-
-static int ndfc_chip_probe(struct platform_device *pdev)
-{
- struct platform_nand_chip *nc = pdev->dev.platform_data;
- struct ndfc_chip_settings *settings = nc->priv;
- struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct ndfc_nand_mtd *nandmtd;
-
- if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS)
- return -EINVAL;
- /* Set the bank settings */
- __raw_writel(settings->bank_settings,
- ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2));
+ ndfc->mtd.priv = chip;
+ ndfc->mtd.owner = THIS_MODULE;
- nandmtd = &ndfc_mtd[pdev->id];
- if (nandmtd->pl_chip)
- return -EBUSY;
+ ret = nand_scan(&ndfc->mtd, 1);
+ if (ret)
+ return ret;
- nandmtd->pl_chip = nc;
- ndfc_chip_init(nandmtd);
-
- /* Scan for chips */
- if (nand_scan(&nandmtd->mtd, nc->nr_chips)) {
- nandmtd->pl_chip = NULL;
- return -ENODEV;
- }
+ ndfc->mtd.name = ndfc->ofdev->dev.bus_id;
#ifdef CONFIG_MTD_PARTITIONS
- printk("Number of partitions %d\n", nc->nr_partitions);
- if (nc->nr_partitions) {
- /* Add the full device, so complete dumps can be made */
- add_mtd_device(&nandmtd->mtd);
- add_mtd_partitions(&nandmtd->mtd, nc->partitions,
- nc->nr_partitions);
-
- } else
-#else
- add_mtd_device(&nandmtd->mtd);
+ ret = parse_mtd_partitions(&ndfc->mtd, part_types, &parts, 0);
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_MTD_OF_PARTS
+ if (ret == 0) {
+ ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, node, &parts);
+ if (ret < 0)
+ return ret;
+ }
#endif
- atomic_inc(&ndfc->childs_active);
- return 0;
-}
+ if (ret > 0)
+ return add_mtd_partitions(&ndfc->mtd, parts, ret);
+#endif
-static int ndfc_chip_remove(struct platform_device *pdev)
-{
- return 0;
+ return add_mtd_device(&ndfc->mtd);
}
-static int ndfc_nand_probe(struct platform_device *pdev)
+static int __devinit ndfc_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
{
- struct platform_nand_ctrl *nc = pdev->dev.platform_data;
- struct ndfc_controller_settings *settings = nc->priv;
- struct resource *res = pdev->resource;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- unsigned long long phys = settings->ndfc_erpn | res->start;
+ const u32 *reg;
+ u32 ccr;
+ int err, len;
-#ifndef CONFIG_PHYS_64BIT
- ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
-#else
- ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
-#endif
+ spin_lock_init(&ndfc->ndfc_control.lock);
+ init_waitqueue_head(&ndfc->ndfc_control.wq);
+ ndfc->ofdev = ofdev;
+ dev_set_drvdata(&ofdev->dev, ndfc);
+
+ /* Read the reg property to get the chip select */
+ reg = of_get_property(ofdev->node, "reg", &len);
+ if (reg == NULL || len != 12) {
+ dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
+ return -ENOENT;
+ }
+ ndfc->chip_select = reg[0];
+
+ ndfc->ndfcbase = of_iomap(ofdev->node, 0);
if (!ndfc->ndfcbase) {
- printk(KERN_ERR "NDFC: ioremap failed\n");
+ dev_err(&ofdev->dev, "failed to get memory\n");
return -EIO;
}
- __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR);
+ ccr = NDFC_CCR_BS(ndfc->chip_select);
- spin_lock_init(&ndfc->ndfc_control.lock);
- init_waitqueue_head(&ndfc->ndfc_control.wq);
+ /* It is ok if ccr does not exist - just default to 0 */
+ reg = of_get_property(ofdev->node, "ccr", NULL);
+ if (reg)
+ ccr |= *reg;
+
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
- platform_set_drvdata(pdev, ndfc);
+ /* Set the bank settings if given */
+ reg = of_get_property(ofdev->node, "bank-settings", NULL);
+ if (reg) {
+ int offset = NDFC_BCFG0 + (ndfc->chip_select << 2);
+ out_be32(ndfc->ndfcbase + offset, *reg);
+ }
- printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n",
- __raw_readl(ndfc->ndfcbase + NDFC_REVID));
+ err = ndfc_chip_init(ndfc, ofdev->node);
+ if (err) {
+ iounmap(ndfc->ndfcbase);
+ return err;
+ }
return 0;
}
-static int ndfc_nand_remove(struct platform_device *pdev)
+static int __devexit ndfc_remove(struct of_device *ofdev)
{
- struct ndfc_controller *ndfc = platform_get_drvdata(pdev);
+ struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
- if (atomic_read(&ndfc->childs_active))
- return -EBUSY;
+ nand_release(&ndfc->mtd);
- if (ndfc) {
- platform_set_drvdata(pdev, NULL);
- iounmap(ndfc_ctrl.ndfcbase);
- ndfc_ctrl.ndfcbase = NULL;
- }
return 0;
}
-/* driver device registration */
-
-static struct platform_driver ndfc_chip_driver = {
- .probe = ndfc_chip_probe,
- .remove = ndfc_chip_remove,
- .driver = {
- .name = "ndfc-chip",
- .owner = THIS_MODULE,
- },
+static const struct of_device_id ndfc_match[] = {
+ { .compatible = "amcc,ndfc", },
+ {}
};
+MODULE_DEVICE_TABLE(of, ndfc_match);
-static struct platform_driver ndfc_nand_driver = {
- .probe = ndfc_nand_probe,
- .remove = ndfc_nand_remove,
- .driver = {
- .name = "ndfc-nand",
- .owner = THIS_MODULE,
+static struct of_platform_driver ndfc_driver = {
+ .driver = {
+ .name = "ndfc",
},
+ .match_table = ndfc_match,
+ .probe = ndfc_probe,
+ .remove = __devexit_p(ndfc_remove),
};
static int __init ndfc_nand_init(void)
{
- int ret;
-
- spin_lock_init(&ndfc_ctrl.ndfc_control.lock);
- init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq);
-
- ret = platform_driver_register(&ndfc_nand_driver);
- if (!ret)
- ret = platform_driver_register(&ndfc_chip_driver);
- return ret;
+ return of_register_platform_driver(&ndfc_driver);
}
static void __exit ndfc_nand_exit(void)
{
- platform_driver_unregister(&ndfc_chip_driver);
- platform_driver_unregister(&ndfc_nand_driver);
+ of_unregister_platform_driver(&ndfc_driver);
}
module_init(ndfc_nand_init);
@@ -316,6 +292,4 @@ module_exit(ndfc_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION("Platform driver for NDFC");
-MODULE_ALIAS("platform:ndfc-chip");
-MODULE_ALIAS("platform:ndfc-nand");
+MODULE_DESCRIPTION("OF Platform driver for NDFC");
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-04 3:28 Sean MacLennan
@ 2008-12-04 14:01 ` Josh Boyer
2008-12-04 17:17 ` Sean MacLennan
` (2 more replies)
0 siblings, 3 replies; 28+ messages in thread
From: Josh Boyer @ 2008-12-04 14:01 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linuxppc-dev, linux-mtd
On Wed, 3 Dec 2008 22:28:32 -0500
Sean MacLennan <smaclennan@pikatech.com> wrote:
Hi Sean,
A couple of comments/requests below.
> The current ndfc driver only compiles under arch/ppc. This arch was
> removed from the kernel. I notice the event entry for the ndfc in
> Kconfig has been removed in 2.6.28.
>
> This patch converts the ndfc to a proper OF (OpenFirmware) driver. I
> can give a working example of the DTS if needed.
In addition to an example DTS patch (probably to warp itself), could
you briefly write up a binding and put it in
Documentation/powerpc/dts-bindings/amcc (or similar)? Also please CC
the devicetree-discuss list on that part.
> The patch has been in production use on the PIKA Warp Appliance and is
> in use by others. The Warp basically boots from NAND, so the ndfc driver
> is very important to us.
Looking over the patch it seems pretty straight-forward and I don't see
anything immediately wrong with it. You do have a number of
semi-unrelated changes to the actual port to of_platform though, like
the s/__raw_writel/out_be32 stuff, the addition of partition parsing,
etc. I'm wondering if you could do those fixups separately from the
actual port.
Also, could you document why the data structures changed as they did in
the changelog or perhaps in a summary email.
You also seem to only support a single NAND chip, however the NDFC can
support multiple chips. Have you looked at how the the fsl_elbc_nand
driver does multiple chip support? If not, could you at least document
the limitation in the patch?
> This is a bi-monthly posting ;)
Keep at it Sean. Your work is appreciated, even if the rest of us are
slow to review.
josh
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-04 14:01 ` Josh Boyer
@ 2008-12-04 17:17 ` Sean MacLennan
2008-12-09 0:34 ` Sean MacLennan
2008-12-09 0:51 ` Sean MacLennan
2 siblings, 0 replies; 28+ messages in thread
From: Sean MacLennan @ 2008-12-04 17:17 UTC (permalink / raw)
To: Josh Boyer, linux-mtd, linuxppc-dev
On Thu, 4 Dec 2008 09:01:07 -0500
"Josh Boyer" <jwboyer@linux.vnet.ibm.com> wrote:
> On Wed, 3 Dec 2008 22:28:32 -0500
> Sean MacLennan <smaclennan@pikatech.com> wrote:
>
> Hi Sean,
>
> A couple of comments/requests below.
>
> In addition to an example DTS patch (probably to warp itself), could
> you briefly write up a binding and put it in
> Documentation/powerpc/dts-bindings/amcc (or similar)? Also please CC
> the devicetree-discuss list on that part.
The DTS patch was a separate email to the linuxppc-dev list. I'll try to
find it.
I will look into writing up the binding.
> Looking over the patch it seems pretty straight-forward and I don't
> see anything immediately wrong with it. You do have a number of
> semi-unrelated changes to the actual port to of_platform though, like
> the s/__raw_writel/out_be32 stuff, the addition of partition parsing,
> etc. I'm wondering if you could do those fixups separately from the
> actual port.
>
> Also, could you document why the data structures changed as they did
> in the changelog or perhaps in a summary email.
The __raw_writel changes where from feedback from this list. I will try
to find the email.
This patch originally goes back to January... so I have problems
remembering why all the changes where made ;) Believe it or not, we
have gone through 3 or 4 repositories since then. Finding history is
basically impossible :( So I have to try to rely on an email trail.
> You also seem to only support a single NAND chip, however the NDFC can
> support multiple chips. Have you looked at how the the fsl_elbc_nand
> driver does multiple chip support? If not, could you at least
> document the limitation in the patch?
I will document the limitation. I do not have access to a board with
multiple chips and I don't like submitting something I can't test.
Cheers,
Sean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-04 14:01 ` Josh Boyer
2008-12-04 17:17 ` Sean MacLennan
@ 2008-12-09 0:34 ` Sean MacLennan
2008-12-09 2:11 ` Anton Vorontsov
2008-12-09 6:10 ` Stefan Roese
2008-12-09 0:51 ` Sean MacLennan
2 siblings, 2 replies; 28+ messages in thread
From: Sean MacLennan @ 2008-12-09 0:34 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev, devicetree-discuss, linux-mtd
On Thu, 4 Dec 2008 09:01:07 -0500
"Josh Boyer" <jwboyer@linux.vnet.ibm.com> wrote:
> In addition to an example DTS patch (probably to warp itself), could
> you briefly write up a binding and put it in
> Documentation/powerpc/dts-bindings/amcc (or similar)? Also please CC
> the devicetree-discuss list on that part.
Here is a start at the doc. I have sent it as a patch, but could just
as easily send raw text.
The example comes from the warp dts, just with less partitions, so I
have not included a warp dts patch here.
Cheers,
Sean
diff --git a/Documentation/powerpc/dts-bindings/amcc/ndfc.txt
b/Documentation/powerpc/dts-bindings/amcc/ndfc.txt new file mode 100644
index 0000000..668f4a9
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/amcc/ndfc.txt
@@ -0,0 +1,31 @@
+AMCC NDFC (NanD Flash Controller)
+
+Required properties:
+- compatible : "amcc,ndfc".
+- reg : should specify chip select and size used for the chip (0x2000).
+
+Optional properties:
+- ccr : NDFC config and control register value (default 0).
+- bank-settings : NDFC bank configuration register value (default 0).
+- partition(s) - follows the OF MTD standard for partitions
+
+Example:
+
+nand@1,0 {
+ compatible = "amcc,ndfc";
+ reg = <0x00000001 0x00000000 0x00002000>;
+ ccr = <0x00001000>;
+ bank-settings = <0x80002222>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "kernel";
+ reg = <0x00000000 0x00200000>;
+ };
+ partition@200000 {
+ label = "root";
+ reg = <0x00200000 0x03E00000>;
+ };
+};
+
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-04 14:01 ` Josh Boyer
2008-12-04 17:17 ` Sean MacLennan
2008-12-09 0:34 ` Sean MacLennan
@ 2008-12-09 0:51 ` Sean MacLennan
2 siblings, 0 replies; 28+ messages in thread
From: Sean MacLennan @ 2008-12-09 0:51 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev, linux-mtd
On Thu, 4 Dec 2008 09:01:07 -0500
"Josh Boyer" <jwboyer@linux.vnet.ibm.com> wrote:
> You also seem to only support a single NAND chip, however the NDFC can
> support multiple chips. Have you looked at how the the fsl_elbc_nand
> driver does multiple chip support? If not, could you at least
> document the limitation in the patch?
Signed-off-by: Sean MacLennan <smaclennan@pikatech.com>
---
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 0352d5c..3dd85e8 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -2,11 +2,15 @@
* drivers/mtd/ndfc.c
*
* Overview:
- * Platform independend driver for NDFC (NanD Flash Controller)
+ * Platform independent driver for NDFC (NanD Flash Controller)
* integrated into EP440 cores
*
* Ported to an OF platform driver by Sean MacLennan
*
+ * The NDFC supports multiple chips, but this driver only supports a
+ * single chip since I do not have access to any boards with
+ * multiple chips.
+ *
* Author: Thomas Gleixner
*
* Copyright 2006 IBM
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-09 0:34 ` Sean MacLennan
@ 2008-12-09 2:11 ` Anton Vorontsov
2008-12-09 2:45 ` Sean MacLennan
2008-12-09 6:10 ` Stefan Roese
1 sibling, 1 reply; 28+ messages in thread
From: Anton Vorontsov @ 2008-12-09 2:11 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linuxppc-dev, devicetree-discuss, linux-mtd
Hi Sean,
On Mon, Dec 08, 2008 at 07:34:46PM -0500, Sean MacLennan wrote:
> On Thu, 4 Dec 2008 09:01:07 -0500
> "Josh Boyer" <jwboyer@linux.vnet.ibm.com> wrote:
>
> > In addition to an example DTS patch (probably to warp itself), could
> > you briefly write up a binding and put it in
> > Documentation/powerpc/dts-bindings/amcc (or similar)? Also please CC
> > the devicetree-discuss list on that part.
>
> Here is a start at the doc. I have sent it as a patch, but could just
> as easily send raw text.
>
> The example comes from the warp dts, just with less partitions, so I
> have not included a warp dts patch here.
>
> Cheers,
> Sean
>
> diff --git a/Documentation/powerpc/dts-bindings/amcc/ndfc.txt
> b/Documentation/powerpc/dts-bindings/amcc/ndfc.txt new file mode 100644
> index 0000000..668f4a9
> --- /dev/null
> +++ b/Documentation/powerpc/dts-bindings/amcc/ndfc.txt
> @@ -0,0 +1,31 @@
> +AMCC NDFC (NanD Flash Controller)
> +
> +Required properties:
> +- compatible : "amcc,ndfc".
> +- reg : should specify chip select and size used for the chip (0x2000).
> +
> +Optional properties:
> +- ccr : NDFC config and control register value (default 0).
> +- bank-settings : NDFC bank configuration register value (default 0).
> +- partition(s) - follows the OF MTD standard for partitions
> +
> +Example:
> +
> +nand@1,0 {
> + compatible = "amcc,ndfc";
The first line in this file says that this is a controller...
> + reg = <0x00000001 0x00000000 0x00002000>;
> + ccr = <0x00001000>;
> + bank-settings = <0x80002222>;
> + #address-cells = <1>;
> + #size-cells = <1>;
> + partition@0 {
So this is a controller with partitions? ;-)
Recalling my own mistakes with the FSL UPM NAND controller bindings,
and Josh's comment:
http://www.mail-archive.com/linuxppc-dev@ozlabs.org/msg16572.html
I think the bindings should look like this:
nand-controller@.. {
...controller's properties...
nand-chip@... {
...chip's properties...
partition@... {
...partition's properties...
};
};
nand-chip@... {
...
};
};
Sure, I understand that there are plenty of boards with the "old"
scheme flashed into the firmware... Just something you might
want to consider for the future updates for the driver/bindings.
Thanks,
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-09 2:11 ` Anton Vorontsov
@ 2008-12-09 2:45 ` Sean MacLennan
2008-12-09 3:32 ` Josh Boyer
0 siblings, 1 reply; 28+ messages in thread
From: Sean MacLennan @ 2008-12-09 2:45 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev, devicetree-discuss, linux-mtd
On Tue, 9 Dec 2008 05:11:15 +0300
"Anton Vorontsov" <avorontsov@ru.mvista.com> wrote:
> So this is a controller with partitions? ;-)
Actually, I did it this way to mimic the look of the NOR. Really, we
shouldn't care about the NAND chip.
Here is the complete NOR and NAND DTS:
nor@0,0 {
compatible = "amd,s29gl032a", "cfi-flash";
bank-width = <2>;
reg = <0x00000000 0x00000000 0x00400000>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "splash";
reg = <0x00000000 0x00020000>;
};
partition@300000 {
label = "fpga";
reg = <0x0300000 0x00040000>;
};
partition@340000 {
label = "env";
reg = <0x0340000 0x00040000>;
};
partition@380000 {
label = "u-boot";
reg = <0x0380000 0x00080000>;
};
};
nand@1,0 {
compatible = "amcc,ndfc";
reg = <0x00000001 0x00000000 0x00002000>;
ccr = <0x00001000>;
bank-settings = <0x80002222>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "kernel";
reg = <0x00000000 0x00200000>;
};
partition@200000 {
label = "root";
reg = <0x00200000 0x03E00000>;
};
partition@40000000 {
label = "persistent";
reg = <0x04000000 0x04000000>;
};
partition@80000000 {
label = "persistent1";
reg = <0x08000000 0x04000000>;
};
partition@C0000000 {
label = "persistent2";
reg = <0x0C000000 0x04000000>;
};
};
Now I know I am cheating a bit.... but it does make it *look*
consistent.
But comments are welcome. I also could remove the partitions for now. A
partially supported NDFC is better than none at all.
Cheers,
Sean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-09 2:45 ` Sean MacLennan
@ 2008-12-09 3:32 ` Josh Boyer
2008-12-09 4:54 ` Sean MacLennan
0 siblings, 1 reply; 28+ messages in thread
From: Josh Boyer @ 2008-12-09 3:32 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linuxppc-dev, avorontsov, linux-mtd, devicetree-discuss
On Mon, 8 Dec 2008 21:45:12 -0500
Sean MacLennan <smaclennan@pikatech.com> wrote:
> On Tue, 9 Dec 2008 05:11:15 +0300
> "Anton Vorontsov" <avorontsov@ru.mvista.com> wrote:
>
> > So this is a controller with partitions? ;-)
>
> Actually, I did it this way to mimic the look of the NOR. Really, we
> shouldn't care about the NAND chip.
Except there is no controller in front of the NOR. It's all just
MMIOs. With NDFC, there is a controller, you have to do things to it
to talk to different chips, etc.
josh
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-09 3:32 ` Josh Boyer
@ 2008-12-09 4:54 ` Sean MacLennan
2008-12-09 7:57 ` Mitch Bradley
0 siblings, 1 reply; 28+ messages in thread
From: Sean MacLennan @ 2008-12-09 4:54 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev, avorontsov, linux-mtd, devicetree-discuss
On Mon, 8 Dec 2008 22:32:27 -0500
"Josh Boyer" <jwboyer@linux.vnet.ibm.com> wrote:
> Except there is no controller in front of the NOR. It's all just
> MMIOs. With NDFC, there is a controller, you have to do things to it
> to talk to different chips, etc.
Ok, I have the following dts working... would this be better? It
basically follows the fsl,upm-nand model. I can produce a new patch to
ndfc.c for this:
ndfc@1,0 {
compatible = "amcc,ndfc";
reg = <0x00000001 0x00000000 0x00002000>;
ccr = <0x00001000>;
bank-settings = <0x80002222>;
#address-cells = <1>;
#size-cells = <1>;
nand {
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "kernel";
reg = <0x00000000 0x00200000>;
};
partition@200000 {
label = "root";
reg = <0x00200000 0x03E00000>;
};
partition@40000000 {
label = "persistent";
reg = <0x04000000 0x04000000>;
};
partition@80000000 {
label = "persistent1";
reg = <0x08000000 0x04000000>;
};
partition@C0000000 {
label = "persistent2";
reg = <0x0C000000 0x04000000>;
};
};
};
Here is the boot output for both the NOR and the NAND (just for
comparison):
ffc00000.nor: Found 1 x16 devices at 0x0 in 16-bit bank
Amd/Fujitsu Extended Query Table at 0x0040
ffc00000.nor: CFI does not contain boot bank location. Assuming top.
number of CFI chips: 1
cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.
RedBoot partition parsing not available
Creating 4 MTD partitions on "ffc00000.nor":
0x00000000-0x00020000 : "splash"
0x00300000-0x00340000 : "fpga"
0x00340000-0x00380000 : "env"
0x00380000-0x00400000 : "u-boot"
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Scanning device for bad blocks
Creating 5 MTD partitions on "d0000000.ndfc.nand":
0x00000000-0x00200000 : "kernel"
0x00200000-0x04000000 : "root"
0x04000000-0x08000000 : "persistent"
0x08000000-0x0c000000 : "persistent1"
0x0c000000-0x10000000 : "persistent2"
If everybody likes this better, I can produce a code patch.
Cheers,
Sean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-09 0:34 ` Sean MacLennan
2008-12-09 2:11 ` Anton Vorontsov
@ 2008-12-09 6:10 ` Stefan Roese
2008-12-09 11:24 ` Josh Boyer
2008-12-10 23:16 ` Sean MacLennan
1 sibling, 2 replies; 28+ messages in thread
From: Stefan Roese @ 2008-12-09 6:10 UTC (permalink / raw)
To: linuxppc-dev; +Cc: linux-mtd, devicetree-discuss, Sean MacLennan
On Tuesday 09 December 2008, Sean MacLennan wrote:
> On Thu, 4 Dec 2008 09:01:07 -0500
>
> "Josh Boyer" <jwboyer@linux.vnet.ibm.com> wrote:
> > In addition to an example DTS patch (probably to warp itself), could
> > you briefly write up a binding and put it in
> > Documentation/powerpc/dts-bindings/amcc (or similar)? Also please CC
> > the devicetree-discuss list on that part.
>
> Here is a start at the doc. I have sent it as a patch, but could just
> as easily send raw text.
>
> The example comes from the warp dts, just with less partitions, so I
> have not included a warp dts patch here.
>
> Cheers,
> Sean
>
> diff --git a/Documentation/powerpc/dts-bindings/amcc/ndfc.txt
> b/Documentation/powerpc/dts-bindings/amcc/ndfc.txt new file mode 100644
> index 0000000..668f4a9
> --- /dev/null
> +++ b/Documentation/powerpc/dts-bindings/amcc/ndfc.txt
> @@ -0,0 +1,31 @@
> +AMCC NDFC (NanD Flash Controller)
> +
> +Required properties:
> +- compatible : "amcc,ndfc".
The 4xx NAND controller was first implemented on the 440EP, IIRC. So I'm
pretty sure that this controller is an IBM core and not am AMCC core. So this
should be "ibm,ndfc".
And with this change it makes no sense to put this file "ndfc.txt" into the
amcc directory.
Josh, where should this go then?
Best regards,
Stefan
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-09 4:54 ` Sean MacLennan
@ 2008-12-09 7:57 ` Mitch Bradley
2008-12-10 4:01 ` Sean MacLennan
0 siblings, 1 reply; 28+ messages in thread
From: Mitch Bradley @ 2008-12-09 7:57 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linuxppc-dev, devicetree-discuss, avorontsov, linux-mtd
One address/size cell isn't enough for the next generation of NAND FLASH
chips.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-09 6:10 ` Stefan Roese
@ 2008-12-09 11:24 ` Josh Boyer
2008-12-10 23:16 ` Sean MacLennan
1 sibling, 0 replies; 28+ messages in thread
From: Josh Boyer @ 2008-12-09 11:24 UTC (permalink / raw)
To: Stefan Roese; +Cc: linuxppc-dev, devicetree-discuss, linux-mtd, Sean MacLennan
On Tue, 9 Dec 2008 07:10:27 +0100
Stefan Roese <sr@denx.de> wrote:
> On Tuesday 09 December 2008, Sean MacLennan wrote:
> > On Thu, 4 Dec 2008 09:01:07 -0500
> >
> > "Josh Boyer" <jwboyer@linux.vnet.ibm.com> wrote:
> > > In addition to an example DTS patch (probably to warp itself), could
> > > you briefly write up a binding and put it in
> > > Documentation/powerpc/dts-bindings/amcc (or similar)? Also please CC
> > > the devicetree-discuss list on that part.
> >
> > Here is a start at the doc. I have sent it as a patch, but could just
> > as easily send raw text.
> >
> > The example comes from the warp dts, just with less partitions, so I
> > have not included a warp dts patch here.
> >
> > Cheers,
> > Sean
> >
> > diff --git a/Documentation/powerpc/dts-bindings/amcc/ndfc.txt
> > b/Documentation/powerpc/dts-bindings/amcc/ndfc.txt new file mode 100644
> > index 0000000..668f4a9
> > --- /dev/null
> > +++ b/Documentation/powerpc/dts-bindings/amcc/ndfc.txt
> > @@ -0,0 +1,31 @@
> > +AMCC NDFC (NanD Flash Controller)
> > +
> > +Required properties:
> > +- compatible : "amcc,ndfc".
>
> The 4xx NAND controller was first implemented on the 440EP, IIRC. So I'm
> pretty sure that this controller is an IBM core and not am AMCC core. So this
> should be "ibm,ndfc".
That is true. It's an IBM blue logic core.
> And with this change it makes no sense to put this file "ndfc.txt" into the
> amcc directory.
>
> Josh, where should this go then?
I declare it to be: dts-bindings/4xx/
mostly because I don't want the bindings scattered across two
directories simply because of the timeframe they showed up in the
marketplace.
If there are better ideas, I'm all ears.
josh
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-09 7:57 ` Mitch Bradley
@ 2008-12-10 4:01 ` Sean MacLennan
2008-12-10 8:28 ` Mitch Bradley
0 siblings, 1 reply; 28+ messages in thread
From: Sean MacLennan @ 2008-12-10 4:01 UTC (permalink / raw)
To: Mitch Bradley; +Cc: linuxppc-dev, devicetree-discuss, avorontsov, linux-mtd
On Mon, 08 Dec 2008 21:57:12 -1000
"Mitch Bradley" <wmb@firmworks.com> wrote:
> One address/size cell isn't enough for the next generation of NAND
> FLASH chips.
>
I am no dts expert, but I thought I could put:
nand {
#address-cells = <1>;
#size-cells = <1>;
in my dts and you could put:
nand {
#address-cells = <2>;
#size-cells = <2>;
and, assuming we specified the reg entry right, everything would just
work. Is that assumption wrong?
And if the assumption is true, should I make a note in the doc that you
can make the address and size bigger?
Cheers,
Sean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-10 4:01 ` Sean MacLennan
@ 2008-12-10 8:28 ` Mitch Bradley
0 siblings, 0 replies; 28+ messages in thread
From: Mitch Bradley @ 2008-12-10 8:28 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linuxppc-dev, devicetree-discuss, avorontsov, linux-mtd
>
> n Mon, 08 Dec 2008 21:57:12 -1000
> "Mitch Bradley" <wmb@firmworks.com> wrote:
>
>
>> > One address/size cell isn't enough for the next generation of NAND
>> > FLASH chips.
>> >
>>
>
> I am no dts expert, but I thought I could put:
>
> nand {
> #address-cells = <1>;
> #size-cells = <1>;
>
> in my dts and you could put:
>
> nand {
> #address-cells = <2>;
> #size-cells = <2>;
>
> and, assuming we specified the reg entry right, everything would just
> work. Is that assumption wrong?
>
> And if the assumption is true, should I make a note in the doc that you
> can make the address and size bigger?
>
> Cheers,
> Sean
>
>
In principle that is correct, but the device tree partition parser in
the Linux kernel assumes one address cell and one size cell, or at least
it did the last time I looked.
I wrote a patch to fix that and circulated it on the linuxppc list, but
since lost interest. OLPC (my main focus) is probably going to switch to
managed NAND (SSD, LBA-NAND, eMMC, or some such thing with a built-in
Flash Translation Layer) at some point. Raw NAND is starting to go by
the wayside.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-09 6:10 ` Stefan Roese
2008-12-09 11:24 ` Josh Boyer
@ 2008-12-10 23:16 ` Sean MacLennan
2008-12-17 4:14 ` Sean MacLennan
2008-12-17 13:26 ` Josh Boyer
1 sibling, 2 replies; 28+ messages in thread
From: Sean MacLennan @ 2008-12-10 23:16 UTC (permalink / raw)
To: Stefan Roese; +Cc: linuxppc-dev, linux-mtd, devicetree-discuss, Arnd Bergmann
Here is an updated patch. Doc has been moved to 4xx and amcc changed to
ibm.
Arnd: I removed your acked-by just in case you don't approve of the new
flash layout. Feel free to ack again.
Cheers,
Sean
Port of the ndfc driver to an OF platform driver.
Signed-off-by: Sean MacLennan <smaclennan@pikatech.com>
---
diff --git a/Documentation/powerpc/dts-bindings/4xx/ndfc.txt b/Documentation/powerpc/dts-bindings/4xx/ndfc.txt
new file mode 100644
index 0000000..869f0b5
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/4xx/ndfc.txt
@@ -0,0 +1,39 @@
+AMCC NDFC (NanD Flash Controller)
+
+Required properties:
+- compatible : "ibm,ndfc".
+- reg : should specify chip select and size used for the chip (0x2000).
+
+Optional properties:
+- ccr : NDFC config and control register value (default 0).
+- bank-settings : NDFC bank configuration register value (default 0).
+
+Notes:
+- partition(s) - follows the OF MTD standard for partitions
+
+Example:
+
+ndfc@1,0 {
+ compatible = "ibm,ndfc";
+ reg = <0x00000001 0x00000000 0x00002000>;
+ ccr = <0x00001000>;
+ bank-settings = <0x80002222>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ nand {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "kernel";
+ reg = <0x00000000 0x00200000>;
+ };
+ partition@200000 {
+ label = "root";
+ reg = <0x00200000 0x03E00000>;
+ };
+ };
+};
+
+
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1c2e945..5705f85 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -163,6 +163,13 @@ config MTD_NAND_S3C2410_HWECC
incorrect ECC generation, and if using these, the default of
software ECC is preferable.
+config MTD_NAND_NDFC
+ tristate "NDFC NanD Flash Controller"
+ depends on 4xx
+ select MTD_NAND_ECC_SMC
+ help
+ NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
+
config MTD_NAND_S3C2410_CLKSTOP
bool "S3C2410 NAND IDLE clock stop"
depends on MTD_NAND_S3C2410
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 955959e..582cf80 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -2,12 +2,20 @@
* drivers/mtd/ndfc.c
*
* Overview:
- * Platform independend driver for NDFC (NanD Flash Controller)
+ * Platform independent driver for NDFC (NanD Flash Controller)
* integrated into EP440 cores
*
+ * Ported to an OF platform driver by Sean MacLennan
+ *
+ * The NDFC supports multiple chips, but this driver only supports a
+ * single chip since I do not have access to any boards with
+ * multiple chips.
+ *
* Author: Thomas Gleixner
*
* Copyright 2006 IBM
+ * Copyright 2008 PIKA Technologies
+ * Sean MacLennan <smaclennan@pikatech.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 the
@@ -21,27 +29,20 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/ndfc.h>
#include <linux/mtd/mtd.h>
-#include <linux/platform_device.h>
-
+#include <linux/of_platform.h>
#include <asm/io.h>
-#ifdef CONFIG_40x
-#include <asm/ibm405.h>
-#else
-#include <asm/ibm44x.h>
-#endif
-
-struct ndfc_nand_mtd {
- struct mtd_info mtd;
- struct nand_chip chip;
- struct platform_nand_chip *pl_chip;
-};
-static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS];
struct ndfc_controller {
- void __iomem *ndfcbase;
- struct nand_hw_control ndfc_control;
- atomic_t childs_active;
+ struct of_device *ofdev;
+ void __iomem *ndfcbase;
+ struct mtd_info mtd;
+ struct nand_chip chip;
+ int chip_select;
+ struct nand_hw_control ndfc_control;
+#ifdef CONFIG_MTD_PARTITIONS
+ struct mtd_partition *parts;
+#endif
};
static struct ndfc_controller ndfc_ctrl;
@@ -50,17 +51,14 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
{
uint32_t ccr;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct nand_chip *nandchip = mtd->priv;
- struct ndfc_nand_mtd *nandmtd = nandchip->priv;
- struct platform_nand_chip *pchip = nandmtd->pl_chip;
- ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+ ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
if (chip >= 0) {
ccr &= ~NDFC_CCR_BS_MASK;
- ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
+ ccr |= NDFC_CCR_BS(chip + ndfc->chip_select);
} else
ccr |= NDFC_CCR_RESET_CE;
- __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
}
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
@@ -80,7 +78,7 @@ static int ndfc_ready(struct mtd_info *mtd)
{
struct ndfc_controller *ndfc = &ndfc_ctrl;
- return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
+ return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
}
static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
@@ -88,9 +86,9 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
uint32_t ccr;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+ ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
ccr |= NDFC_CCR_RESET_ECC;
- __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
wmb();
}
@@ -102,9 +100,10 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
uint8_t *p = (uint8_t *)&ecc;
wmb();
- ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC);
- ecc_code[0] = p[1];
- ecc_code[1] = p[2];
+ ecc = in_be32(ndfc->ndfcbase + NDFC_ECC);
+ /* The NDFC uses Smart Media (SMC) bytes order */
+ ecc_code[0] = p[2];
+ ecc_code[1] = p[1];
ecc_code[2] = p[3];
return 0;
@@ -123,7 +122,7 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA);
+ *p++ = in_be32(ndfc->ndfcbase + NDFC_DATA);
}
static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
@@ -132,7 +131,7 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA);
+ out_be32(ndfc->ndfcbase + NDFC_DATA, *p++);
}
static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
@@ -141,7 +140,7 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA))
+ if (*p++ != in_be32(ndfc->ndfcbase + NDFC_DATA))
return -EFAULT;
return 0;
}
@@ -149,10 +148,19 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
/*
* Initialize chip structure
*/
-static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
+static int ndfc_chip_init(struct ndfc_controller *ndfc,
+ struct device_node *node)
{
- struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct nand_chip *chip = &mtd->chip;
+#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ static const char *part_types[] = { "cmdlinepart", NULL };
+#else
+ static const char *part_types[] = { NULL };
+#endif
+#endif
+ struct device_node *flash_np;
+ struct nand_chip *chip = &ndfc->chip;
+ int ret;
chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
@@ -160,8 +168,6 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip->dev_ready = ndfc_ready;
chip->select_chip = ndfc_select_chip;
chip->chip_delay = 50;
- chip->priv = mtd;
- chip->options = mtd->pl_chip->options;
chip->controller = &ndfc->ndfc_control;
chip->read_buf = ndfc_read_buf;
chip->write_buf = ndfc_write_buf;
@@ -172,143 +178,136 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = 256;
chip->ecc.bytes = 3;
- chip->ecclayout = chip->ecc.layout = mtd->pl_chip->ecclayout;
- mtd->mtd.priv = chip;
- mtd->mtd.owner = THIS_MODULE;
-}
-
-static int ndfc_chip_probe(struct platform_device *pdev)
-{
- struct platform_nand_chip *nc = pdev->dev.platform_data;
- struct ndfc_chip_settings *settings = nc->priv;
- struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct ndfc_nand_mtd *nandmtd;
-
- if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS)
- return -EINVAL;
-
- /* Set the bank settings */
- __raw_writel(settings->bank_settings,
- ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2));
- nandmtd = &ndfc_mtd[pdev->id];
- if (nandmtd->pl_chip)
- return -EBUSY;
+ ndfc->mtd.priv = chip;
+ ndfc->mtd.owner = THIS_MODULE;
- nandmtd->pl_chip = nc;
- ndfc_chip_init(nandmtd);
-
- /* Scan for chips */
- if (nand_scan(&nandmtd->mtd, nc->nr_chips)) {
- nandmtd->pl_chip = NULL;
+ flash_np = of_get_next_child(node, NULL);
+ if (!flash_np)
return -ENODEV;
+
+ ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
+ ndfc->ofdev->dev.bus_id, flash_np->name);
+ if (!ndfc->mtd.name) {
+ ret = -ENOMEM;
+ goto err;
}
-#ifdef CONFIG_MTD_PARTITIONS
- printk("Number of partitions %d\n", nc->nr_partitions);
- if (nc->nr_partitions) {
- /* Add the full device, so complete dumps can be made */
- add_mtd_device(&nandmtd->mtd);
- add_mtd_partitions(&nandmtd->mtd, nc->partitions,
- nc->nr_partitions);
+ ret = nand_scan(&ndfc->mtd, 1);
+ if (ret)
+ goto err;
- } else
-#else
- add_mtd_device(&nandmtd->mtd);
+#ifdef CONFIG_MTD_PARTITIONS
+ ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0);
+ if (ret < 0)
+ goto err;
+
+#ifdef CONFIG_MTD_OF_PARTS
+ if (ret == 0) {
+ ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
+ &ndfc->parts);
+ if (ret < 0)
+ goto err;
+ }
#endif
- atomic_inc(&ndfc->childs_active);
- return 0;
-}
+ if (ret > 0)
+ ret = add_mtd_partitions(&ndfc->mtd, ndfc->parts, ret);
+ else
+#endif
+ ret = add_mtd_device(&ndfc->mtd);
-static int ndfc_chip_remove(struct platform_device *pdev)
-{
- return 0;
+err:
+ of_node_put(flash_np);
+ if (ret)
+ kfree(ndfc->mtd.name);
+ return ret;
}
-static int ndfc_nand_probe(struct platform_device *pdev)
+static int __devinit ndfc_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
{
- struct platform_nand_ctrl *nc = pdev->dev.platform_data;
- struct ndfc_controller_settings *settings = nc->priv;
- struct resource *res = pdev->resource;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- unsigned long long phys = settings->ndfc_erpn | res->start;
+ const u32 *reg;
+ u32 ccr;
+ int err, len;
-#ifndef CONFIG_PHYS_64BIT
- ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
-#else
- ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
-#endif
+ spin_lock_init(&ndfc->ndfc_control.lock);
+ init_waitqueue_head(&ndfc->ndfc_control.wq);
+ ndfc->ofdev = ofdev;
+ dev_set_drvdata(&ofdev->dev, ndfc);
+
+ /* Read the reg property to get the chip select */
+ reg = of_get_property(ofdev->node, "reg", &len);
+ if (reg == NULL || len != 12) {
+ dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
+ return -ENOENT;
+ }
+ ndfc->chip_select = reg[0];
+
+ ndfc->ndfcbase = of_iomap(ofdev->node, 0);
if (!ndfc->ndfcbase) {
- printk(KERN_ERR "NDFC: ioremap failed\n");
+ dev_err(&ofdev->dev, "failed to get memory\n");
return -EIO;
}
- __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR);
+ ccr = NDFC_CCR_BS(ndfc->chip_select);
- spin_lock_init(&ndfc->ndfc_control.lock);
- init_waitqueue_head(&ndfc->ndfc_control.wq);
+ /* It is ok if ccr does not exist - just default to 0 */
+ reg = of_get_property(ofdev->node, "ccr", NULL);
+ if (reg)
+ ccr |= *reg;
- platform_set_drvdata(pdev, ndfc);
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
- printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n",
- __raw_readl(ndfc->ndfcbase + NDFC_REVID));
+ /* Set the bank settings if given */
+ reg = of_get_property(ofdev->node, "bank-settings", NULL);
+ if (reg) {
+ int offset = NDFC_BCFG0 + (ndfc->chip_select << 2);
+ out_be32(ndfc->ndfcbase + offset, *reg);
+ }
+
+ err = ndfc_chip_init(ndfc, ofdev->node);
+ if (err) {
+ iounmap(ndfc->ndfcbase);
+ return err;
+ }
return 0;
}
-static int ndfc_nand_remove(struct platform_device *pdev)
+static int __devexit ndfc_remove(struct of_device *ofdev)
{
- struct ndfc_controller *ndfc = platform_get_drvdata(pdev);
+ struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
- if (atomic_read(&ndfc->childs_active))
- return -EBUSY;
+ nand_release(&ndfc->mtd);
- if (ndfc) {
- platform_set_drvdata(pdev, NULL);
- iounmap(ndfc_ctrl.ndfcbase);
- ndfc_ctrl.ndfcbase = NULL;
- }
return 0;
}
-/* driver device registration */
-
-static struct platform_driver ndfc_chip_driver = {
- .probe = ndfc_chip_probe,
- .remove = ndfc_chip_remove,
- .driver = {
- .name = "ndfc-chip",
- .owner = THIS_MODULE,
- },
+static const struct of_device_id ndfc_match[] = {
+ { .compatible = "ibm,ndfc", },
+ {}
};
+MODULE_DEVICE_TABLE(of, ndfc_match);
-static struct platform_driver ndfc_nand_driver = {
- .probe = ndfc_nand_probe,
- .remove = ndfc_nand_remove,
- .driver = {
- .name = "ndfc-nand",
- .owner = THIS_MODULE,
+static struct of_platform_driver ndfc_driver = {
+ .driver = {
+ .name = "ndfc",
},
+ .match_table = ndfc_match,
+ .probe = ndfc_probe,
+ .remove = __devexit_p(ndfc_remove),
};
static int __init ndfc_nand_init(void)
{
- int ret;
-
- spin_lock_init(&ndfc_ctrl.ndfc_control.lock);
- init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq);
-
- ret = platform_driver_register(&ndfc_nand_driver);
- if (!ret)
- ret = platform_driver_register(&ndfc_chip_driver);
- return ret;
+ return of_register_platform_driver(&ndfc_driver);
}
static void __exit ndfc_nand_exit(void)
{
- platform_driver_unregister(&ndfc_chip_driver);
- platform_driver_unregister(&ndfc_nand_driver);
+ of_unregister_platform_driver(&ndfc_driver);
}
module_init(ndfc_nand_init);
@@ -316,6 +315,4 @@ module_exit(ndfc_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION("Platform driver for NDFC");
-MODULE_ALIAS("platform:ndfc-chip");
-MODULE_ALIAS("platform:ndfc-nand");
+MODULE_DESCRIPTION("OF Platform driver for NDFC");
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-10 23:16 ` Sean MacLennan
@ 2008-12-17 4:14 ` Sean MacLennan
2008-12-17 11:34 ` Josh Boyer
2008-12-17 13:26 ` Josh Boyer
1 sibling, 1 reply; 28+ messages in thread
From: Sean MacLennan @ 2008-12-17 4:14 UTC (permalink / raw)
To: Josh Boyer
Cc: linuxppc-dev, Stefan Roese, linux-mtd, Arnd Bergmann,
devicetree-discuss
On Wed, 10 Dec 2008 18:16:34 -0500
"Sean MacLennan" <sean.maclennan@ottawa.kanatek.ca> wrote:
> Here is an updated patch. Doc has been moved to 4xx and amcc changed
> to ibm.
Anybody? Even if it is not perfect, it would be better to have
a driver that at least compiles ;)
Cheers,
Sean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-17 4:14 ` Sean MacLennan
@ 2008-12-17 11:34 ` Josh Boyer
0 siblings, 0 replies; 28+ messages in thread
From: Josh Boyer @ 2008-12-17 11:34 UTC (permalink / raw)
To: Sean MacLennan
Cc: devicetree-discuss, Arnd Bergmann, linuxppc-dev, linux-mtd,
Stefan Roese, dwmw2
On Tue, Dec 16, 2008 at 11:14:00PM -0500, Sean MacLennan wrote:
>On Wed, 10 Dec 2008 18:16:34 -0500
>"Sean MacLennan" <sean.maclennan@ottawa.kanatek.ca> wrote:
>
>> Here is an updated patch. Doc has been moved to 4xx and amcc changed
>> to ibm.
>
>Anybody? Even if it is not perfect, it would be better to have
>a driver that at least compiles ;)
Reviewing it today. Looked pretty good at first glance. It would be
nice to get David or Thomas to Ack it.
josh
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-10 23:16 ` Sean MacLennan
2008-12-17 4:14 ` Sean MacLennan
@ 2008-12-17 13:26 ` Josh Boyer
1 sibling, 0 replies; 28+ messages in thread
From: Josh Boyer @ 2008-12-17 13:26 UTC (permalink / raw)
To: Sean MacLennan, dwmw2
Cc: linuxppc-dev, linux-mtd, Stefan Roese, devicetree-discuss,
Arnd Bergmann
On Wed, Dec 10, 2008 at 06:16:34PM -0500, Sean MacLennan wrote:
>Here is an updated patch. Doc has been moved to 4xx and amcc changed to
>ibm.
>
>Arnd: I removed your acked-by just in case you don't approve of the new
>flash layout. Feel free to ack again.
>
>Cheers,
> Sean
>
>Port of the ndfc driver to an OF platform driver.
>
>Signed-off-by: Sean MacLennan <smaclennan@pikatech.com>
Acked-By: Josh Boyer <jwboyer@linux.vnet.ibm.com>
David, if you have no objections I'd like to take this patch
through my tree. I'll fixup the subject and commit log when
I do.
josh
>---
>diff --git a/Documentation/powerpc/dts-bindings/4xx/ndfc.txt b/Documentation/powerpc/dts-bindings/4xx/ndfc.txt
>new file mode 100644
>index 0000000..869f0b5
>--- /dev/null
>+++ b/Documentation/powerpc/dts-bindings/4xx/ndfc.txt
>@@ -0,0 +1,39 @@
>+AMCC NDFC (NanD Flash Controller)
>+
>+Required properties:
>+- compatible : "ibm,ndfc".
>+- reg : should specify chip select and size used for the chip (0x2000).
>+
>+Optional properties:
>+- ccr : NDFC config and control register value (default 0).
>+- bank-settings : NDFC bank configuration register value (default 0).
>+
>+Notes:
>+- partition(s) - follows the OF MTD standard for partitions
>+
>+Example:
>+
>+ndfc@1,0 {
>+ compatible = "ibm,ndfc";
>+ reg = <0x00000001 0x00000000 0x00002000>;
>+ ccr = <0x00001000>;
>+ bank-settings = <0x80002222>;
>+ #address-cells = <1>;
>+ #size-cells = <1>;
>+
>+ nand {
>+ #address-cells = <1>;
>+ #size-cells = <1>;
>+
>+ partition@0 {
>+ label = "kernel";
>+ reg = <0x00000000 0x00200000>;
>+ };
>+ partition@200000 {
>+ label = "root";
>+ reg = <0x00200000 0x03E00000>;
>+ };
>+ };
>+};
>+
>+
>diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
>index 1c2e945..5705f85 100644
>--- a/drivers/mtd/nand/Kconfig
>+++ b/drivers/mtd/nand/Kconfig
>@@ -163,6 +163,13 @@ config MTD_NAND_S3C2410_HWECC
> incorrect ECC generation, and if using these, the default of
> software ECC is preferable.
>
>+config MTD_NAND_NDFC
>+ tristate "NDFC NanD Flash Controller"
>+ depends on 4xx
>+ select MTD_NAND_ECC_SMC
>+ help
>+ NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
>+
> config MTD_NAND_S3C2410_CLKSTOP
> bool "S3C2410 NAND IDLE clock stop"
> depends on MTD_NAND_S3C2410
>diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
>index 955959e..582cf80 100644
>--- a/drivers/mtd/nand/ndfc.c
>+++ b/drivers/mtd/nand/ndfc.c
>@@ -2,12 +2,20 @@
> * drivers/mtd/ndfc.c
> *
> * Overview:
>- * Platform independend driver for NDFC (NanD Flash Controller)
>+ * Platform independent driver for NDFC (NanD Flash Controller)
> * integrated into EP440 cores
> *
>+ * Ported to an OF platform driver by Sean MacLennan
>+ *
>+ * The NDFC supports multiple chips, but this driver only supports a
>+ * single chip since I do not have access to any boards with
>+ * multiple chips.
>+ *
> * Author: Thomas Gleixner
> *
> * Copyright 2006 IBM
>+ * Copyright 2008 PIKA Technologies
>+ * Sean MacLennan <smaclennan@pikatech.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 the
>@@ -21,27 +29,20 @@
> #include <linux/mtd/partitions.h>
> #include <linux/mtd/ndfc.h>
> #include <linux/mtd/mtd.h>
>-#include <linux/platform_device.h>
>-
>+#include <linux/of_platform.h>
> #include <asm/io.h>
>-#ifdef CONFIG_40x
>-#include <asm/ibm405.h>
>-#else
>-#include <asm/ibm44x.h>
>-#endif
>-
>-struct ndfc_nand_mtd {
>- struct mtd_info mtd;
>- struct nand_chip chip;
>- struct platform_nand_chip *pl_chip;
>-};
>
>-static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS];
>
> struct ndfc_controller {
>- void __iomem *ndfcbase;
>- struct nand_hw_control ndfc_control;
>- atomic_t childs_active;
>+ struct of_device *ofdev;
>+ void __iomem *ndfcbase;
>+ struct mtd_info mtd;
>+ struct nand_chip chip;
>+ int chip_select;
>+ struct nand_hw_control ndfc_control;
>+#ifdef CONFIG_MTD_PARTITIONS
>+ struct mtd_partition *parts;
>+#endif
> };
>
> static struct ndfc_controller ndfc_ctrl;
>@@ -50,17 +51,14 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
> {
> uint32_t ccr;
> struct ndfc_controller *ndfc = &ndfc_ctrl;
>- struct nand_chip *nandchip = mtd->priv;
>- struct ndfc_nand_mtd *nandmtd = nandchip->priv;
>- struct platform_nand_chip *pchip = nandmtd->pl_chip;
>
>- ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
>+ ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
> if (chip >= 0) {
> ccr &= ~NDFC_CCR_BS_MASK;
>- ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
>+ ccr |= NDFC_CCR_BS(chip + ndfc->chip_select);
> } else
> ccr |= NDFC_CCR_RESET_CE;
>- __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
>+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
> }
>
> static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>@@ -80,7 +78,7 @@ static int ndfc_ready(struct mtd_info *mtd)
> {
> struct ndfc_controller *ndfc = &ndfc_ctrl;
>
>- return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
>+ return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
> }
>
> static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
>@@ -88,9 +86,9 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
> uint32_t ccr;
> struct ndfc_controller *ndfc = &ndfc_ctrl;
>
>- ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
>+ ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
> ccr |= NDFC_CCR_RESET_ECC;
>- __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
>+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
> wmb();
> }
>
>@@ -102,9 +100,10 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
> uint8_t *p = (uint8_t *)&ecc;
>
> wmb();
>- ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC);
>- ecc_code[0] = p[1];
>- ecc_code[1] = p[2];
>+ ecc = in_be32(ndfc->ndfcbase + NDFC_ECC);
>+ /* The NDFC uses Smart Media (SMC) bytes order */
>+ ecc_code[0] = p[2];
>+ ecc_code[1] = p[1];
> ecc_code[2] = p[3];
>
> return 0;
>@@ -123,7 +122,7 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
> uint32_t *p = (uint32_t *) buf;
>
> for(;len > 0; len -= 4)
>- *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA);
>+ *p++ = in_be32(ndfc->ndfcbase + NDFC_DATA);
> }
>
> static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>@@ -132,7 +131,7 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
> uint32_t *p = (uint32_t *) buf;
>
> for(;len > 0; len -= 4)
>- __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA);
>+ out_be32(ndfc->ndfcbase + NDFC_DATA, *p++);
> }
>
> static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>@@ -141,7 +140,7 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
> uint32_t *p = (uint32_t *) buf;
>
> for(;len > 0; len -= 4)
>- if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA))
>+ if (*p++ != in_be32(ndfc->ndfcbase + NDFC_DATA))
> return -EFAULT;
> return 0;
> }
>@@ -149,10 +148,19 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
> /*
> * Initialize chip structure
> */
>-static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
>+static int ndfc_chip_init(struct ndfc_controller *ndfc,
>+ struct device_node *node)
> {
>- struct ndfc_controller *ndfc = &ndfc_ctrl;
>- struct nand_chip *chip = &mtd->chip;
>+#ifdef CONFIG_MTD_PARTITIONS
>+#ifdef CONFIG_MTD_CMDLINE_PARTS
>+ static const char *part_types[] = { "cmdlinepart", NULL };
>+#else
>+ static const char *part_types[] = { NULL };
>+#endif
>+#endif
>+ struct device_node *flash_np;
>+ struct nand_chip *chip = &ndfc->chip;
>+ int ret;
>
> chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
> chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
>@@ -160,8 +168,6 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
> chip->dev_ready = ndfc_ready;
> chip->select_chip = ndfc_select_chip;
> chip->chip_delay = 50;
>- chip->priv = mtd;
>- chip->options = mtd->pl_chip->options;
> chip->controller = &ndfc->ndfc_control;
> chip->read_buf = ndfc_read_buf;
> chip->write_buf = ndfc_write_buf;
>@@ -172,143 +178,136 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
> chip->ecc.mode = NAND_ECC_HW;
> chip->ecc.size = 256;
> chip->ecc.bytes = 3;
>- chip->ecclayout = chip->ecc.layout = mtd->pl_chip->ecclayout;
>- mtd->mtd.priv = chip;
>- mtd->mtd.owner = THIS_MODULE;
>-}
>-
>-static int ndfc_chip_probe(struct platform_device *pdev)
>-{
>- struct platform_nand_chip *nc = pdev->dev.platform_data;
>- struct ndfc_chip_settings *settings = nc->priv;
>- struct ndfc_controller *ndfc = &ndfc_ctrl;
>- struct ndfc_nand_mtd *nandmtd;
>-
>- if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS)
>- return -EINVAL;
>-
>- /* Set the bank settings */
>- __raw_writel(settings->bank_settings,
>- ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2));
>
>- nandmtd = &ndfc_mtd[pdev->id];
>- if (nandmtd->pl_chip)
>- return -EBUSY;
>+ ndfc->mtd.priv = chip;
>+ ndfc->mtd.owner = THIS_MODULE;
>
>- nandmtd->pl_chip = nc;
>- ndfc_chip_init(nandmtd);
>-
>- /* Scan for chips */
>- if (nand_scan(&nandmtd->mtd, nc->nr_chips)) {
>- nandmtd->pl_chip = NULL;
>+ flash_np = of_get_next_child(node, NULL);
>+ if (!flash_np)
> return -ENODEV;
>+
>+ ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
>+ ndfc->ofdev->dev.bus_id, flash_np->name);
>+ if (!ndfc->mtd.name) {
>+ ret = -ENOMEM;
>+ goto err;
> }
>
>-#ifdef CONFIG_MTD_PARTITIONS
>- printk("Number of partitions %d\n", nc->nr_partitions);
>- if (nc->nr_partitions) {
>- /* Add the full device, so complete dumps can be made */
>- add_mtd_device(&nandmtd->mtd);
>- add_mtd_partitions(&nandmtd->mtd, nc->partitions,
>- nc->nr_partitions);
>+ ret = nand_scan(&ndfc->mtd, 1);
>+ if (ret)
>+ goto err;
>
>- } else
>-#else
>- add_mtd_device(&nandmtd->mtd);
>+#ifdef CONFIG_MTD_PARTITIONS
>+ ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0);
>+ if (ret < 0)
>+ goto err;
>+
>+#ifdef CONFIG_MTD_OF_PARTS
>+ if (ret == 0) {
>+ ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
>+ &ndfc->parts);
>+ if (ret < 0)
>+ goto err;
>+ }
> #endif
>
>- atomic_inc(&ndfc->childs_active);
>- return 0;
>-}
>+ if (ret > 0)
>+ ret = add_mtd_partitions(&ndfc->mtd, ndfc->parts, ret);
>+ else
>+#endif
>+ ret = add_mtd_device(&ndfc->mtd);
>
>-static int ndfc_chip_remove(struct platform_device *pdev)
>-{
>- return 0;
>+err:
>+ of_node_put(flash_np);
>+ if (ret)
>+ kfree(ndfc->mtd.name);
>+ return ret;
> }
>
>-static int ndfc_nand_probe(struct platform_device *pdev)
>+static int __devinit ndfc_probe(struct of_device *ofdev,
>+ const struct of_device_id *match)
> {
>- struct platform_nand_ctrl *nc = pdev->dev.platform_data;
>- struct ndfc_controller_settings *settings = nc->priv;
>- struct resource *res = pdev->resource;
> struct ndfc_controller *ndfc = &ndfc_ctrl;
>- unsigned long long phys = settings->ndfc_erpn | res->start;
>+ const u32 *reg;
>+ u32 ccr;
>+ int err, len;
>
>-#ifndef CONFIG_PHYS_64BIT
>- ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
>-#else
>- ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
>-#endif
>+ spin_lock_init(&ndfc->ndfc_control.lock);
>+ init_waitqueue_head(&ndfc->ndfc_control.wq);
>+ ndfc->ofdev = ofdev;
>+ dev_set_drvdata(&ofdev->dev, ndfc);
>+
>+ /* Read the reg property to get the chip select */
>+ reg = of_get_property(ofdev->node, "reg", &len);
>+ if (reg == NULL || len != 12) {
>+ dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
>+ return -ENOENT;
>+ }
>+ ndfc->chip_select = reg[0];
>+
>+ ndfc->ndfcbase = of_iomap(ofdev->node, 0);
> if (!ndfc->ndfcbase) {
>- printk(KERN_ERR "NDFC: ioremap failed\n");
>+ dev_err(&ofdev->dev, "failed to get memory\n");
> return -EIO;
> }
>
>- __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR);
>+ ccr = NDFC_CCR_BS(ndfc->chip_select);
>
>- spin_lock_init(&ndfc->ndfc_control.lock);
>- init_waitqueue_head(&ndfc->ndfc_control.wq);
>+ /* It is ok if ccr does not exist - just default to 0 */
>+ reg = of_get_property(ofdev->node, "ccr", NULL);
>+ if (reg)
>+ ccr |= *reg;
>
>- platform_set_drvdata(pdev, ndfc);
>+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
>
>- printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n",
>- __raw_readl(ndfc->ndfcbase + NDFC_REVID));
>+ /* Set the bank settings if given */
>+ reg = of_get_property(ofdev->node, "bank-settings", NULL);
>+ if (reg) {
>+ int offset = NDFC_BCFG0 + (ndfc->chip_select << 2);
>+ out_be32(ndfc->ndfcbase + offset, *reg);
>+ }
>+
>+ err = ndfc_chip_init(ndfc, ofdev->node);
>+ if (err) {
>+ iounmap(ndfc->ndfcbase);
>+ return err;
>+ }
>
> return 0;
> }
>
>-static int ndfc_nand_remove(struct platform_device *pdev)
>+static int __devexit ndfc_remove(struct of_device *ofdev)
> {
>- struct ndfc_controller *ndfc = platform_get_drvdata(pdev);
>+ struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
>
>- if (atomic_read(&ndfc->childs_active))
>- return -EBUSY;
>+ nand_release(&ndfc->mtd);
>
>- if (ndfc) {
>- platform_set_drvdata(pdev, NULL);
>- iounmap(ndfc_ctrl.ndfcbase);
>- ndfc_ctrl.ndfcbase = NULL;
>- }
> return 0;
> }
>
>-/* driver device registration */
>-
>-static struct platform_driver ndfc_chip_driver = {
>- .probe = ndfc_chip_probe,
>- .remove = ndfc_chip_remove,
>- .driver = {
>- .name = "ndfc-chip",
>- .owner = THIS_MODULE,
>- },
>+static const struct of_device_id ndfc_match[] = {
>+ { .compatible = "ibm,ndfc", },
>+ {}
> };
>+MODULE_DEVICE_TABLE(of, ndfc_match);
>
>-static struct platform_driver ndfc_nand_driver = {
>- .probe = ndfc_nand_probe,
>- .remove = ndfc_nand_remove,
>- .driver = {
>- .name = "ndfc-nand",
>- .owner = THIS_MODULE,
>+static struct of_platform_driver ndfc_driver = {
>+ .driver = {
>+ .name = "ndfc",
> },
>+ .match_table = ndfc_match,
>+ .probe = ndfc_probe,
>+ .remove = __devexit_p(ndfc_remove),
> };
>
> static int __init ndfc_nand_init(void)
> {
>- int ret;
>-
>- spin_lock_init(&ndfc_ctrl.ndfc_control.lock);
>- init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq);
>-
>- ret = platform_driver_register(&ndfc_nand_driver);
>- if (!ret)
>- ret = platform_driver_register(&ndfc_chip_driver);
>- return ret;
>+ return of_register_platform_driver(&ndfc_driver);
> }
>
> static void __exit ndfc_nand_exit(void)
> {
>- platform_driver_unregister(&ndfc_chip_driver);
>- platform_driver_unregister(&ndfc_nand_driver);
>+ of_unregister_platform_driver(&ndfc_driver);
> }
>
> module_init(ndfc_nand_init);
>@@ -316,6 +315,4 @@ module_exit(ndfc_nand_exit);
>
> MODULE_LICENSE("GPL");
> MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
>-MODULE_DESCRIPTION("Platform driver for NDFC");
>-MODULE_ALIAS("platform:ndfc-chip");
>-MODULE_ALIAS("platform:ndfc-nand");
>+MODULE_DESCRIPTION("OF Platform driver for NDFC");
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH] ndfc driver
@ 2008-12-23 12:26 Kostas Nakos
2008-12-23 22:00 ` Sean MacLennan
0 siblings, 1 reply; 28+ messages in thread
From: Kostas Nakos @ 2008-12-23 12:26 UTC (permalink / raw)
To: linux-mtd
Hello list,
with respect to Sean's updated patch (
http://lists.infradead.org/pipermail/linux-mtd/2008-December/023932.html
) of the ndfc driver:
We are using an AMCC PPC440EPx based board which requires the ndfc
driver to handle the nand memory. We have encountered 2 problems with
this latest patch:
1) Kernel oops after of_iomap() of ndfc_probe(). The external nand
memory is bound to chip select 0. The respective dts "reg" line was 'reg
= <0 d0000000 2000>;'. Using chip selects greater than zero do not crash
the kernel.
2) Byte order wrong in ndfc_calculate_ecc(). ecc_code[0] and ecc_code[1]
have been exchanged in this version of the patch which lead to ecc
errors being reported during mounting (and of course, a failed mount
operation).
These problems have been solved: (1) -hackish way- by using a dts line
like this 'reg = <1 d0000000 2000>;' and calculating the chip select in
ndfc_probe() like this 'ndfc->chip_select = reg[0] - 1;'. (2) has been
fixed by returning to the previous byte order of ecc_code.
Cheers,
Kostas
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-23 12:26 [PATCH] ndfc driver Kostas Nakos
@ 2008-12-23 22:00 ` Sean MacLennan
2008-12-24 6:58 ` knakos
2008-12-29 10:58 ` Kostas Nakos
0 siblings, 2 replies; 28+ messages in thread
From: Sean MacLennan @ 2008-12-23 22:00 UTC (permalink / raw)
To: Kostas Nakos; +Cc: linux-mtd
On Tue, 23 Dec 2008 14:26:18 +0200
"Kostas Nakos" <knakos@inaccessnetworks.com> wrote:
> Hello list,
>
> with respect to Sean's updated patch (
> http://lists.infradead.org/pipermail/linux-mtd/2008-December/023932.html
> ) of the ndfc driver:
>
> We are using an AMCC PPC440EPx based board which requires the ndfc
> driver to handle the nand memory. We have encountered 2 problems with
> this latest patch:
>
> 1) Kernel oops after of_iomap() of ndfc_probe(). The external nand
> memory is bound to chip select 0. The respective dts "reg" line was
> 'reg = <0 d0000000 2000>;'. Using chip selects greater than zero do
> not crash the kernel.
I am not a DTS expert, I just use it ;) But are you sure the second
value should be d0000000?
> 2) Byte order wrong in ndfc_calculate_ecc(). ecc_code[0] and
> ecc_code[1] have been exchanged in this version of the patch which
> lead to ecc errors being reported during mounting (and of course, a
> failed mount operation).
Are you using u-boot and, if so, what version? The ecc_code was
changed to match u-boot. We are using a heavily modified 1.3.3.
This may need to be a config option, since we cannot guarantee what
version of u-boot they are running.
Cheers,
Sean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-23 22:00 ` Sean MacLennan
@ 2008-12-24 6:58 ` knakos
2008-12-27 1:56 ` Sean MacLennan
2008-12-29 10:58 ` Kostas Nakos
1 sibling, 1 reply; 28+ messages in thread
From: knakos @ 2008-12-24 6:58 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linux-mtd
Hi Sean,
Thanks for your comments.
On Tue, 23 Dec 2008 17:00:40 -0500, Sean MacLennan
<smaclennan@pikatech.com> wrote:
> I am not a DTS expert, I just use it ;) But are you sure the second
> value should be d0000000?
Same here :-) These values were used in the previous incarnation of the dts
file
with a 2.6.26 kernel so I "migrated" them to 2.6.28-rc8. During my numerous
experiments to get the driver working, I *think* I have tried out both <0 0
2000>
and <1 0 2000>, based on your provided template, and they yielded no good
results.
BTW, what I think the crash was all about when iomap()-ing to chip select
0,
was that addresses, in this instance, of "0d0000000" collided with the
kernel
somehow, as opposed to "1d0000000" or "2d0000000" which did not. Still,
this is
an un-educated guess :-)
> Are you using u-boot and, if so, what version? The ecc_code was
> changed to match u-boot. We are using a heavily modified 1.3.3.
>
> This may need to be a config option, since we cannot guarantee what
> version of u-boot they are running.
Yep, we're using u-boot.
OK, this makes sense and I would also like to point out that I was trying
to
mount partitions created with the previous ndfc driver & kernel.
Unfortunately, I won't have access to the board until next week and I
cannot
remember accurately the u-boot version. So, if you're patient, I'll run
your
suggested reg <...> tests and provide more info on this after Xmas :-)
Thanks again,
Kostas
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-24 6:58 ` knakos
@ 2008-12-27 1:56 ` Sean MacLennan
0 siblings, 0 replies; 28+ messages in thread
From: Sean MacLennan @ 2008-12-27 1:56 UTC (permalink / raw)
To: knakos; +Cc: linux-mtd
On Wed, 24 Dec 2008 08:58:18 +0200
"knakos" <knakos@inaccessnetworks.com> wrote:
> Unfortunately, I won't have access to the board until next week and I
> cannot
> remember accurately the u-boot version. So, if you're patient, I'll
> run your
> suggested reg <...> tests and provide more info on this after Xmas :-)
No problem. I will probably have no email access for the next week.
Cheers,
Sean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-23 22:00 ` Sean MacLennan
2008-12-24 6:58 ` knakos
@ 2008-12-29 10:58 ` Kostas Nakos
2009-01-06 1:23 ` Sean MacLennan
1 sibling, 1 reply; 28+ messages in thread
From: Kostas Nakos @ 2008-12-29 10:58 UTC (permalink / raw)
To: linux-mtd
Sean MacLennan wrote:
> I am not a DTS expert, I just use it ;) But are you sure the second
> value should be d0000000?
Alright, with:
<0 0 2000> ->
__ioremap(): phys addr 0x0 is RAM lr c0008c94
ndfc 0.ndfc: failed to get memory
ndfc: probe of 0.ndfc failed with error -5
I notice that the 0xd0000000 value is also defined in the (our) platform
include for our platform in u-boot (include/configs/...):
#define CFG_NAND_ADDR 0xd0000000
> Are you using u-boot and, if so, what version? The ecc_code was
> changed to match u-boot. We are using a heavily modified 1.3.3.
The uboot version string is:
U-Boot 1.3.3-svn2646 (Jul 11 2008 - 15:45:55)
Best Regards,
Kostas
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2008-12-29 10:58 ` Kostas Nakos
@ 2009-01-06 1:23 ` Sean MacLennan
2009-01-07 9:51 ` Kostas Nakos
0 siblings, 1 reply; 28+ messages in thread
From: Sean MacLennan @ 2009-01-06 1:23 UTC (permalink / raw)
To: Kostas Nakos; +Cc: linux-mtd
On Mon, 29 Dec 2008 12:58:22 +0200
"Kostas Nakos" <knakos@inaccessnetworks.com> wrote:
> Alright, with:
>
> <0 0 2000> ->
>
> __ioremap(): phys addr 0x0 is RAM lr c0008c94
> ndfc 0.ndfc: failed to get memory
> ndfc: probe of 0.ndfc failed with error -5
>
> I notice that the 0xd0000000 value is also defined in the (our)
> platform include for our platform in u-boot (include/configs/...):
>
> #define CFG_NAND_ADDR 0xd0000000
That is where the NAND is on the warp. Could you post the complete dts?
Cheers,
Sean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2009-01-06 1:23 ` Sean MacLennan
@ 2009-01-07 9:51 ` Kostas Nakos
2009-01-07 17:21 ` Sean MacLennan
0 siblings, 1 reply; 28+ messages in thread
From: Kostas Nakos @ 2009-01-07 9:51 UTC (permalink / raw)
Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 388 bytes --]
Sean MacLennan wrote:
> That is where the NAND is on the warp. Could you post the complete dts?
Of course; attached. This is the one I use to boot the 2.6.28 kernel
(with the hackish ndfc patches). The only changes required while
migrating the entire dts from 2.6.26 to .28 concern just the ndfc block
and particularly the parameter names according to the new scheme.
Thanks,
Kostas
[-- Attachment #2: device.dts --]
[-- Type: text/plain, Size: 15928 bytes --]
/ {
#address-cells = <2>;
#size-cells = <1>;
model = "amcc";
compatible = "amcc";
dcr-parent = <&/cpus/cpu@0>;
aliases {
ethernet0 = &EMAC0;
ethernet1 = &EMAC1;
serial0 = &UART0;
serial1 = &UART1;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
model = "PowerPC,440EPx";
reg = <0>;
clock-frequency = <0>; /* Filled in by zImage */
timebase-frequency = <0>; /* Filled in by zImage */
i-cache-line-size = <20>;
d-cache-line-size = <20>;
i-cache-size = <8000>;
d-cache-size = <8000>;
dcr-controller;
dcr-access-method = "native";
};
};
memory {
device_type = "memory";
reg = <0 0 0>; /* Filled in by zImage */
};
UIC0: interrupt-controller0 {
compatible = "ibm,uic-440epx","ibm,uic";
interrupt-controller;
cell-index = <0>;
dcr-reg = <0c0 009>;
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
};
UIC1: interrupt-controller1 {
compatible = "ibm,uic-440epx","ibm,uic";
interrupt-controller;
cell-index = <1>;
dcr-reg = <0d0 009>;
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
interrupts = <1e 4 1f 4>; /* cascade */
interrupt-parent = <&UIC0>;
};
UIC2: interrupt-controller2 {
compatible = "ibm,uic-440epx","ibm,uic";
interrupt-controller;
cell-index = <2>;
dcr-reg = <0e0 009>;
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
interrupts = <1c 4 1d 4>; /* cascade */
interrupt-parent = <&UIC0>;
};
SDR0: sdr {
compatible = "ibm,sdr-440epx", "ibm,sdr-440ep";
dcr-reg = <00e 002>;
};
CPR0: cpr {
compatible = "ibm,cpr-440epx", "ibm,cpr-440ep";
dcr-reg = <00c 002>;
};
plb {
compatible = "ibm,plb-440epx", "ibm,plb4";
#address-cells = <2>;
#size-cells = <1>;
ranges;
clock-frequency = <0>; /* Filled in by zImage */
SDRAM0: sdram {
compatible = "ibm,sdram-440epx", "ibm,sdram-44x-ddr2denali";
dcr-reg = <010 2>;
};
DMA0: dma {
compatible = "ibm,dma-440epx", "ibm,dma-4xx";
dcr-reg = <100 027>;
};
MAL0: mcmal {
compatible = "ibm,mcmal-440epx", "ibm,mcmal2";
dcr-reg = <180 62>;
num-tx-chans = <2>;
num-rx-chans = <2>;
interrupt-parent = <&MAL0>;
interrupts = <0 1 2 3 4>;
#interrupt-cells = <1>;
#address-cells = <0>;
#size-cells = <0>;
interrupt-map = </*TXEOB*/ 0 &UIC0 a 4
/*RXEOB*/ 1 &UIC0 b 4
/*SERR*/ 2 &UIC1 0 4
/*TXDE*/ 3 &UIC1 1 4
/*RXDE*/ 4 &UIC1 2 4>;
interrupt-map-mask = <ffffffff>;
};
ndfc@0,d0000000 {
device_type = "nand";
compatible = "ibm,ndfc";
reg = <1 d0000000 2000>;
bank-settings = <80002222>;
ccr = <00001000>;
#address-cells = <1>;
#size-cells = <1>;
nand {
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "u-boot";
reg = <0 60000>;
};
partition@1 {
label = "uboot-env-1";
reg = <60000 4000>;
};
partition@2 {
label = "uboot-env-2";
reg = <64000 4000>;
};
partition@3 {
label = "device-tree";
reg = <68000 4000>;
};
partition@4 {
label = "bootfs";
reg = <6c000 340000>;
};
partition@5 {
label = "rootfs";
reg = <3ac000 0>;
};
};
};
USB0: ehci@e0000300 {
compatible = "ibm,usb-ehci-440epx", "usb-ehci";
interrupt-parent = <&UIC0>;
interrupts = <1a 4>;
reg = <0 e0000300 90 0 e0000390 70>;
big-endian;
};
POB0: opb {
compatible = "ibm,opb-440epx", "ibm,opb";
#address-cells = <1>;
#size-cells = <1>;
ranges = <00000000 1 00000000 80000000
80000000 1 80000000 80000000>;
interrupt-parent = <&UIC1>;
interrupts = <7 4>;
clock-frequency = <0>; /* Filled in by zImage */
EBC0: ebc {
compatible = "ibm,ebc-440epx", "ibm,ebc";
dcr-reg = <012 2>;
#address-cells = <2>;
#size-cells = <1>;
clock-frequency = <0>; /* Filled in by zImage */
interrupts = <5 1>;
interrupt-parent = <&UIC1>;
};
UART0: serial@ef600300 {
device_type = "serial";
compatible = "ns16550";
reg = <ef600300 8>;
virtual-reg = <ef600300>;
clock-frequency = <0>; /* Filled in by zImage */
current-speed = <1c200>;
interrupt-parent = <&UIC0>;
interrupts = <0 4>;
};
UART1: serial@ef600400 {
device_type = "serial";
compatible = "ns16550";
reg = <ef600400 8>;
virtual-reg = <ef600400>;
clock-frequency = <0>;
current-speed = <0>;
interrupt-parent = <&UIC0>;
interrupts = <1 4>;
};
IIC0: i2c@ef600700 {
compatible = "ibm,iic-440gpx", "ibm,iic";
reg = <ef600700 14>;
index = <0>;
interrupt-parent = <&UIC0>;
interrupts = <2 4>;
};
IIC1: i2c@ef600800 {
compatible = "ibm,iic-440gpx", "ibm,iic";
reg = <ef600800 14>;
index = <1>;
interrupt-parent = <&UIC0>;
interrupts = <7 4>;
};
GPIO0: gpio@ef600b00 {
compatible = "ibm,gpio-440ep";
reg = <ef600b00 48>;
#gpio-cells = <2>;
gpio-controller;
};
GPIO1: gpio@ef600c00 {
compatible = "ibm,gpio-440ep";
reg = <ef600c00 48>;
#gpio-cells = <2>;
gpio-controller;
};
ZMII0: emac-zmii@ef600d00 {
compatible = "ibm,zmii-440epx", "ibm,zmii";
reg = <ef600d00 c>;
};
RGMII0: emac-rgmii@ef601000 {
compatible = "ibm,rgmii-440epx", "ibm,rgmii";
reg = <ef601000 8>;
has-mdio;
};
EMAC0: ethernet@ef600e00 {
device_type = "network";
compatible = "ibm,emac-440epx", "ibm,emac4";
interrupt-parent = <&EMAC0>;
interrupts = <0 1>;
#interrupt-cells = <1>;
#address-cells = <0>;
#size-cells = <0>;
interrupt-map = </*Status*/ 0 &UIC0 18 4
/*Wake*/ 1 &UIC1 1d 4>;
reg = <ef600e00 70>;
local-mac-address = [000000000000];
mal-device = <&MAL0>;
mal-tx-channel = <0>;
mal-rx-channel = <0>;
cell-index = <0>;
max-frame-size = <2328>;
rx-fifo-size = <1000>;
tx-fifo-size = <800>;
phy-mode = "rgmii";
phy-map = <00000000>;
zmii-device = <&ZMII0>;
zmii-channel = <0>;
rgmii-device = <&RGMII0>;
rgmii-channel = <0>;
has-inverted-stacr-oc;
has-new-stacr-staopc;
};
EMAC1: ethernet@ef600f00 {
device_type = "network";
compatible = "ibm,emac-440epx", "ibm,emac4";
interrupt-parent = <&EMAC1>;
interrupts = <0 1>;
#interrupt-cells = <1>;
#address-cells = <0>;
#size-cells = <0>;
interrupt-map = </*Status*/ 0 &UIC0 19 4
/*Wake*/ 1 &UIC1 1f 4>;
reg = <ef600f00 70>;
local-mac-address = [000000000000];
mal-device = <&MAL0>;
mal-tx-channel = <1>;
mal-rx-channel = <1>;
cell-index = <1>;
max-frame-size = <2328>;
rx-fifo-size = <1000>;
tx-fifo-size = <800>;
phy-mode = "rgmii";
phy-map = <00000000>;
zmii-device = <&ZMII0>;
zmii-channel = <1>;
rgmii-device = <&RGMII0>;
rgmii-channel = <1>;
has-inverted-stacr-oc;
has-new-stacr-staopc;
};
LEDS0: led0 {
compatible = "gpio-led";
label="led0";
gpios = <&GPIO1 1 0>;
};
LEDS1: led1 {
compatible = "gpio-led";
label="led1";
gpios = <&GPIO1 0 0>;
};
LEDS2: led2 {
compatible = "gpio-led";
label="led2";
gpios = <&GPIO0 1f 0>;
};
LEDS3: led3 {
compatible = "gpio-led";
label="led3";
gpios = <&GPIO0 1e 0>;
};
LEDS4: led4 {
compatible = "gpio-led";
label="led4";
gpios = <&GPIO0 1d 0>;
};
BUTTON0: button {
gpios = <&GPIO1 c 0
>;
compatible = "gpio-button";
interrupt-parent = <&UIC0>;
interrupts = <1b 2>;
};
};
PCI0: pci@1ec000000 {
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
compatible = "ibm,plb440epx-pci", "ibm,plb-pci";
primary;
reg = <1 eec00000 8 /* Config space access */
1 eed00000 4 /* IACK */
1 eed00000 4 /* Special cycle */
1 ef400000 40>; /* Internal registers */
ranges = <02000000 0 80000000 1 80000000 0 40000000
01000000 0 00000000 1 e8000000 0 00010000
01000000 0 00000000 1 e8800000 0 03800000>;
dma-ranges = <42000000 0 0 0 0 0 80000000>;
interrupt-map-mask = <2800 0 0 0>;
interrupt-map = <
2000 0 0 0 &UIC2 3 8
2800 0 0 0 &UIC2 4 8
>;
};
};
chosen {
linux,stdout-path = "/plb/opb/serial@ef600300";
bootargs = "console=ttyS0,115200 root=1f05 rootfstype=jffs2 getty_cons=ttyS0";
};
};
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2009-01-07 9:51 ` Kostas Nakos
@ 2009-01-07 17:21 ` Sean MacLennan
2009-01-08 15:37 ` Kostas Nakos
0 siblings, 1 reply; 28+ messages in thread
From: Sean MacLennan @ 2009-01-07 17:21 UTC (permalink / raw)
To: Kostas Nakos; +Cc: linux-mtd
On Wed, 07 Jan 2009 11:51:18 +0200
"Kostas Nakos" <knakos@inaccessnetworks.com> wrote:
> Of course; attached. This is the one I use to boot the 2.6.28 kernel
> (with the hackish ndfc patches). The only changes required while
> migrating the entire dts from 2.6.26 to .28 concern just the ndfc
> block and particularly the parameter names according to the new
> scheme.
The ndfc entry must be a child of the ebc entry. So move the ndfc into
the ebc entry, and change the reg back to <0 0 2000>. It should then
work.
Cheers,
Sean
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] ndfc driver
2009-01-07 17:21 ` Sean MacLennan
@ 2009-01-08 15:37 ` Kostas Nakos
0 siblings, 0 replies; 28+ messages in thread
From: Kostas Nakos @ 2009-01-08 15:37 UTC (permalink / raw)
To: Sean MacLennan; +Cc: linux-mtd
Sean MacLennan wrote:
> The ndfc entry must be a child of the ebc entry. So move the ndfc into
> the ebc entry, and change the reg back to <0 0 2000>. It should then
> work.
OK, I tried that. I had the same crashes, unless I reverted to my hacks
and also set the address to 0xd0000000. So, exactly the same behavior.
Note also that the dts in use has been derived from a sequoia-based dev
board setup, back in 2.6.26. Let me know if there's anything else you
want me to try out.
Thanks for your efforts,
Kostas
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2009-01-08 15:37 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-23 12:26 [PATCH] ndfc driver Kostas Nakos
2008-12-23 22:00 ` Sean MacLennan
2008-12-24 6:58 ` knakos
2008-12-27 1:56 ` Sean MacLennan
2008-12-29 10:58 ` Kostas Nakos
2009-01-06 1:23 ` Sean MacLennan
2009-01-07 9:51 ` Kostas Nakos
2009-01-07 17:21 ` Sean MacLennan
2009-01-08 15:37 ` Kostas Nakos
-- strict thread matches above, loose matches on Subject: below --
2008-12-04 3:28 Sean MacLennan
2008-12-04 14:01 ` Josh Boyer
2008-12-04 17:17 ` Sean MacLennan
2008-12-09 0:34 ` Sean MacLennan
2008-12-09 2:11 ` Anton Vorontsov
2008-12-09 2:45 ` Sean MacLennan
2008-12-09 3:32 ` Josh Boyer
2008-12-09 4:54 ` Sean MacLennan
2008-12-09 7:57 ` Mitch Bradley
2008-12-10 4:01 ` Sean MacLennan
2008-12-10 8:28 ` Mitch Bradley
2008-12-09 6:10 ` Stefan Roese
2008-12-09 11:24 ` Josh Boyer
2008-12-10 23:16 ` Sean MacLennan
2008-12-17 4:14 ` Sean MacLennan
2008-12-17 11:34 ` Josh Boyer
2008-12-17 13:26 ` Josh Boyer
2008-12-09 0:51 ` Sean MacLennan
2008-10-30 6:08 Sean MacLennan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox