// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016, The Linux Foundation. All rights reserved. */ #include <linux/bitops.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/dma/qcom_adm.h> #include <linux/dma/qcom_bam_dma.h> #include <linux/module.h> #include <linux/mtd/partitions.h> #include <linux/mtd/rawnand.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> /* NANDc reg offsets */ #define NAND_FLASH_CMD … #define NAND_ADDR0 … #define NAND_ADDR1 … #define NAND_FLASH_CHIP_SELECT … #define NAND_EXEC_CMD … #define NAND_FLASH_STATUS … #define NAND_BUFFER_STATUS … #define NAND_DEV0_CFG0 … #define NAND_DEV0_CFG1 … #define NAND_DEV0_ECC_CFG … #define NAND_AUTO_STATUS_EN … #define NAND_DEV1_CFG0 … #define NAND_DEV1_CFG1 … #define NAND_READ_ID … #define NAND_READ_STATUS … #define NAND_DEV_CMD0 … #define NAND_DEV_CMD1 … #define NAND_DEV_CMD2 … #define NAND_DEV_CMD_VLD … #define SFLASHC_BURST_CFG … #define NAND_ERASED_CW_DETECT_CFG … #define NAND_ERASED_CW_DETECT_STATUS … #define NAND_EBI2_ECC_BUF_CFG … #define FLASH_BUF_ACC … #define NAND_CTRL … #define NAND_VERSION … #define NAND_READ_LOCATION_0 … #define NAND_READ_LOCATION_1 … #define NAND_READ_LOCATION_2 … #define NAND_READ_LOCATION_3 … #define NAND_READ_LOCATION_LAST_CW_0 … #define NAND_READ_LOCATION_LAST_CW_1 … #define NAND_READ_LOCATION_LAST_CW_2 … #define NAND_READ_LOCATION_LAST_CW_3 … /* dummy register offsets, used by write_reg_dma */ #define NAND_DEV_CMD1_RESTORE … #define NAND_DEV_CMD_VLD_RESTORE … /* NAND_FLASH_CMD bits */ #define PAGE_ACC … #define LAST_PAGE … /* NAND_FLASH_CHIP_SELECT bits */ #define NAND_DEV_SEL … #define DM_EN … /* NAND_FLASH_STATUS bits */ #define FS_OP_ERR … #define FS_READY_BSY_N … #define FS_MPU_ERR … #define FS_DEVICE_STS_ERR … #define FS_DEVICE_WP … /* NAND_BUFFER_STATUS bits */ #define BS_UNCORRECTABLE_BIT … #define BS_CORRECTABLE_ERR_MSK … /* NAND_DEVn_CFG0 bits */ #define DISABLE_STATUS_AFTER_WRITE … #define CW_PER_PAGE … #define UD_SIZE_BYTES … #define UD_SIZE_BYTES_MASK … #define ECC_PARITY_SIZE_BYTES_RS … #define SPARE_SIZE_BYTES … #define SPARE_SIZE_BYTES_MASK … #define NUM_ADDR_CYCLES … #define STATUS_BFR_READ … #define SET_RD_MODE_AFTER_STATUS … /* NAND_DEVn_CFG0 bits */ #define DEV0_CFG1_ECC_DISABLE … #define WIDE_FLASH … #define NAND_RECOVERY_CYCLES … #define CS_ACTIVE_BSY … #define BAD_BLOCK_BYTE_NUM … #define BAD_BLOCK_IN_SPARE_AREA … #define WR_RD_BSY_GAP … #define ENABLE_BCH_ECC … /* NAND_DEV0_ECC_CFG bits */ #define ECC_CFG_ECC_DISABLE … #define ECC_SW_RESET … #define ECC_MODE … #define ECC_PARITY_SIZE_BYTES_BCH … #define ECC_NUM_DATA_BYTES … #define ECC_NUM_DATA_BYTES_MASK … #define ECC_FORCE_CLK_OPEN … /* NAND_DEV_CMD1 bits */ #define READ_ADDR … /* NAND_DEV_CMD_VLD bits */ #define READ_START_VLD … #define READ_STOP_VLD … #define WRITE_START_VLD … #define ERASE_START_VLD … #define SEQ_READ_START_VLD … /* NAND_EBI2_ECC_BUF_CFG bits */ #define NUM_STEPS … /* NAND_ERASED_CW_DETECT_CFG bits */ #define ERASED_CW_ECC_MASK … #define AUTO_DETECT_RES … #define MASK_ECC … #define RESET_ERASED_DET … #define ACTIVE_ERASED_DET … #define CLR_ERASED_PAGE_DET … #define SET_ERASED_PAGE_DET … /* NAND_ERASED_CW_DETECT_STATUS bits */ #define PAGE_ALL_ERASED … #define CODEWORD_ALL_ERASED … #define PAGE_ERASED … #define CODEWORD_ERASED … #define ERASED_PAGE … #define ERASED_CW … /* NAND_READ_LOCATION_n bits */ #define READ_LOCATION_OFFSET … #define READ_LOCATION_SIZE … #define READ_LOCATION_LAST … /* Version Mask */ #define NAND_VERSION_MAJOR_MASK … #define NAND_VERSION_MAJOR_SHIFT … #define NAND_VERSION_MINOR_MASK … #define NAND_VERSION_MINOR_SHIFT … /* NAND OP_CMDs */ #define OP_PAGE_READ … #define OP_PAGE_READ_WITH_ECC … #define OP_PAGE_READ_WITH_ECC_SPARE … #define OP_PAGE_READ_ONFI_READ … #define OP_PROGRAM_PAGE … #define OP_PAGE_PROGRAM_WITH_ECC … #define OP_PROGRAM_PAGE_SPARE … #define OP_BLOCK_ERASE … #define OP_CHECK_STATUS … #define OP_FETCH_ID … #define OP_RESET_DEVICE … /* Default Value for NAND_DEV_CMD_VLD */ #define NAND_DEV_CMD_VLD_VAL … /* NAND_CTRL bits */ #define BAM_MODE_EN … /* * the NAND controller performs reads/writes with ECC in 516 byte chunks. * the driver calls the chunks 'step' or 'codeword' interchangeably */ #define NANDC_STEP_SIZE … /* * the largest page size we support is 8K, this will have 16 steps/codewords * of 512 bytes each */ #define MAX_NUM_STEPS … /* we read at most 3 registers per codeword scan */ #define MAX_REG_RD … /* ECC modes supported by the controller */ #define ECC_NONE … #define ECC_RS_4BIT … #define ECC_BCH_4BIT … #define ECC_BCH_8BIT … #define nandc_set_read_loc_first(chip, reg, cw_offset, read_size, is_last_read_loc) … #define nandc_set_read_loc_last(chip, reg, cw_offset, read_size, is_last_read_loc) … /* * Returns the actual register address for all NAND_DEV_ registers * (i.e. NAND_DEV_CMD0, NAND_DEV_CMD1, NAND_DEV_CMD2 and NAND_DEV_CMD_VLD) */ #define dev_cmd_reg_addr(nandc, reg) … /* Returns the NAND register physical address */ #define nandc_reg_phys(chip, offset) … /* Returns the dma address for reg read buffer */ #define reg_buf_dma_addr(chip, vaddr) … #define QPIC_PER_CW_CMD_ELEMENTS … #define QPIC_PER_CW_CMD_SGL … #define QPIC_PER_CW_DATA_SGL … #define QPIC_NAND_COMPLETION_TIMEOUT … /* * Flags used in DMA descriptor preparation helper functions * (i.e. read_reg_dma/write_reg_dma/read_data_dma/write_data_dma) */ /* Don't set the EOT in current tx BAM sgl */ #define NAND_BAM_NO_EOT … /* Set the NWD flag in current BAM sgl */ #define NAND_BAM_NWD … /* Finish writing in the current BAM sgl and start writing in another BAM sgl */ #define NAND_BAM_NEXT_SGL … /* * Erased codeword status is being used two times in single transfer so this * flag will determine the current value of erased codeword status register */ #define NAND_ERASED_CW_SET … #define MAX_ADDRESS_CYCLE … /* * This data type corresponds to the BAM transaction which will be used for all * NAND transfers. * @bam_ce - the array of BAM command elements * @cmd_sgl - sgl for NAND BAM command pipe * @data_sgl - sgl for NAND BAM consumer/producer pipe * @last_data_desc - last DMA desc in data channel (tx/rx). * @last_cmd_desc - last DMA desc in command channel. * @txn_done - completion for NAND transfer. * @bam_ce_pos - the index in bam_ce which is available for next sgl * @bam_ce_start - the index in bam_ce which marks the start position ce * for current sgl. It will be used for size calculation * for current sgl * @cmd_sgl_pos - current index in command sgl. * @cmd_sgl_start - start index in command sgl. * @tx_sgl_pos - current index in data sgl for tx. * @tx_sgl_start - start index in data sgl for tx. * @rx_sgl_pos - current index in data sgl for rx. * @rx_sgl_start - start index in data sgl for rx. * @wait_second_completion - wait for second DMA desc completion before making * the NAND transfer completion. */ struct bam_transaction { … }; /* * This data type corresponds to the nand dma descriptor * @dma_desc - low level DMA engine descriptor * @list - list for desc_info * * @adm_sgl - sgl which will be used for single sgl dma descriptor. Only used by * ADM * @bam_sgl - sgl which will be used for dma descriptor. Only used by BAM * @sgl_cnt - number of SGL in bam_sgl. Only used by BAM * @dir - DMA transfer direction */ struct desc_info { … }; /* * holds the current register values that we want to write. acts as a contiguous * chunk of memory which we use to write the controller registers through DMA. */ struct nandc_regs { … }; /* * NAND controller data struct * * @dev: parent device * * @base: MMIO base * * @core_clk: controller clock * @aon_clk: another controller clock * * @regs: a contiguous chunk of memory for DMA register * writes. contains the register values to be * written to controller * * @props: properties of current NAND controller, * initialized via DT match data * * @controller: base controller structure * @host_list: list containing all the chips attached to the * controller * * @chan: dma channel * @cmd_crci: ADM DMA CRCI for command flow control * @data_crci: ADM DMA CRCI for data flow control * * @desc_list: DMA descriptor list (list of desc_infos) * * @data_buffer: our local DMA buffer for page read/writes, * used when we can't use the buffer provided * by upper layers directly * @reg_read_buf: local buffer for reading back registers via DMA * * @base_phys: physical base address of controller registers * @base_dma: dma base address of controller registers * @reg_read_dma: contains dma address for register read buffer * * @buf_size/count/start: markers for chip->legacy.read_buf/write_buf * functions * @max_cwperpage: maximum QPIC codewords required. calculated * from all connected NAND devices pagesize * * @reg_read_pos: marker for data read in reg_read_buf * * @cmd1/vld: some fixed controller register values * * @exec_opwrite: flag to select correct number of code word * while reading status */ struct qcom_nand_controller { … }; /* * NAND special boot partitions * * @page_offset: offset of the partition where spare data is not protected * by ECC (value in pages) * @page_offset: size of the partition where spare data is not protected * by ECC (value in pages) */ struct qcom_nand_boot_partition { … }; /* * Qcom op for each exec_op transfer * * @data_instr: data instruction pointer * @data_instr_idx: data instruction index * @rdy_timeout_ms: wait ready timeout in ms * @rdy_delay_ns: Additional delay in ns * @addr1_reg: Address1 register value * @addr2_reg: Address2 register value * @cmd_reg: CMD register value * @flag: flag for misc instruction */ struct qcom_op { … }; /* * NAND chip structure * * @boot_partitions: array of boot partitions where offset and size of the * boot partitions are stored * * @chip: base NAND chip structure * @node: list node to add itself to host_list in * qcom_nand_controller * * @nr_boot_partitions: count of the boot partitions where spare data is not * protected by ECC * * @cs: chip select value for this chip * @cw_size: the number of bytes in a single step/codeword * of a page, consisting of all data, ecc, spare * and reserved bytes * @cw_data: the number of bytes within a codeword protected * by ECC * @ecc_bytes_hw: ECC bytes used by controller hardware for this * chip * * @last_command: keeps track of last command on this chip. used * for reading correct status * * @cfg0, cfg1, cfg0_raw..: NANDc register configurations needed for * ecc/non-ecc mode for the current nand flash * device * * @status: value to be returned if NAND_CMD_STATUS command * is executed * @codeword_fixup: keep track of the current layout used by * the driver for read/write operation. * @use_ecc: request the controller to use ECC for the * upcoming read/write * @bch_enabled: flag to tell whether BCH ECC mode is used */ struct qcom_nand_host { … }; /* * This data type corresponds to the NAND controller properties which varies * among different NAND controllers. * @ecc_modes - ecc mode for NAND * @dev_cmd_reg_start - NAND_DEV_CMD_* registers starting offset * @is_bam - whether NAND controller is using BAM * @is_qpic - whether NAND CTRL is part of qpic IP * @qpic_v2 - flag to indicate QPIC IP version 2 * @use_codeword_fixup - whether NAND has different layout for boot partitions */ struct qcom_nandc_props { … }; /* Frees the BAM transaction memory */ static void free_bam_transaction(struct qcom_nand_controller *nandc) { … } /* Allocates and Initializes the BAM transaction */ static struct bam_transaction * alloc_bam_transaction(struct qcom_nand_controller *nandc) { … } /* Clears the BAM transaction indexes */ static void clear_bam_transaction(struct qcom_nand_controller *nandc) { … } /* Callback for DMA descriptor completion */ static void qpic_bam_dma_done(void *data) { … } static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip) { … } static inline struct qcom_nand_controller * get_qcom_nand_controller(struct nand_chip *chip) { … } static inline u32 nandc_read(struct qcom_nand_controller *nandc, int offset) { … } static inline void nandc_write(struct qcom_nand_controller *nandc, int offset, u32 val) { … } static inline void nandc_read_buffer_sync(struct qcom_nand_controller *nandc, bool is_cpu) { … } static __le32 *offset_to_nandc_reg(struct nandc_regs *regs, int offset) { … } static void nandc_set_reg(struct nand_chip *chip, int offset, u32 val) { … } /* Helper to check the code word, whether it is last cw or not */ static bool qcom_nandc_is_last_cw(struct nand_ecc_ctrl *ecc, int cw) { … } /* helper to configure location register values */ static void nandc_set_read_loc(struct nand_chip *chip, int cw, int reg, int cw_offset, int read_size, int is_last_read_loc) { … } /* helper to configure address register values */ static void set_address(struct qcom_nand_host *host, u16 column, int page) { … } /* * update_rw_regs: set up read/write register values, these will be * written to the NAND controller registers via DMA * * @num_cw: number of steps for the read/write operation * @read: read or write operation * @cw : which code word */ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read, int cw) { … } /* * Maps the scatter gather list for DMA transfer and forms the DMA descriptor * for BAM. This descriptor will be added in the NAND DMA descriptor queue * which will be submitted to DMA engine. */ static int prepare_bam_async_desc(struct qcom_nand_controller *nandc, struct dma_chan *chan, unsigned long flags) { … } /* * Prepares the command descriptor for BAM DMA which will be used for NAND * register reads and writes. The command descriptor requires the command * to be formed in command element type so this function uses the command * element from bam transaction ce array and fills the same with required * data. A single SGL can contain multiple command elements so * NAND_BAM_NEXT_SGL will be used for starting the separate SGL * after the current command element. */ static int prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read, int reg_off, const void *vaddr, int size, unsigned int flags) { … } /* * Prepares the data descriptor for BAM DMA which will be used for NAND * data reads and writes. */ static int prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read, const void *vaddr, int size, unsigned int flags) { … } static int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read, int reg_off, const void *vaddr, int size, bool flow_control) { … } /* * read_reg_dma: prepares a descriptor to read a given number of * contiguous registers to the reg_read_buf pointer * * @first: offset of the first register in the contiguous block * @num_regs: number of registers to read * @flags: flags to control DMA descriptor preparation */ static int read_reg_dma(struct qcom_nand_controller *nandc, int first, int num_regs, unsigned int flags) { … } /* * write_reg_dma: prepares a descriptor to write a given number of * contiguous registers * * @first: offset of the first register in the contiguous block * @num_regs: number of registers to write * @flags: flags to control DMA descriptor preparation */ static int write_reg_dma(struct qcom_nand_controller *nandc, int first, int num_regs, unsigned int flags) { … } /* * read_data_dma: prepares a DMA descriptor to transfer data from the * controller's internal buffer to the buffer 'vaddr' * * @reg_off: offset within the controller's data buffer * @vaddr: virtual address of the buffer we want to write to * @size: DMA transaction size in bytes * @flags: flags to control DMA descriptor preparation */ static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off, const u8 *vaddr, int size, unsigned int flags) { … } /* * write_data_dma: prepares a DMA descriptor to transfer data from * 'vaddr' to the controller's internal buffer * * @reg_off: offset within the controller's data buffer * @vaddr: virtual address of the buffer we want to read from * @size: DMA transaction size in bytes * @flags: flags to control DMA descriptor preparation */ static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off, const u8 *vaddr, int size, unsigned int flags) { … } /* * Helper to prepare DMA descriptors for configuring registers * before reading a NAND page. */ static void config_nand_page_read(struct nand_chip *chip) { … } /* * Helper to prepare DMA descriptors for configuring registers * before reading each codeword in NAND page. */ static void config_nand_cw_read(struct nand_chip *chip, bool use_ecc, int cw) { … } /* * Helper to prepare dma descriptors to configure registers needed for reading a * single codeword in page */ static void config_nand_single_cw_page_read(struct nand_chip *chip, bool use_ecc, int cw) { … } /* * Helper to prepare DMA descriptors used to configure registers needed for * before writing a NAND page. */ static void config_nand_page_write(struct nand_chip *chip) { … } /* * Helper to prepare DMA descriptors for configuring registers * before writing each codeword in NAND page. */ static void config_nand_cw_write(struct nand_chip *chip) { … } /* helpers to submit/free our list of dma descriptors */ static int submit_descs(struct qcom_nand_controller *nandc) { … } /* reset the register read buffer for next NAND operation */ static void clear_read_regs(struct qcom_nand_controller *nandc) { … } /* * when using BCH ECC, the HW flags an error in NAND_FLASH_STATUS if it read * an erased CW, and reports an erased CW in NAND_ERASED_CW_DETECT_STATUS. * * when using RS ECC, the HW reports the same erros when reading an erased CW, * but it notifies that it is an erased CW by placing special characters at * certain offsets in the buffer. * * verify if the page is erased or not, and fix up the page for RS ECC by * replacing the special characters with 0xff. */ static bool erased_chunk_check_and_fixup(u8 *data_buf, int data_len) { … } struct read_stats { … }; /* reads back FLASH_STATUS register set by the controller */ static int check_flash_errors(struct qcom_nand_host *host, int cw_cnt) { … } /* performs raw read for one codeword */ static int qcom_nandc_read_cw_raw(struct mtd_info *mtd, struct nand_chip *chip, u8 *data_buf, u8 *oob_buf, int page, int cw) { … } /* * Bitflips can happen in erased codewords also so this function counts the * number of 0 in each CW for which ECC engine returns the uncorrectable * error. The page will be assumed as erased if this count is less than or * equal to the ecc->strength for each CW. * * 1. Both DATA and OOB need to be checked for number of 0. The * top-level API can be called with only data buf or OOB buf so use * chip->data_buf if data buf is null and chip->oob_poi if oob buf * is null for copying the raw bytes. * 2. Perform raw read for all the CW which has uncorrectable errors. * 3. For each CW, check the number of 0 in cw_data and usable OOB bytes. * The BBM and spare bytes bit flip won’t affect the ECC so don’t check * the number of bitflips in this area. */ static int check_for_erased_page(struct qcom_nand_host *host, u8 *data_buf, u8 *oob_buf, unsigned long uncorrectable_cws, int page, unsigned int max_bitflips) { … } /* * reads back status registers set by the controller to notify page read * errors. this is equivalent to what 'ecc->correct()' would do. */ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf, u8 *oob_buf, int page) { … } /* * helper to perform the actual page read operation, used by ecc->read_page(), * ecc->read_oob() */ static int read_page_ecc(struct qcom_nand_host *host, u8 *data_buf, u8 *oob_buf, int page) { … } /* * a helper that copies the last step/codeword of a page (containing free oob) * into our local buffer */ static int copy_last_cw(struct qcom_nand_host *host, int page) { … } static bool qcom_nandc_is_boot_partition(struct qcom_nand_host *host, int page) { … } static void qcom_nandc_codeword_fixup(struct qcom_nand_host *host, int page) { … } /* implements ecc->read_page() */ static int qcom_nandc_read_page(struct nand_chip *chip, u8 *buf, int oob_required, int page) { … } /* implements ecc->read_page_raw() */ static int qcom_nandc_read_page_raw(struct nand_chip *chip, u8 *buf, int oob_required, int page) { … } /* implements ecc->read_oob() */ static int qcom_nandc_read_oob(struct nand_chip *chip, int page) { … } /* implements ecc->write_page() */ static int qcom_nandc_write_page(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { … } /* implements ecc->write_page_raw() */ static int qcom_nandc_write_page_raw(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { … } /* * implements ecc->write_oob() * * the NAND controller cannot write only data or only OOB within a codeword * since ECC is calculated for the combined codeword. So update the OOB from * chip->oob_poi, and pad the data area with OxFF before writing. */ static int qcom_nandc_write_oob(struct nand_chip *chip, int page) { … } static int qcom_nandc_block_bad(struct nand_chip *chip, loff_t ofs) { … } static int qcom_nandc_block_markbad(struct nand_chip *chip, loff_t ofs) { … } /* * NAND controller page layout info * * Layout with ECC enabled: * * |----------------------| |---------------------------------| * | xx.......yy| | *********xx.......yy| * | DATA xx..ECC..yy| | DATA **SPARE**xx..ECC..yy| * | (516) xx.......yy| | (516-n*4) **(n*4)**xx.......yy| * | xx.......yy| | *********xx.......yy| * |----------------------| |---------------------------------| * codeword 1,2..n-1 codeword n * <---(528/532 Bytes)--> <-------(528/532 Bytes)---------> * * n = Number of codewords in the page * . = ECC bytes * * = Spare/free bytes * x = Unused byte(s) * y = Reserved byte(s) * * 2K page: n = 4, spare = 16 bytes * 4K page: n = 8, spare = 32 bytes * 8K page: n = 16, spare = 64 bytes * * the qcom nand controller operates at a sub page/codeword level. each * codeword is 528 and 532 bytes for 4 bit and 8 bit ECC modes respectively. * the number of ECC bytes vary based on the ECC strength and the bus width. * * the first n - 1 codewords contains 516 bytes of user data, the remaining * 12/16 bytes consist of ECC and reserved data. The nth codeword contains * both user data and spare(oobavail) bytes that sum up to 516 bytes. * * When we access a page with ECC enabled, the reserved bytes(s) are not * accessible at all. When reading, we fill up these unreadable positions * with 0xffs. When writing, the controller skips writing the inaccessible * bytes. * * Layout with ECC disabled: * * |------------------------------| |---------------------------------------| * | yy xx.......| | bb *********xx.......| * | DATA1 yy DATA2 xx..ECC..| | DATA1 bb DATA2 **SPARE**xx..ECC..| * | (size1) yy (size2) xx.......| | (size1) bb (size2) **(n*4)**xx.......| * | yy xx.......| | bb *********xx.......| * |------------------------------| |---------------------------------------| * codeword 1,2..n-1 codeword n * <-------(528/532 Bytes)------> <-----------(528/532 Bytes)-----------> * * n = Number of codewords in the page * . = ECC bytes * * = Spare/free bytes * x = Unused byte(s) * y = Dummy Bad Bock byte(s) * b = Real Bad Block byte(s) * size1/size2 = function of codeword size and 'n' * * when the ECC block is disabled, one reserved byte (or two for 16 bit bus * width) is now accessible. For the first n - 1 codewords, these are dummy Bad * Block Markers. In the last codeword, this position contains the real BBM * * In order to have a consistent layout between RAW and ECC modes, we assume * the following OOB layout arrangement: * * |-----------| |--------------------| * |yyxx.......| |bb*********xx.......| * |yyxx..ECC..| |bb*FREEOOB*xx..ECC..| * |yyxx.......| |bb*********xx.......| * |yyxx.......| |bb*********xx.......| * |-----------| |--------------------| * first n - 1 nth OOB region * OOB regions * * n = Number of codewords in the page * . = ECC bytes * * = FREE OOB bytes * y = Dummy bad block byte(s) (inaccessible when ECC enabled) * x = Unused byte(s) * b = Real bad block byte(s) (inaccessible when ECC enabled) * * This layout is read as is when ECC is disabled. When ECC is enabled, the * inaccessible Bad Block byte(s) are ignored when we write to a page/oob, * and assumed as 0xffs when we read a page/oob. The ECC, unused and * dummy/real bad block bytes are grouped as ecc bytes (i.e, ecc->bytes is * the sum of the three). */ static int qcom_nand_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *oobregion) { … } static int qcom_nand_ooblayout_free(struct mtd_info *mtd, int section, struct mtd_oob_region *oobregion) { … } static const struct mtd_ooblayout_ops qcom_nand_ooblayout_ops = …; static int qcom_nandc_calc_ecc_bytes(int step_size, int strength) { … } NAND_ECC_CAPS_SINGLE(…); static int qcom_nand_attach_chip(struct nand_chip *chip) { … } static int qcom_op_cmd_mapping(struct nand_chip *chip, u8 opcode, struct qcom_op *q_op) { … } /* NAND framework ->exec_op() hooks and related helpers */ static int qcom_parse_instructions(struct nand_chip *chip, const struct nand_subop *subop, struct qcom_op *q_op) { … } static void qcom_delay_ns(unsigned int ns) { … } static int qcom_wait_rdy_poll(struct nand_chip *chip, unsigned int time_ms) { … } static int qcom_read_status_exec(struct nand_chip *chip, const struct nand_subop *subop) { … } static int qcom_read_id_type_exec(struct nand_chip *chip, const struct nand_subop *subop) { … } static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_subop *subop) { … } static int qcom_param_page_type_exec(struct nand_chip *chip, const struct nand_subop *subop) { … } static const struct nand_op_parser qcom_op_parser = …; static int qcom_check_op(struct nand_chip *chip, const struct nand_operation *op) { … } static int qcom_nand_exec_op(struct nand_chip *chip, const struct nand_operation *op, bool check_only) { … } static const struct nand_controller_ops qcom_nandc_ops = …; static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc) { … } static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) { … } /* one time setup of a few nand controller registers */ static int qcom_nandc_setup(struct qcom_nand_controller *nandc) { … } static const char * const probes[] = …; static int qcom_nand_host_parse_boot_partitions(struct qcom_nand_controller *nandc, struct qcom_nand_host *host, struct device_node *dn) { … } static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc, struct qcom_nand_host *host, struct device_node *dn) { … } static int qcom_probe_nand_devices(struct qcom_nand_controller *nandc) { … } /* parse custom DT properties here */ static int qcom_nandc_parse_dt(struct platform_device *pdev) { … } static int qcom_nandc_probe(struct platform_device *pdev) { … } static void qcom_nandc_remove(struct platform_device *pdev) { … } static const struct qcom_nandc_props ipq806x_nandc_props = …; static const struct qcom_nandc_props ipq4019_nandc_props = …; static const struct qcom_nandc_props ipq8074_nandc_props = …; static const struct qcom_nandc_props sdx55_nandc_props = …; /* * data will hold a struct pointer containing more differences once we support * more controller variants */ static const struct of_device_id qcom_nandc_of_match[] = …; MODULE_DEVICE_TABLE(of, qcom_nandc_of_match); static struct platform_driver qcom_nandc_driver = …; module_platform_driver(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;