]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/mtd/nand/mxc_nand_spl.c
Update from 2013.01 to 2013.07
[karo-tx-uboot.git] / drivers / mtd / nand / mxc_nand_spl.c
similarity index 58%
rename from nand_spl/nand_boot_fsl_nfc.c
rename to drivers/mtd/nand/mxc_nand_spl.c
index a40c99877c0e612ee5f56e84f1904936113e683d..69b736a848dbca6b3e0c8a4365ace5e317e7d53f 100644 (file)
  * (C) Copyright 2006-2008
  * Stefan Roese, DENX Software Engineering, sr at denx.de.
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 #include <nand.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/io.h>
-#include <fsl_nfc.h>
+#include "mxc_nand.h"
 
-static struct fsl_nfc_regs *const nfc = (void *)NFC_BASE_ADDR;
+#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
+static struct mxc_nand_regs *const nfc = (void *)NFC_BASE_ADDR;
+#elif defined(MXC_NFC_V3_2)
+static struct mxc_nand_regs *const nfc = (void *)NFC_BASE_ADDR_AXI;
+static struct mxc_nand_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_OOBSIZE / 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_OOBSIZE / 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_OOBSIZE / 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;
+       if (CONFIG_SYS_NAND_OOBSIZE / ecc_per_page > 16)
+               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 +161,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 +176,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,10 +188,10 @@ 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;
+       int err_limit = CONFIG_SYS_NAND_OOBSIZE / ecc_per_page > 16 ? 8 : 4;
        int subpages = CONFIG_SYS_NAND_PAGE_SIZE / 512;
 
        do {
@@ -160,7 +206,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);
 
@@ -224,7 +277,7 @@ static int is_badblock(int pagenumber)
        return 0;
 }
 
-static int nand_load(unsigned int from, unsigned int size, unsigned char *buf)
+int nand_spl_load_image(uint32_t from, unsigned int size, void *buf)
 {
        int i;
        unsigned int page;
@@ -237,6 +290,7 @@ static int nand_load(unsigned int from, unsigned int size, unsigned char *buf)
        page = from / CONFIG_SYS_NAND_PAGE_SIZE;
        i = 0;
 
+       size = roundup(size, CONFIG_SYS_NAND_PAGE_SIZE);
        while (i < size / CONFIG_SYS_NAND_PAGE_SIZE) {
                if (nfc_read_page(page, buf) < 0)
                        return -1;
@@ -266,14 +320,7 @@ static int nand_load(unsigned int from, unsigned int size, unsigned char *buf)
        return 0;
 }
 
-#if defined(CONFIG_ARM)
-void board_init_f (ulong bootflag)
-{
-       relocate_code (CONFIG_SYS_TEXT_BASE - TOTAL_MALLOC_LEN, NULL,
-                      CONFIG_SYS_TEXT_BASE);
-}
-#endif
-
+#ifndef CONFIG_SPL_FRAMEWORK
 /*
  * The main entry for NAND booting. It's necessary that SDRAM is already
  * configured and available since this code loads the main U-Boot image
@@ -287,8 +334,9 @@ void nand_boot(void)
         * CONFIG_SYS_NAND_U_BOOT_OFFS and CONFIG_SYS_NAND_U_BOOT_SIZE must
         * be aligned to full pages
         */
-       if (!nand_load(CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
-                      (uchar *)CONFIG_SYS_NAND_U_BOOT_DST)) {
+       if (!nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
+                       CONFIG_SYS_NAND_U_BOOT_SIZE,
+                       (uchar *)CONFIG_SYS_NAND_U_BOOT_DST)) {
                /* Copy from NAND successful, start U-boot */
                uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
                uboot();
@@ -297,12 +345,7 @@ void nand_boot(void)
                hang();
        }
 }
+#endif
 
-/*
- * Called in case of an exception.
- */
-void hang(void)
-{
-       /* Loop forever */
-       while (1) ;
-}
+void nand_init(void) {}
+void nand_deselect(void) {}