Chinaunix首页 | 论坛 | 博客
  • 博客访问: 517042
  • 博文数量: 87
  • 博客积分: 4086
  • 博客等级: 上校
  • 技术积分: 900
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-23 15:55
文章分类

全部博文(87)

文章存档

2012年(3)

2010年(13)

2009年(7)

2008年(64)

我的朋友

分类: LINUX

2008-11-03 18:11:05

    搞定了博创经典270平台上的nand flash驱动,把源码奉上,供大家参考!
 

#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/arch/gpio.h>

#include <asm/io.h>
#include <asm/irq.h>

#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/mach-types.h>

#define GPIO_NAND_CS    (82)
#define GPIO_NAND_RB    (83)

/* MTD structure for CM-X270 board */
static struct mtd_info *up270_nand_mtd;

/* remaped IO address of the device */
static void __iomem *up270_nand_io;

/*
 * Define static partitions for flash device
 */

static struct mtd_partition partition_info[] = {
    [0] = {
        .name    = "UP270-nand",
        .offset    = 0,
        .size    = 0x4000000,
    }
};
#define NUM_PARTITIONS (ARRAY_SIZE(partition_info))

const char *part_probes[] = { "cmdlinepart", NULL };

static u_char up270_read_byte(struct mtd_info *mtd)
{
    struct nand_chip *this = mtd->priv;

    return readl(this->IO_ADDR_R);
}

static void up270_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
    int i;
    struct nand_chip *this = mtd->priv;

    for (i=0; i<len; i++)
        writel(*buf++, this->IO_ADDR_W);
}

static void up270_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
    int i;
    struct nand_chip *this = mtd->priv;

    for (i=0; i<len; i++)
        *buf++ = readl(this->IO_ADDR_R);
}

static int up270_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
    int i;
    struct nand_chip *this = mtd->priv;

    for (i=0; i<len; i++)
        if (buf[i] != (u_char)(readl(this->IO_ADDR_R)))
            return -EFAULT;

    return 0;
}

static inline void nand_cs_on(void)
{
    gpio_set_value(GPIO_NAND_CS, 0);
}

static void nand_cs_off(void)
{
    dsb();
    gpio_set_value(GPIO_NAND_CS, 1);
}

/*
 *    hardware specific access to control-lines
 */

static void up270_hwcontrol(struct mtd_info *mtd, int dat,
             unsigned int ctrl)
{
    struct nand_chip* this = mtd->priv;
    unsigned int nandaddr = (unsigned int)this->IO_ADDR_W;

    dsb();

    if (ctrl & NAND_CTRL_CHANGE) {
        if ( ctrl & NAND_ALE )
            nandaddr |= (1 << 2);
        else
            nandaddr &= ~(1 << 2);
        if ( ctrl & NAND_CLE )
            nandaddr |= (1 << 3);
        else
            nandaddr &= ~(1 << 3);
        if ( ctrl & NAND_NCE )
            nand_cs_on();
        else
            nand_cs_off();
    }

    dsb();

    this->IO_ADDR_W = (void __iomem*)nandaddr;
    if (dat != NAND_CMD_NONE)
        writel(dat, this->IO_ADDR_W);

    dsb();
}

/*
 *    read device ready pin
 */

static int up270_device_ready(struct mtd_info *mtd)
{
    dsb();
    return (gpio_get_value(GPIO_NAND_RB));
}

/*
 * Main initialization routine
 */

static int up270_init(void)
{
    struct nand_chip *this;
    const char *part_type;
    struct mtd_partition *mtd_parts;
    int mtd_parts_nb = 0;
    int ret;

    ret = gpio_request(GPIO_NAND_CS, "NAND CS");
    if (ret) {
        printk("UP270: failed to request NAND CS gpio\n");
        return ret;
    }

    gpio_direction_output(GPIO_NAND_CS, 1);

    ret = gpio_request(GPIO_NAND_RB, "NAND R/B");
    if (ret) {
        printk("UP270: failed to request NAND R/B gpio\n");
        goto err_gpio_request;
    }

    gpio_direction_input(GPIO_NAND_RB);


    /* Allocate memory for MTD device structure and private data */
    up270_nand_mtd = kzalloc(sizeof(struct mtd_info) +
                 sizeof(struct nand_chip),
                 GFP_KERNEL);
    if (!up270_nand_mtd) {
        printk("Unable to allocate UP270 NAND MTD device structure.\n");
        ret = -ENOMEM;
        goto err_kzalloc;
    }

    up270_nand_io = ioremap(0x04000000, 12);
    if (!up270_nand_io) {
        printk("Unable to ioremap NAND device\n");
        ret = -EINVAL;
        goto err_ioremap;
    }

    /* Get pointer to private data */
    this = (struct nand_chip *)(&up270_nand_mtd[1]);

    /* Link the private data with the MTD structure */
    up270_nand_mtd->owner = THIS_MODULE;
    up270_nand_mtd->priv = this;

    /* insert callbacks */
    this->IO_ADDR_R = up270_nand_io;
    this->IO_ADDR_W = up270_nand_io;
    this->cmd_ctrl = up270_hwcontrol;
    this->dev_ready = up270_device_ready;

    /* 15 us command delay time */
    this->chip_delay = 20;
    this->ecc.mode = NAND_ECC_SOFT;

    /* read/write functions */
    this->read_byte = up270_read_byte;
    this->read_buf = up270_read_buf;
    this->write_buf = up270_write_buf;
    this->verify_buf = up270_verify_buf;

    /* Scan to find existence of the device */
    if (nand_scan (up270_nand_mtd, 1)) {
        printk(KERN_NOTICE "No NAND device\n");
        ret = -ENXIO;
        goto err_scan;
    }

#ifdef CONFIG_MTD_CMDLINE_PARTS
    mtd_parts_nb = parse_mtd_partitions(up270_nand_mtd, part_probes,
                     &mtd_parts, 0);
    if (mtd_parts_nb > 0)
        part_type = "command line";
    else
        mtd_parts_nb = 0;
#endif
    if (!mtd_parts_nb) {
        mtd_parts = partition_info;
        mtd_parts_nb = NUM_PARTITIONS;
        part_type = "static";
    }

    /* Register the partitions */
    printk(KERN_NOTICE "Using %s partition definition\n", part_type);
    ret = add_mtd_partitions(up270_nand_mtd, mtd_parts, mtd_parts_nb);
    if (ret)
        goto err_scan;

    /* Return happy */
    return 0;

err_scan:
    iounmap(up270_nand_io);
err_ioremap:
    kfree(up270_nand_mtd);
err_kzalloc:
    gpio_free(GPIO_NAND_RB);
err_gpio_request:
    gpio_free(GPIO_NAND_CS);

    return ret;

}
module_init(up270_init);

/*
 * Clean up routine
 */

static void up270_cleanup(void)
{
    /* Release resources, unregister device */
    nand_release(up270_nand_mtd);

    gpio_free(GPIO_NAND_RB);
    gpio_free(GPIO_NAND_CS);

    iounmap(up270_nand_io);

    /* Free the MTD device structure */
    kfree (up270_nand_mtd);
}
module_exit(up270_cleanup);

MODULE_LICENSE("GPL");

 

这个是根据内核中的cmx270板子的代码修改而来。

阅读(2014) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~