📄 nand_s3c2410.c
字号:
/* * NAND controller on SAMSUNG S3C2410 * * bushi@mizi.com * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. */#include <linux/init.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/mtd/partitions.h>#include <linux/delay.h>#include <asm/arch/hardware.h>#include <asm/sizes.h>//#define NUM_PARTITIONS 5#define NUM_PARTITIONS 2static struct mtd_info *s3c2410_nand_mtd = NULL;static struct mtd_partition def_partition_info[] = {
{ name: "bon", offset: 0, size: 0x04000000}, { name: "mtd", offset: 0x00400000, size: 0x03af8000},};/*static struct mtd_partition def_partition_info[] = {
{ name: "vivi",
offset: 0,
size: 0x00020000},
{ name: "param",
offset: 0x00020000,
size: 0x00010000},
{ name: "kernel",
offset: 0x00030000,
size: 0x000c0000},
{ name: "root",
offset: 0x00100000,
size: 0x00300000},
{ name: "user",
offset: 0x00400000,
size: 0x03af8000}
};*//* * if you use the BON, * the partition table for MTD blkdev will be generated by "bon_check_mtd()". */#ifdef CONFIG_MTD_NAND_BONFSstatic int mtd_num = 0;static struct mtd_partition *partition_info = NULL;extern struct nand_oobinfo bonfs_oob;extern int bon_check_mtd(struct mtd_info *mtd, struct mtd_partition **mtd_table);#endif /* CONFIG_MTD_NAND_BONFS */static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip){ if (chip == 0) NFCONF &= ~NFCONF_nFCE_HIGH; else NFCONF |= NFCONF_nFCE_HIGH;}static int s3c2410_nand_device_ready(struct mtd_info *mtd){ return (NFSTAT & NFSTAT_RnB) ? 1:0;}static void s3c2410_nand_write_cmd(struct mtd_info *mtd, u_char var){ NFCMD=(u_char)var;}static void s3c2410_nand_write_addr(struct mtd_info *mtd, u_char var){ NFADDR=(u_char)var;}static void s3c2410_nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr){ register struct nand_chip *this = mtd->priv; /* * Write out the command to the device. */ if (command == NAND_CMD_SEQIN) { int readcmd; if (column >= mtd->oobblock) { /* OOB area */ column -= mtd->oobblock; readcmd = NAND_CMD_READOOB; } else if (column < 256) { /* First 256 bytes --> READ0 */ readcmd = NAND_CMD_READ0; } else { column -= 256; readcmd = NAND_CMD_READ1; } NFCMD = readcmd; } NFCMD = (command & 0xFF); if (column != -1 || page_addr != -1) { /* Serially input address */ if (column != -1) NFADDR = (column & 0xFF); if (page_addr != -1) { NFADDR = (unsigned char)(page_addr & 0xff); NFADDR = (unsigned char)((page_addr >> 8) & 0xff); /* One more address cycle for higher density devices */ if (mtd->size & 0x0c000000) NFADDR = (unsigned char)((page_addr >> 16) & 0x0f); } /* Latch in address */ } /* * program and erase have their own busy handlers * status and sequential in needs no delay */ switch (command) { case NAND_CMD_PAGEPROG: case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: case NAND_CMD_SEQIN: case NAND_CMD_STATUS: return; case NAND_CMD_RESET: if (this->dev_ready) break; NFCMD = NAND_CMD_STATUS; while ( !(NFDATA & 0x40)); return; /* This applies to read commands */ default: if (!this->dev_ready) { udelay (this->chip_delay); return; } } /* wait until command is processed */ while (!this->dev_ready(mtd));}int __init s3c2410_nand_init (void){ struct nand_chip *this; u_int16_t nfconf; int err = 0; /* Allocate memory for MTD device structure and private data */ s3c2410_nand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL); if (!s3c2410_nand_mtd) { printk ("Unable to allocate NAND MTD device structure.\n"); err = -ENOMEM; goto out; } /* Get pointer to private data */ this = (struct nand_chip *) (&s3c2410_nand_mtd[1]); /* Initialize structures */ memset((char *) s3c2410_nand_mtd, 0, sizeof(struct mtd_info)); memset((char *) this, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ s3c2410_nand_mtd->priv = this;#if 1 /* * boot-loader's stuff */ nfconf = NFCONF; nfconf |= NFCONF_FCTRL_EN; nfconf &= ~NFCONF_TWRPH1; /* 0x0 */ nfconf |= NFCONF_TWRPH0_3; /* 0x3 */ nfconf &= ~NFCONF_TACLS; /* 0x0 */ NFCONF = nfconf;// NFCONF &= ~NFCONF_nFCE_HIGH;// NFCMD= NAND_CMD_RESET;// udelay(500);// NFCONF |= NFCONF_nFCE_HIGH; #endif /* Set address of NAND IO lines */// this->IO_ADDR_R = io_p2v(0x4e00000c);// this->IO_ADDR_W = io_p2v(0x4e00000c); this->select_chip = s3c2410_nand_select_chip; this->dev_ready = s3c2410_nand_device_ready; this->write_cmd = s3c2410_nand_write_cmd; this->write_addr = s3c2410_nand_write_addr; this->cmdfunc = s3c2410_nand_cmdfunc; this->eccmode = NAND_ECC_SOFT; /* 20 us command delay time */ this->chip_delay = 200; /* Scan to find existance of the device */ if (nand_scan (s3c2410_nand_mtd, 1)) { err = -ENXIO; goto out_mtd; } /* Allocate memory for internal data buffer */ this->data_buf = kmalloc (sizeof(u_char) * (s3c2410_nand_mtd->oobblock + s3c2410_nand_mtd->oobsize), GFP_KERNEL); if (!this->data_buf) { printk ("Unable to allocate NAND data buffer\n"); err = -ENOMEM; goto out_mtd; }#ifdef CONFIG_MTD_NAND_BONFS s3c2410_nand_mtd->oobinfo = bonfs_oob; mtd_num = bon_check_mtd(s3c2410_nand_mtd, &partition_info); if (mtd_num > 1) add_mtd_partitions(s3c2410_nand_mtd, partition_info, mtd_num); else{// add_mtd_device(s3c2410_nand_mtd); def_partition_info[0].oobsel=&bonfs_oob; add_mtd_partitions(s3c2410_nand_mtd, &def_partition_info, NUM_PARTITIONS); }#else add_mtd_device(s3c2410_nand_mtd);// add_mtd_partitions(s3c2410_nand_mtd, partition_info, NUM_PARTITIONS); #endif goto out;out_cac: kfree (this->data_buf); out_mtd: kfree (s3c2410_nand_mtd);out: return err;}module_init(s3c2410_nand_init);/* * Clean up routine */#ifdef MODULEstatic void __exit s3c2410_nand_cleanup (void){ struct nand_chip *this = (struct nand_chip *) &s3c2410_nand_mtd[1]; /* Unregister partitions */ del_mtd_partitions(s3c2410_nand_mtd); /* Unregister the device */ del_mtd_device (s3c2410_nand_mtd); /* Free internal data buffers */ kfree (this->data_buf); /* Free the MTD device structure */ kfree (s3c2410_nand_mtd);}module_exit(s3c2410_nand_cleanup);#endifMODULE_LICENSE("GPL");MODULE_AUTHOR("SeonKon Choi <bushi@mizi.com>; MIZI Research, Inc.");/* * NAND Flash Controller (Page 6-1 ~ 6-8) * * Register NFCONF NAND Flash Configuration [word, R/W, 0x00000000] NFCMD NAND Flash Command Set [word, R/W, 0x00000000] NFADDR NAND Flash Address Set [word, R/W, 0x00000000] NFDATA NAND Flash Data [word, R/W, 0x00000000] NFSTAT NAND Flash Status [word, R, 0x00000000] NFECC NAND Flash ECC [3 bytes, R, 0x00000000] * */ #if 0#define bNAND_CTL(Nb) __REG(0x4e000000 + (Nb))#define NFCONF bNAND_CTL(0x00)#define NFCMD bNAND_CTL(0x04)#define NFADDR bNAND_CTL(0x08)#define NFDATA bNAND_CTL(0x0c)#define NFSTAT bNAND_CTL(0x10)#define NFECC bNAND_CTL(0x14)#define fNFCONF_TWRPH1 Fld(3,0)#define NFCONF_TWRPH1 FMsk(fNFCONF_TWRPH1)#define NFCONF_TWRPH1_0 FInsrt(0x0, fNFCONF_TWRPH1) /* 0 */#define fNFCONF_TWRPH0 Fld(3,4)#define NFCONF_TWRPH0 FMsk(fNFCONF_TWRPH0)#define NFCONF_TWRPH0_3 FInsrt(0x3, fNFCONF_TWRPH0) /* 3 */#define fNFCONF_TACLS Fld(3,8)#define NFCONF_TACLS FMsk(fNFCONF_TACLS)#define NFCONF_TACLS_0 FInsrt(0x0, fNFCONF_TACLS) /* 0 */#define fNFCONF_nFCE Fld(1,11)#define NFCONF_nFCE FMsk(fNFCONF_nFCE)#define NFCONF_nFCE_LOW FInsrt(0x0, fNFCONF_nFCE) /* active */#define NFCONF_nFCE_HIGH FInsrt(0x1, fNFCONF_nFCE) /* inactive */#define fNFCONF_ECC Fld(1,12)#define NFCONF_ECC FMsk(fNFCONF_ECC)#define NFCONF_ECC_NINIT FInsrt(0x0, fNFCONF_ECC) /* not initialize */#define NFCONF_ECC_INIT FInsrt(0x1, fNFCONF_ECC) /* initialize */#define fNFCONF_ADDRSTEP Fld(1,13) /* Addressing Step */#define NFCONF_ADDRSTEP FMsk(fNFCONF_ADDRSTEP)#define fNFCONF_PAGESIZE Fld(1,14)#define NFCONF_PAGESIZE FMsk(fNFCONF_PAGESIZE)#define NFCONF_PAGESIZE_256 FInsrt(0x0, fNFCONF_PAGESIZE) /* 256 bytes */#define NFCONF_PAGESIZE_512 FInsrt(0x1, fNFCONF_PAGESIZE) /* 512 bytes */#define fNFCONF_FCTRL Fld(1,15) /* Flash controller enable/disable */#define NFCONF_FCTRL FMsk(fNFCONF_FCTRL)#define NFCONF_FCTRL_DIS FInsrt(0x0, fNFCONF_FCTRL) /* Disable */#define NFCONF_FCTRL_EN FInsrt(0x1, fNFCONF_FCTRL) /* Enable */#define NFSTAT_RnB (1 << 0)#define NFSTAT_nFWE (1 << 8)#define NFSTAT_nFRE (1 << 9)#define NFSTAT_ALE (1 << 10)#define NFSTAT_CLE (1 << 11)#define NFSTAT_AUTOBOOT (1 << 15)#endif /* 0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -