From patchwork Thu Apr 11 19:35:37 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Beno=C3=AEt_Th=C3=A9baudeau?= X-Patchwork-Id: 235895 X-Patchwork-Delegate: albert.aribaud@free.fr 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 457692C009E for ; Fri, 12 Apr 2013 05:38:24 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 730424A0C7; Thu, 11 Apr 2013 21:38:10 +0200 (CEST) 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 Fc036LnFm-II; Thu, 11 Apr 2013 21:38:10 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 059DE4A0EB; Thu, 11 Apr 2013 21:36:26 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 92F8E4A08A for ; Thu, 11 Apr 2013 21:36:17 +0200 (CEST) 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 jvDNKkhpuecZ for ; Thu, 11 Apr 2013 21:36:09 +0200 (CEST) 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 zose-mta13.web4all.fr (zose-mta13.web4all.fr [178.33.204.91]) by theia.denx.de (Postfix) with ESMTPS id 7C2E64A033 for ; Thu, 11 Apr 2013 21:36:08 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by zose-mta13.web4all.fr (Postfix) with ESMTP id 2E4F96A1E2; Thu, 11 Apr 2013 21:36:08 +0200 (CEST) X-Virus-Scanned: amavisd-new at Received: from zose-mta13.web4all.fr ([127.0.0.1]) by localhost (zose-mta13.web4all.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id LL9uevZhmgaR; Thu, 11 Apr 2013 21:36:06 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by zose-mta13.web4all.fr (Postfix) with ESMTP id 5EF0B6A1DC; Thu, 11 Apr 2013 21:36:06 +0200 (CEST) X-Virus-Scanned: amavisd-new at Received: from zose-mta13.web4all.fr ([127.0.0.1]) by localhost (zose-mta13.web4all.fr [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id Fux0t1Dx8OJr; Thu, 11 Apr 2013 21:36:04 +0200 (CEST) Received: from advdt005-ubuntu.?none? (cie44-1-88-188-188-98.fbx.proxad.net [88.188.188.98]) by zose-mta13.web4all.fr (Postfix) with ESMTPA id 39F0E6A1BB; Thu, 11 Apr 2013 21:36:04 +0200 (CEST) From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= To: u-boot@lists.denx.de, Scott Wood , Stefano Babic , Albert Aribaud Date: Thu, 11 Apr 2013 21:35:37 +0200 Message-Id: <1365708963-14562-4-git-send-email-benoit.thebaudeau@advansee.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1365708963-14562-1-git-send-email-benoit.thebaudeau@advansee.com> References: <1365708963-14562-1-git-send-email-benoit.thebaudeau@advansee.com> MIME-Version: 1.0 Subject: [U-Boot] [PATCH v12 04/30] nand: mxc: 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 Signed-off-by: Benoît Thébaudeau Acked-by: Scott Wood Tested-by: Fabio Estevam --- Changes in v12: None Changes in v11: None Changes in v10: None Changes in v9: - Drop the now unused SRC register definitions. Changes in v8: - Rebase on Fabio's patches using CONFIG_SYS_NAND_BUSWIDTH_16BIT instead of NAND Flash boot config pins to determine NAND Flash bus width. Changes in v7: None Changes in v6: None Changes in v5: None Changes in v4: None Changes in v3: - Separate code reformatting from behavioral changes. Changes in v2: None drivers/mtd/nand/mxc_nand.c | 119 ++++++++++++++++++++++++++++++++++++++---- include/fsl_nfc.h | 79 +++++++++++++++++++++++++++- nand_spl/nand_boot_fsl_nfc.c | 67 +++++++++++++++++++++++- 3 files changed, 250 insertions(+), 15 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 6ae95d6..db72cdc 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, @@ -127,10 +131,17 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries, uint32_t tmp; while (max_retries-- > 0) { +#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); @@ -182,7 +193,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 @@ -198,11 +209,18 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, } } +#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 = readnfc(&host->regs->config1); + uint32_t config1 = readnfc(&host->regs->config1); if (spare_only) config1 |= NFC_CONFIG1_SP_EN; else @@ -225,7 +243,14 @@ 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); +#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) { @@ -242,7 +267,7 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id, /* 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; /* @@ -262,10 +287,16 @@ 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 */ 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 = readnfc(&host->regs->config1); @@ -284,15 +315,19 @@ 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 */ writenfc(1, &host->regs->buf_addr); +#endif /* Read status into main buffer */ tmp = readnfc(&host->regs->config1); @@ -304,12 +339,16 @@ static uint16_t get_dev_status(struct mxc_nand_host *host) /* 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; } @@ -328,6 +367,7 @@ 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; +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) uint16_t tmp = readnfc(&host->regs->config1); if (on) @@ -335,6 +375,15 @@ static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) 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_V3_CONFIG2_ECC_EN; + else + tmp &= ~NFC_V3_CONFIG2_ECC_EN; + writenfc(tmp, &host->ip_regs->config2); +#endif } #ifdef CONFIG_MXC_NAND_HWECC @@ -346,7 +395,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) @@ -1136,8 +1185,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 @@ -1165,13 +1214,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; @@ -1209,6 +1262,7 @@ 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 = readnfc(&host->regs->config1); tmp |= NFC_V2_CONFIG1_ONE_CYCLE; @@ -1243,6 +1297,49 @@ int board_nand_init(struct nand_chip *this) /* Unlock Block Command for given address range */ 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 013e9e2..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,9 +120,28 @@ 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 }; +#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 FCMD to 1, rest to 0 for Command operation */ #define NFC_CMD 0x1 @@ -131,20 +160,66 @@ struct fsl_nfc_regs { /* 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) + +#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 #endif /* __FSL_NFC_H */ diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index 615e820..1096727 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -30,12 +30,18 @@ #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; +#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1) while (!(readnfc(&nfc->config2) & NFC_V1_V2_CONFIG2_INT)) ; @@ -43,11 +49,56 @@ static void nfc_wait_ready(void) 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; @@ -123,7 +174,13 @@ static void nfc_nand_data_output(void) int i; #endif +#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 @@ -144,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; @@ -163,7 +220,13 @@ static int nfc_nand_check_ecc(void) static void nfc_nand_read_page(unsigned int page_address) { /* 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);