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

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Driver for NAND MLC Controller in LPC32xx
 *
 * Author: Roland Stigge <[email protected]>
 *
 * Copyright © 2011 WORK Microwave GmbH
 * Copyright © 2011, 2012 Roland Stigge
 *
 * NAND Flash Controller Operation:
 * - Read: Auto Decode
 * - Write: Auto Encode
 * - Tested Page Sizes: 2048, 4096
 */

#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/gpio/consumer.h>
#include <linux/mtd/lpc32xx_mlc.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>

#define DRV_NAME

/**********************************************************************
* MLC NAND controller register offsets
**********************************************************************/

#define MLC_BUFF(x)
#define MLC_DATA(x)
#define MLC_CMD(x)
#define MLC_ADDR(x)
#define MLC_ECC_ENC_REG(x)
#define MLC_ECC_DEC_REG(x)
#define MLC_ECC_AUTO_ENC_REG(x)
#define MLC_ECC_AUTO_DEC_REG(x)
#define MLC_RPR(x)
#define MLC_WPR(x)
#define MLC_RUBP(x)
#define MLC_ROBP(x)
#define MLC_SW_WP_ADD_LOW(x)
#define MLC_SW_WP_ADD_HIG(x)
#define MLC_ICR(x)
#define MLC_TIME_REG(x)
#define MLC_IRQ_MR(x)
#define MLC_IRQ_SR(x)
#define MLC_LOCK_PR(x)
#define MLC_ISR(x)
#define MLC_CEH(x)

/**********************************************************************
* MLC_CMD bit definitions
**********************************************************************/
#define MLCCMD_RESET

/**********************************************************************
* MLC_ICR bit definitions
**********************************************************************/
#define MLCICR_WPROT
#define MLCICR_LARGEBLOCK
#define MLCICR_LONGADDR
#define MLCICR_16BIT

/**********************************************************************
* MLC_TIME_REG bit definitions
**********************************************************************/
#define MLCTIMEREG_TCEA_DELAY(n)
#define MLCTIMEREG_BUSY_DELAY(n)
#define MLCTIMEREG_NAND_TA(n)
#define MLCTIMEREG_RD_HIGH(n)
#define MLCTIMEREG_RD_LOW(n)
#define MLCTIMEREG_WR_HIGH(n)
#define MLCTIMEREG_WR_LOW(n)

/**********************************************************************
* MLC_IRQ_MR and MLC_IRQ_SR bit definitions
**********************************************************************/
#define MLCIRQ_NAND_READY
#define MLCIRQ_CONTROLLER_READY
#define MLCIRQ_DECODE_FAILURE
#define MLCIRQ_DECODE_ERROR
#define MLCIRQ_ECC_READY
#define MLCIRQ_WRPROT_FAULT

/**********************************************************************
* MLC_LOCK_PR bit definitions
**********************************************************************/
#define MLCLOCKPR_MAGIC

/**********************************************************************
* MLC_ISR bit definitions
**********************************************************************/
#define MLCISR_DECODER_FAILURE
#define MLCISR_ERRORS
#define MLCISR_ERRORS_DETECTED
#define MLCISR_ECC_READY
#define MLCISR_CONTROLLER_READY
#define MLCISR_NAND_READY

/**********************************************************************
* MLC_CEH bit definitions
**********************************************************************/
#define MLCCEH_NORMAL

struct lpc32xx_nand_cfg_mlc {};

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

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

static const struct mtd_ooblayout_ops lpc32xx_ooblayout_ops =;

static struct nand_bbt_descr lpc32xx_nand_bbt =;

static struct nand_bbt_descr lpc32xx_nand_bbt_mirror =;

struct lpc32xx_nand_host {};

/*
 * Activate/Deactivate DMA Operation:
 *
 * Using the PL080 DMA Controller for transferring the 512 byte subpages
 * instead of doing readl() / writel() in a loop slows it down significantly.
 * Measurements via getnstimeofday() upon 512 byte subpage reads reveal:
 *
 * - readl() of 128 x 32 bits in a loop: ~20us
 * - DMA read of 512 bytes (32 bit, 4...128 words bursts): ~60us
 * - DMA read of 512 bytes (32 bit, no bursts): ~100us
 *
 * This applies to the transfer itself. In the DMA case: only the
 * wait_for_completion() (DMA setup _not_ included).
 *
 * Note that the 512 bytes subpage transfer is done directly from/to a
 * FIFO/buffer inside the NAND controller. Most of the time (~400-800us for a
 * 2048 bytes page) is spent waiting for the NAND IRQ, anyway. (The NAND
 * controller transferring data between its internal buffer to/from the NAND
 * chip.)
 *
 * Therefore, using the PL080 DMA is disabled by default, for now.
 *
 */
static int use_dma;

static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host)
{}

/*
 * Hardware specific access to control lines
 */
static void lpc32xx_nand_cmd_ctrl(struct nand_chip *nand_chip, int cmd,
				  unsigned int ctrl)
{}

/*
 * Read Device Ready (NAND device _and_ controller ready)
 */
static int lpc32xx_nand_device_ready(struct nand_chip *nand_chip)
{}

static irqreturn_t lpc3xxx_nand_irq(int irq, void *data)
{}

static int lpc32xx_waitfunc_nand(struct nand_chip *chip)
{}

static int lpc32xx_waitfunc_controller(struct nand_chip *chip)
{}

static int lpc32xx_waitfunc(struct nand_chip *chip)
{}

/*
 * Enable NAND write protect
 */
static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
{}

/*
 * Disable NAND write protect
 */
static void lpc32xx_wp_disable(struct lpc32xx_nand_host *host)
{}

static void lpc32xx_dma_complete_func(void *completion)
{}

static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
			    enum dma_transfer_direction dir)
{}

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

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

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

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

/* Prepares MLC for transfers with H/W ECC enabled: always enabled anyway */
static void lpc32xx_ecc_enable(struct nand_chip *chip, int mode)
{}

static int lpc32xx_dma_setup(struct lpc32xx_nand_host *host)
{}

static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev)
{}

static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
{}

static const struct nand_controller_ops lpc32xx_nand_controller_ops =;

/*
 * Probe for NAND controller
 */
static int lpc32xx_nand_probe(struct platform_device *pdev)
{}

/*
 * Remove NAND device
 */
static void lpc32xx_nand_remove(struct platform_device *pdev)
{}

static int lpc32xx_nand_resume(struct platform_device *pdev)
{}

static int lpc32xx_nand_suspend(struct platform_device *pdev, pm_message_t pm)
{}

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

static struct platform_driver lpc32xx_nand_driver =;

module_platform_driver();

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