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

📄 mx2_nand.c

📁 nandflash k9g808u0a在pxa270的驱动,由于pxa270没有nandflash接口
💻 C
📖 第 1 页 / 共 2 页
字号:
	}}static voidmx2nand_write_word(struct mtd_info *mtd, u16 word){	u8 *buf = (u8 *) & word;	mx2nand_write_byte(mtd, buf[0]);	mx2nand_write_byte(mtd, buf[1]);}static voidmx2nand_read_buf(struct mtd_info *mtd, u_char * buf, int len){	int i;	for (i = 0; i < len; i++) {		buf[i] = mx2nand_read_byte(mtd);	}}static voidmx2nand_write_buf(struct mtd_info *mtd, const u_char * buf, int len){	int i;	for (i = 0; i < len; i++) {		mx2nand_write_byte(mtd, buf[i]);	}}static intmx2nand_verify_buf(struct mtd_info *mtd, const u_char * buf, int len){	int i;	char b;	for (i = 0; i < len; i++) {		b = mx2nand_read_byte(mtd);		if (buf[i] != b) {			return -EFAULT;		}	}	return 0;}static voidmx2nand_hwcontrol(struct mtd_info *mtd, int cmd){	struct nand_chip *chip_priv = mtd->priv;	struct mx2nand_priv *mx2_priv = chip_priv->priv;	switch (cmd) {	case NAND_CTL_SETNCE:	/* Enable NFC Clock */		mx_module_clk_open(IPG_MODULE_NFC);		mx2_priv->mode = 0;		break;	case NAND_CTL_CLRNCE:	/* Disable NFC Clock */		mx_module_clk_close(IPG_MODULE_NFC);		mx2_priv->mode = 0;		break;	case NAND_CTL_SETCLE:	/* Send Command mode start */		mx2_priv->mode = cmd;		NFC_CONFIGURATION = 0x0002;		NFC_ULOCK_START_BLK = 0;		NFC_ULOCK_END_BLK = 0xffff;	/*unlock all */		NFC_NF_WR_PROT = 0x0004;		NFC_RAM_BUF_ADDR = 0x3;		break;	case NAND_CTL_CLRCLE:	/* Send Command mode end */		mx2_priv->mode = 0;		break;	case NAND_CTL_SETALE:	/* Send address mode start */		mx2_priv->mode = cmd;		break;	case NAND_CTL_CLRALE:	/* Send address mode end */		mx2_priv->mode = 0;		break;	default:		mx2_priv->mode = 0;	}}const static struct mtd_partition mx2nand_partition_info[] = {      {name:"ipl",	      offset:0,      size:0x04000},      {name:"spl",	      offset:MTDPART_OFS_APPEND,      size:0x100000},      {name:"kernel",	      offset:MTDPART_OFS_APPEND,      size:0x200000},      {name:"RootDisk",	      offset:MTDPART_OFS_APPEND,      size:MTDPART_SIZ_FULL}};#define MX2_NAND_PARTITIONS_NUM 4/*NAND pinout:NFCE_B   T15  PF1NFCLE    U15  PF3NFALE    U14  PF4NFWE_B   T13  PF6NFRE_B   W13  PF5NFWP_B   L12  PF2NFRB     M12  PF0NFIO0..7  W12, U13, L11, T12, U12, T11, V13, M11  PF7..PF14A13..A15, A21..A25  F3, F1, G3, G1, H3, L2, L1, M2Note: PF0..PF14 port mux mode is PRIMARY*/#define MX2_NAND_GPIO_PORTF_MASK 0x7fff#define MX2_NFCCLK 25000000 /*max Nand Flash Controller clock freq in Hz*/static voidmx2nand_setup_clock(void){u32 tmpclock;u32 maxclock;	/*NFC clock may not be slower that HCLK ?*/	maxclock = mx_module_get_clk(HCLK);	if (maxclock > MX2_NFCCLK)		maxclock = MX2_NFCCLK;		/*there is no lower boundary limit. Upper boundary is checked in mx2nand_validate_clock*/	tmpclock = mx_module_get_clk(FCLK);	tmpclock = tmpclock/maxclock + ((tmpclock%maxclock > ((u32)maxclock >> 1)) ? 1 : 0);	if (tmpclock) {		tmpclock--; /*slow clock OK*/	}	#ifdef CONFIG_MX2TO1	CRM_PCDR = (CRM_PCDR & ~PCDR_NFCDIV) | (tmpclock << PCDR_NFCDIV_SHIFT);	/*clock control */#else	CRM_PCDR0 = (CRM_PCDR0 & ~PCDR0_NFCDIV) | (tmpclock << PCDR0_NFCDIV_SHIFT);	/*clock control */#endif}static inline int __initmx2nand_validate_clock(void){u32 tmpclock;/* although  NFC DIVISOR gets clock form FCLK, MPLL clock is selected as a base for calculations,  assuming the worst-case (and typical) scenario of PRESC Divisor = 0.  It is hard to impelement suspend/resume for this driver  - the only way to stop MTD from accessing it would be to destroy partitions, what may be  confusing to the user  On the other hand, even with the limitation of the above assumption, the maximal MPLL frequency  allowed is 512 MHz, which is enough to cover the known 350 and 266 MHz options*/	tmpclock = mx_module_get_clk(MPLL);	tmpclock = tmpclock/MX2_NFCCLK + ((tmpclock%MX2_NFCCLK > ((u32)MX2_NFCCLK >> 1)) ? 1 : 0);	if (tmpclock) {		tmpclock--; /*slow clock OK*/	}#ifdef CONFIG_MX2TO1	if (tmpclock > ((u32)PCDR_NFCDIV >> PCDR_NFCDIV_SHIFT)) {		printk(KERN_ERR "MX2 NAND: FCLK too fast, cannot operate\n");		return -1; /*FCLK is too fast*/	}#else	if (tmpclock > ((u32)PCDR0_NFCDIV >> PCDR0_NFCDIV_SHIFT)) {		printk(KERN_ERR "MX2 NAND: FCLK too fast, cannot operate\n");		return -1; /*FCLK is too fast*/	}#endif	return 0;}/** * Module initialization routine */int __initmx2nand_init(void){	struct nand_chip *this;	int mtd_parts_nb = 0;	int tmp;#ifdef CONFIG_MX2_16_BIT_NAND	printk(KERN_INFO "MX2 NAND: 16-bit i/o mode\n");#else	printk(KERN_INFO "MX2 NAND: 8-bit i/o mode\n");#endif	if (!(request_region(NFC_BASE, NFC_IO_SIZE, "mx2nand"))) {		printk(KERN_ERR "MX2 NAND: NFC region is already in use \n");		mx2nand_cleanup();		return -1;	}	mx2nand_region_init = 1;	SYS_FMCR &= ~(1 << 4);	if (mx2nand_validate_clock() < 0) {		mx2nand_cleanup();		return -EFAULT;	}	mx2nand_setup_clock();	tmp = mx2_register_gpios(PORT_F, MX2_NAND_GPIO_PORTF_MASK, PRIMARY);	if (tmp < 0) {		printk(KERN_ERR		       "MX2 NAND: Unable to request GPIO pins: PORT F, mask 0x%x\n",		       MX2_NAND_GPIO_PORTF_MASK);		mx2nand_cleanup();		return tmp;	}	mx2nand_gpio_init = 1;	/* Allocate memory for MTD device structure and private data */	mx2nand_mtd =	    kmalloc(sizeof (struct mtd_info) + sizeof (struct nand_chip) +		    sizeof (struct mx2nand_priv), GFP_KERNEL);	if (!mx2nand_mtd) {		printk(KERN_ERR		       "MX2 NAND: Not enough memory for a MTD device structure\n");		mx2nand_cleanup();		return -ENOMEM;	}	/* Initialize structures */	memset((char *) mx2nand_mtd, 0,	       sizeof (struct mtd_info) + sizeof (struct nand_chip) +	       sizeof (struct mx2nand_priv));	/* Get pointer to private data */	this =	    (struct nand_chip *) ((char *) mx2nand_mtd +				  sizeof (struct mtd_info));	/* Link the private data with the MTD structure */	mx2nand_mtd->priv = this;	this->hwcontrol = mx2nand_hwcontrol;	this->read_byte = mx2nand_read_byte;	this->write_byte = mx2nand_write_byte;	/*used to send out a command or address */	this->read_word = mx2nand_read_word;	/*used once at initialization 16-bit */	this->write_word = mx2nand_write_word;	/*never used */	this->read_buf = mx2nand_read_buf;	this->write_buf = mx2nand_write_buf;	this->verify_buf = mx2nand_verify_buf;	/* ECC handling */	this->autooob = &mx2nand_oob;	this->enable_hwecc = mx2nand_enable_hwecc;	this->calculate_ecc = mx2nand_calculate_ecc;	this->eccmode = NAND_ECC_HW3_512;	this->correct_data = mx2nand_correct_data;	/* end of ECC handling */	/* BBT handling */	this->scan_bbt = mx2nand_scan_bbt;#ifdef CONFIG_MX2_16_BIT_NAND	this->options |= NAND_BUSWIDTH_16;#endif	this->priv =	    (struct mx2nand_priv *) ((char *) mx2nand_mtd +				     sizeof (struct mtd_info) +				     sizeof (struct nand_chip));	/* Scan to find existence of the device */	tmp = nand_scan(mx2nand_mtd, 1);	if (tmp) {		printk(KERN_ERR "MX2 NAND: device not found\n");		mx2nand_cleanup();		return -ENXIO;	}	if ((mx2nand_mtd->oobsize != 16) || (mx2nand_mtd->oobblock != 512)) {		printk(KERN_ERR		       "MX2 NAND: Unsupported NAND Flash configuration\n");		mx2nand_cleanup();		return -EFAULT;	}	/* Register the partitions */#ifdef CONFIG_MTD_PARTITIONS#ifdef CONFIG_MTD_CMDLINE_PARTS	{		struct mtd_partition *mtd_parts;		mx2nand_mtd->name = "mx2-nand";		mtd_parts_nb =		    parse_mtd_partitions(mx2nand_mtd, mx2nand_probes,					 &mtd_parts, 0);		if (mtd_parts_nb > 0)			tmp =			    add_mtd_partitions(mx2nand_mtd, mtd_parts,					       mtd_parts_nb);	}#endif				/* end of CONFIG_MTD_CMDLINE_PARTS */	if (mtd_parts_nb <= 0) {		tmp = add_mtd_partitions(mx2nand_mtd, mx2nand_partition_info,					 MX2_NAND_PARTITIONS_NUM);	}	if (tmp < 0) {		printk(KERN_ERR "MX2 NAND: Error registering MTD partitions\n");		mx2nand_cleanup();		return tmp;	}#else				/* if !CONFIG_MTD_PARTITIONS */	tmp = add_mtd_device(mx2nand_mtd);	if (tmp < 0) {		printk(KERN_ERR "MX2 NAND: Error registering MTD device\n");		mx2nand_cleanup();		return tmp;	}#endif				/* end of CONFIG_MTD_PARTITIONS */#if 1 /*CEE LDM*/	mx21_ldm_bus_register(&__device_ldm, &__driver_ldm);	mx2nand_ldm_inited = 1;#endif	/* Return happy */	return 0;}/** * Module clean up routine */static void __initmx2nand_cleanup(void){#if 1 /*CEE LDM*/	if (mx2nand_ldm_inited)		mx21_ldm_bus_unregister(&__device_ldm, &__driver_ldm);#endif#ifdef CONFIG_MTD_PARTITIONS	/* Clean up partitions */	del_mtd_partitions(mx2nand_mtd);#else	/* Unregister the device */	del_mtd_device(mx2nand_mtd);#endif	/* Free the MTD device structure */	kfree(mx2nand_mtd);	if (mx2nand_gpio_init) {		mx2_unregister_gpios(PORT_F, MX2_NAND_GPIO_PORTF_MASK);	}	if (mx2nand_region_init) {		release_region(NFC_BASE, NFC_IO_SIZE);	}}module_init(mx2nand_init);module_exit(mx2nand_cleanup);MODULE_LICENSE("GPL");MODULE_AUTHOR("MontaVista Software, Inc");MODULE_DESCRIPTION("MTD Driver for MX2 Nand Flash Controller");

⌨️ 快捷键说明

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