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

// SPDX-License-Identifier: GPL-2.0
/*
 * ST Microelectronics
 * Flexible Static Memory Controller (FSMC)
 * Driver for NAND portions
 *
 * Copyright © 2010 ST Microelectronics
 * Vipin Kumar <[email protected]>
 * Ashish Priyadarshi
 *
 * Based on drivers/mtd/nand/nomadik_nand.c (removed in v3.8)
 *  Copyright © 2007 STMicroelectronics Pvt. Ltd.
 *  Copyright © 2009 Alessandro Rubini
 */

#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/dma-direction.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/resource.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand-ecc-sw-hamming.h>
#include <linux/mtd/rawnand.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/mtd/partitions.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/amba/bus.h>
#include <mtd/mtd-abi.h>

/* fsmc controller registers for NOR flash */
#define CTRL
	/* ctrl register definitions */
	#define BANK_ENABLE
	#define MUXED
	#define NOR_DEV
	#define WIDTH_16
	#define RSTPWRDWN
	#define WPROT
	#define WRT_ENABLE
	#define WAIT_ENB

#define CTRL_TIM
	/* ctrl_tim register definitions */

#define FSMC_NOR_BANK_SZ
#define FSMC_NOR_REG_SIZE

#define FSMC_NOR_REG(base, bank, reg)

/* fsmc controller registers for NAND flash */
#define FSMC_PC
	/* pc register definitions */
	#define FSMC_RESET
	#define FSMC_WAITON
	#define FSMC_ENABLE
	#define FSMC_DEVTYPE_NAND
	#define FSMC_DEVWID_16
	#define FSMC_ECCEN
	#define FSMC_ECCPLEN_256
	#define FSMC_TCLR_SHIFT
	#define FSMC_TCLR_MASK
	#define FSMC_TAR_SHIFT
	#define FSMC_TAR_MASK
#define STS
	/* sts register definitions */
	#define FSMC_CODE_RDY
#define COMM
	/* comm register definitions */
	#define FSMC_TSET_SHIFT
	#define FSMC_TSET_MASK
	#define FSMC_TWAIT_SHIFT
	#define FSMC_TWAIT_MASK
	#define FSMC_THOLD_SHIFT
	#define FSMC_THOLD_MASK
	#define FSMC_THIZ_SHIFT
	#define FSMC_THIZ_MASK
#define ATTRIB
#define IOATA
#define ECC1
#define ECC2
#define ECC3
#define FSMC_NAND_BANK_SZ

#define FSMC_BUSY_WAIT_TIMEOUT

/*
 * According to SPEAr300 Reference Manual (RM0082)
 *  TOUDEL = 7ns (Output delay from the flip-flops to the board)
 *  TINDEL = 5ns (Input delay from the board to the flipflop)
 */
#define TOUTDEL
#define TINDEL

struct fsmc_nand_timings {};

enum access_mode {};

/**
 * struct fsmc_nand_data - structure for FSMC NAND device state
 *
 * @base:		Inherit from the nand_controller struct
 * @pid:		Part ID on the AMBA PrimeCell format
 * @nand:		Chip related info for a NAND flash.
 *
 * @bank:		Bank number for probed device.
 * @dev:		Parent device
 * @mode:		Access mode
 * @clk:		Clock structure for FSMC.
 *
 * @read_dma_chan:	DMA channel for read access
 * @write_dma_chan:	DMA channel for write access to NAND
 * @dma_access_complete: Completion structure
 *
 * @dev_timings:	NAND timings
 *
 * @data_pa:		NAND Physical port for Data.
 * @data_va:		NAND port for Data.
 * @cmd_va:		NAND port for Command.
 * @addr_va:		NAND port for Address.
 * @regs_va:		Registers base address for a given bank.
 */
struct fsmc_nand_data {};

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

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

static const struct mtd_ooblayout_ops fsmc_ecc1_ooblayout_ops =;

/*
 * ECC placement definitions in oobfree type format.
 * There are 13 bytes of ecc for every 512 byte block and it has to be read
 * consecutively and immediately after the 512 byte data block for hardware to
 * generate the error bit offsets in 512 byte data.
 */
static int fsmc_ecc4_ooblayout_ecc(struct mtd_info *mtd, int section,
				   struct mtd_oob_region *oobregion)
{}

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

static const struct mtd_ooblayout_ops fsmc_ecc4_ooblayout_ops =;

static inline struct fsmc_nand_data *nand_to_fsmc(struct nand_chip *chip)
{}

/*
 * fsmc_nand_setup - FSMC (Flexible Static Memory Controller) init routine
 *
 * This routine initializes timing parameters related to NAND memory access in
 * FSMC registers
 */
static void fsmc_nand_setup(struct fsmc_nand_data *host,
			    struct fsmc_nand_timings *tims)
{}

static int fsmc_calc_timings(struct fsmc_nand_data *host,
			     const struct nand_sdr_timings *sdrt,
			     struct fsmc_nand_timings *tims)
{}

static int fsmc_setup_interface(struct nand_chip *nand, int csline,
				const struct nand_interface_config *conf)
{}

/*
 * fsmc_enable_hwecc - Enables Hardware ECC through FSMC registers
 */
static void fsmc_enable_hwecc(struct nand_chip *chip, int mode)
{}

/*
 * fsmc_read_hwecc_ecc4 - Hardware ECC calculator for ecc4 option supported by
 * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction up to
 * max of 8-bits)
 */
static int fsmc_read_hwecc_ecc4(struct nand_chip *chip, const u8 *data,
				u8 *ecc)
{}

/*
 * fsmc_read_hwecc_ecc1 - Hardware ECC calculator for ecc1 option supported by
 * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction up to
 * max of 1-bit)
 */
static int fsmc_read_hwecc_ecc1(struct nand_chip *chip, const u8 *data,
				u8 *ecc)
{}

static int fsmc_correct_ecc1(struct nand_chip *chip,
			     unsigned char *buf,
			     unsigned char *read_ecc,
			     unsigned char *calc_ecc)
{}

/* Count the number of 0's in buff upto a max of max_bits */
static int count_written_bits(u8 *buff, int size, int max_bits)
{}

static void dma_complete(void *param)
{}

static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len,
		    enum dma_data_direction direction)
{}

/*
 * fsmc_write_buf - write buffer to chip
 * @host:	FSMC NAND controller
 * @buf:	data buffer
 * @len:	number of bytes to write
 */
static void fsmc_write_buf(struct fsmc_nand_data *host, const u8 *buf,
			   int len)
{}

/*
 * fsmc_read_buf - read chip data into buffer
 * @host:	FSMC NAND controller
 * @buf:	buffer to store date
 * @len:	number of bytes to read
 */
static void fsmc_read_buf(struct fsmc_nand_data *host, u8 *buf, int len)
{}

/*
 * fsmc_read_buf_dma - read chip data into buffer
 * @host:	FSMC NAND controller
 * @buf:	buffer to store date
 * @len:	number of bytes to read
 */
static void fsmc_read_buf_dma(struct fsmc_nand_data *host, u8 *buf,
			      int len)
{}

/*
 * fsmc_write_buf_dma - write buffer to chip
 * @host:	FSMC NAND controller
 * @buf:	data buffer
 * @len:	number of bytes to write
 */
static void fsmc_write_buf_dma(struct fsmc_nand_data *host, const u8 *buf,
			       int len)
{}

/*
 * fsmc_exec_op - hook called by the core to execute NAND operations
 *
 * This controller is simple enough and thus does not need to use the parser
 * provided by the core, instead, handle every situation here.
 */
static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
			bool check_only)
{}

/*
 * fsmc_read_page_hwecc
 * @chip:	nand chip info structure
 * @buf:	buffer to store read data
 * @oob_required:	caller expects OOB data read to chip->oob_poi
 * @page:	page number to read
 *
 * This routine is needed for fsmc version 8 as reading from NAND chip has to be
 * performed in a strict sequence as follows:
 * data(512 byte) -> ecc(13 byte)
 * After this read, fsmc hardware generates and reports error data bits(up to a
 * max of 8 bits)
 */
static int fsmc_read_page_hwecc(struct nand_chip *chip, u8 *buf,
				int oob_required, int page)
{}

/*
 * fsmc_bch8_correct_data
 * @mtd:	mtd info structure
 * @dat:	buffer of read data
 * @read_ecc:	ecc read from device spare area
 * @calc_ecc:	ecc calculated from read data
 *
 * calc_ecc is a 104 bit information containing maximum of 8 error
 * offset information of 13 bits each in 512 bytes of read data.
 */
static int fsmc_bch8_correct_data(struct nand_chip *chip, u8 *dat,
				  u8 *read_ecc, u8 *calc_ecc)
{}

static bool filter(struct dma_chan *chan, void *slave)
{}

static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
				     struct fsmc_nand_data *host,
				     struct nand_chip *nand)
{}

static int fsmc_nand_attach_chip(struct nand_chip *nand)
{}

static const struct nand_controller_ops fsmc_nand_controller_ops =;

/**
 * fsmc_nand_disable() - Disables the NAND bank
 * @host: The instance to disable
 */
static void fsmc_nand_disable(struct fsmc_nand_data *host)
{}

/*
 * fsmc_nand_probe - Probe function
 * @pdev:       platform device structure
 */
static int __init fsmc_nand_probe(struct platform_device *pdev)
{}

/*
 * Clean up routine
 */
static void fsmc_nand_remove(struct platform_device *pdev)
{}

#ifdef CONFIG_PM_SLEEP
static int fsmc_nand_suspend(struct device *dev)
{}

static int fsmc_nand_resume(struct device *dev)
{}
#endif

static SIMPLE_DEV_PM_OPS(fsmc_nand_pm_ops, fsmc_nand_suspend, fsmc_nand_resume);

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

static struct platform_driver fsmc_nand_driver =;

module_platform_driver_probe();

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