smc_s3c2410.c

来自「移植到2410开发板上的源代码」· C语言 代码 · 共 410 行

C
410
字号
/* * MTD NAND device driver for S3C2410 Development Board * based on smc.c *  * 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/slab.h>#include <linux/module.h>#include <linux/mtd/mtd.h>#include <linux/mtd/nand.h>#include <linux/irq.h>#include <asm/io.h>#include <linux/delay.h>#ifdef CONFIG_PM#include <linux/pm.h>#endif#ifdef CONFIG_PMstruct pm_dev *smc_pm_dev;#endif#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)/* * nandy: 芒闭揪啊 富窍辨: bon阑 荤侩且 版快俊绰 荤侩窍搁 救等翠聪促.   (bon捞 mtd partition阑 殿废沁扁锭巩俊...)   tolkien: 绊磨 巴. *///#undef CONFIG_MTD_SMC_S3C2410_SMDK_PARTITION  //commented by liuke//liuke begin#define CONFIG_MTD_SMC_S3C2410_SMDK_PARTITION//liuke end/* * MTD structure for S3C2410 Development Board */static struct mtd_info *s3c2410_mtd = NULL;#ifdef CONFIG_MTD_SMC_S3C2410_SMDK_PARTITION#include <linux/mtd/partitions.h>/*static struct mtd_partition smc_partitions[] = {	{		name:		"kernel",		size:		0x000c0000,		offset:		0x0,		mask_flags:	MTD_WRITEABLE,	//force read-only 	}, {		name:		"root",		size:		0x00a00000,		offset:		MTDPART_OFS_APPEND,		mask_flags:	MTD_WRITEABLE,  // force read-only 	}};*//*static struct mtd_partition partition_info64k[] = {        // BOOTLOADER + KERNEL         { name: "S3C2410 flash partition 0 BOOTLOADER AND KERNEL",          offset: 0,          size:   1 * SZ_1M},        { name: "S3C2410 flash partition 1 ROOTDISK-CRAMFS",          offset: 1 * SZ_1M,          size:   1 * SZ_1M},        { name: "S3C2410 flash partition 2 TESTOS-EXT2",          offset: 2 * SZ_1M,          size:   6 * SZ_1M},        { name: "S3C2410 flash partition 3 JFFS2-1",          offset: 8 * SZ_1M,          size:   16 * SZ_1M},        { name: "S3C2410 flash partition 4 JFFS2-2",          offset: 24 * SZ_1M,          size:   8  * SZ_1M},        { name: "S3C2410 flash partition 5 JFFS2-3",          offset: 32 * SZ_1M,          size:   32  * SZ_1M},};*/static struct mtd_partition smc_partitions[] = {        {                name:           "boot",                offset:         0,                size:           0x00030000,		mask_flags:           0        }, 		{                name:           "kernel",                offset:         0x00030000,                size:           0x001D0000,                mask_flags:           0        }, 	{                name:           "rootfs",                offset:         0x00200000,//		size:           0x00600000,		size:		0x01e00000,                mask_flags:           0        },/*	{		name:		"ext-fs1",		offset:		0x00800000,		size:		0x00800000,		mask_flags:	0	},		{		name:		"ext-fs2",		offset:		0x01000000,		size:		0x01000000,		mask_flags:	0	},*/	{		name:		"ext-fs3",		offset:		0x02000000,		size:		0x02000000,		mask_flags:	0	}};  /*static struct mtd_partition smc_partitions[] = {        {                name:           "vivi",                offset:         0,                size:           0x00020000,		mask_flags:           0        }, 	{                name:           "param",                offset:         0x00020000,                size:           0x00010000,                mask_flags:           0        }, 	{                name:           "kernel",                offset:         0x00030000,                size:           0x000C0000,                mask_flags:           0        }, 	{                name:           "rootcramfscn",                offset:         0x00100000,                size:           0x01f00000,                mask_flags:           0        }};*/#endifstatic 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)) {      /* Busy */      udelay(10);    }}inline int smc_insert(struct nand_chip *this) {    /* Scan to find existance of the device */    if (smc_scan (s3c2410_mtd)) {      return -ENXIO;    }    /* Allocate memory for internal data buffer */    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) {      /* Free internal data buffer */      kfree (this->data_buf);      this->data_buf = NULL;    }}#ifdef CONFIG_PMstatic unsigned long nfcon;static ints3c2410_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;			/* Chip Enable -> RESET -> Wait for Ready -> Chip Disable */			this->hwcontrol(NAND_CTL_SETNCE);			this->write_cmd(NAND_CMD_RESET);			this->wait_for_ready();			this->hwcontrol(NAND_CTL_CLRNCE);			break;	}	return 0;}#endif/* * Main initialization routine */int __init smc_s3c2410_init (void){    struct nand_chip *this;    u_int16_t nfconf;    /* Allocate memory for MTD device structure and private data */    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;    }    /* Get pointer to private data */    this = (struct nand_chip *) (&s3c2410_mtd[1]);    /* Initialize structures */    memset((char *) s3c2410_mtd, 0, sizeof(struct mtd_info));    memset((char *) this, 0, sizeof(struct nand_chip));    /* Link the private data with the MTD structure */    s3c2410_mtd->priv = this;    /* set NAND Flash controller */    {      nfconf = NFCONF;      /* NAND Flash controller enable */      nfconf |= NFCONF_FCTRL_EN;      /* Set flash memory timing */      nfconf &= ~NFCONF_TWRPH1;   /* 0x0 */      nfconf |= NFCONF_TWRPH0_3;  /* 0x3 */      nfconf &= ~NFCONF_TACLS;    /* 0x0 */      NFCONF = nfconf;    }    /* Set address of NAND IO lines */    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;    /* Chip Enable -> RESET -> Wait for Ready -> Chip Disable */    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);/* * Clean up routine */#ifdef MODULEstatic void __exit smc_s3c2410_cleanup (void){    struct nand_chip *this = (struct nand_chip *) &s3c2410_mtd[1];    smc_remove(this);    /* Free the MTD device structure */    kfree (s3c2410_mtd);}module_exit(smc_s3c2410_cleanup);#endifMODULE_LICENSE("GPL");MODULE_AUTHOR("Yong-iL Joh <tolkien@mizi.com>");MODULE_DESCRIPTION("SMC Card on S3C2410 board");/* | $Id: smc_s3c2410.c,v 1.1.2.2 2002/05/30 08:14:44 cgjeong Exp $ | | Local Variables: | mode: c | mode: font-lock | version-control: t | delete-old-versions: t | c-basic-offset: 2 | tab-width: 8 | End: | | -*- End-Of-File -*- */

⌨️ 快捷键说明

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