linux/drivers/mtd/nand/raw/mxc_nand.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright 2008 Sascha Hauer, [email protected]
 */

#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.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 <linux/of.h>
#include <linux/bitfield.h>

#define DRIVER_NAME

/* Addresses for NFC registers */
#define NFC_V1_V2_BUF_SIZE
#define NFC_V1_V2_BUF_ADDR
#define NFC_V1_V2_FLASH_ADDR
#define NFC_V1_V2_FLASH_CMD
#define NFC_V1_V2_CONFIG
#define NFC_V1_V2_ECC_STATUS_RESULT
#define NFC_V1_V2_RSLTMAIN_AREA
#define NFC_V21_RSLTSPARE_AREA
#define NFC_V1_V2_WRPROT
#define NFC_V1_UNLOCKSTART_BLKADDR
#define NFC_V1_UNLOCKEND_BLKADDR
#define NFC_V21_UNLOCKSTART_BLKADDR0
#define NFC_V21_UNLOCKSTART_BLKADDR1
#define NFC_V21_UNLOCKSTART_BLKADDR2
#define NFC_V21_UNLOCKSTART_BLKADDR3
#define NFC_V21_UNLOCKEND_BLKADDR0
#define NFC_V21_UNLOCKEND_BLKADDR1
#define NFC_V21_UNLOCKEND_BLKADDR2
#define NFC_V21_UNLOCKEND_BLKADDR3
#define NFC_V1_V2_NF_WRPRST
#define NFC_V1_V2_CONFIG1
#define NFC_V1_V2_CONFIG2

#define NFC_V1_V2_ECC_STATUS_RESULT_ERM

#define NFC_V2_CONFIG1_ECC_MODE_4
#define NFC_V1_V2_CONFIG1_SP_EN
#define NFC_V1_V2_CONFIG1_ECC_EN
#define NFC_V1_V2_CONFIG1_INT_MSK
#define NFC_V1_V2_CONFIG1_BIG
#define NFC_V1_V2_CONFIG1_RST
#define NFC_V1_V2_CONFIG1_CE
#define NFC_V2_CONFIG1_ONE_CYCLE
#define NFC_V2_CONFIG1_PPB(x)
#define NFC_V2_CONFIG1_FP_INT

#define NFC_V1_V2_CONFIG2_INT

/*
 * Operation modes for the NFC. Valid for v1, v2 and v3
 * type controllers.
 */
#define NFC_CMD
#define NFC_ADDR
#define NFC_INPUT
#define NFC_OUTPUT
#define NFC_ID
#define NFC_STATUS

#define NFC_V3_FLASH_CMD
#define NFC_V3_FLASH_ADDR0

#define NFC_V3_CONFIG1
#define NFC_V3_CONFIG1_SP_EN
#define NFC_V3_CONFIG1_RBA(x)

#define NFC_V3_ECC_STATUS_RESULT

#define NFC_V3_LAUNCH

#define NFC_V3_WRPROT
#define NFC_V3_WRPROT_LOCK_TIGHT
#define NFC_V3_WRPROT_LOCK
#define NFC_V3_WRPROT_UNLOCK
#define NFC_V3_WRPROT_BLS_UNLOCK

#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0

#define NFC_V3_CONFIG2
#define NFC_V3_CONFIG2_PS_512
#define NFC_V3_CONFIG2_PS_2048
#define NFC_V3_CONFIG2_PS_4096
#define NFC_V3_CONFIG2_ONE_CYCLE
#define NFC_V3_CONFIG2_ECC_EN
#define NFC_V3_CONFIG2_2CMD_PHASES
#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0
#define NFC_V3_CONFIG2_ECC_MODE_8
#define NFC_V3_CONFIG2_PPB(x, shift)
#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x)
#define NFC_V3_CONFIG2_INT_MSK
#define NFC_V3_CONFIG2_ST_CMD(x)
#define NFC_V3_CONFIG2_SPAS(x)

#define NFC_V3_CONFIG3
#define NFC_V3_CONFIG3_ADD_OP(x)
#define NFC_V3_CONFIG3_FW8
#define NFC_V3_CONFIG3_SBB(x)
#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x)
#define NFC_V3_CONFIG3_RBB_MODE
#define NFC_V3_CONFIG3_NO_SDMA

#define NFC_V3_IPC
#define NFC_V3_IPC_CREQ
#define NFC_V3_IPC_INT

#define NFC_V3_DELAY_LINE

struct mxc_nand_host;

struct mxc_nand_devtype_data {};

struct mxc_nand_host {};

static const char * const part_probes[] =;

static void memcpy32_fromio(void *trg, const void __iomem  *src, size_t size)
{}

static void memcpy16_fromio(void *trg, const void __iomem  *src, size_t size)
{}

static inline void memcpy32_toio(void __iomem *trg, const void *src, int size)
{}

static void memcpy16_toio(void __iomem *trg, const void *src, int size)
{}

/*
 * The controller splits a page into data chunks of 512 bytes + partial oob.
 * There are writesize / 512 such chunks, the size of the partial oob parts is
 * oobsize / #chunks rounded down to a multiple of 2. The last oob chunk then
 * contains additionally the byte lost by rounding (if any).
 * This function handles the needed shuffling between host->data_buf (which
 * holds a page in natural order, i.e. writesize bytes data + oobsize bytes
 * spare) and the NFC buffer.
 */
static void copy_spare(struct mtd_info *mtd, bool bfrom, void *buf)
{}

static int check_int_v3(struct mxc_nand_host *host)
{}

static int check_int_v1_v2(struct mxc_nand_host *host)
{}

static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
{}

static void irq_control_v3(struct mxc_nand_host *host, int activate)
{}

static void irq_control(struct mxc_nand_host *host, int activate)
{}

static u32 get_ecc_status_v1(struct nand_chip *chip)
{}

static u32 get_ecc_status_v2_v3(struct nand_chip *chip, unsigned int ecc_stat)
{}

static u32 get_ecc_status_v2(struct nand_chip *chip)
{}

static u32 get_ecc_status_v3(struct nand_chip *chip)
{}

static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
{}

/* This function polls the NANDFC to wait for the basic operation to
 * complete by checking the INT bit of config2 register.
 */
static int wait_op_done(struct mxc_nand_host *host, int useirq)
{}

static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
{}

/* This function issues the specified command to the NAND device and
 * waits for completion. */
static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
{}

static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
{}

/* 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. */
static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
{}

static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
{}

static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
{}

static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
{}

static void send_read_id_v3(struct mxc_nand_host *host)
{}

/* Request the NANDFC to perform a read of the NAND device ID. */
static void send_read_id_v1_v2(struct mxc_nand_host *host)
{}

static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
{}

/* This function requests the NANDFC to perform a read of the
 * NAND device status and returns the current status. */
static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
{}

static void mxc_nand_enable_hwecc_v1_v2(struct nand_chip *chip, bool enable)
{}

static void mxc_nand_enable_hwecc_v3(struct nand_chip *chip, bool enable)
{}

static int mxc_nand_read_page_v1(struct nand_chip *chip)
{}

static int mxc_nand_read_page_v2_v3(struct nand_chip *chip)
{}

static int mxc_nand_read_page(struct nand_chip *chip, uint8_t *buf,
			      int oob_required, int page)
{}

static int mxc_nand_read_page_raw(struct nand_chip *chip, uint8_t *buf,
				  int oob_required, int page)
{}

static int mxc_nand_read_oob(struct nand_chip *chip, int page)
{}

static int mxc_nand_write_page_ecc(struct nand_chip *chip, const uint8_t *buf,
				   int oob_required, int page)
{}

static int mxc_nand_write_page_raw(struct nand_chip *chip, const uint8_t *buf,
				   int oob_required, int page)
{}

static int mxc_nand_write_oob(struct nand_chip *chip, int page)
{}

/* This function is used by upper layer for select and
 * deselect of the NAND chip */
static void mxc_nand_select_chip_v1_v3(struct nand_chip *nand_chip, int chip)
{}

static void mxc_nand_select_chip_v2(struct nand_chip *nand_chip, int chip)
{}

#define MXC_V1_ECCBYTES

static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
				struct mtd_oob_region *oobregion)
{}

static int mxc_v1_ooblayout_free(struct mtd_info *mtd, int section,
				 struct mtd_oob_region *oobregion)
{}

static const struct mtd_ooblayout_ops mxc_v1_ooblayout_ops =;

static int mxc_v2_ooblayout_ecc(struct mtd_info *mtd, int section,
				struct mtd_oob_region *oobregion)
{}

static int mxc_v2_ooblayout_free(struct mtd_info *mtd, int section,
				 struct mtd_oob_region *oobregion)
{}

static const struct mtd_ooblayout_ops mxc_v2_ooblayout_ops =;

/*
 * v2 and v3 type controllers can do 4bit or 8bit ecc depending
 * on how much oob the nand chip has. For 8bit ecc we need at least
 * 26 bytes of oob data per 512 byte block.
 */
static int get_eccsize(struct mtd_info *mtd)
{}

static void preset_v1(struct mtd_info *mtd)
{}

static int mxc_nand_v2_setup_interface(struct nand_chip *chip, int csline,
				       const struct nand_interface_config *conf)
{}

static void preset_v2(struct mtd_info *mtd)
{}

static void preset_v3(struct mtd_info *mtd)
{}

/*
 * The generic flash bbt descriptors overlap with our ecc
 * hardware, so define some i.MX specific ones.
 */
static uint8_t bbt_pattern[] =;
static uint8_t mirror_pattern[] =;

static struct nand_bbt_descr bbt_main_descr =;

static struct nand_bbt_descr bbt_mirror_descr =;

/* v1 + irqpending_quirk: i.MX21 */
static const struct mxc_nand_devtype_data imx21_nand_devtype_data =;

/* v1 + !irqpending_quirk: i.MX27, i.MX31 */
static const struct mxc_nand_devtype_data imx27_nand_devtype_data =;

/* v21: i.MX25, i.MX35 */
static const struct mxc_nand_devtype_data imx25_nand_devtype_data =;

/* v3.2a: i.MX51 */
static const struct mxc_nand_devtype_data imx51_nand_devtype_data =;

/* v3.2b: i.MX53 */
static const struct mxc_nand_devtype_data imx53_nand_devtype_data =;

static inline int is_imx21_nfc(struct mxc_nand_host *host)
{}

static inline int is_imx27_nfc(struct mxc_nand_host *host)
{}

static inline int is_imx25_nfc(struct mxc_nand_host *host)
{}

static const struct of_device_id mxcnd_dt_ids[] =;
MODULE_DEVICE_TABLE(of, mxcnd_dt_ids);

static int mxcnd_attach_chip(struct nand_chip *chip)
{}

static int mxcnd_setup_interface(struct nand_chip *chip, int chipnr,
				 const struct nand_interface_config *conf)
{}

static void memff16_toio(void *buf, int n)
{}

static void copy_page_to_sram(struct mtd_info *mtd, const void *buf, int buf_len)
{}

static void copy_page_from_sram(struct mtd_info *mtd)
{}

static int mxcnd_do_exec_op(struct nand_chip *chip,
			    const struct nand_subop *op)
{}

#define MAX_DATA_SIZE

static const struct nand_op_parser mxcnd_op_parser =;

static int mxcnd_exec_op(struct nand_chip *chip,
			 const struct nand_operation *op, bool check_only)
{}

static const struct nand_controller_ops mxcnd_controller_ops =;

static int mxcnd_probe(struct platform_device *pdev)
{}

static void mxcnd_remove(struct platform_device *pdev)
{}

static struct platform_driver mxcnd_driver =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();