⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c2410.c

📁 基于s3c2410的nandflash 和norflash的驱动开发
💻 C
字号:
2410 nand flash的驱动文件
#include <linux/slab.h>                            
#include <linux/module.h>                          
#include <linux/mtd/mtd.h>                         
#include <linux/mtd/nand.h>                        
#include <linux/mtd/compatmac.h>                   
#include <linux/irq.h>                             
#include <asm/io.h>                                
#include <asm/hardware.h>                          
#include <asm/sizes.h>                             
#include <linux/compiler.h>                        
#include <linux/delay.h>                           
#include <linux/interrupt.h>                       
#include <linux/sched.h>                           
                                                      
static struct mtd_info * smc _mtd = NULL;        
                                                   
#include <linux/mtd/partitions.h>                  
                                                   
  //对应于开发板的NAND Flash参数
static struct mtd_partition smc_partitions[] = {
	{
		name:		"vivi",
		size:		0x00030000,
		offset:		0x0,
		mask_flags:	MTD_WRITEABLE,
	},{
		name:		"kernel",
		size:		0x000d0000,
		offset:		0x00030000,
		mask_flags:	MTD_WRITEABLE,	//force read-only 
	}, {
		name:		"root",
		size:		0x03200000,
		offset:		0x00100000,
		mask_flags:	MTD_WRITEABLE,  // force read-only
	},{
		name:           "user_file",
                size:           0x00A00000,
                offset:         0x03300000,
	}
};
                                                                           
static void smc_hwcontrol(int cmd) {
    switch (cmd) {
    case NAND_CTL_SETNCE:	NFCONF &= ~NFCONF_nFCE_HIGH; break;
    case NAND_CTL_CLRNCE:	NFCONF |= NFCONF_nFCE_HIGH; break;
    case NAND_CTL_SETCLE:	break;
    case NAND_CTL_CLRCLE:	break;
    case NAND_CTL_SETALE:	break;
    case NAND_CTL_CLRALE:	break;
    case NAND_CTL_DAT_IN:	break;
    case NAND_CTL_DAT_OUT:	break;
    }
}                                 
 static void write_cmd(u_char val) {
    NFCMD = (u_char) val;
}

static void write_addr(u_char val) {
    NFADDR = (u_char) val;
}

static u_char read_data(void) {
    return (u_char) NFDATA;
}

static void write_data(u_char val) {
    NFDATA = (u_char) val;
}

static void wait_for_ready(void) {
    while (!(NFSTAT & NFSTAT_RnB)) {
      /* 忙 */
      udelay(10);
    }
}

inline int smc_insert(struct nand_chip *this) {
    /* Scan to find existance of the device */
    if (smc_scan (s3c2410_mtd)) {
      return -ENXIO;
    }
    /* 为内部缓冲区分配内存 */
    this->data_buf = kmalloc(sizeof(u_char) * 
			     (s3c2410_mtd->oobblock + s3c2410_mtd->oobsize), 
			     GFP_KERNEL);
    if (!this->data_buf) {
      printk ("Unable to allocate NAND data buffer for S3C2410.\n");
      this->data_buf = NULL;
      return -ENOMEM;
    }
#ifdef CONFIG_MTD_SMC_S3C2410_SMDK_PARTITION
    add_mtd_partitions(s3c2410_mtd, &smc_partitions, 
		       sizeof(smc_partitions)/sizeof(smc_partitions[0]));
//#else
    add_mtd_device(s3c2410_mtd);
#endif

    return 0;
}

inline void smc_remove(struct nand_chip *this) {
#if defined(CONFIG_MTD_SMC_S3C2410_SMDK_PARTITION) 
    del_mtd_partitions(s3c2410_mtd);
//#else
    del_mtd_device(s3c2410_mtd);
#endif

    s3c2410_mtd->size = 0;
    if (this->data_buf != NULL) {
      /* 释放数据缓冲区*/
      kfree (this->data_buf);
      this->data_buf = NULL;
    }
}

#ifdef CONFIG_PM
static unsigned long nfcon;
static int
s3c2410_smc_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
{
	struct nand_chip *this = (struct nand_chip *)pm_dev->data;
	switch (req) {
		case PM_SUSPEND:
			nfcon = NFCONF;
			break;
		case PM_RESUME:
			NFCONF = nfcon;
			/* 使能芯片-> 复位 -> 等待到可读 -> 屏蔽芯片 */
			this->hwcontrol(NAND_CTL_SETNCE);
			this->write_cmd(NAND_CMD_RESET);
			this->wait_for_ready();
			this->hwcontrol(NAND_CTL_CLRNCE);
			break;

	}
	return 0;
}
#endif
/*
 * 主程序
 */
int __init smc_s3c2410_init (void)
{
    struct nand_chip *this;
    u_int16_t nfconf;
    /*为 MTD设备分配内存 */
    s3c2410_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
			GFP_KERNEL);
    if (!s3c2410_mtd) {
      printk ("Unable to allocate S3C2410 NAND MTD device structure.\n");
      return -ENOMEM;
    }

    /* 取得指向数据的指针*/
    this = (struct nand_chip *) (&s3c2410_mtd[1]);

    /* 初始化结构 */
    memset((char *) s3c2410_mtd, 0, sizeof(struct mtd_info));
    memset((char *) this, 0, sizeof(struct nand_chip));

      s3c2410_mtd->priv = this;

    /* 设置闪存控制器*/
    {
      nfconf = NFCONF;
      /* 使能闪存控制器*/
      nfconf |= NFCONF_FCTRL_EN;

      /* 设置闪存时序 */
      nfconf &= ~NFCONF_TWRPH1;   /* 0x0 */
      nfconf |= NFCONF_TWRPH0_3;  /* 0x3 */
      nfconf &= ~NFCONF_TACLS;    /* 0x0 */

      NFCONF = nfconf;
    }

    /* 设置NAND的I/O地址 */
    this->hwcontrol = smc_hwcontrol;
    this->write_cmd = write_cmd;
    this->write_addr = write_addr;
    this->read_data = read_data;
    this->write_data = write_data;
    this->wait_for_ready = wait_for_ready;

    /* 使能芯片-> 复位 -> 等待到可读 -> 屏蔽芯片 */
    this->hwcontrol(NAND_CTL_SETNCE);
    this->write_cmd(NAND_CMD_RESET);
    this->wait_for_ready();
    this->hwcontrol(NAND_CTL_CLRNCE);
    smc_insert(this);
#ifdef CONFIG_PM
	smc_pm_dev = pm_register(PM_DEBUG_DEV, PM_SYS_MISC, s3c2410_smc_pm_callback);
	if (smc_pm_dev)
		smc_pm_dev->data = &s3c2410_mtd[1];
#endif

    return 0;
}
module_init(smc_s3c2410_init);

#ifdef MODULE
static void __exit smc_s3c2410_cleanup (void)
{
    struct nand_chip *this = (struct nand_chip *) &s3c2410_mtd[1];

    smc_remove(this);

    /* 释放MTD设备 */
    kfree (s3c2410_mtd);
}
module_exit(smc_s3c2410_cleanup);
#endif

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SMC Card on S3C2410 board");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -