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

📄 mxc_nd.c

📁 飞思卡尔芯片imx27下的MTD模块的驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
 */static u16 get_dev_status(void){	volatile u16 *mainBuf = MAIN_AREA1;	u32 store;	u16 ret;	/* Issue status request to NAND device */	/* store the main area1 first word, later do recovery */	store = *((u32 *) mainBuf);	/*	 * NANDFC buffer 1 is used for device status to prevent	 * corruption of read/write buffer on status requests.	 */	NFC_BUF_ADDR = 1;	/* Send the Read status command before reading status */	send_cmd(NAND_CMD_STATUS, true);	/* Read status into main buffer */	NFC_CONFIG1 &= (~(NFC_SP_EN));	NFC_CONFIG2 = NFC_STATUS;	/* Wait for operation to complete */	wait_op_done(TROP_US_DELAY, 0, true);	/* get status, then recovery area 1 data */	ret = mainBuf[0];	*((u32 *) mainBuf) = store;	/* Status is placed in first word of main buffer */	return ret;}/*! * This functions is used by upper layer to checks if device is ready * * @param       mtd     MTD structure for the NAND Flash * * @return  0 if device is busy else 1 */static int mxc_nand_dev_ready(struct mtd_info *mtd){	/* 	 * NFC handles R/B internally.Therefore,this function	 * always returns status as ready.	 */	return 1;}static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode){	/*	 * If HW ECC is enabled, we turn it on during init.  There is	 * no need to enable again here.	 */}static int mxc_nand_correct_data(struct mtd_info *mtd, u_char * dat,				 u_char * read_ecc, u_char * calc_ecc){	/*	 * 1-Bit errors are automatically corrected in HW.  No need for	 * additional correction.  2-Bit errors cannot be corrected by	 * HW ECC, so we need to return failure	 */	u16 ecc_status = NFC_ECC_STATUS_RESULT;	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {		DEBUG(MTD_DEBUG_LEVEL0,		      "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");		return -1;	}	return 0;}static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,				  u_char * ecc_code){	/*	 * Just return success.  HW ECC does not read/write the NFC spare	 * buffer.  Only the FLASH spare area contains the calcuated ECC.	 */	return 0;}/*! * This function reads byte from the NAND Flash * * @param       mtd     MTD structure for the NAND Flash * * @return    data read from the NAND Flash */static u_char mxc_nand_read_byte(struct mtd_info *mtd){	u_char retVal = 0;	u16 col, rdWord;	volatile u16 *mainBuf = MAIN_AREA0;	volatile u16 *spareBuf = SPARE_AREA0;	/* Check for status request */	if (g_nandfc_info.bStatusRequest) {		return (get_dev_status() & 0xFF);	}	/* Get column for 16-bit access */	col = g_nandfc_info.colAddr >> 1;	/* If we are accessing the spare region */	if (g_nandfc_info.bSpareOnly) {		rdWord = spareBuf[col];	} else {		rdWord = mainBuf[col];	}	/* Pick upper/lower byte of word from RAM buffer */	if (g_nandfc_info.colAddr & 0x1) {		retVal = (rdWord >> 8) & 0xFF;	} else {		retVal = rdWord & 0xFF;	}	/* Update saved column address */	g_nandfc_info.colAddr++;	return retVal;}/*!  * This function reads word from the NAND Flash  *  * @param       mtd     MTD structure for the NAND Flash  *  * @return    data read from the NAND Flash  */static u16 mxc_nand_read_word(struct mtd_info *mtd){	u16 col;	u16 rdWord, retVal;	volatile u16 *p;	DEBUG(MTD_DEBUG_LEVEL3,	      "mxc_nand_read_word(col = %d)\n", g_nandfc_info.colAddr);	col = g_nandfc_info.colAddr;	/* Adjust saved column address */	if (col < mtd->writesize && g_nandfc_info.bSpareOnly)		col += mtd->writesize;	if (col < mtd->writesize)		p = (MAIN_AREA0) + (col >> 1);	else		p = (SPARE_AREA0) + ((col - mtd->writesize) >> 1);	if (col & 1) {		rdWord = *p;		retVal = (rdWord >> 8) & 0xff;		rdWord = *(p + 1);		retVal |= (rdWord << 8) & 0xff00;	} else {		retVal = *p;	}	/* Update saved column address */	g_nandfc_info.colAddr = col + 2;	return retVal;}/*! * This function writes data of length \b len to buffer \b buf. The data to be * written on NAND Flash is first copied to RAMbuffer. After the Data Input * Operation by the NFC, the data is written to NAND Flash * * @param       mtd     MTD structure for the NAND Flash * @param       buf     data to be written to NAND Flash * @param       len     number of bytes to be written */static void mxc_nand_write_buf(struct mtd_info *mtd,			       const u_char * buf, int len){	int n;	int col;	int i = 0;	DEBUG(MTD_DEBUG_LEVEL3,	      "mxc_nand_write_buf(col = %d, len = %d)\n", g_nandfc_info.colAddr,	      len);	col = g_nandfc_info.colAddr;	/* Adjust saved column address */	if (col < mtd->writesize && g_nandfc_info.bSpareOnly)		col += mtd->writesize;	n = mtd->writesize + mtd->oobsize - col;	n = min(len, n);	DEBUG(MTD_DEBUG_LEVEL3,	      "%s:%d: col = %d, n = %d\n", __FUNCTION__, __LINE__, col, n);	while (n) {		volatile u32 *p;		if (col < mtd->writesize)			p = (volatile u32 *)((ulong) (MAIN_AREA0) + (col & ~3));		else			p = (volatile u32 *)((ulong) (SPARE_AREA0) -					     mtd->writesize + (col & ~3));		DEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __FUNCTION__,		      __LINE__, p);		if (((col | (int)&buf[i]) & 3) || n < 16) {			u32 data = 0;			if (col & 3 || n < 4)				data = *p;			switch (col & 3) {			case 0:				if (n) {					data = (data & 0xffffff00) |					    (buf[i++] << 0);					n--;					col++;				}			case 1:				if (n) {					data = (data & 0xffff00ff) |					    (buf[i++] << 8);					n--;					col++;				}			case 2:				if (n) {					data = (data & 0xff00ffff) |					    (buf[i++] << 16);					n--;					col++;				}			case 3:				if (n) {					data = (data & 0x00ffffff) |					    (buf[i++] << 24);					n--;					col++;				}			}			*p = data;		} else {			int m = mtd->writesize - col;			if (col >= mtd->writesize)				m += mtd->oobsize;			m = min(n, m) & ~3;			DEBUG(MTD_DEBUG_LEVEL3,			      "%s:%d: n = %d, m = %d, i = %d, col = %d\n",			      __FUNCTION__, __LINE__, n, m, i, col);			memcpy((void *)(p), &buf[i], m);			col += m;			i += m;			n -= m;		}	}	/* Update saved column address */	g_nandfc_info.colAddr = col;}/*! * This function id is used to read the data buffer from the NAND Flash. To * read the data from NAND Flash first the data output cycle is initiated by * the NFC, which copies the data to RAMbuffer. This data of length \b len is * then copied to buffer \b buf. * * @param       mtd     MTD structure for the NAND Flash * @param       buf     data to be read from NAND Flash * @param       len     number of bytes to be read */static void mxc_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len){	int n;	int col;	int i = 0;	DEBUG(MTD_DEBUG_LEVEL3,	      "mxc_nand_read_buf(col = %d, len = %d)\n", g_nandfc_info.colAddr,	      len);	col = g_nandfc_info.colAddr;	/* Adjust saved column address */	if (col < mtd->writesize && g_nandfc_info.bSpareOnly)		col += mtd->writesize;	n = mtd->writesize + mtd->oobsize - col;	n = min(len, n);	while (n) {		volatile u32 *p;		if (col < mtd->writesize)			p = (volatile u32 *)((ulong) (MAIN_AREA0) + (col & ~3));		else			p = (volatile u32 *)((ulong) (SPARE_AREA0) -					     mtd->writesize + (col & ~3));		if (((col | (int)&buf[i]) & 3) || n < 16) {			u32 data;			data = *p;			switch (col & 3) {			case 0:				if (n) {					buf[i++] = (u8) (data);					n--;					col++;				}			case 1:				if (n) {					buf[i++] = (u8) (data >> 8);					n--;					col++;				}			case 2:				if (n) {					buf[i++] = (u8) (data >> 16);					n--;					col++;				}			case 3:				if (n) {					buf[i++] = (u8) (data >> 24);					n--;					col++;				}			}		} else {			int m = mtd->writesize - col;			if (col >= mtd->writesize)				m += mtd->oobsize;			m = min(n, m) & ~3;			memcpy(&buf[i], (void *)(p), m);			col += m;			i += m;			n -= m;		}	}	/* Update saved column address */	g_nandfc_info.colAddr = col;}/*! * This function is used by the upper layer to verify the data in NAND Flash * with the data in the \b buf. * * @param       mtd     MTD structure for the NAND Flash * @param       buf     data to be verified * @param       len     length of the data to be verified * * @return      -EFAULT if error else 0 * */static intmxc_nand_verify_buf(struct mtd_info *mtd, const u_char * buf, int len){	return -EFAULT;}/*! * This function is used by upper layer for select and deselect of the NAND * chip * * @param       mtd     MTD structure for the NAND Flash * @param       chip    val indicating select or deselect */static void mxc_nand_select_chip(struct mtd_info *mtd, int chip){#ifdef CONFIG_MTD_NAND_MXC_FORCE_CE	if (chip > 0) {		DEBUG(MTD_DEBUG_LEVEL0,		      "ERROR:  Illegal chip select (chip = %d)\n", chip);		return;	}	if (chip == -1) {		NFC_CONFIG1 &= (~(NFC_CE));		return;	}	NFC_CONFIG1 |= NFC_CE;#endif	switch (chip) {	case -1:		/* Disable the NFC clock */		clk_disable(nfc_clk);		break;	case 0:		/* Enable the NFC clock */		clk_enable(nfc_clk);		break;	default:		break;	}}/*! * This function is used by the upper layer to write command to NAND Flash for * different operations to be carried out on NAND Flash * * @param       mtd             MTD structure for the NAND Flash * @param       command         command for NAND Flash * @param       column          column offset for the page read * @param       page_addr       page to be read from NAND Flash */static void mxc_nand_command(struct mtd_info *mtd, unsigned command,			     int column, int page_addr){	bool useirq = true;	DEBUG(MTD_DEBUG_LEVEL3,	      "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",	      command, column, page_addr);	/*	 * Reset command state information	 */	g_nandfc_info.bStatusRequest = false;	/*	 * Command pre-processing step	 */	switch (command) {	case NAND_CMD_STATUS:		g_nandfc_info.colAddr = 0;		g_nandfc_info.bStatusRequest = true;

⌨️ 快捷键说明

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