MTD driver for MLC NAND chips
z l
zql at glomationinc.com
Sat Oct 27 19:41:39 EDT 2007
> Show your board driver. You did look carefully at
> the BUG() at line 174
> of nand_base.c, I hope? It hints quite heavily at
> where to look.
>
I did try to trace things back back but didn't see
anything obvious.
Below is the driver,
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/sizes.h>
#define GESBC_NAND_FLASH_DATA 0x10000000
#define GPIO_PADR EP93XX_GPIO_REG(0x0)
#define GPIO_PADDR EP93XX_GPIO_REG(0x10)
#define SMCBCR1 (EP93XX_AHB_VIRT_BASE + 0x00082000 +
0x04)
/*
* MTD structure for GESBC-93xx board
*/
static struct mtd_info *gesbc_mtd = NULL;
/*
* Module stuff
*/
static unsigned long gesbc_fio_pbase =
GESBC_NAND_FLASH_DATA;
#ifdef CONFIG_MTD_PARTITIONS
/*
* Define static partitions for flash device
*/
static struct mtd_partition partition_info32[] = {
{ .name= "GESBC NAND FLASH",
.offset= 0,
.size= 128*1024*1024 },
};
/*
* Define static partitions for flash device
*/
static struct mtd_partition partition_info128[] = {
{ .name= "GESBC NAND FLASH",
.offset= 0,
.size= 128*1024*1024 },
};
/*
* Define static partitions for flash device
*/
static struct mtd_partition partition_info256[] = {
{ .name= "GESBC NAND FLASH",
.offset= 0,
.size= 256*1024*1024 },
};
/*
* Define static partitions for flash device
*/
static struct mtd_partition partition_info512[] = {
{ .name= "GESBC NAND FLASH",
.offset= 0,
.size= 512*1024*1024 },
};
#define NUM_PARTITIONS 1
#endif
/*
* hardware specific access to control-lines
* NAND_NCE: bit 0 -> bit 3
* NAND_CLE: bit 1 -> bit 4
* NAND_ALE: bit 2 -> bit 6
*/
static void gesbc_hwcontrol(struct mtd_info *mtd, int
cmd, int ctrl)
{
unsigned long flags;
struct nand_chip *chip = mtd->priv;
/* Disbale interrupt to avoid race condition */
local_irq_save(flags);
if (ctrl & NAND_CTRL_CHANGE) {
unsigned char bits;
bits = (ctrl & NAND_CLE) << 3;
bits |= (ctrl & NAND_ALE) << 4;
if (ctrl & NAND_NCE)
bits &= ~0x08;
else
bits |= 0x08;
__raw_writel( (__raw_readl(GPIO_PADR) & ~0x58 )|
bits, GPIO_PADR);
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, chip->IO_ADDR_W);
/* Restore interrupt state */
local_irq_restore(flags);
}
/*
* read device ready pin
*/
static int gesbc_device_ready(struct mtd_info *mtd)
{
return (__raw_readl(GPIO_PADR) & 0x80) >> 7;
}
#define MTDID "GESBC-nand"
static const char *probes[] = { "cmdlinepart", NULL };
/*
* Main initialization routine
*/
static int __init gesbc_nand_init (void)
{
struct nand_chip *this;
const char *part_type = 0;
int mtd_parts_nb = 0;
struct mtd_partition *mtd_parts = 0;
unsigned long flags;
void * gesbc_fio_base;
/* Allocate memory for MTD device structure and
private data */
gesbc_mtd = kmalloc(sizeof(struct mtd_info) +
sizeof(struct nand_chip),
GFP_KERNEL);
if (!gesbc_mtd) {
printk("Unable to allocate GESBC NAND MTD device
structure.\n");
return -ENOMEM;
}
/* map physical adress */
gesbc_fio_base = ioremap(gesbc_fio_pbase, SZ_1K);
if(!gesbc_fio_base) {
printk("ioremap GESBC-93xx NAND flash failed\n");
kfree(gesbc_mtd);
return -EIO;
}
/* Get pointer to private data */
this = (struct nand_chip *) (&gesbc_mtd[1]);
/* Initialize structures */
memset((char *) gesbc_mtd, 0, sizeof(struct
mtd_info));
memset((char *) this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */
gesbc_mtd->priv = this;
/* Disbale interrupt to avoid race condition */
local_irq_save(flags);
/*
* Set GPIO Port A control register so that the pins
are configured
* to be outputs for controlling the NAND flash.
*/
__raw_writel((__raw_readl(GPIO_PADDR) | 0x58) &
~0x80, GPIO_PADDR);
/* Clear NCE, clear CLE, clear ALE */
__raw_writel( (__raw_readl(GPIO_PADR) | 0x08 ) &
~0x50, GPIO_PADR);
/* Set SRAM controller to 32 bit (8 bit just doesn't
work, don't know why) bus width and 7 CLK wait state
*/
__raw_writel(0x10003ce0, SMCBCR1);
local_irq_restore(flags);
/* insert callbacks */
this->IO_ADDR_R = (void *) gesbc_fio_base;
this->IO_ADDR_W = (void *) gesbc_fio_base;
this->cmd_ctrl = (void *) gesbc_hwcontrol;
this->dev_ready = gesbc_device_ready;
this->chip_delay = 25;
this->ecc.mode = NAND_ECC_SOFT;
__raw_writel(0xffffffff, gesbc_fio_base);
printk("Searching for NAND flash...\n");
/* Scan to find existence of the device */
if (nand_scan (gesbc_mtd, 1)) {
iounmap((void *)gesbc_fio_base);
kfree (gesbc_mtd);
return -ENXIO;
}
#ifdef CONFIG_MTD_CMDLINE_PARTS
gesbc_mtd->name="GESBC-NAND";
mtd_parts_nb = parse_mtd_partitions(gesbc_mtd,
probes, &mtd_parts, 0);
if (mtd_parts_nb > 0)
part_type = "command line";
else
mtd_parts_nb = 0;
#endif
if (mtd_parts_nb == 0)
{
mtd_parts_nb = NUM_PARTITIONS;
mtd_parts = partition_info32;
if (gesbc_mtd->size >= (128 * 0x100000))
mtd_parts = partition_info128;
if (gesbc_mtd->size >= (256 * 0x100000))
mtd_parts = partition_info256;
if (gesbc_mtd->size >= (512 * 0x100000))
mtd_parts = partition_info512;
part_type = "static";
}
/* Register the partitions */
printk(KERN_NOTICE "Using %s partition definition\n",
part_type);
add_mtd_partitions(gesbc_mtd, mtd_parts,
mtd_parts_nb);
/* Return happy */
return 0;
}
module_init(gesbc_nand_init);
/*
* Clean up routine
*/
static void __exit gesbc_nand_cleanup (void)
{
/* struct nand_chip *this = (struct nand_chip *)
&gesbc_mtd[1]; */
/* Unregister the device */
del_mtd_device (gesbc_mtd);
/* Free the MTD device structure */
kfree (gesbc_mtd);
}
module_exit(gesbc_nand_cleanup);
More information about the linux-mtd
mailing list