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

// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2013 Boris BREZILLON <[email protected]>
 *
 * Derived from:
 *	https://github.com/yuq/sunxi-nfc-mtd
 *	Copyright (C) 2013 Qiang Yu <[email protected]>
 *
 *	https://github.com/hno/Allwinner-Info
 *	Copyright (C) 2013 Henrik Nordström <Henrik Nordström>
 *
 *	Copyright (C) 2013 Dmitriy B. <[email protected]>
 *	Copyright (C) 2013 Sergey Lapin <[email protected]>
 */

#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/reset.h>

#define NFC_REG_CTL
#define NFC_REG_ST
#define NFC_REG_INT
#define NFC_REG_TIMING_CTL
#define NFC_REG_TIMING_CFG
#define NFC_REG_ADDR_LOW
#define NFC_REG_ADDR_HIGH
#define NFC_REG_SECTOR_NUM
#define NFC_REG_CNT
#define NFC_REG_CMD
#define NFC_REG_RCMD_SET
#define NFC_REG_WCMD_SET
#define NFC_REG_A10_IO_DATA
#define NFC_REG_A23_IO_DATA
#define NFC_REG_ECC_CTL
#define NFC_REG_ECC_ST
#define NFC_REG_DEBUG
#define NFC_REG_ECC_ERR_CNT(x)
#define NFC_REG_USER_DATA(x)
#define NFC_REG_SPARE_AREA
#define NFC_REG_PAT_ID
#define NFC_REG_MDMA_ADDR
#define NFC_REG_MDMA_CNT
#define NFC_RAM0_BASE
#define NFC_RAM1_BASE

/* define bit use in NFC_CTL */
#define NFC_EN
#define NFC_RESET
#define NFC_BUS_WIDTH_MSK
#define NFC_BUS_WIDTH_8
#define NFC_BUS_WIDTH_16
#define NFC_RB_SEL_MSK
#define NFC_RB_SEL(x)
#define NFC_CE_SEL_MSK
#define NFC_CE_SEL(x)
#define NFC_CE_CTL
#define NFC_PAGE_SHIFT_MSK
#define NFC_PAGE_SHIFT(x)
#define NFC_SAM
#define NFC_RAM_METHOD
#define NFC_DMA_TYPE_NORMAL
#define NFC_DEBUG_CTL

/* define bit use in NFC_ST */
#define NFC_RB_B2R
#define NFC_CMD_INT_FLAG
#define NFC_DMA_INT_FLAG
#define NFC_CMD_FIFO_STATUS
#define NFC_STA
#define NFC_NATCH_INT_FLAG
#define NFC_RB_STATE(x)

/* define bit use in NFC_INT */
#define NFC_B2R_INT_ENABLE
#define NFC_CMD_INT_ENABLE
#define NFC_DMA_INT_ENABLE
#define NFC_INT_MASK

/* define bit use in NFC_TIMING_CTL */
#define NFC_TIMING_CTL_EDO

/* define NFC_TIMING_CFG register layout */
#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD)

/* define bit use in NFC_CMD */
#define NFC_CMD_LOW_BYTE_MSK
#define NFC_CMD_HIGH_BYTE_MSK
#define NFC_CMD(x)
#define NFC_ADR_NUM_MSK
#define NFC_ADR_NUM(x)
#define NFC_SEND_ADR
#define NFC_ACCESS_DIR
#define NFC_DATA_TRANS
#define NFC_SEND_CMD1
#define NFC_WAIT_FLAG
#define NFC_SEND_CMD2
#define NFC_SEQ
#define NFC_DATA_SWAP_METHOD
#define NFC_ROW_AUTO_INC
#define NFC_SEND_CMD3
#define NFC_SEND_CMD4
#define NFC_CMD_TYPE_MSK
#define NFC_NORMAL_OP
#define NFC_ECC_OP
#define NFC_PAGE_OP

/* define bit use in NFC_RCMD_SET */
#define NFC_READ_CMD_MSK
#define NFC_RND_READ_CMD0_MSK
#define NFC_RND_READ_CMD1_MSK

/* define bit use in NFC_WCMD_SET */
#define NFC_PROGRAM_CMD_MSK
#define NFC_RND_WRITE_CMD_MSK
#define NFC_READ_CMD0_MSK
#define NFC_READ_CMD1_MSK

/* define bit use in NFC_ECC_CTL */
#define NFC_ECC_EN
#define NFC_ECC_PIPELINE
#define NFC_ECC_EXCEPTION
#define NFC_ECC_BLOCK_SIZE_MSK
#define NFC_ECC_BLOCK_512
#define NFC_RANDOM_EN
#define NFC_RANDOM_DIRECTION
#define NFC_ECC_MODE_MSK
#define NFC_ECC_MODE(x)
#define NFC_RANDOM_SEED_MSK
#define NFC_RANDOM_SEED(x)

/* define bit use in NFC_ECC_ST */
#define NFC_ECC_ERR(x)
#define NFC_ECC_ERR_MSK
#define NFC_ECC_PAT_FOUND(x)
#define NFC_ECC_ERR_CNT(b, x)

#define NFC_DEFAULT_TIMEOUT_MS

#define NFC_SRAM_SIZE

#define NFC_MAX_CS

/**
 * struct sunxi_nand_chip_sel - stores information related to NAND Chip Select
 *
 * @cs: the NAND CS id used to communicate with a NAND Chip
 * @rb: the Ready/Busy pin ID. -1 means no R/B pin connected to the NFC
 */
struct sunxi_nand_chip_sel {};

/**
 * struct sunxi_nand_hw_ecc - stores information related to HW ECC support
 *
 * @ecc_ctl: ECC_CTL register value for this NAND chip
 */
struct sunxi_nand_hw_ecc {};

/**
 * struct sunxi_nand_chip - stores NAND chip device related information
 *
 * @node: used to store NAND chips into a list
 * @nand: base NAND chip structure
 * @ecc: ECC controller structure
 * @clk_rate: clk_rate required for this NAND chip
 * @timing_cfg: TIMING_CFG register value for this NAND chip
 * @timing_ctl: TIMING_CTL register value for this NAND chip
 * @nsels: number of CS lines required by the NAND chip
 * @sels: array of CS lines descriptions
 */
struct sunxi_nand_chip {};

static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
{}

/*
 * NAND Controller capabilities structure: stores NAND controller capabilities
 * for distinction between compatible strings.
 *
 * @has_mdma:		Use mbus dma mode, otherwise general dma
 *			through MBUS on A23/A33 needs extra configuration.
 * @reg_io_data:	I/O data register
 * @dma_maxburst:	DMA maxburst
 */
struct sunxi_nfc_caps {};

/**
 * struct sunxi_nfc - stores sunxi NAND controller information
 *
 * @controller: base controller structure
 * @dev: parent device (used to print error messages)
 * @regs: NAND controller registers
 * @ahb_clk: NAND controller AHB clock
 * @mod_clk: NAND controller mod clock
 * @reset: NAND controller reset line
 * @assigned_cs: bitmask describing already assigned CS lines
 * @clk_rate: NAND controller current clock rate
 * @chips: a list containing all the NAND chips attached to this NAND
 *	   controller
 * @complete: a completion object used to wait for NAND controller events
 * @dmac: the DMA channel attached to the NAND controller
 * @caps: NAND Controller capabilities
 */
struct sunxi_nfc {};

static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_controller *ctrl)
{}

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

static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events,
				 bool use_polling, unsigned int timeout_ms)
{}

static int sunxi_nfc_wait_cmd_fifo_empty(struct sunxi_nfc *nfc)
{}

static int sunxi_nfc_rst(struct sunxi_nfc *nfc)
{}

static int sunxi_nfc_dma_op_prepare(struct sunxi_nfc *nfc, const void *buf,
				    int chunksize, int nchunks,
				    enum dma_data_direction ddir,
				    struct scatterlist *sg)
{}

static void sunxi_nfc_dma_op_cleanup(struct sunxi_nfc *nfc,
				     enum dma_data_direction ddir,
				     struct scatterlist *sg)
{}

static void sunxi_nfc_select_chip(struct nand_chip *nand, unsigned int cs)
{}

static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len)
{}

static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf,
				int len)
{}

/* These seed values have been extracted from Allwinner's BSP */
static const u16 sunxi_nfc_randomizer_page_seeds[] =;

/*
 * sunxi_nfc_randomizer_ecc512_seeds and sunxi_nfc_randomizer_ecc1024_seeds
 * have been generated using
 * sunxi_nfc_randomizer_step(seed, (step_size * 8) + 15), which is what
 * the randomizer engine does internally before de/scrambling OOB data.
 *
 * Those tables are statically defined to avoid calculating randomizer state
 * at runtime.
 */
static const u16 sunxi_nfc_randomizer_ecc512_seeds[] =;

static const u16 sunxi_nfc_randomizer_ecc1024_seeds[] =;

static u16 sunxi_nfc_randomizer_step(u16 state, int count)
{}

static u16 sunxi_nfc_randomizer_state(struct nand_chip *nand, int page,
				      bool ecc)
{}

static void sunxi_nfc_randomizer_config(struct nand_chip *nand, int page,
					bool ecc)
{}

static void sunxi_nfc_randomizer_enable(struct nand_chip *nand)
{}

static void sunxi_nfc_randomizer_disable(struct nand_chip *nand)
{}

static void sunxi_nfc_randomize_bbm(struct nand_chip *nand, int page, u8 *bbm)
{}

static void sunxi_nfc_randomizer_write_buf(struct nand_chip *nand,
					   const uint8_t *buf, int len,
					   bool ecc, int page)
{}

static void sunxi_nfc_randomizer_read_buf(struct nand_chip *nand, uint8_t *buf,
					  int len, bool ecc, int page)
{}

static void sunxi_nfc_hw_ecc_enable(struct nand_chip *nand)
{}

static void sunxi_nfc_hw_ecc_disable(struct nand_chip *nand)
{}

static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf)
{}

static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
{}

static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob,
						int step, bool bbm, int page)
{}

static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand,
						const u8 *oob, int step,
						bool bbm, int page)
{}

static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand,
					  unsigned int *max_bitflips, int ret)
{}

static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob,
				    int step, u32 status, bool *erased)
{}

static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
				       u8 *data, int data_off,
				       u8 *oob, int oob_off,
				       int *cur_off,
				       unsigned int *max_bitflips,
				       bool bbm, bool oob_required, int page)
{}

static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand,
					    u8 *oob, int *cur_off,
					    bool randomize, int page)
{}

static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf,
					    int oob_required, int page,
					    int nchunks)
{}

static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
					const u8 *data, int data_off,
					const u8 *oob, int oob_off,
					int *cur_off, bool bbm,
					int page)
{}

static void sunxi_nfc_hw_ecc_write_extra_oob(struct nand_chip *nand,
					     u8 *oob, int *cur_off,
					     int page)
{}

static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf,
				      int oob_required, int page)
{}

static int sunxi_nfc_hw_ecc_read_page_dma(struct nand_chip *nand, u8 *buf,
					  int oob_required, int page)
{}

static int sunxi_nfc_hw_ecc_read_subpage(struct nand_chip *nand,
					 u32 data_offs, u32 readlen,
					 u8 *bufpoi, int page)
{}

static int sunxi_nfc_hw_ecc_read_subpage_dma(struct nand_chip *nand,
					     u32 data_offs, u32 readlen,
					     u8 *buf, int page)
{}

static int sunxi_nfc_hw_ecc_write_page(struct nand_chip *nand,
				       const uint8_t *buf, int oob_required,
				       int page)
{}

static int sunxi_nfc_hw_ecc_write_subpage(struct nand_chip *nand,
					  u32 data_offs, u32 data_len,
					  const u8 *buf, int oob_required,
					  int page)
{}

static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand,
					   const u8 *buf,
					   int oob_required,
					   int page)
{}

static int sunxi_nfc_hw_ecc_read_oob(struct nand_chip *nand, int page)
{}

static int sunxi_nfc_hw_ecc_write_oob(struct nand_chip *nand, int page)
{}

static const s32 tWB_lut[] =;
static const s32 tRHW_lut[] =;

static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration,
		u32 clk_period)
{}

#define sunxi_nand_lookup_timing(l, p, c)

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

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

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

static const struct mtd_ooblayout_ops sunxi_nand_ooblayout_ops =;

static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
				       struct nand_ecc_ctrl *ecc,
				       struct device_node *np)
{}

static int sunxi_nand_attach_chip(struct nand_chip *nand)
{}

static int sunxi_nfc_exec_subop(struct nand_chip *nand,
				const struct nand_subop *subop)
{}

static int sunxi_nfc_soft_waitrdy(struct nand_chip *nand,
				  const struct nand_subop *subop)
{}

static const struct nand_op_parser sunxi_nfc_op_parser =;

static const struct nand_op_parser sunxi_nfc_norb_op_parser =;

static int sunxi_nfc_exec_op(struct nand_chip *nand,
			     const struct nand_operation *op, bool check_only)
{}

static const struct nand_controller_ops sunxi_nand_controller_ops =;

static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
{}

static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
				struct device_node *np)
{}

static int sunxi_nand_chips_init(struct device *dev, struct sunxi_nfc *nfc)
{}

static int sunxi_nfc_dma_init(struct sunxi_nfc *nfc, struct resource *r)
{}

static int sunxi_nfc_probe(struct platform_device *pdev)
{}

static void sunxi_nfc_remove(struct platform_device *pdev)
{}

static const struct sunxi_nfc_caps sunxi_nfc_a10_caps =;

static const struct sunxi_nfc_caps sunxi_nfc_a23_caps =;

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

static struct platform_driver sunxi_nfc_driver =;
module_platform_driver();

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