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

📄 k9f5608.c

📁 深圳英培特EduKit-III实验箱实验程序。一共有10多个
💻 C
字号:
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>

/*
 * MTD structure for s3c44b0 board
 */
static struct mtd_info *s3c44b0_mtd = NULL;

/*
 * Values specific to the s3c44b0 board (used with s3c44b0 processor)
 */
#define S3C44B0_IO_BASE		0x01d20000	/* Start of s3c44b0 IO address space */
#define S3C44B0_FIO_BASE	0x04400000	/* Address where flash is mapped */
#define S3C44B0_PBDR		0x000c
#define S3C44B0_PCDR		0x0014
					/*
					 * IO offset to Port C data register
					 * where the CLE, ALE and NCE pins
					 * are wired to.
					 */
#define S3C44B0_PBDDR		0x0008
#define S3C44B0_PCDDR		0x0010
#define S3C44B0_PFDDR		0x0034		/*
					 * IO offset to Port F data direction
					 * register so we can control the IO
					 * lines.
					 */

/*
 * Module stuff
 */

static int s3c44b0_io_base = S3C44B0_IO_BASE;
static int s3c44b0_fio_base = S3C44B0_FIO_BASE;
static int s3c44b0_pbdr = S3C44B0_PBDR;
static int s3c44b0_pcdr = S3C44B0_PCDR;
static int s3c44b0_pbddr = S3C44B0_PBDDR;
static int s3c44b0_pcddr = S3C44B0_PCDDR;
static int s3c44b0_pfddr = S3C44B0_PFDDR;

#ifdef MODULE
MODULE_PARM(s3c44b0_io_base, "i");
MODULE_PARM(s3c44b0_fio_base, "i");
MODULE_PARM(s3c44b0_pbdr, "i");
MODULE_PARM(s3c44b0_pcdr, "i");
MODULE_PARM(s3c44b0_pbddr, "i");
MODULE_PARM(s3c44b0_pcddr, "i");
MODULE_PARM(s3c44b0_pfddr, "i");

__setup("s3c44b0_io_base = ", s3c44b0_io_base);
__setup("s3c44b0_fio_base = ", s3c44b0_fio_base);
__setup("s3c44b0_pbdr = ", s3c44b0_pbdr);
__setup("s3c44b0_pcdr = ", s3c44b0_pcdr);
__setup("s3c44b0_pbddr = ", s3c44b0_pbddr);
__setup("s3c44b0_pcddr = ", s3c44b0_pcddr);
__setup("s3c44b0_pfddr = ", s3c44b0_pfddr);
#endif

/*
 * Define partitions for flash device
 */
const static struct mtd_partition partition_info[] = {
	{ name: "S3C44B0 jffs2 partition",
	  offset: 0,
	  size: 32*1024*1024 },
};
#define NUM_PARTITIONS 1


/* 
 *	hardware specific access to control-lines
*/
void s3c44b0_hwcontrol(int cmd) {
    switch(cmd){
	case NAND_CTL_SETCLE: (*(volatile unsigned char *)(s3c44b0_io_base + s3c44b0_pcdr)) |=  0x0200; break;
	case NAND_CTL_CLRCLE: (*(volatile unsigned char *)(s3c44b0_io_base + s3c44b0_pcdr)) &= ~0x0200; break;

	case NAND_CTL_SETALE: (*(volatile unsigned char *)(s3c44b0_io_base + s3c44b0_pcdr)) |=  0x0100; break;
	case NAND_CTL_CLRALE: (*(volatile unsigned char *)(s3c44b0_io_base + s3c44b0_pcdr)) &= ~0x0100; break;

	case NAND_CTL_SETNCE: (*(volatile unsigned char *)(s3c44b0_io_base + s3c44b0_pbdr)) &= ~0x200; break;
	case NAND_CTL_CLRNCE: (*(volatile unsigned char *)(s3c44b0_io_base + s3c44b0_pbdr)) |=  0x200; break;
    }
}

/*
 * Main initialization routine
 */
int __init s3c44b0_init (void)
{
	int i;
	struct nand_chip *this;

	/* Allocate memory for MTD device structure and private data */
	s3c44b0_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
				GFP_KERNEL);
	if (!s3c44b0_mtd) {
		printk ("Unable to allocate s3c44b0 NAND MTD device structure.\n");
		return -ENOMEM;
	}

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

	/* Initialize structures */
	memset((char *) s3c44b0_mtd, 0, sizeof(struct mtd_info));
	memset((char *) this, 0, sizeof(struct nand_chip));

	/* Link the private data with the MTD structure */
	s3c44b0_mtd->priv = this;

	/*
	 * Set GPIO Port F control register so that the pins are configured
	 * to be outputs for controlling the NAND flash.
	 */
	(*(volatile unsigned *)(s3c44b0_io_base + s3c44b0_pbddr)) &= 0x5ff;//bit [9] set 0; or set 1 |0x200
	(*(volatile unsigned *)(s3c44b0_io_base + s3c44b0_pcddr)) = 0x0ff5ffff;//[16,17]=01, [18,19]=01
	(*(volatile unsigned *)(s3c44b0_io_base + s3c44b0_pfddr)) &= 0x3ffcf;//[4,5] set 0
	//for (i=0;i<3000;i++);

	/* Set address of NAND IO lines */
	this->IO_ADDR_R = s3c44b0_fio_base;
	this->IO_ADDR_W = s3c44b0_fio_base;
	/* Set address of hardware control function */
	this->hwcontrol = s3c44b0_hwcontrol;
	/* 15 us command delay time */
	this->chip_delay = 15;		

	/* Scan to find existence of the device */
	if (nand_scan (s3c44b0_mtd)) {
		kfree (s3c44b0_mtd);
		return -ENXIO;
	}

	/* Allocate memory for internal data buffer */
	this->data_buf = kmalloc (sizeof(u_char) * (s3c44b0_mtd->oobblock + s3c44b0_mtd->oobsize), GFP_KERNEL);
	if (!this->data_buf) {
		printk ("Unable to allocate NAND data buffer for s3c44b0.\n");
		kfree (s3c44b0_mtd);
		return -ENOMEM;
	}

	/* Allocate memory for internal data buffer */
	this->data_cache = kmalloc (sizeof(u_char) * (s3c44b0_mtd->oobblock + s3c44b0_mtd->oobsize), GFP_KERNEL);
	if (!this->data_cache) {
		printk ("Unable to allocate NAND data cache for s3c44b0.\n");
		kfree (this->data_buf);
		kfree (s3c44b0_mtd);
		return -ENOMEM;
	}
	this->cache_page = -1;

	/* Register the partitions */
		add_mtd_partitions(s3c44b0_mtd, (struct mtd_partition *)partition_info, NUM_PARTITIONS);

	/* Return happy */
	return 0;
}
module_init(s3c44b0_init);

/*
 * Clean up routine
 */
#ifdef MODULE
static void __exit s3c44b0_cleanup (void)
{
	struct nand_chip *this = (struct nand_chip *) &s3c44b0_mtd[1];

	/* Unregister the device */
	del_mtd_device (s3c44b0_mtd);

	/* Free internal data buffer */
	kfree (this->data_buf);
	kfree (this->page_cache);

	/* Free the MTD device structure */
	kfree (s3c44b0_mtd);
}
module_exit(s3c44b0_cleanup);
#endif

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Steven J. Hill <sjhill@cotw.com");
MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on s3c44b0 board");

⌨️ 快捷键说明

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