5  *   Platform independend driver for NDFC (NanD Flash Controller)
 
   6  *   integrated into EP440 cores
 
   8  *  Author: Thomas Gleixner
 
  12  *  This program is free software; you can redistribute  it and/or modify it
 
  13  *  under  the terms of  the GNU General  Public License as published by the
 
  14  *  Free Software Foundation;  either version 2 of the  License, or (at your
 
  15  *  option) any later version.
 
  18 #include <linux/module.h>
 
  19 #include <linux/mtd/nand.h>
 
  20 #include <linux/mtd/nand_ecc.h>
 
  21 #include <linux/mtd/partitions.h>
 
  22 #include <linux/mtd/ndfc.h>
 
  23 #include <linux/mtd/mtd.h>
 
  24 #include <linux/platform_device.h>
 
  28 #include <asm/ibm405.h>
 
  30 #include <asm/ibm44x.h>
 
  33 struct ndfc_nand_mtd {
 
  35         struct nand_chip                chip;
 
  36         struct platform_nand_chip       *pl_chip;
 
  39 static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS];
 
  41 struct ndfc_controller {
 
  42         void __iomem            *ndfcbase;
 
  43         struct nand_hw_control  ndfc_control;
 
  44         atomic_t                childs_active;
 
  47 static struct ndfc_controller ndfc_ctrl;
 
  49 static void ndfc_select_chip(struct mtd_info *mtd, int chip)
 
  52         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
  53         struct nand_chip *nandchip = mtd->priv;
 
  54         struct ndfc_nand_mtd *nandmtd = nandchip->priv;
 
  55         struct platform_nand_chip *pchip = nandmtd->pl_chip;
 
  57         ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
 
  59                 ccr &= ~NDFC_CCR_BS_MASK;
 
  60                 ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
 
  62                 ccr |= NDFC_CCR_RESET_CE;
 
  63         __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
 
  66 static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 
  68         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
  70         if (cmd == NAND_CMD_NONE)
 
  74                 writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_CMD);
 
  76                 writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE);
 
  79 static int ndfc_ready(struct mtd_info *mtd)
 
  81         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
  83         return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
 
  86 static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
 
  89         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
  91         ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
 
  92         ccr |= NDFC_CCR_RESET_ECC;
 
  93         __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
 
  97 static int ndfc_calculate_ecc(struct mtd_info *mtd,
 
  98                               const u_char *dat, u_char *ecc_code)
 
 100         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
 102         uint8_t *p = (uint8_t *)&ecc;
 
 105         ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC);
 
 114  * Speedups for buffer read/write/verify
 
 116  * NDFC allows 32bit read/write of data. So we can speed up the buffer
 
 117  * functions. No further checking, as nand_base will always read/write
 
 120 static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 
 122         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
 123         uint32_t *p = (uint32_t *) buf;
 
 125         for(;len > 0; len -= 4)
 
 126                 *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA);
 
 129 static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 
 131         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
 132         uint32_t *p = (uint32_t *) buf;
 
 134         for(;len > 0; len -= 4)
 
 135                 __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA);
 
 138 static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 
 140         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
 141         uint32_t *p = (uint32_t *) buf;
 
 143         for(;len > 0; len -= 4)
 
 144                 if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA))
 
 150  * Initialize chip structure
 
 152 static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
 
 154         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
 155         struct nand_chip *chip = &mtd->chip;
 
 157         chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
 
 158         chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
 
 159         chip->cmd_ctrl = ndfc_hwcontrol;
 
 160         chip->dev_ready = ndfc_ready;
 
 161         chip->select_chip = ndfc_select_chip;
 
 162         chip->chip_delay = 50;
 
 164         chip->options = mtd->pl_chip->options;
 
 165         chip->controller = &ndfc->ndfc_control;
 
 166         chip->read_buf = ndfc_read_buf;
 
 167         chip->write_buf = ndfc_write_buf;
 
 168         chip->verify_buf = ndfc_verify_buf;
 
 169         chip->ecc.correct = nand_correct_data;
 
 170         chip->ecc.hwctl = ndfc_enable_hwecc;
 
 171         chip->ecc.calculate = ndfc_calculate_ecc;
 
 172         chip->ecc.mode = NAND_ECC_HW;
 
 173         chip->ecc.size = 256;
 
 175         chip->ecclayout = chip->ecc.layout = mtd->pl_chip->ecclayout;
 
 176         mtd->mtd.priv = chip;
 
 177         mtd->mtd.owner = THIS_MODULE;
 
 180 static int ndfc_chip_probe(struct platform_device *pdev)
 
 182         struct platform_nand_chip *nc = pdev->dev.platform_data;
 
 183         struct ndfc_chip_settings *settings = nc->priv;
 
 184         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
 185         struct ndfc_nand_mtd *nandmtd;
 
 187         if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS)
 
 190         /* Set the bank settings */
 
 191         __raw_writel(settings->bank_settings,
 
 192                      ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2));
 
 194         nandmtd = &ndfc_mtd[pdev->id];
 
 195         if (nandmtd->pl_chip)
 
 198         nandmtd->pl_chip = nc;
 
 199         ndfc_chip_init(nandmtd);
 
 202         if (nand_scan(&nandmtd->mtd, nc->nr_chips)) {
 
 203                 nandmtd->pl_chip = NULL;
 
 207 #ifdef CONFIG_MTD_PARTITIONS
 
 208         printk("Number of partitions %d\n", nc->nr_partitions);
 
 209         if (nc->nr_partitions) {
 
 210                 /* Add the full device, so complete dumps can be made */
 
 211                 add_mtd_device(&nandmtd->mtd);
 
 212                 add_mtd_partitions(&nandmtd->mtd, nc->partitions,
 
 217                 add_mtd_device(&nandmtd->mtd);
 
 220         atomic_inc(&ndfc->childs_active);
 
 224 static int ndfc_chip_remove(struct platform_device *pdev)
 
 229 static int ndfc_nand_probe(struct platform_device *pdev)
 
 231         struct platform_nand_ctrl *nc = pdev->dev.platform_data;
 
 232         struct ndfc_controller_settings *settings = nc->priv;
 
 233         struct resource *res = pdev->resource;
 
 234         struct ndfc_controller *ndfc = &ndfc_ctrl;
 
 235         unsigned long long phys = settings->ndfc_erpn | res->start;
 
 237 #ifndef CONFIG_PHYS_64BIT
 
 238         ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
 
 240         ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
 
 242         if (!ndfc->ndfcbase) {
 
 243                 printk(KERN_ERR "NDFC: ioremap failed\n");
 
 247         __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR);
 
 249         spin_lock_init(&ndfc->ndfc_control.lock);
 
 250         init_waitqueue_head(&ndfc->ndfc_control.wq);
 
 252         platform_set_drvdata(pdev, ndfc);
 
 254         printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n",
 
 255                __raw_readl(ndfc->ndfcbase + NDFC_REVID));
 
 260 static int ndfc_nand_remove(struct platform_device *pdev)
 
 262         struct ndfc_controller *ndfc = platform_get_drvdata(pdev);
 
 264         if (atomic_read(&ndfc->childs_active))
 
 268                 platform_set_drvdata(pdev, NULL);
 
 269                 iounmap(ndfc_ctrl.ndfcbase);
 
 270                 ndfc_ctrl.ndfcbase = NULL;
 
 275 /* driver device registration */
 
 277 static struct platform_driver ndfc_chip_driver = {
 
 278         .probe          = ndfc_chip_probe,
 
 279         .remove         = ndfc_chip_remove,
 
 282                 .owner  = THIS_MODULE,
 
 286 static struct platform_driver ndfc_nand_driver = {
 
 287         .probe          = ndfc_nand_probe,
 
 288         .remove         = ndfc_nand_remove,
 
 291                 .owner  = THIS_MODULE,
 
 295 static int __init ndfc_nand_init(void)
 
 299         spin_lock_init(&ndfc_ctrl.ndfc_control.lock);
 
 300         init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq);
 
 302         ret = platform_driver_register(&ndfc_nand_driver);
 
 304                 ret = platform_driver_register(&ndfc_chip_driver);
 
 308 static void __exit ndfc_nand_exit(void)
 
 310         platform_driver_unregister(&ndfc_chip_driver);
 
 311         platform_driver_unregister(&ndfc_nand_driver);
 
 314 module_init(ndfc_nand_init);
 
 315 module_exit(ndfc_nand_exit);
 
 317 MODULE_LICENSE("GPL");
 
 318 MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
 
 319 MODULE_DESCRIPTION("Platform driver for NDFC");
 
 320 MODULE_ALIAS("platform:ndfc-chip");
 
 321 MODULE_ALIAS("platform:ndfc-nand");