linux/drivers/mtd/nand/raw/arasan-nand-controller.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Arasan NAND Flash Controller Driver
 *
 * Copyright (C) 2014 - 2020 Xilinx, Inc.
 * Author:
 *   Miquel Raynal <[email protected]>
 * Original work (fully rewritten):
 *   Punnaiah Choudary Kalluri <[email protected]>
 *   Naga Sureshkumar Relli <[email protected]>
 */

#include <linux/bch.h>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/rawnand.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#define PKT_REG
#define PKT_SIZE(x)
#define PKT_STEPS(x)

#define MEM_ADDR1_REG

#define MEM_ADDR2_REG
#define ADDR2_STRENGTH(x)
#define ADDR2_CS(x)

#define CMD_REG
#define CMD_1(x)
#define CMD_2(x)
#define CMD_PAGE_SIZE(x)
#define CMD_DMA_ENABLE
#define CMD_NADDRS(x)
#define CMD_ECC_ENABLE

#define PROG_REG
#define PROG_PGRD
#define PROG_ERASE
#define PROG_STATUS
#define PROG_PGPROG
#define PROG_RDID
#define PROG_RDPARAM
#define PROG_RST
#define PROG_GET_FEATURE
#define PROG_SET_FEATURE
#define PROG_CHG_RD_COL_ENH

#define INTR_STS_EN_REG
#define INTR_SIG_EN_REG
#define INTR_STS_REG
#define WRITE_READY
#define READ_READY
#define XFER_COMPLETE
#define DMA_BOUNDARY
#define EVENT_MASK

#define READY_STS_REG

#define DMA_ADDR0_REG
#define DMA_ADDR1_REG

#define FLASH_STS_REG

#define TIMING_REG
#define TCCS_TIME_500NS
#define TCCS_TIME_300NS
#define TCCS_TIME_200NS
#define TCCS_TIME_100NS
#define FAST_TCAD
#define DQS_BUFF_SEL_IN(x)
#define DQS_BUFF_SEL_OUT(x)

#define DATA_PORT_REG

#define ECC_CONF_REG
#define ECC_CONF_COL(x)
#define ECC_CONF_LEN(x)
#define ECC_CONF_BCH_EN

#define ECC_ERR_CNT_REG
#define GET_PKT_ERR_CNT(x)
#define GET_PAGE_ERR_CNT(x)

#define ECC_SP_REG
#define ECC_SP_CMD1(x)
#define ECC_SP_CMD2(x)
#define ECC_SP_ADDRS(x)

#define ECC_1ERR_CNT_REG
#define ECC_2ERR_CNT_REG

#define DATA_INTERFACE_REG
#define DIFACE_SDR_MODE(x)
#define DIFACE_DDR_MODE(x)
#define DIFACE_SDR
#define DIFACE_NVDDR

#define ANFC_MAX_CS
#define ANFC_DFLT_TIMEOUT_US
#define ANFC_MAX_CHUNK_SIZE
#define ANFC_MAX_PARAM_SIZE
#define ANFC_MAX_STEPS
#define ANFC_MAX_PKT_SIZE
#define ANFC_MAX_ADDR_CYC
#define ANFC_RSVD_ECC_BYTES

#define ANFC_XLNX_SDR_DFLT_CORE_CLK
#define ANFC_XLNX_SDR_HS_CORE_CLK

static struct gpio_desc *anfc_default_cs_array[2] =;

/**
 * struct anfc_op - Defines how to execute an operation
 * @pkt_reg: Packet register
 * @addr1_reg: Memory address 1 register
 * @addr2_reg: Memory address 2 register
 * @cmd_reg: Command register
 * @prog_reg: Program register
 * @steps: Number of "packets" to read/write
 * @rdy_timeout_ms: Timeout for waits on Ready/Busy pin
 * @len: Data transfer length
 * @read: Data transfer direction from the controller point of view
 * @buf: Data buffer
 */
struct anfc_op {};

/**
 * struct anand - Defines the NAND chip related information
 * @node:		Used to store NAND chips into a list
 * @chip:		NAND chip information structure
 * @rb:			Ready-busy line
 * @page_sz:		Register value of the page_sz field to use
 * @clk:		Expected clock frequency to use
 * @data_iface:		Data interface timing mode to use
 * @timings:		NV-DDR specific timings to use
 * @ecc_conf:		Hardware ECC configuration value
 * @strength:		Register value of the ECC strength
 * @raddr_cycles:	Row address cycle information
 * @caddr_cycles:	Column address cycle information
 * @ecc_bits:		Exact number of ECC bits per syndrome
 * @ecc_total:		Total number of ECC bytes
 * @errloc:		Array of errors located with soft BCH
 * @hw_ecc:		Buffer to store syndromes computed by hardware
 * @bch:		BCH structure
 * @cs_idx:		Array of chip-select for this device, values are indexes
 *			of the controller structure @gpio_cs array
 * @ncs_idx:		Size of the @cs_idx array
 */
struct anand {};

/**
 * struct arasan_nfc - Defines the Arasan NAND flash controller driver instance
 * @dev:		Pointer to the device structure
 * @base:		Remapped register area
 * @controller_clk:		Pointer to the system clock
 * @bus_clk:		Pointer to the flash clock
 * @controller:		Base controller structure
 * @chips:		List of all NAND chips attached to the controller
 * @cur_clk:		Current clock rate
 * @cs_array:		CS array. Native CS are left empty, the other cells are
 *			populated with their corresponding GPIO descriptor.
 * @ncs:		Size of @cs_array
 * @cur_cs:		Index in @cs_array of the currently in use CS
 * @native_cs:		Currently selected native CS
 * @spare_cs:		Native CS that is not wired (may be selected when a GPIO
 *			CS is in use)
 */
struct arasan_nfc {};

static struct anand *to_anand(struct nand_chip *nand)
{}

static struct arasan_nfc *to_anfc(struct nand_controller *ctrl)
{}

static int anfc_wait_for_event(struct arasan_nfc *nfc, unsigned int event)
{}

static int anfc_wait_for_rb(struct arasan_nfc *nfc, struct nand_chip *chip,
			    unsigned int timeout_ms)
{}

static void anfc_trigger_op(struct arasan_nfc *nfc, struct anfc_op *nfc_op)
{}

static int anfc_pkt_len_config(unsigned int len, unsigned int *steps,
			       unsigned int *pktsize)
{}

static bool anfc_is_gpio_cs(struct arasan_nfc *nfc, int nfc_cs)
{}

static int anfc_relative_to_absolute_cs(struct anand *anand, int num)
{}

static void anfc_assert_cs(struct arasan_nfc *nfc, unsigned int nfc_cs_idx)
{}

static int anfc_select_target(struct nand_chip *chip, int target)
{}

/*
 * When using the embedded hardware ECC engine, the controller is in charge of
 * feeding the engine with, first, the ECC residue present in the data array.
 * A typical read operation is:
 * 1/ Assert the read operation by sending the relevant command/address cycles
 *    but targeting the column of the first ECC bytes in the OOB area instead of
 *    the main data directly.
 * 2/ After having read the relevant number of ECC bytes, the controller uses
 *    the RNDOUT/RNDSTART commands which are set into the "ECC Spare Command
 *    Register" to move the pointer back at the beginning of the main data.
 * 3/ It will read the content of the main area for a given size (pktsize) and
 *    will feed the ECC engine with this buffer again.
 * 4/ The ECC engine derives the ECC bytes for the given data and compare them
 *    with the ones already received. It eventually trigger status flags and
 *    then set the "Buffer Read Ready" flag.
 * 5/ The corrected data is then available for reading from the data port
 *    register.
 *
 * The hardware BCH ECC engine is known to be inconstent in BCH mode and never
 * reports uncorrectable errors. Because of this bug, we have to use the
 * software BCH implementation in the read path.
 */
static int anfc_read_page_hw_ecc(struct nand_chip *chip, u8 *buf,
				 int oob_required, int page)
{}

static int anfc_sel_read_page_hw_ecc(struct nand_chip *chip, u8 *buf,
				     int oob_required, int page)
{
	int ret;

	ret = anfc_select_target(chip, chip->cur_cs);
	if (ret)
		return ret;

	return anfc_read_page_hw_ecc(chip, buf, oob_required, page);
};

static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
				  int oob_required, int page)
{}

static int anfc_sel_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
				      int oob_required, int page)
{
	int ret;

	ret = anfc_select_target(chip, chip->cur_cs);
	if (ret)
		return ret;

	return anfc_write_page_hw_ecc(chip, buf, oob_required, page);
};

/* NAND framework ->exec_op() hooks and related helpers */
static int anfc_parse_instructions(struct nand_chip *chip,
				   const struct nand_subop *subop,
				   struct anfc_op *nfc_op)
{}

static int anfc_rw_pio_op(struct arasan_nfc *nfc, struct anfc_op *nfc_op)
{}

static int anfc_misc_data_type_exec(struct nand_chip *chip,
				    const struct nand_subop *subop,
				    u32 prog_reg)
{}

static int anfc_param_read_type_exec(struct nand_chip *chip,
				     const struct nand_subop *subop)
{}

static int anfc_data_read_type_exec(struct nand_chip *chip,
				    const struct nand_subop *subop)
{}

static int anfc_param_write_type_exec(struct nand_chip *chip,
				      const struct nand_subop *subop)
{}

static int anfc_data_write_type_exec(struct nand_chip *chip,
				     const struct nand_subop *subop)
{}

static int anfc_misc_zerolen_type_exec(struct nand_chip *chip,
				       const struct nand_subop *subop,
				       u32 prog_reg)
{}

static int anfc_status_type_exec(struct nand_chip *chip,
				 const struct nand_subop *subop)
{}

static int anfc_reset_type_exec(struct nand_chip *chip,
				const struct nand_subop *subop)
{}

static int anfc_erase_type_exec(struct nand_chip *chip,
				const struct nand_subop *subop)
{}

static int anfc_wait_type_exec(struct nand_chip *chip,
			       const struct nand_subop *subop)
{}

static const struct nand_op_parser anfc_op_parser =;

static int anfc_check_op(struct nand_chip *chip,
			 const struct nand_operation *op)
{}

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

static int anfc_setup_interface(struct nand_chip *chip, int target,
				const struct nand_interface_config *conf)
{}

static int anfc_calc_hw_ecc_bytes(int step_size, int strength)
{}

static const int anfc_hw_ecc_512_strengths[] =;

static const int anfc_hw_ecc_1024_strengths[] =;

static const struct nand_ecc_step_info anfc_hw_ecc_step_infos[] =;

static const struct nand_ecc_caps anfc_hw_ecc_caps =;

static int anfc_init_hw_ecc_controller(struct arasan_nfc *nfc,
				       struct nand_chip *chip)
{}

static int anfc_attach_chip(struct nand_chip *chip)
{}

static void anfc_detach_chip(struct nand_chip *chip)
{}

static const struct nand_controller_ops anfc_ops =;

static int anfc_chip_init(struct arasan_nfc *nfc, struct device_node *np)
{}

static void anfc_chips_cleanup(struct arasan_nfc *nfc)
{}

static int anfc_chips_init(struct arasan_nfc *nfc)
{}

static void anfc_reset(struct arasan_nfc *nfc)
{}

static int anfc_parse_cs(struct arasan_nfc *nfc)
{}

static int anfc_probe(struct platform_device *pdev)
{}

static void anfc_remove(struct platform_device *pdev)
{}

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

static struct platform_driver anfc_driver =;
module_platform_driver();

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