root/include/linux/mtd/nand-qpic-common.h
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * QCOM QPIC common APIs header file
 *
 * Copyright (c) 2023 Qualcomm Inc.
 * Authors:     Md sadre Alam   <quic_mdalam@quicinc.com>
 *
 */
#ifndef __MTD_NAND_QPIC_COMMON_H__
#define __MTD_NAND_QPIC_COMMON_H__

/* NANDc reg offsets */
#define NAND_FLASH_CMD                  0x00
#define NAND_ADDR0                      0x04
#define NAND_ADDR1                      0x08
#define NAND_FLASH_CHIP_SELECT          0x0c
#define NAND_EXEC_CMD                   0x10
#define NAND_FLASH_STATUS               0x14
#define NAND_BUFFER_STATUS              0x18
#define NAND_DEV0_CFG0                  0x20
#define NAND_DEV0_CFG1                  0x24
#define NAND_DEV0_ECC_CFG               0x28
#define NAND_AUTO_STATUS_EN             0x2c
#define NAND_DEV1_CFG0                  0x30
#define NAND_DEV1_CFG1                  0x34
#define NAND_READ_ID                    0x40
#define NAND_READ_STATUS                0x44
#define NAND_DEV_CMD0                   0xa0
#define NAND_DEV_CMD1                   0xa4
#define NAND_DEV_CMD2                   0xa8
#define NAND_DEV_CMD_VLD                0xac
#define SFLASHC_BURST_CFG               0xe0
#define NAND_ERASED_CW_DETECT_CFG       0xe8
#define NAND_ERASED_CW_DETECT_STATUS    0xec
#define NAND_EBI2_ECC_BUF_CFG           0xf0
#define FLASH_BUF_ACC                   0x100

#define NAND_CTRL                       0xf00
#define NAND_VERSION                    0xf08
#define NAND_READ_LOCATION_0            0xf20
#define NAND_READ_LOCATION_1            0xf24
#define NAND_READ_LOCATION_2            0xf28
#define NAND_READ_LOCATION_3            0xf2c
#define NAND_READ_LOCATION_LAST_CW_0    0xf40
#define NAND_READ_LOCATION_LAST_CW_1    0xf44
#define NAND_READ_LOCATION_LAST_CW_2    0xf48
#define NAND_READ_LOCATION_LAST_CW_3    0xf4c

/* dummy register offsets, used by qcom_write_reg_dma */
#define NAND_DEV_CMD1_RESTORE           0xdead
#define NAND_DEV_CMD_VLD_RESTORE        0xbeef

/* NAND_FLASH_CMD bits */
#define PAGE_ACC                        BIT(4)
#define LAST_PAGE                       BIT(5)

/* NAND_FLASH_CHIP_SELECT bits */
#define NAND_DEV_SEL                    0
#define DM_EN                           BIT(2)

/* NAND_FLASH_STATUS bits */
#define FS_OP_ERR                       BIT(4)
#define FS_READY_BSY_N                  BIT(5)
#define FS_MPU_ERR                      BIT(8)
#define FS_DEVICE_STS_ERR               BIT(16)
#define FS_DEVICE_WP                    BIT(23)

/* NAND_BUFFER_STATUS bits */
#define BS_UNCORRECTABLE_BIT            BIT(8)
#define BS_CORRECTABLE_ERR_MSK          0x1f

/* NAND_DEVn_CFG0 bits */
#define DISABLE_STATUS_AFTER_WRITE      BIT(4)
#define CW_PER_PAGE_MASK                GENMASK(8, 6)
#define UD_SIZE_BYTES_MASK              GENMASK(18, 9)
#define ECC_PARITY_SIZE_BYTES_RS        GENMASK(22, 19)
#define SPARE_SIZE_BYTES_MASK           GENMASK(26, 23)
#define NUM_ADDR_CYCLES_MASK            GENMASK(29, 27)
#define STATUS_BFR_READ                 BIT(30)
#define SET_RD_MODE_AFTER_STATUS        BIT(31)

/* NAND_DEVn_CFG0 bits */
#define DEV0_CFG1_ECC_DISABLE           BIT(0)
#define WIDE_FLASH                      BIT(1)
#define NAND_RECOVERY_CYCLES_MASK       GENMASK(4, 2)
#define CS_ACTIVE_BSY                   BIT(5)
#define BAD_BLOCK_BYTE_NUM_MASK         GENMASK(15, 6)
#define BAD_BLOCK_IN_SPARE_AREA         BIT(16)
#define WR_RD_BSY_GAP_MASK              GENMASK(22, 17)
#define ENABLE_BCH_ECC                  BIT(27)

/* NAND_DEV0_ECC_CFG bits */
#define ECC_CFG_ECC_DISABLE             BIT(0)
#define ECC_SW_RESET                    BIT(1)
#define ECC_MODE_MASK                   GENMASK(5, 4)
#define ECC_MODE_4BIT                   0
#define ECC_MODE_8BIT                   1
#define ECC_PARITY_SIZE_BYTES_BCH_MASK  GENMASK(12, 8)
#define ECC_NUM_DATA_BYTES_MASK         GENMASK(25, 16)
#define ECC_FORCE_CLK_OPEN              BIT(30)

/* NAND_DEV_CMD1 bits */
#define READ_ADDR_MASK                  GENMASK(7, 0)

/* NAND_DEV_CMD_VLD bits */
#define READ_START_VLD                  BIT(0)
#define READ_STOP_VLD                   BIT(1)
#define WRITE_START_VLD                 BIT(2)
#define ERASE_START_VLD                 BIT(3)
#define SEQ_READ_START_VLD              BIT(4)

/* NAND_EBI2_ECC_BUF_CFG bits */
#define NUM_STEPS_MASK                  GENMASK(9, 0)

/* NAND_ERASED_CW_DETECT_CFG bits */
#define ERASED_CW_ECC_MASK              1
#define AUTO_DETECT_RES                 0
#define MASK_ECC                        BIT(ERASED_CW_ECC_MASK)
#define RESET_ERASED_DET                BIT(AUTO_DETECT_RES)
#define ACTIVE_ERASED_DET               (0 << AUTO_DETECT_RES)
#define CLR_ERASED_PAGE_DET             (RESET_ERASED_DET | MASK_ECC)
#define SET_ERASED_PAGE_DET             (ACTIVE_ERASED_DET | MASK_ECC)

/* NAND_ERASED_CW_DETECT_STATUS bits */
#define PAGE_ALL_ERASED                 BIT(7)
#define CODEWORD_ALL_ERASED             BIT(6)
#define PAGE_ERASED                     BIT(5)
#define CODEWORD_ERASED                 BIT(4)
#define ERASED_PAGE                     (PAGE_ALL_ERASED | PAGE_ERASED)
#define ERASED_CW                       (CODEWORD_ALL_ERASED | CODEWORD_ERASED)

/* NAND_READ_LOCATION_n bits */
#define READ_LOCATION_OFFSET_MASK       GENMASK(9, 0)
#define READ_LOCATION_SIZE_MASK         GENMASK(25, 16)
#define READ_LOCATION_LAST_MASK         BIT(31)

/* Version Mask */
#define NAND_VERSION_MAJOR_MASK         0xf0000000
#define NAND_VERSION_MAJOR_SHIFT        28
#define NAND_VERSION_MINOR_MASK         0x0fff0000
#define NAND_VERSION_MINOR_SHIFT        16

/* NAND OP_CMDs */
#define OP_PAGE_READ                    0x2
#define OP_PAGE_READ_WITH_ECC           0x3
#define OP_PAGE_READ_WITH_ECC_SPARE     0x4
#define OP_PAGE_READ_ONFI_READ          0x5
#define OP_PROGRAM_PAGE                 0x6
#define OP_PAGE_PROGRAM_WITH_ECC        0x7
#define OP_PROGRAM_PAGE_SPARE           0x9
#define OP_BLOCK_ERASE                  0xa
#define OP_CHECK_STATUS                 0xc
#define OP_FETCH_ID                     0xb
#define OP_RESET_DEVICE                 0xd

/* Default Value for NAND_DEV_CMD_VLD */
#define NAND_DEV_CMD_VLD_VAL            (READ_START_VLD | WRITE_START_VLD | \
                                         ERASE_START_VLD | SEQ_READ_START_VLD)

/* NAND_CTRL bits */
#define BAM_MODE_EN                     BIT(0)

/*
 * 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                 512

/*
 * the largest page size we support is 8K, this will have 16 steps/codewords
 * of 512 bytes each
 */
#define MAX_NUM_STEPS                   (SZ_8K / NANDC_STEP_SIZE)

/* we read at most 3 registers per codeword scan */
#define MAX_REG_RD                      (3 * MAX_NUM_STEPS)

/* ECC modes supported by the controller */
#define ECC_NONE        BIT(0)
#define ECC_RS_4BIT     BIT(1)
#define ECC_BCH_4BIT    BIT(2)
#define ECC_BCH_8BIT    BIT(3)

/*
 * 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) ((nandc)->props->dev_cmd_reg_start + (reg))

/* Returns the dma address for reg read buffer */
#define reg_buf_dma_addr(chip, vaddr) \
        ((chip)->reg_read_dma + \
        ((u8 *)(vaddr) - (u8 *)(chip)->reg_read_buf))

#define QPIC_PER_CW_CMD_ELEMENTS        32
#define QPIC_PER_CW_CMD_SGL             32
#define QPIC_PER_CW_DATA_SGL            8

#define QPIC_NAND_COMPLETION_TIMEOUT    msecs_to_jiffies(2000)

/*
 * Flags used in DMA descriptor preparation helper functions
 * (i.e. qcom_read_reg_dma/qcom_write_reg_dma/qcom_read_data_dma/qcom_write_data_dma)
 */
/* Don't set the EOT in current tx BAM sgl */
#define NAND_BAM_NO_EOT                 BIT(0)
/* Set the NWD flag in current BAM sgl */
#define NAND_BAM_NWD                    BIT(1)
/* Finish writing in the current BAM sgl and start writing in another BAM sgl */
#define NAND_BAM_NEXT_SGL               BIT(2)
/*
 * 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              BIT(4)

#define MAX_ADDRESS_CYCLE               5

/*
 * 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_nitems - the number of elements in the @bam_ce array
 * @cmd_sgl_nitems - the number of elements in the @cmd_sgl array
 * @data_sgl_nitems - the number of elements in the @data_sgl array
 * @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.
 */
struct bam_transaction {
        struct bam_cmd_element *bam_ce;
        struct scatterlist *cmd_sgl;
        struct scatterlist *data_sgl;
        struct dma_async_tx_descriptor *last_data_desc;
        struct dma_async_tx_descriptor *last_cmd_desc;
        struct completion txn_done;

        unsigned int bam_ce_nitems;
        unsigned int cmd_sgl_nitems;
        unsigned int data_sgl_nitems;

        struct_group(bam_positions,
                u32 bam_ce_pos;
                u32 bam_ce_start;
                u32 cmd_sgl_pos;
                u32 cmd_sgl_start;
                u32 tx_sgl_pos;
                u32 tx_sgl_start;
                u32 rx_sgl_pos;
                u32 rx_sgl_start;

        );
};

/*
 * 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 {
        struct dma_async_tx_descriptor *dma_desc;
        struct list_head node;

        union {
                struct scatterlist adm_sgl;
                struct {
                        struct scatterlist *bam_sgl;
                        int sgl_cnt;
                };
        };
        enum dma_data_direction dir;
};

/*
 * 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 {
        __le32 cmd;
        __le32 addr0;
        __le32 addr1;
        __le32 chip_sel;
        __le32 exec;

        __le32 cfg0;
        __le32 cfg1;
        __le32 ecc_bch_cfg;

        __le32 clrflashstatus;
        __le32 clrreadstatus;

        __le32 cmd1;
        __le32 vld;

        __le32 orig_cmd1;
        __le32 orig_vld;

        __le32 ecc_buf_cfg;
        __le32 read_location0;
        __le32 read_location1;
        __le32 read_location2;
        __le32 read_location3;
        __le32 read_location_last0;
        __le32 read_location_last1;
        __le32 read_location_last2;
        __le32 read_location_last3;
        __le32 spi_cfg;
        __le32 num_addr_cycle;
        __le32 busy_wait_cnt;
        __le32 flash_feature;

        __le32 erased_cw_detect_cfg_clr;
        __le32 erased_cw_detect_cfg_set;
};

/*
 * NAND controller data struct
 *
 * @dev:                        parent device
 *
 * @base:                       MMIO base
 *
 * @core_clk:                   controller clock
 * @aon_clk:                    another controller clock
 * @iomacro_clk:                io macro 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
 * @qspi:                       qpic spi 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 {
        struct device *dev;

        void __iomem *base;

        struct clk *core_clk;
        struct clk *aon_clk;

        struct nandc_regs *regs;
        struct bam_transaction *bam_txn;

        const struct qcom_nandc_props *props;

        struct nand_controller *controller;
        struct qpic_spi_nand *qspi;
        struct list_head host_list;

        union {
                /* will be used only by QPIC for BAM DMA */
                struct {
                        struct dma_chan *tx_chan;
                        struct dma_chan *rx_chan;
                        struct dma_chan *cmd_chan;
                };

                /* will be used only by EBI2 for ADM DMA */
                struct {
                        struct dma_chan *chan;
                        unsigned int cmd_crci;
                        unsigned int data_crci;
                };
        };

        struct list_head desc_list;

        u8              *data_buffer;
        __le32          *reg_read_buf;

        phys_addr_t base_phys;
        dma_addr_t base_dma;
        dma_addr_t reg_read_dma;

        int             buf_size;
        int             buf_count;
        int             buf_start;
        unsigned int    max_cwperpage;

        int reg_read_pos;

        u32 cmd1, vld;
        bool exec_opwrite;
};

/*
 * 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
 * @supports_bam - whether NAND controller is using BAM
 * @nandc_part_of_qpic - whether NAND controller is part of qpic IP
 * @qpic_version2 - flag to indicate QPIC IP version 2
 * @use_codeword_fixup - whether NAND has different layout for boot partitions
 */
struct qcom_nandc_props {
        u32 ecc_modes;
        u32 dev_cmd_reg_start;
        u32 bam_offset;
        bool supports_bam;
        bool nandc_part_of_qpic;
        bool qpic_version2;
        bool use_codeword_fixup;
};

void qcom_free_bam_transaction(struct qcom_nand_controller *nandc);
struct bam_transaction *qcom_alloc_bam_transaction(struct qcom_nand_controller *nandc);
void qcom_clear_bam_transaction(struct qcom_nand_controller *nandc);
void qcom_qpic_bam_dma_done(void *data);
void qcom_nandc_dev_to_mem(struct qcom_nand_controller *nandc, bool is_cpu);
int qcom_prepare_bam_async_desc(struct qcom_nand_controller *nandc,
                                struct dma_chan *chan, unsigned long flags);
int qcom_prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read,
                               int reg_off, const void *vaddr, int size, unsigned int flags);
int qcom_prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read,
                                const void *vaddr, int size, unsigned int flags);
int qcom_prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read, int reg_off,
                           const void *vaddr, int size, bool flow_control);
int qcom_read_reg_dma(struct qcom_nand_controller *nandc, int first, int num_regs,
                      unsigned int flags);
int qcom_write_reg_dma(struct qcom_nand_controller *nandc, __le32 *vaddr, int first,
                       int num_regs, unsigned int flags);
int qcom_read_data_dma(struct qcom_nand_controller *nandc, int reg_off, const u8 *vaddr,
                       int size, unsigned int flags);
int qcom_write_data_dma(struct qcom_nand_controller *nandc, int reg_off, const u8 *vaddr,
                        int size, unsigned int flags);
int qcom_submit_descs(struct qcom_nand_controller *nandc);
void qcom_clear_read_regs(struct qcom_nand_controller *nandc);
void qcom_nandc_unalloc(struct qcom_nand_controller *nandc);
int qcom_nandc_alloc(struct qcom_nand_controller *nandc);
#endif