📄 mxc_nd.c
字号:
*/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 + -