From patchwork Tue Jan 8 09:33:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 210323 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id F2B682C0093 for ; Tue, 8 Jan 2013 20:33:46 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 674D94A0ED; Tue, 8 Jan 2013 10:33:45 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id IduCh57azC9q; Tue, 8 Jan 2013 10:33:45 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 93DBF4A0F1; Tue, 8 Jan 2013 10:33:42 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 1ECEA4A0F1 for ; Tue, 8 Jan 2013 10:33:39 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id PFeKH1k33nXE for ; Tue, 8 Jan 2013 10:33:36 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-out.m-online.net (mail-out.m-online.net [212.18.0.9]) by theia.denx.de (Postfix) with ESMTPS id 5B0BE4A0ED for ; Tue, 8 Jan 2013 10:33:35 +0100 (CET) Received: from frontend1.mail.m-online.net (unknown [192.168.8.180]) by mail-out.m-online.net (Postfix) with ESMTP id 3YgSvg0c1Lz4KK36; Tue, 8 Jan 2013 10:33:35 +0100 (CET) X-Auth-Info: RbkAAdLrpzcE1elQ5NC4vMw/OY5KIykBe0NrIOeVO/s= Received: from mashiro.lan (unknown [195.140.253.167]) by smtp-auth.mnet-online.de (Postfix) with ESMTPA id 3YgSvf5rcpzbbfM; Tue, 8 Jan 2013 10:33:34 +0100 (CET) From: Marek Vasut To: u-boot@lists.denx.de Date: Tue, 8 Jan 2013 10:33:29 +0100 Message-Id: <1357637609-18663-1-git-send-email-marex@denx.de> X-Mailer: git-send-email 1.7.10.4 MIME-Version: 1.0 Cc: Scott Wood Subject: [U-Boot] [PATCH 1/2] mxc nand: Add support for i.MX5 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Benoît Thébaudeau Signed-off-by: Benoît Thébaudeau Cc: Scott Wood Cc: Stefano Babic --- arch/arm/include/asm/arch-mx5/imx-regs.h | 9 ++ drivers/mtd/nand/mxc_nand.c | 219 ++++++++++++++++++++++-------- include/fsl_nfc.h | 149 +++++++++++++------- nand_spl/nand_boot_fsl_nfc.c | 114 ++++++++++++---- 4 files changed, 364 insertions(+), 127 deletions(-) NOTE: I'm seeing issues when this is compiled into U-Boot. U-Boot won't boot on my MX53 board and will hang right after printing "DRAM:" and before printing the CPU info. I suspect it's some kind of unaligned access. NOTE2: I fixed a few complaints from GCC and rebased on top of master. diff --git a/arch/arm/include/asm/arch-mx5/imx-regs.h b/arch/arm/include/asm/arch-mx5/imx-regs.h index 1d060fd..6821e75 100644 --- a/arch/arm/include/asm/arch-mx5/imx-regs.h +++ b/arch/arm/include/asm/arch-mx5/imx-regs.h @@ -234,6 +234,15 @@ #define CS0_32M_CS1_32M_CS2_32M_CS3_32M 3 /* + * SRC register definitions + */ +#if defined(CONFIG_MX51) +#define SRC_SBMR_NF16B (1 << 2) +#elif defined(CONFIG_MX53) +#define SRC_SBMR_NF16B (1 << 13) +#endif + +/* * CSPI register definitions */ #define MXC_ECSPI diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index d0ded48..cead757 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -22,7 +22,8 @@ #include #include #include -#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) +#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35) || \ + defined(CONFIG_MX51) || defined(CONFIG_MX53) #include #endif #include @@ -36,6 +37,9 @@ struct mxc_nand_host { struct nand_chip *nand; struct fsl_nfc_regs __iomem *regs; +#ifdef MXC_NFC_V3_2 + struct fsl_nfc_ip_regs __iomem *ip_regs; +#endif int spare_only; int status_request; int pagesize_2k; @@ -77,7 +81,7 @@ static struct nand_ecclayout nand_hw_eccoob2k = { .oobfree = { {2, 4}, {11, 11}, {27, 11}, {43, 11}, {59, 5} }, }; #endif -#elif defined(MXC_NFC_V2_1) +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) #ifndef CONFIG_SYS_NAND_LARGEPAGE static struct nand_ecclayout nand_hw_eccoob = { .eccbytes = 9, @@ -130,6 +134,16 @@ static int is_16bit_nand(void) else return 0; } +#elif defined(CONFIG_MX51) || defined(CONFIG_MX53) +static int is_16bit_nand(void) +{ + struct src *src = (struct src *)SRC_BASE_ADDR; + + if (readl(&src->sbmr) & SRC_SBMR_NF16B) + return 1; + else + return 0; +} #else #warning "8/16 bit NAND autodetection not supported" static int is_16bit_nand(void) @@ -150,7 +164,7 @@ static uint32_t *mxc_nand_memcpy32(uint32_t *dest, uint32_t *source, size_t size /* * This function polls the NANDFC to wait for the basic operation to - * complete by checking the INT bit of config2 register. + * complete by checking the INT bit. */ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint16_t param) @@ -158,10 +172,17 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint32_t tmp; while (max_retries-- > 0) { - if (readw(&host->regs->config2) & NFC_INT) { - tmp = readw(&host->regs->config2); - tmp &= ~NFC_INT; - writew(tmp, &host->regs->config2); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + tmp = readnfc(&host->regs->config2); + if (tmp & NFC_V1_V2_CONFIG2_INT) { + tmp &= ~NFC_V1_V2_CONFIG2_INT; + writenfc(tmp, &host->regs->config2); +#elif defined(MXC_NFC_V3_2) + tmp = readnfc(&host->ip_regs->ipc); + if (tmp & NFC_V3_IPC_INT) { + tmp &= ~NFC_V3_IPC_INT; + writenfc(tmp, &host->ip_regs->ipc); +#endif break; } udelay(1); @@ -180,8 +201,8 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd); - writew(cmd, &host->regs->flash_cmd); - writew(NFC_CMD, &host->regs->config2); + writenfc(cmd, &host->regs->flash_cmd); + writenfc(NFC_CMD, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, cmd); @@ -196,8 +217,8 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr) { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x)\n", addr); - writew(addr, &host->regs->flash_addr); - writew(NFC_ADDR, &host->regs->config2); + writenfc(addr, &host->regs->flash_addr); + writenfc(NFC_ADDR, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, addr); @@ -213,7 +234,7 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, if (spare_only) MTDDEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only); - if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { int i; /* * The controller copies the 64 bytes of spare data from @@ -229,19 +250,26 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, } } - writew(buf_id, &host->regs->buf_addr); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(buf_id, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + tmp |= NFC_V3_CONFIG1_RBA(buf_id); + writenfc(tmp, &host->regs->config1); +#endif /* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint16_t config1 = readw(&host->regs->config1); + uint32_t config1 = readnfc(&host->regs->config1); if (spare_only) - config1 |= NFC_SP_EN; + config1 |= NFC_CONFIG1_SP_EN; else - config1 &= ~NFC_SP_EN; - writew(config1, &host->regs->config1); + config1 &= ~NFC_CONFIG1_SP_EN; + writenfc(config1, &host->regs->config1); } - writew(NFC_INPUT, &host->regs->config2); + writenfc(NFC_INPUT, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); @@ -256,24 +284,31 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, { MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only); - writew(buf_id, &host->regs->buf_addr); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(buf_id, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + tmp |= NFC_V3_CONFIG1_RBA(buf_id); + writenfc(tmp, &host->regs->config1); +#endif /* Configure spare or page+spare access */ if (!host->pagesize_2k) { - uint32_t config1 = readw(&host->regs->config1); + uint32_t config1 = readnfc(&host->regs->config1); if (spare_only) - config1 |= NFC_SP_EN; + config1 |= NFC_CONFIG1_SP_EN; else - config1 &= ~NFC_SP_EN; - writew(config1, &host->regs->config1); + config1 &= ~NFC_CONFIG1_SP_EN; + writenfc(config1, &host->regs->config1); } - writew(NFC_OUTPUT, &host->regs->config2); + writenfc(NFC_OUTPUT, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); - if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { int i; /* @@ -293,17 +328,23 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, /* Request the NANDFC to perform a read of the NAND device ID. */ static void send_read_id(struct mxc_nand_host *host) { - uint16_t tmp; + uint32_t tmp; +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* NANDFC buffer 0 is used for device ID output */ - writew(0x0, &host->regs->buf_addr); + writenfc(0x0, &host->regs->buf_addr); +#elif defined(MXC_NFC_V3_2) + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(tmp, &host->regs->config1); +#endif /* Read ID into main buffer */ - tmp = readw(&host->regs->config1); - tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_CONFIG1_SP_EN; + writenfc(tmp, &host->regs->config1); - writew(NFC_ID, &host->regs->config2); + writenfc(NFC_ID, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0); @@ -315,32 +356,40 @@ static void send_read_id(struct mxc_nand_host *host) */ static uint16_t get_dev_status(struct mxc_nand_host *host) { +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) void __iomem *main_buf = host->regs->main_area[1]; uint32_t store; - uint16_t ret, tmp; +#endif + uint32_t ret, tmp; /* Issue status request to NAND device */ +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* store the main area1 first word, later do recovery */ store = readl(main_buf); /* NANDFC buffer 1 is used for device status */ - writew(1, &host->regs->buf_addr); + writenfc(1, &host->regs->buf_addr); +#endif /* Read status into main buffer */ - tmp = readw(&host->regs->config1); - tmp &= ~NFC_SP_EN; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp &= ~NFC_CONFIG1_SP_EN; + writenfc(tmp, &host->regs->config1); - writew(NFC_STATUS, &host->regs->config2); + writenfc(NFC_STATUS, &host->regs->operation); /* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, 0); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) /* * Status is placed in first word of main buffer * get status, then recovery area 1 data */ ret = readw(main_buf); writel(store, main_buf); +#elif defined(MXC_NFC_V3_2) + ret = readnfc(&host->regs->config1) >> 16; +#endif return ret; } @@ -359,13 +408,23 @@ static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t tmp = readw(&host->regs->config1); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + uint16_t tmp = readnfc(&host->regs->config1); + + if (on) + tmp |= NFC_V1_V2_CONFIG1_ECC_EN; + else + tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; + writenfc(tmp, &host->regs->config1); +#elif defined(MXC_NFC_V3_2) + uint32_t tmp = readnfc(&host->ip_regs->config2); if (on) - tmp |= NFC_ECC_EN; + tmp |= NFC_V3_CONFIG2_ECC_EN; else - tmp &= ~NFC_ECC_EN; - writew(tmp, &host->regs->config1); + tmp &= ~NFC_V3_CONFIG2_ECC_EN; + writenfc(tmp, &host->ip_regs->config2); +#endif } #ifdef CONFIG_MXC_NAND_HWECC @@ -377,7 +436,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) */ } -#ifdef MXC_NFC_V2_1 +#if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd) @@ -698,7 +757,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, * additional correction. 2-Bit errors cannot be corrected by * HW ECC, so we need to return failure */ - uint16_t ecc_status = readw(&host->regs->ecc_status_result); + uint32_t ecc_status = readnfc(&host->regs->ecc_status_result); if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { MTDDEBUG(MTD_DEBUG_LEVEL0, @@ -1167,8 +1226,8 @@ static struct nand_bbt_descr bbt_mirror_descr = { int board_nand_init(struct nand_chip *this) { struct mtd_info *mtd; -#ifdef MXC_NFC_V2_1 - uint16_t tmp; +#if defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) + uint32_t tmp; #endif #ifdef CONFIG_SYS_NAND_USE_FLASH_BBT @@ -1196,13 +1255,17 @@ int board_nand_init(struct nand_chip *this) this->verify_buf = mxc_nand_verify_buf; host->regs = (struct fsl_nfc_regs __iomem *)CONFIG_MXC_NAND_REGS_BASE; +#ifdef MXC_NFC_V3_2 + host->ip_regs = + (struct fsl_nfc_ip_regs __iomem *)CONFIG_MXC_NAND_IP_REGS_BASE; +#endif host->clk_act = 1; #ifdef CONFIG_MXC_NAND_HWECC this->ecc.calculate = mxc_nand_calculate_ecc; this->ecc.hwctl = mxc_nand_enable_hwecc; this->ecc.correct = mxc_nand_correct_data; - if (is_mxc_nfc_21()) { + if (is_mxc_nfc_21() || is_mxc_nfc_32()) { this->ecc.mode = NAND_ECC_HW_SYNDROME; this->ecc.read_page = mxc_nand_read_page_syndrome; this->ecc.read_page_raw = mxc_nand_read_page_raw_syndrome; @@ -1240,25 +1303,26 @@ int board_nand_init(struct nand_chip *this) this->ecc.layout = &nand_hw_eccoob; #endif +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) #ifdef MXC_NFC_V2_1 - tmp = readw(&host->regs->config1); - tmp |= NFC_ONE_CYCLE; - tmp |= NFC_4_8N_ECC; - writew(tmp, &host->regs->config1); + tmp = readnfc(&host->regs->config1); + tmp |= NFC_V2_CONFIG1_ONE_CYCLE; + tmp |= NFC_V2_CONFIG1_ECC_MODE_4; + writenfc(tmp, &host->regs->config1); if (host->pagesize_2k) - writew(64/2, &host->regs->spare_area_size); + writenfc(64/2, &host->regs->spare_area_size); else - writew(16/2, &host->regs->spare_area_size); + writenfc(16/2, &host->regs->spare_area_size); #endif /* * preset operation * Unlock the internal RAM Buffer */ - writew(0x2, &host->regs->config); + writenfc(0x2, &host->regs->config); /* Blocks to be unlocked */ - writew(0x0, &host->regs->unlockstart_blkaddr); + writenfc(0x0, &host->regs->unlockstart_blkaddr); /* Originally (Freescale LTIB 2.6.21) 0x4000 was written to the * unlockend_blkaddr, but the magic 0x4000 does not always work * when writing more than some 32 megabytes (on 2k page nands) @@ -1270,10 +1334,53 @@ int board_nand_init(struct nand_chip *this) * This might be NAND chip specific and the i.MX31 datasheet is * extremely vague about the semantics of this register. */ - writew(0xFFFF, &host->regs->unlockend_blkaddr); + writenfc(0xFFFF, &host->regs->unlockend_blkaddr); /* Unlock Block Command for given address range */ - writew(0x4, &host->regs->wrprot); + writenfc(0x4, &host->regs->wrprot); +#elif defined(MXC_NFC_V3_2) + writenfc(NFC_V3_CONFIG1_RBA(0), &host->regs->config1); + writenfc(NFC_V3_IPC_CREQ, &host->ip_regs->ipc); + + /* Unlock the internal RAM Buffer */ + writenfc(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK, + &host->ip_regs->wrprot); + + /* Blocks to be unlocked */ + for (tmp = 0; tmp < CONFIG_SYS_NAND_MAX_CHIPS; tmp++) + writenfc(0x0 | 0xFFFF << 16, + &host->ip_regs->wrprot_unlock_blkaddr[tmp]); + + writenfc(0, &host->ip_regs->ipc); + + tmp = readnfc(&host->ip_regs->config2); + tmp &= ~(NFC_V3_CONFIG2_SPAS_MASK | NFC_V3_CONFIG2_EDC_MASK | + NFC_V3_CONFIG2_ECC_MODE_8 | NFC_V3_CONFIG2_PS_MASK); + tmp |= NFC_V3_CONFIG2_ONE_CYCLE; + + if (host->pagesize_2k) { + tmp |= NFC_V3_CONFIG2_SPAS(64/2); + tmp |= NFC_V3_CONFIG2_PS_2048; + } else { + tmp |= NFC_V3_CONFIG2_SPAS(16/2); + tmp |= NFC_V3_CONFIG2_PS_512; + } + + writenfc(tmp, &host->ip_regs->config2); + + tmp = NFC_V3_CONFIG3_NUM_OF_DEVS(0) | + NFC_V3_CONFIG3_NO_SDMA | + NFC_V3_CONFIG3_RBB_MODE | + NFC_V3_CONFIG3_SBB(6) | /* Reset default */ + NFC_V3_CONFIG3_ADD_OP(0); + + if (!(this->options & NAND_BUSWIDTH_16)) + tmp |= NFC_V3_CONFIG3_FW8; + + writenfc(tmp, &host->ip_regs->config3); + + writenfc(0, &host->ip_regs->delay_line); +#endif return 0; } diff --git a/include/fsl_nfc.h b/include/fsl_nfc.h index ff537b4..48a6448 100644 --- a/include/fsl_nfc.h +++ b/include/fsl_nfc.h @@ -33,7 +33,8 @@ * to support up to 2K byte pagesize nand. * Reading or writing a 2K page requires 4 FDI/FDO cycles. * - * MX25 and MX35 have version 2.1, which has: + * MX25 and MX35 have version 2.1, and MX51 and MX53 have version 3.2, which + * have: * 8 512-byte main buffers and * 8 64-byte spare buffers * to support up to 4K byte pagesize nand. @@ -44,20 +45,29 @@ #define MXC_NFC_V1 #define is_mxc_nfc_1() 1 #define is_mxc_nfc_21() 0 +#define is_mxc_nfc_32() 0 #elif defined(CONFIG_MX25) || defined(CONFIG_MX35) #define MXC_NFC_V2_1 #define is_mxc_nfc_1() 0 #define is_mxc_nfc_21() 1 +#define is_mxc_nfc_32() 0 +#elif defined(CONFIG_MX51) || defined(CONFIG_MX53) +#define MXC_NFC_V3 +#define MXC_NFC_V3_2 +#define is_mxc_nfc_1() 0 +#define is_mxc_nfc_21() 0 +#define is_mxc_nfc_32() 1 #else #error "MXC NFC implementation not supported" #endif +#define is_mxc_nfc_3() is_mxc_nfc_32() #if defined(MXC_NFC_V1) #define NAND_MXC_NR_BUFS 4 #define NAND_MXC_SPARE_BUF_SIZE 16 #define NAND_MXC_REG_OFFSET 0xe00 #define NAND_MXC_2K_MULTI_CYCLE -#elif defined(MXC_NFC_V2_1) +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) #define NAND_MXC_NR_BUFS 8 #define NAND_MXC_SPARE_BUF_SIZE 64 #define NAND_MXC_REG_OFFSET 0x1e00 @@ -110,61 +120,106 @@ struct fsl_nfc_regs { u16 unlockend_blkaddr2; u16 unlockstart_blkaddr3; u16 unlockend_blkaddr3; +#elif defined(MXC_NFC_V3_2) + u32 flash_cmd; + u32 flash_addr[12]; + u32 config1; + u32 ecc_status_result; + u32 status_sum; + u32 launch; #endif }; -/* - * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register for Command - * operation - */ -#define NFC_CMD 0x1 +#ifdef MXC_NFC_V3_2 +struct fsl_nfc_ip_regs { + u32 wrprot; + u32 wrprot_unlock_blkaddr[8]; + u32 config2; + u32 config3; + u32 ipc; + u32 err_addr; + u32 delay_line; +}; +#endif -/* - * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register for Address - * operation - */ -#define NFC_ADDR 0x2 +/* Set FCMD to 1, rest to 0 for Command operation */ +#define NFC_CMD 0x1 -/* - * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register for Input - * operation - */ -#define NFC_INPUT 0x4 +/* Set FADD to 1, rest to 0 for Address operation */ +#define NFC_ADDR 0x2 -/* - * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register for Data - * Output operation - */ -#define NFC_OUTPUT 0x8 +/* Set FDI to 1, rest to 0 for Input operation */ +#define NFC_INPUT 0x4 -/* - * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register for Read ID - * operation - */ -#define NFC_ID 0x10 +/* Set FDO to 001, rest to 0 for Data Output operation */ +#define NFC_OUTPUT 0x8 -/* - * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register for Read - * Status operation - */ -#define NFC_STATUS 0x20 +/* Set FDO to 010, rest to 0 for Read ID operation */ +#define NFC_ID 0x10 -/* - * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read Status - * operation - */ -#define NFC_INT 0x8000 +/* Set FDO to 100, rest to 0 for Read Status operation */ +#define NFC_STATUS 0x20 + +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) +#define NFC_CONFIG1_SP_EN (1 << 2) +#define NFC_CONFIG1_RST (1 << 6) +#define NFC_CONFIG1_CE (1 << 7) +#elif defined(MXC_NFC_V3_2) +#define NFC_CONFIG1_SP_EN (1 << 0) +#define NFC_CONFIG1_CE (1 << 1) +#define NFC_CONFIG1_RST (1 << 2) +#endif +#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3) +#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4) +#define NFC_V1_V2_CONFIG1_BIG (1 << 5) +#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0) +#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8) +#define NFC_V2_CONFIG1_FP_INT (1 << 11) +#define NFC_V3_CONFIG1_RBA_MASK (0x7 << 4) +#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7) << 4) + +#define NFC_V1_V2_CONFIG2_INT (1 << 15) +#define NFC_V3_CONFIG2_PS_MASK (0x3 << 0) +#define NFC_V3_CONFIG2_PS_512 (0 << 0) +#define NFC_V3_CONFIG2_PS_2048 (1 << 0) +#define NFC_V3_CONFIG2_PS_4096 (2 << 0) +#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2) +#define NFC_V3_CONFIG2_ECC_EN (1 << 3) +#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4) +#define NFC_V3_CONFIG2_NUM_ADDR_PH0 (1 << 5) +#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6) +#define NFC_V3_CONFIG2_PPB_MASK (0x3 << 7) +#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7) +#define NFC_V3_CONFIG2_EDC_MASK (0x7 << 9) +#define NFC_V3_CONFIG2_EDC(x) (((x) & 0x7) << 9) +#define NFC_V3_CONFIG2_NUM_ADDR_PH1(x) (((x) & 0x3) << 12) +#define NFC_V3_CONFIG2_INT_MSK (1 << 15) +#define NFC_V3_CONFIG2_SPAS_MASK (0xff << 16) +#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16) +#define NFC_V3_CONFIG2_ST_CMD_MASK (0xff << 24) +#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24) + +#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0) +#define NFC_V3_CONFIG3_FW8 (1 << 3) +#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8) +#define NFC_V3_CONFIG3_NUM_OF_DEVS(x) (((x) & 0x7) << 12) +#define NFC_V3_CONFIG3_RBB_MODE (1 << 15) +#define NFC_V3_CONFIG3_NO_SDMA (1 << 20) + +#define NFC_V3_WRPROT_UNLOCK (1 << 2) +#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6) + +#define NFC_V3_IPC_CREQ (1 << 0) +#define NFC_V3_IPC_INT (1 << 31) -#ifdef MXC_NFC_V2_1 -#define NFC_4_8N_ECC (1 << 0) +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) +#define operation config2 +#define readnfc readw +#define writenfc writew +#elif defined(MXC_NFC_V3_2) +#define operation launch +#define readnfc readl +#define writenfc writel #endif -#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_FP_INT (1 << 11) #endif /* __FSL_NFC_H */ diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index a40c998..1096727 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -30,64 +30,117 @@ #include #include +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) static struct fsl_nfc_regs *const nfc = (void *)NFC_BASE_ADDR; +#elif defined(MXC_NFC_V3_2) +static struct fsl_nfc_regs *const nfc = (void *)NFC_BASE_ADDR_AXI; +static struct fsl_nfc_ip_regs *const nfc_ip = (void *)NFC_BASE_ADDR; +#endif static void nfc_wait_ready(void) { uint32_t tmp; - while (!(readw(&nfc->config2) & NFC_INT)) +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + while (!(readnfc(&nfc->config2) & NFC_V1_V2_CONFIG2_INT)) ; /* Reset interrupt flag */ - tmp = readw(&nfc->config2); - tmp &= ~NFC_INT; - writew(tmp, &nfc->config2); + tmp = readnfc(&nfc->config2); + tmp &= ~NFC_V1_V2_CONFIG2_INT; + writenfc(tmp, &nfc->config2); +#elif defined(MXC_NFC_V3_2) + while (!(readnfc(&nfc_ip->ipc) & NFC_V3_IPC_INT)) + ; + + /* Reset interrupt flag */ + tmp = readnfc(&nfc_ip->ipc); + tmp &= ~NFC_V3_IPC_INT; + writenfc(tmp, &nfc_ip->ipc); +#endif } static void nfc_nand_init(void) { -#if defined(MXC_NFC_V2_1) +#if defined(MXC_NFC_V3_2) + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int tmp; + + tmp = (readnfc(&nfc_ip->config2) & ~(NFC_V3_CONFIG2_SPAS_MASK | + NFC_V3_CONFIG2_EDC_MASK | NFC_V3_CONFIG2_PS_MASK)) | + NFC_V3_CONFIG2_SPAS(CONFIG_SYS_NAND_SPARE_SIZE / 2) | + NFC_V3_CONFIG2_INT_MSK | NFC_V3_CONFIG2_ECC_EN | + NFC_V3_CONFIG2_ONE_CYCLE; + if (CONFIG_SYS_NAND_PAGE_SIZE == 4096) + tmp |= NFC_V3_CONFIG2_PS_4096; + else if (CONFIG_SYS_NAND_PAGE_SIZE == 2048) + tmp |= NFC_V3_CONFIG2_PS_2048; + else if (CONFIG_SYS_NAND_PAGE_SIZE == 512) + tmp |= NFC_V3_CONFIG2_PS_512; + /* + * if spare size is larger that 16 bytes per 512 byte hunk + * then use 8 symbol correction instead of 4 + */ + if (CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16) + tmp |= NFC_V3_CONFIG2_ECC_MODE_8; + else + tmp &= ~NFC_V3_CONFIG2_ECC_MODE_8; + writenfc(tmp, &nfc_ip->config2); + + tmp = NFC_V3_CONFIG3_NUM_OF_DEVS(0) | + NFC_V3_CONFIG3_NO_SDMA | + NFC_V3_CONFIG3_RBB_MODE | + NFC_V3_CONFIG3_SBB(6) | /* Reset default */ + NFC_V3_CONFIG3_ADD_OP(0); +#ifndef CONFIG_SYS_NAND_BUSWIDTH_16 + tmp |= NFC_V3_CONFIG3_FW8; +#endif + writenfc(tmp, &nfc_ip->config3); + + writenfc(0, &nfc_ip->delay_line); +#elif defined(MXC_NFC_V2_1) int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int config1; - writew(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size); + writenfc(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size); /* unlocking RAM Buff */ - writew(0x2, &nfc->config); + writenfc(0x2, &nfc->config); /* hardware ECC checking and correct */ - config1 = readw(&nfc->config1) | NFC_ECC_EN | NFC_INT_MSK | - NFC_ONE_CYCLE | NFC_FP_INT; + config1 = readnfc(&nfc->config1) | NFC_V1_V2_CONFIG1_ECC_EN | + NFC_V1_V2_CONFIG1_INT_MSK | NFC_V2_CONFIG1_ONE_CYCLE | + NFC_V2_CONFIG1_FP_INT; /* * if spare size is larger that 16 bytes per 512 byte hunk * then use 8 symbol correction instead of 4 */ if (CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16) - config1 &= ~NFC_4_8N_ECC; + config1 &= ~NFC_V2_CONFIG1_ECC_MODE_4; else - config1 |= NFC_4_8N_ECC; - writew(config1, &nfc->config1); + config1 |= NFC_V2_CONFIG1_ECC_MODE_4; + writenfc(config1, &nfc->config1); #elif defined(MXC_NFC_V1) /* unlocking RAM Buff */ - writew(0x2, &nfc->config); + writenfc(0x2, &nfc->config); /* hardware ECC checking and correct */ - writew(NFC_ECC_EN | NFC_INT_MSK, &nfc->config1); + writenfc(NFC_V1_V2_CONFIG1_ECC_EN | NFC_V1_V2_CONFIG1_INT_MSK, + &nfc->config1); #endif } static void nfc_nand_command(unsigned short command) { - writew(command, &nfc->flash_cmd); - writew(NFC_CMD, &nfc->config2); + writenfc(command, &nfc->flash_cmd); + writenfc(NFC_CMD, &nfc->operation); nfc_wait_ready(); } static void nfc_nand_address(unsigned short address) { - writew(address, &nfc->flash_addr); - writew(NFC_ADDR, &nfc->config2); + writenfc(address, &nfc->flash_addr); + writenfc(NFC_ADDR, &nfc->operation); nfc_wait_ready(); } @@ -121,8 +174,14 @@ static void nfc_nand_data_output(void) int i; #endif - writew(0, &nfc->buf_addr); - writew(NFC_OUTPUT, &nfc->config2); +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(0, &nfc->buf_addr); +#elif defined(MXC_NFC_V3_2) + int config1 = readnfc(&nfc->config1); + config1 &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(config1, &nfc->config1); +#endif + writenfc(NFC_OUTPUT, &nfc->operation); nfc_wait_ready(); #ifdef NAND_MXC_2K_MULTI_CYCLE /* @@ -130,8 +189,8 @@ static void nfc_nand_data_output(void) * for pages larger than 512 bytes. */ for (i = 1; i < CONFIG_SYS_NAND_PAGE_SIZE / 512; i++) { - writew(i, &nfc->buf_addr); - writew(NFC_OUTPUT, &nfc->config2); + writenfc(i, &nfc->buf_addr); + writenfc(NFC_OUTPUT, &nfc->operation); nfc_wait_ready(); } #endif @@ -142,7 +201,7 @@ static int nfc_nand_check_ecc(void) #if defined(MXC_NFC_V1) u16 ecc_status = readw(&nfc->ecc_status_result); return (ecc_status & 0x3) == 2 || (ecc_status >> 2) == 2; -#elif defined(MXC_NFC_V2_1) +#elif defined(MXC_NFC_V2_1) || defined(MXC_NFC_V3_2) u32 ecc_status = readl(&nfc->ecc_status_result); int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; int err_limit = CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page > 16 ? 8 : 4; @@ -160,7 +219,14 @@ static int nfc_nand_check_ecc(void) static void nfc_nand_read_page(unsigned int page_address) { - writew(0, &nfc->buf_addr); /* read in first 0 buffer */ + /* read in first 0 buffer */ +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) + writenfc(0, &nfc->buf_addr); +#elif defined(MXC_NFC_V3_2) + int config1 = readnfc(&nfc->config1); + config1 &= ~NFC_V3_CONFIG1_RBA_MASK; + writenfc(config1, &nfc->config1); +#endif nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page_address);