os/linux-2.6-tag--devboard-R2_10-4/arch/cris/arch-v32/drivers/nandflash.c

Go to the documentation of this file.
00001 /*
00002  *  arch/cris/arch-v32/drivers/nandflash.c
00003  *
00004  *  Copyright (c) 2004
00005  *
00006  *  Derived from drivers/mtd/nand/spia.c
00007  *        Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
00008  * 
00009  * $Id: nandflash.c,v 1.1.1.1 2008/11/27 20:04:00 elphel Exp $
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License version 2 as
00013  * published by the Free Software Foundation.
00014  *
00015  */
00016 
00017 #include <linux/slab.h>
00018 #include <linux/init.h>
00019 #include <linux/module.h>
00020 #include <linux/mtd/mtd.h>
00021 #include <linux/mtd/nand.h>
00022 #include <linux/mtd/partitions.h>
00023 #include <asm/arch/memmap.h>
00024 #include <asm/arch/hwregs/reg_map.h>
00025 #include <asm/arch/hwregs/reg_rdwr.h>
00026 #include <asm/arch/hwregs/gio_defs.h>
00027 #include <asm/arch/hwregs/bif_core_defs.h>
00028 #include <asm/io.h>
00029 #include <linux/time.h> //debug - AF
00030 
00031 
00032 #define CE_BIT 4
00033 #define CLE_BIT 5
00034 #define ALE_BIT 6
00035 #define BY_BIT 7
00036 
00037 /* Bitmask for control pins */
00038 #define PIN_BITMASK ((1 << CE_BIT) | (1 << CLE_BIT) | (1 << ALE_BIT))
00039 
00040 /* Bitmask for mtd nand control bits */
00041 #define CTRL_BITMASK (NAND_NCE | NAND_CLE | NAND_ALE)
00042 
00044 #define DEBUG_ELPHEL_MTD 1
00045 static struct mtd_info *crisv32_mtd = NULL;
00046 /* 
00047  *      hardware specific access to control-lines
00048 */
00049 
00050 volatile unsigned long *port_dummy_addr; 
00051 
00052 
00053 static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd,
00054                               unsigned int ctrl)
00055 {
00056 //   unsigned long flags;
00057    reg_gio_rw_pa_dout dout;
00058    struct nand_chip *this = mtd->priv;
00059 #if DEBUG_ELPHEL_MTD
00060    reg_bif_core_rw_grp3_cfg csr3_cfg=REG_RD(bif_core, regi_bif_core, rw_grp3_cfg);
00061    int dd=((int *) &csr3_cfg)[0];
00062    int dbg_mark=0;
00063 #endif
00064 //      local_irq_save(flags);
00065         /* control bits change */
00066    if (ctrl & NAND_CTRL_CHANGE) {
00067      dout = REG_RD(gio, regi_gio, rw_pa_dout);
00068 #if DEBUG_ELPHEL_MTD
00069      if (dd & 0x10000000)  dbg_mark= (dout.data & (1 << CE_BIT)) && (ctrl & NAND_NCE);
00070 #endif
00071      dout.data &= ~PIN_BITMASK;
00073 #if (CE_BIT == 4 && NAND_NCE == 1 &&  \
00074      CLE_BIT == 5 && NAND_CLE == 2 && \
00075      ALE_BIT == 6 && NAND_ALE == 4)
00076                 /* Pins in same order as control bits, but shifted.
00077                  * Optimize for this case; works for 2.6.18 */
00078       if (!(ctrl & NAND_NCE)) ctrl &= ~(NAND_ALE | NAND_CLE); // Andrey - same as in bootloader, turn off ALE, CLE if no CE. Optimize if works
00079                 dout.data |= ((ctrl & CTRL_BITMASK) ^ NAND_NCE) << CE_BIT;
00080 #warning using FAST nand bits =================================, yes, here
00081 #else
00082                 /* the slow way */
00083                 if (!(ctrl & NAND_NCE))
00084                         dout.data |= (1 << CE_BIT);
00085                 if (ctrl & NAND_CLE)
00086                         dout.data |= (1 << CLE_BIT);
00087                 if (ctrl & NAND_ALE)
00088                         dout.data |= (1 << ALE_BIT);
00089 #warning using SLOW nand bits =================================
00090 #endif
00091       REG_WR(gio, regi_gio, rw_pa_dout, dout);
00092         }
00093 #if DEBUG_ELPHEL_MTD
00094    if (dbg_mark) printk("}");
00095 #endif
00096 
00097         /* command to chip */
00098         if (cmd != NAND_CMD_NONE) {
00099                 writeb(cmd, this->IO_ADDR_W);
00101 //      if (port_dummy_addr[0]) {  local_irq_restore(flags) };
00102 //      else                    {  local_irq_restore(flags) };
00103       if (port_dummy_addr[0]) return;
00104       return;
00105    }
00106 //      local_irq_restore(flags);
00107 }
00108 
00109 /*
00110 *       read device ready pin
00111 */
00112 int crisv32_device_ready(struct mtd_info *mtd)
00113 {
00114    reg_gio_rw_pa_dout dout; //AF
00115    dout = REG_RD(gio, regi_gio, rw_pa_dout); // AF
00116    if (dout.data & NAND_NCE) printk("probed READY while NCE==1 !!!\n");
00117 //printk("R"); // command
00118         reg_gio_r_pa_din din = REG_RD(gio, regi_gio, r_pa_din);
00119         return ((din.data & (1 << BY_BIT)) >> BY_BIT);
00120 }
00121 
00122 /*
00123  * Main initialization routine
00124  */
00125 struct mtd_info* __init crisv32_nand_flash_probe (void)
00126 {
00127         void __iomem *read_cs;
00128         void __iomem *write_cs;
00129 
00130         reg_bif_core_rw_grp3_cfg bif_cfg = REG_RD(bif_core, regi_bif_core, rw_grp3_cfg);
00131         reg_gio_rw_pa_oe pa_oe = REG_RD(gio, regi_gio, rw_pa_oe);
00132         struct nand_chip *this;
00133         int err = 0;
00134 
00135         /* Allocate memory for MTD device structure and private data */
00136         crisv32_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
00137                                 GFP_KERNEL);
00138         if (!crisv32_mtd) {
00139                 printk ("Unable to allocate CRISv32 NAND MTD device structure.\n");
00140                 err = -ENOMEM;
00141                 return NULL;
00142         }
00143 
00144         read_cs   = ioremap(MEM_CSP0_START | MEM_NON_CACHEABLE, 8192);
00145         write_cs  = ioremap(MEM_CSP1_START | MEM_NON_CACHEABLE, 8192);
00146 
00147         if (!read_cs || !write_cs) {
00148                 printk("CRISv32 NAND ioremap failed\n");
00149                 err = -EIO;
00150                 goto out_mtd;
00151         }
00152    port_dummy_addr= (unsigned long *) ioremap(MEM_CSR1_START | MEM_NON_CACHEABLE, 8192);
00153    if (!port_dummy_addr) {
00154       printk("CRISv32 NAND - port_dummy_addr ioremap failed\n");
00155       err = -EIO;
00156       goto out_dummy;
00157    }
00158 
00159         /* Get pointer to private data */
00160         this = (struct nand_chip *) (&crisv32_mtd[1]);
00161 
00162         pa_oe.oe |= 1 << CE_BIT;
00163         pa_oe.oe |= 1 << ALE_BIT;
00164         pa_oe.oe |= 1 << CLE_BIT;
00165         pa_oe.oe &= ~ (1 << BY_BIT);
00166         REG_WR(gio, regi_gio, rw_pa_oe, pa_oe);
00167 
00168         bif_cfg.gated_csp0 = regk_bif_core_rd;
00169         bif_cfg.gated_csp1 = regk_bif_core_wr;
00170         REG_WR(bif_core, regi_bif_core, rw_grp3_cfg, bif_cfg);
00171 
00172         /* Initialize structures */
00173         memset((char *) crisv32_mtd, 0, sizeof(struct mtd_info));
00174         memset((char *) this, 0, sizeof(struct nand_chip));
00175 
00176         /* Link the private data with the MTD structure */
00177         crisv32_mtd->priv = this;
00178 
00179         /* Set address of NAND IO lines */
00180         this->IO_ADDR_R = read_cs;
00181         this->IO_ADDR_W = write_cs;
00182         this->cmd_ctrl = crisv32_hwcontrol;
00183         this->dev_ready = crisv32_device_ready;
00184         /* 20 us command delay time */
00185         this->chip_delay = 20;          
00186         this->ecc.mode = NAND_ECC_SOFT;
00187 
00188         /* Enable the following for a flash based bad block table */
00189         /* this->options = NAND_USE_FLASH_BBT; */
00190         this->options = NAND_USE_FLASH_BBT;
00191 
00192         /* Scan to find existance of the device */
00193         if (nand_scan (crisv32_mtd, 1)) {
00194                 err = -ENXIO;
00195                 goto out_ior;
00196         }
00198    int isg=0;
00199    int old= ((int *) &bif_cfg)[0];
00200    switch ((((this->full_id) >> 24) & 0xff) & 0x88) {
00201    case 0x00: isg=50; //cycle 50ns
00202       bif_cfg.lw=3;
00203       bif_cfg.ew=1;
00204       bif_cfg.zw=1;
00205       break;
00206    case 0x08: isg=30; //cycle 30ns
00207       bif_cfg.lw=1;
00208       bif_cfg.ew=0; 
00209       bif_cfg.zw=0;
00210       break;
00211    case 0x80: isg=25; //cycle 25ns
00212       bif_cfg.lw=0;
00213       bif_cfg.ew=0;
00214       bif_cfg.zw=0;
00215       break;
00216    default: isg=-1; // reserved
00217    };
00218    if (isg>=0) {
00219      printk ("Flash is rated %d ns, modifying bif_core_rw_grp3: old=0x%x, new=0x%x\n",isg,old, ((int *) &bif_cfg)[0]);
00220      REG_WR(bif_core, regi_bif_core, rw_grp3_cfg, bif_cfg);
00221    } else printk ("Unrecognised flash speed grade - ID3=0x%02x\n",(int) ((this->full_id) >> 24) & 0xff);
00222 
00223         return crisv32_mtd;
00224         
00225 out_ior:
00226    iounmap((void *) port_dummy_addr);
00227 out_dummy:
00228         iounmap((void *) read_cs);
00229         iounmap((void *) write_cs);     
00230 out_mtd:
00231         kfree (crisv32_mtd);
00232         return NULL;
00233 }

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1