diff --git a/drivers/nand/Kconfig b/drivers/nand/Kconfig index 1617898..72b2be0 100644 --- a/drivers/nand/Kconfig +++ b/drivers/nand/Kconfig @@ -13,11 +13,6 @@ prompt "i.MX NAND driver" depends on ARCH_IMX21 || ARCH_IMX27 || ARCH_IMX31 || ARCH_IMX35 || ARCH_IMX25 -config NAND_IMX_V2 - bool - prompt "i.MX NAND driver v2 (obsoleted, use v1 instead)" - depends on ARCH_IMX25 - config NAND_IMX_BOOT bool prompt "Support Starting U-Boot from NAND" diff --git a/drivers/nand/Makefile b/drivers/nand/Makefile index 3580520..73f7346 100644 --- a/drivers/nand/Makefile +++ b/drivers/nand/Makefile @@ -6,7 +6,6 @@ obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o obj-$(CONFIG_NAND_IMX) += nand_imx.o -obj-$(CONFIG_NAND_IMX_V2) += nand_imx_v2.o obj-$(CONFIG_NAND_OMAP_GPMC) += nand_omap_gpmc.o obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o obj-$(CONFIG_NAND_S3C24X0) += nand_s3c2410.o diff --git a/drivers/nand/nand_imx_v2.c b/drivers/nand/nand_imx_v2.c deleted file mode 100644 index 32e3564..0000000 --- a/drivers/nand/nand_imx_v2.c +++ /dev/null @@ -1,1133 +0,0 @@ -/* - * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. - */ - -/* - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Addresses for NFC registers - */ -#define MAIN_AREA0 (host->regs + 0x000) -#define MAIN_AREA1 (host->regs + 0x200) -#define SPARE_AREA0 (host->regs + 0x1000) -#define NFC_BUF_SIZE (host->regs + 0x1E00) -#define NFC_BUF_ADDR (host->regs + 0x1E04) -#define NFC_FLASH_ADDR (host->regs + 0x1E06) -#define NFC_FLASH_CMD (host->regs + 0x1E08) -#define NFC_CONFIG (host->regs + 0x1E0A) -#define NFC_ECC_STATUS_RESULT (host->regs + 0x1E0C) -#define NFC_ECC_STATUS_RESULT_1 (host->regs + 0x1E0C) -#define NFC_ECC_STATUS_RESULT_2 (host->regs + 0x1E0E) -#define NFC_SPAS (host->regs + 0x1E10) -#define NFC_WRPROT (host->regs + 0x1E12) -#define NFC_UNLOCKSTART_BLKADDR (host->regs + 0x1E20) -#define NFC_UNLOCKEND_BLKADDR (host->regs + 0x1E22) -#define NFC_UNLOCKSTART_BLKADDR1 (host->regs + 0x1E24) -#define NFC_UNLOCKEND_BLKADDR1 (host->regs + 0x1E26) -#define NFC_UNLOCKSTART_BLKADDR2 (host->regs + 0x1E28) -#define NFC_UNLOCKEND_BLKADDR2 (host->regs + 0x1E2A) -#define NFC_UNLOCKSTART_BLKADDR3 (host->regs + 0x1E2C) -#define NFC_UNLOCKEND_BLKADDR3 (host->regs + 0x1E2E) -#define NFC_NF_WRPRST (host->regs + 0x1E18) -#define NFC_CONFIG1 (host->regs + 0x1E1A) -#define NFC_CONFIG2 (host->regs + 0x1E1C) - -/* - * Set INT to 0, Set 1 to specific operation bit, rest to 0 in LAUNCH_NFC Register for - * Specific operation - */ -#define NFC_CMD 0x1 -#define NFC_ADDR 0x2 -#define NFC_INPUT 0x4 -#define NFC_OUTPUT 0x8 -#define NFC_ID 0x10 -#define NFC_STATUS 0x20 - -/* Bit Definitions */ -#define NFC_OPS_STAT (1 << 15) -#define NFC_SP_EN (1 << 2) -#define NFC_ECC_EN (1 << 3) -#define NFC_INT_MSK (1 << 4) -#define NFC_BIG (1 << 5) -#define NFC_RST (1 << 6) -#define NFC_CE (1 << 7) -#define NFC_ONE_CYCLE (1 << 8) -#define NFC_BLS_LOCKED 0 -#define NFC_BLS_LOCKED_DEFAULT 1 -#define NFC_BLS_UNLCOKED 2 -#define NFC_WPC_LOCK_TIGHT 1 -#define NFC_WPC_LOCK (1 << 1) -#define NFC_WPC_UNLOCK (1 << 2) -#define NFC_FLASH_ADDR_SHIFT 0 -#define NFC_UNLOCK_END_ADDR_SHIFT 0 - -#define NFC_ECC_MODE_4 (1<<0) -#define NFC_ECC_MODE_8 ~(1<<0) -#define NFC_SPAS_16 8 -#define NFC_SPAS_64 32 -#define NFC_SPAS_128 64 -#define NFC_SPAS_218 109 - -static inline void raw_write(unsigned long val, void *reg) -{ - writew(val, reg); - debug("wr: 0x%08x = 0x%08x\n", reg, val); -} - -static inline unsigned long raw_read(void *reg) -{ - unsigned long val = readw(reg); - - debug("rd: 0x%08x = 0x%08x\n", reg, val); - - return val; -} - -struct imx_nand_host { - struct mtd_info mtd; - struct nand_chip nand; - struct device_d *dev; - void __iomem *regs; - - int status_request; - u16 col_addr; -}; - -/* - * Define delays in microsec for NAND device operations - */ -#define TROP_US_DELAY 2000 - -static u8 *data_buf; -static u8 *oob_buf; - -/* - * OOB placement block for use with hardware ecc generation - */ -static struct nand_ecclayout nand_hw_eccoob_512 = { - .eccbytes = 9, - .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, - .oobavail = 4, - .oobfree = {{0, 4}} -}; - -static struct nand_ecclayout nand_hw_eccoob_2k = { - .eccbytes = 9, - .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, - .oobavail = 4, - .oobfree = {{2, 4}} -}; - -static struct nand_ecclayout nand_hw_eccoob_4k = { - .eccbytes = 9, - .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, - .oobavail = 4, - .oobfree = {{2, 4}} -}; - -/* - * @defgroup NAND_MTD NAND Flash MTD Driver for MXC processors - */ - -/* - * @file mxc_nd2.c - * - * @brief This file contains the hardware specific layer for NAND Flash on - * MXC processor - * - * @ingroup NAND_MTD - */ - -static void memcpy32(void *trg, const void *src, int size) -{ - int i; - unsigned int *t = trg; - unsigned const int *s = src; - - if ((ulong)trg & 0x3 || (ulong)src & 0x3 || size & 0x3) - while(1); - - for (i = 0; i < (size >> 2); i++) - *t++ = *s++; -} - -/* - * Functions to transfer data to/from spare erea. - */ -static void -copy_spare(struct mtd_info *mtd, void *pbuf, void *pspare, int len, int bfrom) -{ - u16 i, j; - u16 m = mtd->oobsize; - u16 n = mtd->writesize >> 9; - u8 *d = (u8 *) pbuf; - u8 *s = (u8 *) pspare; - - j = (m / n >> 1) << 1; - - if (bfrom) { - for (i = 0; i < n - 1; i++) - memcpy32(&d[i * j], &s[i * 64], j); - - /* the last section */ - memcpy32(&d[i * j], &s[i * 64], len - i * j); - } else { - for (i = 0; i < n - 1; i++) - memcpy32(&s[i * 64], &d[i * j], j); - - /* the last section */ - memcpy32(&s[i * 64], &d[i * j], len - i * j); - } -} - -/* - * This function polls the NFC to wait for the basic operation to complete by - * checking the INT bit of config2 register. - * - * @param maxRetries number of retry attempts (separated by 1 us) - * @param useirq True if IRQ should be used rather than polling - */ -static void wait_op_done(struct imx_nand_host *host, int maxRetries) -{ - while (maxRetries > 0) { - maxRetries--; - if (raw_read(NFC_CONFIG2) & NFC_OPS_STAT) { - raw_write((raw_read(NFC_CONFIG2) & ~NFC_OPS_STAT), NFC_CONFIG2); - break; - } - udelay(1); - } - - if (maxRetries <= 0) - printf("%s timeout\n", __func__); -} - -/* - * This function issues the specified command to the NAND device and - * waits for completion. - * - * @param cmd command for NAND Flash - * @param useirq True if IRQ should be used rather than polling - */ -static void send_cmd(struct mtd_info *mtd, u16 cmd, int useirq) -{ - struct nand_chip *nand_chip = mtd->priv; - struct imx_nand_host *host = nand_chip->priv; - - /* fill command */ - raw_write(cmd, NFC_FLASH_CMD); - - /* send out command */ - raw_write(NFC_CMD, NFC_CONFIG2); - - wait_op_done(host, TROP_US_DELAY); -} - -/* - * This function sends an address (or partial address) to the - * NAND device. The address is used to select the source/destination for - * a NAND command. - * - * @param addr address to be written to NFC. - * @param useirq True if IRQ should be used rather than polling - */ -static void send_addr(struct imx_nand_host *host, u16 addr, int useirq) -{ - debug("%s: 0x%04x\n", __func__, addr); - - /* fill address */ - raw_write((addr << NFC_FLASH_ADDR_SHIFT), NFC_FLASH_ADDR); - - /* send out address */ - raw_write(NFC_ADDR, NFC_CONFIG2); - - wait_op_done(host, TROP_US_DELAY); -} - -/* - * This function requests the NFC to perform a read of the - * NAND device status and returns the current status. - * - * @return device status - */ -static u16 get_dev_status(struct imx_nand_host *host) -{ - raw_write(1, NFC_BUF_ADDR); - - /* Read status into main buffer */ - raw_write(NFC_STATUS, NFC_CONFIG2); - - wait_op_done(host, TROP_US_DELAY); - - /* Status is placed in first word of main buffer */ - /* get status, then recovery area 1 data */ - return raw_read(MAIN_AREA1); -} - -static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) -{ - struct nand_chip *nand_chip = mtd->priv; - struct imx_nand_host *host = nand_chip->priv; - - raw_write((raw_read(NFC_CONFIG1) | NFC_ECC_EN), NFC_CONFIG1); - return; -} - -/* - * Function to record the ECC corrected/uncorrected errors resulted - * after a page read. This NFC detects and corrects upto to 4 symbols - * of 9-bits each. - */ -static int mxc_check_ecc_status(struct mtd_info *mtd) -{ - struct nand_chip *nand_chip = mtd->priv; - struct imx_nand_host *host = nand_chip->priv; - u32 ecc_stat, err; - int no_subpages = 1; - int ret = 0; - u8 ecc_bit_mask, err_limit; - - ecc_bit_mask = (raw_read(NFC_CONFIG1) & NFC_ECC_MODE_4) ? 0x7 : 0xf; - err_limit = raw_read(NFC_CONFIG1) & NFC_ECC_MODE_4 ? 0x4 : 0x8; - - no_subpages = mtd->writesize >> 9; - - ecc_stat = raw_read(NFC_ECC_STATUS_RESULT); - do { - err = ecc_stat & ecc_bit_mask; - if (err > err_limit) { - mtd->ecc_stats.failed++; - printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); - return -1; - } else { - ret += err; - } - ecc_stat >>= 4; - } while (--no_subpages); - - mtd->ecc_stats.corrected += ret; - pr_debug("%d Symbol Correctable RS-ECC Error\n", ret); - - return ret; -} - -/* - * Function to correct the detected errors. This NFC corrects all the errors - * detected. So this function just return 0. - */ -static int mxc_nand_correct_data(struct mtd_info *mtd, u_char * dat, - u_char * read_ecc, u_char * calc_ecc) -{ - return 0; -} - -/* - * Function to calculate the ECC for the data to be stored in the Nand device. - * This NFC has a hardware RS(511,503) ECC engine together with the RS ECC - * CONTROL blocks are responsible for detection and correction of up to - * 8 symbols of 9 bits each in 528 byte page. - * So this function is just return 0. - */ - -static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) -{ - return 0; -} - -/* - * 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) -{ - struct nand_chip *nand_chip = mtd->priv; - struct imx_nand_host *host = nand_chip->priv; - u16 col = host->col_addr; - - debug("%s: 0x%08x %d\n", __func__, buf, len); - - if (mtd->writesize) { - int j = mtd->writesize - col; - int n = mtd->oobsize + j; - - n = min(n, len); - - if (j > 0) { - if (n > j) { - memcpy(buf, &data_buf[col], j); - memcpy(buf + j, &oob_buf[0], n - j); - } else { - memcpy(buf, &data_buf[col], n); - } - } else { - col -= mtd->writesize; - memcpy(buf, &oob_buf[col], len); - } - - /* update */ - host->col_addr += n; - - } else { - /* At flash identify phase, - * mtd->writesize has not been - * set correctly, it should - * be zero.And len will less 2 - */ - memcpy(buf, &data_buf[col], len); - - /* update */ - host->col_addr += len; - } -} - -/* - * This function reads byte from the NAND Flash - * - * @param mtd MTD structure for the NAND Flash - * - * @return data read from the NAND Flash - */ -static uint8_t mxc_nand_read_byte(struct mtd_info *mtd) -{ - struct nand_chip *nand_chip = mtd->priv; - struct imx_nand_host *host = nand_chip->priv; - uint8_t ret; - - /* Check for status request */ - if (host->status_request) - return get_dev_status(host) & 0xFF; - - mxc_nand_read_buf(mtd, &ret, 1); - - return ret; -} - -/* - * 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 ret; - - mxc_nand_read_buf(mtd, (uint8_t *)&ret, sizeof(u16)); - - return ret; -} - -/* - * 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_byte16(struct mtd_info *mtd) -{ - struct nand_chip *nand_chip = mtd->priv; - struct imx_nand_host *host = nand_chip->priv; - - /* Check for status request */ - if (host->status_request) - return get_dev_status(host) & 0xFF; - - return mxc_nand_read_word(mtd) & 0xFF; -} - -/* - * This function writes data of length \b len from buffer \b buf to the NAND - * internal RAM buffer's MAIN area 0. - * - * @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) -{ - struct nand_chip *nand_chip = mtd->priv; - struct imx_nand_host *host = nand_chip->priv; - u16 col = host->col_addr; - int j = mtd->writesize - col; - int n = mtd->oobsize + j; - - n = min(n, len); - - if (j > 0) { - if (n > j) { - memcpy(&data_buf[col], buf, j); - memcpy(&oob_buf[0], buf + j, n - j); - } else { - memcpy(&data_buf[col], buf, n); - } - } else { - col -= mtd->writesize; - memcpy(&oob_buf[col], buf, len); - } - - /* update */ - host->col_addr += n; -} - -/* - * 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 int mxc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, - int len) -{ - u_char *s = data_buf; - - const u_char *p = buf; - - for (; len > 0; len--) { - if (*p++ != *s++) - return -EFAULT; - } - - return 0; -} - -/* - * 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) -{ -} - -/* - * Function to perform the address cycles. - */ -static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) -{ - struct nand_chip *nand_chip = mtd->priv; - struct imx_nand_host *host = nand_chip->priv; - u32 page_mask = nand_chip->pagemask; - - debug("%s: %d %d\n", __func__, column, page_addr); - - if (column != -1) { - send_addr(host, column & 0xFF, 0); - if (mtd->writesize == 2048) { - /* another col addr cycle for 2k page */ - send_addr(host, (column >> 8) & 0xF, 0); - } else if (mtd->writesize == 4096) { - /* another col addr cycle for 4k page */ - send_addr(host, (column >> 8) & 0x1F, 0); - } - } - if (page_addr != -1) { - do { - send_addr(host, (page_addr & 0xff), 0); - page_mask >>= 8; - page_addr >>= 8; - } while (page_mask != 0); - } -} - -/* - * 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) -{ - struct nand_chip *nand_chip = mtd->priv; - struct imx_nand_host *host = nand_chip->priv; - - debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", - command, column, page_addr); - - /* - * Reset command state information - */ - host->status_request = 0; - - /* - * Command pre-processing step - */ - switch (command) { - case NAND_CMD_STATUS: - host->col_addr = 0; - host->status_request = 1; - break; - - case NAND_CMD_READ0: - host->col_addr = column; - break; - - case NAND_CMD_READOOB: - host->col_addr = column; - command = NAND_CMD_READ0; - break; - - case NAND_CMD_SEQIN: - if (column) { - - /* FIXME: before send SEQIN command for - * partial write,We need read one page out. - * FSL NFC does not support partial write - * It alway send out 512+ecc+512+ecc ... - * for large page nand flash. But for small - * page nand flash, it did support SPARE - * ONLY operation. But to make driver - * simple. We take the same as large page,read - * whole page out and update. As for MLC nand - * NOP(num of operation) = 1. Partial written - * on one programed page is not allowed! We - * can't limit it on the driver, it need the - * upper layer applicaiton take care it - */ - - mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr); - } - - host->col_addr = column; - break; - - case NAND_CMD_PAGEPROG: - /* FIXME:the NFC interal buffer - * access has some limitation, it - * does not allow byte access. To - * make the code simple and ease use - * not every time check the address - * alignment.Use the temp buffer - * to accomadate the data.since We - * know data_buf will be at leat 4 - * byte alignment, so we can use - * memcpy safely - */ - memcpy32(MAIN_AREA0, data_buf, mtd->writesize); - copy_spare(mtd, oob_buf, SPARE_AREA0, mtd->oobsize, 0); - - /* set ram buffer id */ - raw_write(0, NFC_BUF_ADDR); - - /* transfer data from NFC ram to nand */ - raw_write(NFC_INPUT, NFC_CONFIG2); - - wait_op_done(host, TROP_US_DELAY); - - break; - - case NAND_CMD_ERASE1: - case NAND_CMD_ERASE2: - break; - } - - send_cmd(mtd, command, 0); - - mxc_do_addr_cycle(mtd, column, page_addr); - - /* - * Command post-processing step - */ - switch (command) { - case NAND_CMD_READOOB: - case NAND_CMD_READ0: - if (mtd->writesize > 512) { - /* send read confirm command */ - send_cmd(mtd, NAND_CMD_READSTART, 1); - } - - raw_write(0, NFC_BUF_ADDR); - - /* transfer data from nand to NFC ram */ - raw_write(NFC_OUTPUT, NFC_CONFIG2); - - wait_op_done(host, TROP_US_DELAY); - - /* FIXME, the NFC interal buffer - * access has some limitation, it - * does not allow byte access. To - * make the code simple and ease use - * not every time check the address - * alignment.Use the temp buffer - * to accomadate the data.since We - * know data_buf will be at leat 4 - * byte alignment, so we can use - * memcpy safely - */ - memcpy32(data_buf, MAIN_AREA0, mtd->writesize); - copy_spare(mtd, oob_buf, SPARE_AREA0, mtd->oobsize, 1); - - break; - - case NAND_CMD_READID: - raw_write(0, NFC_BUF_ADDR); - - /* Read ID into main buffer */ - raw_write(NFC_ID, NFC_CONFIG2); - - wait_op_done(host, TROP_US_DELAY); - - host->col_addr = column; - memcpy32(data_buf, MAIN_AREA0, 2048); - - break; - } -} - -static int mxc_nand_read_oob(struct mtd_info *mtd, - struct nand_chip *chip, int page, int sndcmd) -{ - if (sndcmd) { - chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); - sndcmd = 0; - } - - memcpy32(chip->oob_poi, oob_buf, mtd->oobsize); - - return sndcmd; -} - -static int mxc_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf) -{ - debug("%s: 0x%08x\n", __func__, buf); - - mxc_check_ecc_status(mtd); - - memcpy32(buf, data_buf, mtd->writesize); - memcpy32(chip->oob_poi, oob_buf, mtd->oobsize); - - return 0; -} - -static void mxc_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) -{ - memcpy32(data_buf, buf, mtd->writesize); - memcpy32(oob_buf, chip->oob_poi, mtd->oobsize); -} - -/* - * We must provide a private bbt decriptor, because the settings from - * the generic one collide with our ECC hardware. - */ -static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' }; -static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' }; - -static struct nand_bbt_descr bbt_main_descr = { - .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE - | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, - .offs = 0, - .len = 4, - .veroffs = 4, - .maxblocks = 4, - .pattern = bbt_pattern -}; - -static struct nand_bbt_descr bbt_mirror_descr = { - .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE - | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, - .offs = 0, - .len = 4, - .veroffs = 4, - .maxblocks = 4, - .pattern = mirror_pattern -}; - -#ifdef CONFIG_ARCH_IMX25 - -#define RCSR_NFC_FMS (1 << 8) -#define RCSR_NFC_4K (1 << 9) -#define RCSR_NFC_16BIT_SEL (1 << 14) - -static void __bare_init mxc_nand_set_writesize(struct mtd_info *mtd, int writesize) -{ - unsigned int rcsr; - - rcsr = readl(IMX_CCM_BASE + CCM_RCSR); - rcsr &= ~(RCSR_NFC_FMS | RCSR_NFC_4K); - - if (writesize == 2048) - rcsr |= RCSR_NFC_FMS; - if (writesize == 4096) - rcsr |= RCSR_NFC_FMS | RCSR_NFC_4K; - - writel(rcsr, IMX_CCM_BASE + CCM_RCSR); -} - -static void __bare_init mxc_nand_set_datawidth(struct mtd_info *mtd, int datawidth) -{ - unsigned int rcsr; - - rcsr = readl(IMX_CCM_BASE + CCM_RCSR); - - if (datawidth == 16) - rcsr |= RCSR_NFC_16BIT_SEL; - else - rcsr &= ~RCSR_NFC_16BIT_SEL; - - - writel(rcsr, IMX_CCM_BASE + CCM_RCSR); -} -#endif - -static void mxc_nfc_init(struct imx_nand_host *host) -{ - /* Disable interrupt */ - raw_write((raw_read(NFC_CONFIG1) | NFC_INT_MSK), NFC_CONFIG1); - - /* disable spare enable */ - raw_write(raw_read(NFC_CONFIG1) & ~NFC_SP_EN, NFC_CONFIG1); - - /* Unlock the internal RAM Buffer */ - raw_write(NFC_BLS_UNLCOKED, NFC_CONFIG); - - /* Blocks to be unlocked */ - raw_write(0x0, NFC_UNLOCKSTART_BLKADDR); - raw_write(0xffff, NFC_UNLOCKEND_BLKADDR); - - /* Unlock Block Command for given address range */ - raw_write(NFC_WPC_UNLOCK, NFC_WRPROT); -} - -static int __init imxnd_probe(struct device_d *dev) -{ - struct nand_chip *this; - struct mtd_info *mtd; - struct imx_nand_platform_data *pdata = dev->platform_data; - struct imx_nand_host *host; - u16 tmp; - int err = 0; - - /* init data buf */ - data_buf = xzalloc(NAND_MAX_PAGESIZE); - oob_buf = xzalloc(NAND_MAX_OOBSIZE); - - /* Allocate memory for MTD device structure and private data */ - host = kzalloc(sizeof(struct imx_nand_host), GFP_KERNEL); - if (!host) { - printk(KERN_ERR "%s: failed to allocate mtd_info\n", - __FUNCTION__); - err = -ENOMEM; - goto err_out; - } - - host->dev = dev; - /* structures must be linked */ - this = &host->nand; - mtd = &host->mtd; - mtd->priv = this; - - /* NAND bus width determines access funtions used by upper layer */ - if (pdata->width == 2) { - this->read_byte = mxc_nand_read_byte16; - this->options |= NAND_BUSWIDTH_16; - mxc_nand_set_datawidth(mtd, 16); - } else - mxc_nand_set_datawidth(mtd, 8); - - /* 50 us command delay time */ - this->chip_delay = 5; - - this->priv = host; - this->cmdfunc = mxc_nand_command; - this->select_chip = mxc_nand_select_chip; - this->read_byte = mxc_nand_read_byte; - this->read_word = mxc_nand_read_word; - this->write_buf = mxc_nand_write_buf; - this->read_buf = mxc_nand_read_buf; - this->verify_buf = mxc_nand_verify_buf; - - /* use flash based bbt */ - this->bbt_td = &bbt_main_descr; - this->bbt_md = &bbt_mirror_descr; - - /* update flash based bbt */ - this->options |= NAND_USE_FLASH_BBT; - - host->regs = (void __iomem *)dev->map_base; - - mxc_nfc_init(host); - - tmp = readw(NFC_CONFIG1); - tmp |= NFC_INT_MSK; - writew(tmp, NFC_CONFIG1); - - if (pdata->hw_ecc) { - this->ecc.read_page = mxc_nand_read_page; - this->ecc.write_page = mxc_nand_write_page; - this->ecc.read_oob = mxc_nand_read_oob; - this->ecc.layout = &nand_hw_eccoob_512; - this->ecc.calculate = mxc_nand_calculate_ecc; - this->ecc.hwctl = mxc_nand_enable_hwecc; - this->ecc.correct = mxc_nand_correct_data; - this->ecc.mode = NAND_ECC_HW; - this->ecc.size = 512; - this->ecc.bytes = 9; - raw_write(raw_read(NFC_CONFIG1) | NFC_ECC_EN, NFC_CONFIG1); - } else { - this->ecc.mode = NAND_ECC_SOFT; - raw_write(raw_read(NFC_CONFIG1) & ~NFC_ECC_EN, NFC_CONFIG1); - } - - /* Reset NAND */ - this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); - - /* Scan to find existence of the device */ - if (nand_scan_ident(mtd, 1)) { - err = -ENXIO; - dev_err(dev, "Unable to find any NAND device\n"); - goto err_out; - } - - if (mtd->writesize == 2048) { - mxc_nand_set_writesize(mtd, 2048); - raw_write(((raw_read(NFC_SPAS) & 0xff00) | NFC_SPAS_64), NFC_SPAS); - raw_write((raw_read(NFC_CONFIG1) | NFC_ECC_MODE_4), NFC_CONFIG1); - this->ecc.layout = &nand_hw_eccoob_2k; - } else if (mtd->writesize == 4096) { - mxc_nand_set_writesize(mtd, 4096); - raw_write(((raw_read(NFC_SPAS) & 0xff00) | NFC_SPAS_128), NFC_SPAS); - raw_write((raw_read(NFC_CONFIG1) | NFC_ECC_MODE_4), NFC_CONFIG1); - this->ecc.layout = &nand_hw_eccoob_4k; - } else { - mxc_nand_set_writesize(mtd, 512); - this->ecc.layout = &nand_hw_eccoob_512; - } - - if (nand_scan_tail(mtd)) { - dev_err(dev, "Unable to find any NAND device.\n"); - err = -ENXIO; - goto err_out; - } - - add_mtd_device(mtd); - -#ifdef CONFIG_MXC_NAND_LOW_LEVEL_ERASE - /* Erase all the blocks of a NAND */ - imx_low_erase(mtd); -#endif - - dev->priv = host; - - return 0; -err_out: - return err; -} - -static struct driver_d imx_nand_driver = { - .name = "imx_nand", - .probe = imxnd_probe, -}; - -/* - * Main initialization routine - * @return 0 if successful; non-zero otherwise - */ -static int __init imx_nand_init(void) -{ - return register_driver(&imx_nand_driver); -} - -device_initcall(imx_nand_init); - -#ifdef CONFIG_NAND_IMX_BOOT - -static void __bare_init noinline boot_send_cmd(struct imx_nand_host *host, u16 cmd) -{ - /* fill command */ - raw_write(cmd, NFC_FLASH_CMD); - - /* send out command */ - raw_write(NFC_CMD, NFC_CONFIG2); - - wait_op_done(host, TROP_US_DELAY); -} - -static void noinline __bare_init boot_send_addr(struct imx_nand_host *host, u16 addr) -{ - /* fill address */ - raw_write((addr << NFC_FLASH_ADDR_SHIFT), NFC_FLASH_ADDR); - - /* send out address */ - raw_write(NFC_ADDR, NFC_CONFIG2); - - wait_op_done(host, TROP_US_DELAY); -} - -static void __bare_init boot_nfc_addr(struct imx_nand_host *host, u32 offs, int pagesize) -{ - switch (pagesize) { - case 512: - boot_send_addr(host, offs & 0xff); - boot_send_addr(host, (offs >> 9) & 0xff); - boot_send_addr(host, (offs >> 17) & 0xff); - boot_send_addr(host, (offs >> 25) & 0xff); - break; - case 2048: - boot_send_addr(host, 0); - boot_send_addr(host, 0); - boot_send_addr(host, (offs >> 11) & 0xff); - boot_send_addr(host, (offs >> 19) & 0xff); - boot_send_addr(host, (offs >> 27) & 0xff); - break; - case 4096: - boot_send_addr(host, 0); - boot_send_addr(host, 0); - boot_send_addr(host, (offs >> 12) & 0xff); - boot_send_addr(host, (offs >> 20) & 0xff); - boot_send_addr(host, (offs >> 27) & 0xff); - break; - } - - if (pagesize > 512) - boot_send_cmd(host, NAND_CMD_READSTART); -} - -static void __bare_init noinline boot_send_read_page(struct imx_nand_host *host, u8 buf_id) -{ - DEBUG(MTD_DEBUG_LEVEL3, "%s(%d)\n", __FUNCTION__, buf_id); - - raw_write(buf_id, NFC_BUF_ADDR); - - /* transfer data from nand to NFC ram */ - raw_write(NFC_OUTPUT, NFC_CONFIG2); - - wait_op_done(host, TROP_US_DELAY); -} - -static int __bare_init block_is_bad(struct imx_nand_host *host, u32 offs, int pagesize) -{ - boot_send_cmd(host, NAND_CMD_READ0); - boot_nfc_addr(host, offs, pagesize); - boot_send_read_page(host, 0); - - /* FIXME: copied from V1 driver. Is this correct? */ - return (raw_read(SPARE_AREA0) & 0xff) == 0xff ? 0 : 1; -} - -void __bare_init imx_nand_load_image(void *dest, int size, int pagesize, - int blocksize) -{ - struct imx_nand_host _host; - struct imx_nand_host *host = &_host; - int width = 1; - u32 page, block; - - host->regs = (void *)IMX_NFC_BASE; - - debug("%s\n", __func__); - - /* disable spare enable */ - raw_write(raw_read(NFC_CONFIG1) & ~NFC_SP_EN, NFC_CONFIG1); - - /* Unlock the internal RAM Buffer */ - raw_write(NFC_BLS_UNLCOKED, NFC_CONFIG); - - /* Blocks to be unlocked */ - raw_write(0x0, NFC_UNLOCKSTART_BLKADDR); - raw_write(0xffff, NFC_UNLOCKEND_BLKADDR); - - /* Unlock Block Command for given address range */ - raw_write(NFC_WPC_UNLOCK, NFC_WRPROT); - - if (readl(IMX_CCM_BASE + CCM_RCSR) & (1 << 14)) - width = 2; - - block = page = 0; - - while (1) { - if (!block_is_bad(host, block * blocksize, pagesize)) { - page = 0; - while (page * pagesize < blocksize) { - debug("page: %d block: %d dest: %p src " - "0x%08x\n", - page, block, dest, - block * blocksize + - page * pagesize); - - boot_send_cmd(host, NAND_CMD_READ0); - boot_nfc_addr(host, block * blocksize + - page * pagesize, pagesize); - boot_send_read_page(host, 0); - page++; - memcpy32(dest, MAIN_AREA0, pagesize); - dest += pagesize; - size -= pagesize; - if (size <= 0) - return; - } - } - block++; - } -} - -#ifdef IMX_NAND_BOOT_DEBUG -#include -static int do_nand_boot_test(cmd_tbl_t *cmdtp, int argc, char *argv[]) -{ - void *dest; - int size, pagesize, blocksize; - - if (argc < 4) - return COMMAND_ERROR_USAGE; - - dest = (void *)strtoul_suffix(argv[1], NULL, 0); - size = strtoul_suffix(argv[2], NULL, 0); - pagesize = strtoul_suffix(argv[3], NULL, 0); - blocksize = strtoul_suffix(argv[4], NULL, 0); - - imx_nand_load_image(dest, size, pagesize, blocksize * 1024); - - return 0; -} - -static const __maybe_unused char cmd_nand_boot_test_help[] = -"Usage: nand_boot_test \n"; - -U_BOOT_CMD_START(nand_boot_test) - .cmd = do_nand_boot_test, - .usage = "load an image from NAND", - U_BOOT_CMD_HELP(cmd_nand_boot_test_help) -U_BOOT_CMD_END - -#endif -#endif