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

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * davinci_nand.c - NAND Flash Driver for DaVinci family chips
 *
 * Copyright © 2006 Texas Instruments.
 *
 * Port to 2.6.23 Copyright © 2008 by:
 *   Sander Huijsen <[email protected]>
 *   Troy Kisky <[email protected]>
 *   Dirk Behme <[email protected]>
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/iopoll.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/slab.h>
#include <linux/of.h>

#include <linux/platform_data/mtd-davinci.h>
#include <linux/platform_data/mtd-davinci-aemif.h>

/*
 * This is a device driver for the NAND flash controller found on the
 * various DaVinci family chips.  It handles up to four SoC chipselects,
 * and some flavors of secondary chipselect (e.g. based on A12) as used
 * with multichip packages.
 *
 * The 1-bit ECC hardware is supported, as well as the newer 4-bit ECC
 * available on chips like the DM355 and OMAP-L137 and needed with the
 * more error-prone MLC NAND chips.
 *
 * This driver assumes EM_WAIT connects all the NAND devices' RDY/nBUSY
 * outputs in a "wire-AND" configuration, with no per-chip signals.
 */
struct davinci_nand_info {};

static DEFINE_SPINLOCK(davinci_nand_lock);
static bool ecc4_busy;

static inline struct davinci_nand_info *to_davinci_nand(struct mtd_info *mtd)
{}

static inline unsigned int davinci_nand_readl(struct davinci_nand_info *info,
		int offset)
{}

static inline void davinci_nand_writel(struct davinci_nand_info *info,
		int offset, unsigned long value)
{}

/*----------------------------------------------------------------------*/

/*
 * 1-bit hardware ECC ... context maintained for each core chipselect
 */

static inline uint32_t nand_davinci_readecc_1bit(struct mtd_info *mtd)
{}

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

/*
 * Read hardware ECC value and pack into three bytes
 */
static int nand_davinci_calculate_1bit(struct nand_chip *chip,
				       const u_char *dat, u_char *ecc_code)
{}

static int nand_davinci_correct_1bit(struct nand_chip *chip, u_char *dat,
				     u_char *read_ecc, u_char *calc_ecc)
{}

/*----------------------------------------------------------------------*/

/*
 * 4-bit hardware ECC ... context maintained over entire AEMIF
 *
 * This is a syndrome engine, but we avoid NAND_ECC_PLACEMENT_INTERLEAVED
 * since that forces use of a problematic "infix OOB" layout.
 * Among other things, it trashes manufacturer bad block markers.
 * Also, and specific to this hardware, it ECC-protects the "prepad"
 * in the OOB ... while having ECC protection for parts of OOB would
 * seem useful, the current MTD stack sometimes wants to update the
 * OOB without recomputing ECC.
 */

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

/* Read raw ECC code after writing to NAND. */
static void
nand_davinci_readecc_4bit(struct davinci_nand_info *info, u32 code[4])
{}

/* Terminate read ECC; or return ECC (as bytes) of data written to NAND. */
static int nand_davinci_calculate_4bit(struct nand_chip *chip,
				       const u_char *dat, u_char *ecc_code)
{}

/* Correct up to 4 bits in data we just read, using state left in the
 * hardware plus the ecc_code computed when it was first written.
 */
static int nand_davinci_correct_4bit(struct nand_chip *chip, u_char *data,
				     u_char *ecc_code, u_char *null)
{}

/*----------------------------------------------------------------------*/

/* An ECC layout for using 4-bit ECC with small-page flash, storing
 * ten ECC bytes plus the manufacturer's bad block marker byte, and
 * and not overlapping the default BBT markers.
 */
static int hwecc4_ooblayout_small_ecc(struct mtd_info *mtd, int section,
				      struct mtd_oob_region *oobregion)
{}

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

static const struct mtd_ooblayout_ops hwecc4_small_ooblayout_ops =;

#if defined(CONFIG_OF)
static const struct of_device_id davinci_nand_of_match[] =;
MODULE_DEVICE_TABLE(of, davinci_nand_of_match);

static struct davinci_nand_pdata
	*nand_davinci_get_pdata(struct platform_device *pdev)
{}
#else
static struct davinci_nand_pdata
	*nand_davinci_get_pdata(struct platform_device *pdev)
{
	return dev_get_platdata(&pdev->dev);
}
#endif

static int davinci_nand_attach_chip(struct nand_chip *chip)
{}

static void nand_davinci_data_in(struct davinci_nand_info *info, void *buf,
				 unsigned int len, bool force_8bit)
{}

static void nand_davinci_data_out(struct davinci_nand_info *info,
				  const void *buf, unsigned int len,
				  bool force_8bit)
{}

static int davinci_nand_exec_instr(struct davinci_nand_info *info,
				   const struct nand_op_instr *instr)
{}

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

static const struct nand_controller_ops davinci_nand_controller_ops =;

static int nand_davinci_probe(struct platform_device *pdev)
{}

static void nand_davinci_remove(struct platform_device *pdev)
{}

static struct platform_driver nand_davinci_driver =;
MODULE_ALIAS();

module_platform_driver();

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