/*
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Sascha Hauer, kernel@pengutronix.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., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/completion.h>
#include <asm/mach/flash.h>
#include <mach/mxc_nand.h>
#include <mach/hardware.h>
#define DRIVER_NAME "mxc_nand"
#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
#define nfc_is_v3_2() (cpu_is_mx51() || cpu_is_mx53())
#define nfc_is_v3() nfc_is_v3_2()
/* Addresses for NFC registers */
#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
#define NFC_V1_V2_WRPROT (host->regs + 0x12)
#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
#define NFC_V21_UNLOCKSTART_BLKADDR0 (host->regs + 0x20)
#define NFC_V21_UNLOCKSTART_BLKADDR1 (host->regs + 0x24)
#define NFC_V21_UNLOCKSTART_BLKADDR2 (host->regs + 0x28)
#define NFC_V21_UNLOCKSTART_BLKADDR3 (host->regs + 0x2c)
#define NFC_V21_UNLOCKEND_BLKADDR0 (host->regs + 0x22)
#define NFC_V21_UNLOCKEND_BLKADDR1 (host->regs + 0x26)
#define NFC_V21_UNLOCKEND_BLKADDR2 (host->regs + 0x2a)
#define NFC_V21_UNLOCKEND_BLKADDR3 (host->regs + 0x2e)
#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
#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_V1_V2_CONFIG1_RST (1 << 6)
#define NFC_V1_V2_CONFIG1_CE (1 << 7)
#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8)
#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9)
#define NFC_V2_CONFIG1_FP_INT (1 << 11)
#define NFC_V1_V2_CONFIG2_INT (1 << 15)
/*
* Operation modes for the NFC. Valid for v1, v2 and v3
* type controllers.
*/
#define NFC_CMD (1 << 0)
#define NFC_ADDR (1 << 1)
#define NFC_INPUT (1 << 2)
#define NFC_OUTPUT (1 << 3)
#define NFC_ID (1 << 4)
#define NFC_STATUS (1 << 5)
#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
#define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04)
#define NFC_V3_CONFIG1 (host->regs_axi + 0x34)
#define NFC_V3_CONFIG1_SP_EN (1 << 0)
#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4)
#define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38)
#define NFC_V3_LAUNCH (host->regs_axi + 0x40)
#define NFC_V3_WRPROT (host->regs_ip + 0x0)
#define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0)
#define NFC_V3_WRPROT_LOCK (1 << 1)
#define NFC_V3_WRPROT_UNLOCK (1 << 2)
#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04)
#define NFC_V3_CONFIG2 (host->regs_ip + 0x24)
#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_PHASE0 (1 << 5)
#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7)
#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
#define NFC_V3_CONFIG3 (host->regs_ip + 0x28)
#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_DEVICES(x) (((x) & 0x7) << 12)
#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
#define NFC_V3_IPC (host->regs_ip + 0x2C)
#define NFC_V3_IPC_CREQ (1 << 0)
#define NFC_V3_IPC_INT (1 << 31)
#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
struct mxc_nand_host {
struct mtd_info mtd;
struct nand_chip nand;
struct device *dev;
void *spare0;
void *main_area0;
void __iomem *base;
void __iomem *regs;
void __iomem *regs_axi;
void __iomem *regs_ip;
int status_request;
struct clk *clk;
int <