diff options
Diffstat (limited to 'target/linux/ipq806x/patches-4.9/861-qcom-mtd-nand-Added-bam-transaction-and-support-addi.patch')
-rw-r--r-- | target/linux/ipq806x/patches-4.9/861-qcom-mtd-nand-Added-bam-transaction-and-support-addi.patch | 755 |
1 files changed, 374 insertions, 381 deletions
diff --git a/target/linux/ipq806x/patches-4.9/861-qcom-mtd-nand-Added-bam-transaction-and-support-addi.patch b/target/linux/ipq806x/patches-4.9/861-qcom-mtd-nand-Added-bam-transaction-and-support-addi.patch index 674de77..84f90b4 100644 --- a/target/linux/ipq806x/patches-4.9/861-qcom-mtd-nand-Added-bam-transaction-and-support-addi.patch +++ b/target/linux/ipq806x/patches-4.9/861-qcom-mtd-nand-Added-bam-transaction-and-support-addi.patch @@ -26,8 +26,6 @@ Signed-off-by: Ram Chandra Jangir <rjangir@codeaurora.org> 2 files changed, 721 insertions(+), 59 deletions(-) create mode 100644 include/linux/dma/qcom_bam_dma.h -diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c -index 76a0ffc..9d941e3 100644 --- a/drivers/mtd/nand/qcom_nandc.c +++ b/drivers/mtd/nand/qcom_nandc.c @@ -22,6 +22,7 @@ @@ -35,7 +33,7 @@ index 76a0ffc..9d941e3 100644 #include <linux/of_device.h> #include <linux/delay.h> +#include <linux/dma/qcom_bam_dma.h> - + /* NANDc reg offsets */ #define NAND_FLASH_CMD 0x00 @@ -53,6 +54,8 @@ @@ -44,13 +42,13 @@ index 76a0ffc..9d941e3 100644 #define NAND_READ_LOCATION_1 0xf24 +#define NAND_READ_LOCATION_2 0xf28 +#define NAND_READ_LOCATION_3 0xf2c - + /* dummy register offsets, used by write_reg_dma */ #define NAND_DEV_CMD1_RESTORE 0xdead @@ -131,6 +134,11 @@ #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 0 +#define READ_LOCATION_SIZE 16 @@ -62,7 +60,7 @@ index 76a0ffc..9d941e3 100644 @@ -148,6 +156,9 @@ #define FETCH_ID 0xb #define RESET_DEVICE 0xd - + +/* NAND_CTRL bits */ +#define BAM_MODE_EN BIT(0) + @@ -72,7 +70,7 @@ index 76a0ffc..9d941e3 100644 @@ -169,12 +180,77 @@ #define ECC_BCH_4BIT BIT(2) #define ECC_BCH_8BIT BIT(3) - + +/* Flags used for BAM DMA desc preparation*/ +/* Don't set the EOT in current tx sgl */ +#define DMA_DESC_FLAG_NO_EOT (0x0001) @@ -138,19 +136,19 @@ index 76a0ffc..9d941e3 100644 + * @bam_desc_data - used for bam desc mappings + */ struct desc_info { - struct list_head node; - - enum dma_data_direction dir; - struct scatterlist sgl; - struct dma_async_tx_descriptor *dma_desc; + struct list_head node; + + enum dma_data_direction dir; + struct scatterlist sgl; + struct dma_async_tx_descriptor *dma_desc; + struct qcom_bam_custom_data bam_desc_data; }; - + /* @@ -202,6 +278,13 @@ struct nandc_regs { - __le32 orig_vld; - - __le32 ecc_buf_cfg; + __le32 orig_vld; + + __le32 ecc_buf_cfg; + __le32 read_location0; + __le32 read_location1; + __le32 read_location2; @@ -159,7 +157,7 @@ index 76a0ffc..9d941e3 100644 + __le32 erased_cw_detect_cfg_clr; + __le32 erased_cw_detect_cfg_set; }; - + /* @@ -217,6 +300,7 @@ struct nandc_regs { * @aon_clk: another controller clock @@ -171,16 +169,16 @@ index 76a0ffc..9d941e3 100644 * @desc_list: DMA descriptor list (list of desc_infos) @@ -242,6 +326,7 @@ struct nandc_regs { struct qcom_nand_controller { - struct nand_hw_control controller; - struct list_head host_list; + struct nand_hw_control controller; + struct list_head host_list; + struct bam_transaction *bam_txn; - - struct device *dev; - + + struct device *dev; + @@ -342,6 +427,45 @@ struct qcom_nand_driver_data { - bool dma_bam_enabled; + bool dma_bam_enabled; }; - + +/* Allocates and Initializes the BAM transaction */ +struct bam_transaction *alloc_bam_transaction( + struct qcom_nand_controller *nandc) @@ -222,11 +220,11 @@ index 76a0ffc..9d941e3 100644 + static inline struct qcom_nand_host *to_qcom_nand_host(struct nand_chip *chip) { - return container_of(chip, struct qcom_nand_host, chip); -@@ -398,6 +522,16 @@ static __le32 *offset_to_nandc_reg(struct nandc_regs *regs, int offset) - return ®s->orig_vld; - case NAND_EBI2_ECC_BUF_CFG: - return ®s->ecc_buf_cfg; + return container_of(chip, struct qcom_nand_host, chip); +@@ -398,6 +522,16 @@ static __le32 *offset_to_nandc_reg(struc + return ®s->orig_vld; + case NAND_EBI2_ECC_BUF_CFG: + return ®s->ecc_buf_cfg; + case NAND_BUFFER_STATUS: + return ®s->clrreadstatus; + case NAND_READ_LOCATION_0: @@ -237,48 +235,48 @@ index 76a0ffc..9d941e3 100644 + return ®s->read_location2; + case NAND_READ_LOCATION_3: + return ®s->read_location3; - default: - return NULL; - } -@@ -439,7 +573,7 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read) + default: + return NULL; + } +@@ -439,7 +573,7 @@ static void update_rw_regs(struct qcom_n { - struct nand_chip *chip = &host->chip; - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - u32 cmd, cfg0, cfg1, ecc_bch_cfg; + u32 cmd, cfg0, cfg1, ecc_bch_cfg, read_location0; - - if (read) { - if (host->use_ecc) -@@ -456,12 +590,20 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read) - - cfg1 = host->cfg1; - ecc_bch_cfg = host->ecc_bch_cfg; + + if (read) { + if (host->use_ecc) +@@ -456,12 +590,20 @@ static void update_rw_regs(struct qcom_n + + cfg1 = host->cfg1; + ecc_bch_cfg = host->ecc_bch_cfg; + if (read) + read_location0 = (0 << READ_LOCATION_OFFSET) | + (host->cw_data << READ_LOCATION_SIZE) | + (1 << READ_LOCATION_LAST); - } else { - cfg0 = (host->cfg0_raw & ~(7U << CW_PER_PAGE)) | - (num_cw - 1) << CW_PER_PAGE; - - cfg1 = host->cfg1_raw; - ecc_bch_cfg = 1 << ECC_CFG_ECC_DISABLE; + } else { + cfg0 = (host->cfg0_raw & ~(7U << CW_PER_PAGE)) | + (num_cw - 1) << CW_PER_PAGE; + + cfg1 = host->cfg1_raw; + ecc_bch_cfg = 1 << ECC_CFG_ECC_DISABLE; + if (read) + read_location0 = (0 << READ_LOCATION_OFFSET) | + (host->cw_size << READ_LOCATION_SIZE) | + (1 << READ_LOCATION_LAST); - } - - nandc_set_reg(nandc, NAND_FLASH_CMD, cmd); -@@ -472,8 +614,104 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read) - nandc_set_reg(nandc, NAND_FLASH_STATUS, host->clrflashstatus); - nandc_set_reg(nandc, NAND_READ_STATUS, host->clrreadstatus); - nandc_set_reg(nandc, NAND_EXEC_CMD, 1); + } + + nandc_set_reg(nandc, NAND_FLASH_CMD, cmd); +@@ -472,8 +614,104 @@ static void update_rw_regs(struct qcom_n + nandc_set_reg(nandc, NAND_FLASH_STATUS, host->clrflashstatus); + nandc_set_reg(nandc, NAND_READ_STATUS, host->clrreadstatus); + nandc_set_reg(nandc, NAND_EXEC_CMD, 1); + + if (read) + nandc_set_reg(nandc, NAND_READ_LOCATION_0, read_location0); - } - ++} ++ +/* + * Prepares the command descriptor for BAM DMA which will be used for NAND + * register read and write. The command descriptor requires the command @@ -339,8 +337,8 @@ index 76a0ffc..9d941e3 100644 + } + + return 0; -+} -+ + } + +/* + * Prepares the data descriptor for BAM DMA which will be used for NAND + * data read and write. @@ -373,25 +371,25 @@ index 76a0ffc..9d941e3 100644 + +/* Prepares the dma desciptor for adm dma engine */ static int prep_dma_desc(struct qcom_nand_controller *nandc, bool read, - int reg_off, const void *vaddr, int size, - bool flow_control) -@@ -552,7 +790,7 @@ static int prep_dma_desc(struct qcom_nand_controller *nandc, bool read, + int reg_off, const void *vaddr, int size, + bool flow_control) +@@ -552,7 +790,7 @@ err: * @num_regs: number of registers to read */ static int read_reg_dma(struct qcom_nand_controller *nandc, int first, - int num_regs) + int num_regs, unsigned int flags) { - bool flow_control = false; - void *vaddr; -@@ -561,10 +799,18 @@ static int read_reg_dma(struct qcom_nand_controller *nandc, int first, - if (first == NAND_READ_ID || first == NAND_FLASH_STATUS) - flow_control = true; - + bool flow_control = false; + void *vaddr; +@@ -561,10 +799,18 @@ static int read_reg_dma(struct qcom_nand + if (first == NAND_READ_ID || first == NAND_FLASH_STATUS) + flow_control = true; + - size = num_regs * sizeof(u32); - vaddr = nandc->reg_read_buf + nandc->reg_read_pos; - nandc->reg_read_pos += num_regs; - + vaddr = nandc->reg_read_buf + nandc->reg_read_pos; + nandc->reg_read_pos += num_regs; + + if (nandc->dma_bam_enabled) { + size = num_regs; + @@ -401,22 +399,22 @@ index 76a0ffc..9d941e3 100644 + + size = num_regs * sizeof(u32); + - return prep_dma_desc(nandc, true, first, vaddr, size, flow_control); + return prep_dma_desc(nandc, true, first, vaddr, size, flow_control); } - -@@ -576,7 +822,7 @@ static int read_reg_dma(struct qcom_nand_controller *nandc, int first, + +@@ -576,7 +822,7 @@ static int read_reg_dma(struct qcom_nand * @num_regs: number of registers to write */ static int write_reg_dma(struct qcom_nand_controller *nandc, int first, - int num_regs) + int num_regs, unsigned int flags) { - bool flow_control = false; - struct nandc_regs *regs = nandc->regs; -@@ -588,12 +834,29 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first, - if (first == NAND_FLASH_CMD) - flow_control = true; - + bool flow_control = false; + struct nandc_regs *regs = nandc->regs; +@@ -588,12 +834,29 @@ static int write_reg_dma(struct qcom_nan + if (first == NAND_FLASH_CMD) + flow_control = true; + + if (first == NAND_ERASED_CW_DETECT_CFG) { + if (flags & DMA_DESC_ERASED_CW_SET) + vaddr = ®s->erased_cw_detect_cfg_set; @@ -427,12 +425,12 @@ index 76a0ffc..9d941e3 100644 + if (first == NAND_EXEC_CMD) + flags |= DMA_DESC_FLAG_BAM_NWD; + - if (first == NAND_DEV_CMD1_RESTORE) - first = NAND_DEV_CMD1; - - if (first == NAND_DEV_CMD_VLD_RESTORE) - first = NAND_DEV_CMD_VLD; - + if (first == NAND_DEV_CMD1_RESTORE) + first = NAND_DEV_CMD1; + + if (first == NAND_DEV_CMD_VLD_RESTORE) + first = NAND_DEV_CMD_VLD; + + if (nandc->dma_bam_enabled) { + size = num_regs; + @@ -440,10 +438,10 @@ index 76a0ffc..9d941e3 100644 + flags); + } + - size = num_regs * sizeof(u32); - - return prep_dma_desc(nandc, false, first, vaddr, size, flow_control); -@@ -608,8 +871,12 @@ static int write_reg_dma(struct qcom_nand_controller *nandc, int first, + size = num_regs * sizeof(u32); + + return prep_dma_desc(nandc, false, first, vaddr, size, flow_control); +@@ -608,8 +871,12 @@ static int write_reg_dma(struct qcom_nan * @size: DMA transaction size in bytes */ static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off, @@ -454,10 +452,10 @@ index 76a0ffc..9d941e3 100644 + return prep_dma_desc_data_bam(nandc, true, reg_off, vaddr, size, + flags); + - return prep_dma_desc(nandc, true, reg_off, vaddr, size, false); + return prep_dma_desc(nandc, true, reg_off, vaddr, size, false); } - -@@ -622,8 +889,12 @@ static int read_data_dma(struct qcom_nand_controller *nandc, int reg_off, + +@@ -622,8 +889,12 @@ static int read_data_dma(struct qcom_nan * @size: DMA transaction size in bytes */ static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off, @@ -468,17 +466,17 @@ index 76a0ffc..9d941e3 100644 + return prep_dma_desc_data_bam(nandc, false, reg_off, vaddr, + size, flags); + - return prep_dma_desc(nandc, false, reg_off, vaddr, size, false); + return prep_dma_desc(nandc, false, reg_off, vaddr, size, false); } - -@@ -633,14 +904,57 @@ static int write_data_dma(struct qcom_nand_controller *nandc, int reg_off, + +@@ -633,14 +904,57 @@ static int write_data_dma(struct qcom_na */ static void config_cw_read(struct qcom_nand_controller *nandc) { - write_reg_dma(nandc, NAND_FLASH_CMD, 3); - write_reg_dma(nandc, NAND_DEV0_CFG0, 3); - write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1); - + - write_reg_dma(nandc, NAND_EXEC_CMD, 1); + write_reg_dma(nandc, NAND_FLASH_CMD, 3, 0); + write_reg_dma(nandc, NAND_DEV0_CFG0, 3, 0); @@ -490,10 +488,10 @@ index 76a0ffc..9d941e3 100644 + if (nandc->dma_bam_enabled) + write_reg_dma(nandc, NAND_READ_LOCATION_0, 1, + DMA_DESC_FLAG_BAM_NEXT_SGL); -+ - + - read_reg_dma(nandc, NAND_FLASH_STATUS, 2); - read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1); ++ + write_reg_dma(nandc, NAND_EXEC_CMD, 1, DMA_DESC_FLAG_BAM_NWD | + DMA_DESC_FLAG_BAM_NEXT_SGL); + @@ -533,9 +531,9 @@ index 76a0ffc..9d941e3 100644 + read_reg_dma(nandc, NAND_ERASED_CW_DETECT_STATUS, 1, + DMA_DESC_FLAG_BAM_NEXT_SGL); } - + /* -@@ -649,19 +963,20 @@ static void config_cw_read(struct qcom_nand_controller *nandc) +@@ -649,19 +963,20 @@ static void config_cw_read(struct qcom_n */ static void config_cw_write_pre(struct qcom_nand_controller *nandc) { @@ -547,137 +545,138 @@ index 76a0ffc..9d941e3 100644 + write_reg_dma(nandc, NAND_EBI2_ECC_BUF_CFG, 1, + DMA_DESC_FLAG_BAM_NEXT_SGL); } - + static void config_cw_write_post(struct qcom_nand_controller *nandc) { - write_reg_dma(nandc, NAND_EXEC_CMD, 1); + write_reg_dma(nandc, NAND_EXEC_CMD, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); - + - read_reg_dma(nandc, NAND_FLASH_STATUS, 1); + read_reg_dma(nandc, NAND_FLASH_STATUS, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); - + - write_reg_dma(nandc, NAND_FLASH_STATUS, 1); - write_reg_dma(nandc, NAND_READ_STATUS, 1); + write_reg_dma(nandc, NAND_FLASH_STATUS, 1, 0); + write_reg_dma(nandc, NAND_READ_STATUS, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); } - + /* -@@ -675,6 +990,8 @@ static int nandc_param(struct qcom_nand_host *host) - struct nand_chip *chip = &host->chip; - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - +@@ -675,6 +990,8 @@ static int nandc_param(struct qcom_nand_ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + clear_bam_transaction(nandc); + - /* - * NAND_CMD_PARAM is called before we know much about the FLASH chip - * in use. we configure the controller to perform a raw read of 512 -@@ -708,9 +1025,13 @@ static int nandc_param(struct qcom_nand_host *host) - - nandc_set_reg(nandc, NAND_DEV_CMD1_RESTORE, nandc->cmd1); - nandc_set_reg(nandc, NAND_DEV_CMD_VLD_RESTORE, nandc->vld); + /* + * NAND_CMD_PARAM is called before we know much about the FLASH chip + * in use. we configure the controller to perform a raw read of 512 +@@ -708,9 +1025,13 @@ static int nandc_param(struct qcom_nand_ + + nandc_set_reg(nandc, NAND_DEV_CMD1_RESTORE, nandc->cmd1); + nandc_set_reg(nandc, NAND_DEV_CMD_VLD_RESTORE, nandc->vld); + nandc_set_reg(nandc, NAND_READ_LOCATION_0, + (0 << READ_LOCATION_OFFSET) | + (512 << READ_LOCATION_SIZE) | + (1 << READ_LOCATION_LAST)); - + - write_reg_dma(nandc, NAND_DEV_CMD_VLD, 1); - write_reg_dma(nandc, NAND_DEV_CMD1, 1); + write_reg_dma(nandc, NAND_DEV_CMD_VLD, 1, 0); + write_reg_dma(nandc, NAND_DEV_CMD1, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); - - nandc->buf_count = 512; - memset(nandc->data_buffer, 0xff, nandc->buf_count); -@@ -718,11 +1039,12 @@ static int nandc_param(struct qcom_nand_host *host) - config_cw_read(nandc); - - read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, + + nandc->buf_count = 512; + memset(nandc->data_buffer, 0xff, nandc->buf_count); +@@ -718,11 +1039,12 @@ static int nandc_param(struct qcom_nand_ + config_cw_read(nandc); + + read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, - nandc->buf_count); + nandc->buf_count, 0); - - /* restore CMD1 and VLD regs */ + + /* restore CMD1 and VLD regs */ - write_reg_dma(nandc, NAND_DEV_CMD1_RESTORE, 1); - write_reg_dma(nandc, NAND_DEV_CMD_VLD_RESTORE, 1); + write_reg_dma(nandc, NAND_DEV_CMD1_RESTORE, 1, 0); + write_reg_dma(nandc, NAND_DEV_CMD_VLD_RESTORE, 1, + DMA_DESC_FLAG_BAM_NEXT_SGL); - - return 0; + + return 0; } -@@ -733,6 +1055,8 @@ static int erase_block(struct qcom_nand_host *host, int page_addr) - struct nand_chip *chip = &host->chip; - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - +@@ -733,6 +1055,8 @@ static int erase_block(struct qcom_nand_ + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + clear_bam_transaction(nandc); + - nandc_set_reg(nandc, NAND_FLASH_CMD, - BLOCK_ERASE | PAGE_ACC | LAST_PAGE); - nandc_set_reg(nandc, NAND_ADDR0, page_addr); -@@ -744,14 +1068,15 @@ static int erase_block(struct qcom_nand_host *host, int page_addr) - nandc_set_reg(nandc, NAND_FLASH_STATUS, host->clrflashstatus); - nandc_set_reg(nandc, NAND_READ_STATUS, host->clrreadstatus); - + nandc_set_reg(nandc, NAND_FLASH_CMD, + BLOCK_ERASE | PAGE_ACC | LAST_PAGE); + nandc_set_reg(nandc, NAND_ADDR0, page_addr); +@@ -744,14 +1068,15 @@ static int erase_block(struct qcom_nand_ + nandc_set_reg(nandc, NAND_FLASH_STATUS, host->clrflashstatus); + nandc_set_reg(nandc, NAND_READ_STATUS, host->clrreadstatus); + - write_reg_dma(nandc, NAND_FLASH_CMD, 3); - write_reg_dma(nandc, NAND_DEV0_CFG0, 2); - write_reg_dma(nandc, NAND_EXEC_CMD, 1); - + - read_reg_dma(nandc, NAND_FLASH_STATUS, 1); + write_reg_dma(nandc, NAND_FLASH_CMD, 3, DMA_DESC_FLAG_BAM_NEXT_SGL); + write_reg_dma(nandc, NAND_DEV0_CFG0, 2, DMA_DESC_FLAG_BAM_NEXT_SGL); + write_reg_dma(nandc, NAND_EXEC_CMD, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); - ++ ++ read_reg_dma(nandc, NAND_FLASH_STATUS, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); + - write_reg_dma(nandc, NAND_FLASH_STATUS, 1); - write_reg_dma(nandc, NAND_READ_STATUS, 1); -+ read_reg_dma(nandc, NAND_FLASH_STATUS, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); -+ + write_reg_dma(nandc, NAND_FLASH_STATUS, 1, 0); + write_reg_dma(nandc, NAND_READ_STATUS, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); - - return 0; + + return 0; } -@@ -765,16 +1090,19 @@ static int read_id(struct qcom_nand_host *host, int column) - if (column == -1) - return 0; - +@@ -765,16 +1090,19 @@ static int read_id(struct qcom_nand_host + if (column == -1) + return 0; + + clear_bam_transaction(nandc); + - nandc_set_reg(nandc, NAND_FLASH_CMD, FETCH_ID); - nandc_set_reg(nandc, NAND_ADDR0, column); - nandc_set_reg(nandc, NAND_ADDR1, 0); + nandc_set_reg(nandc, NAND_FLASH_CMD, FETCH_ID); + nandc_set_reg(nandc, NAND_ADDR0, column); + nandc_set_reg(nandc, NAND_ADDR1, 0); - nandc_set_reg(nandc, NAND_FLASH_CHIP_SELECT, DM_EN); + nandc_set_reg(nandc, NAND_FLASH_CHIP_SELECT, + nandc->dma_bam_enabled ? 0 : DM_EN); - nandc_set_reg(nandc, NAND_EXEC_CMD, 1); - + nandc_set_reg(nandc, NAND_EXEC_CMD, 1); + - write_reg_dma(nandc, NAND_FLASH_CMD, 4); - write_reg_dma(nandc, NAND_EXEC_CMD, 1); + write_reg_dma(nandc, NAND_FLASH_CMD, 4, DMA_DESC_FLAG_BAM_NEXT_SGL); + write_reg_dma(nandc, NAND_EXEC_CMD, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); - + - read_reg_dma(nandc, NAND_READ_ID, 1); + read_reg_dma(nandc, NAND_READ_ID, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); - - return 0; + + return 0; } -@@ -785,15 +1113,61 @@ static int reset(struct qcom_nand_host *host) - struct nand_chip *chip = &host->chip; - struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); - +@@ -785,28 +1113,108 @@ static int reset(struct qcom_nand_host * + struct nand_chip *chip = &host->chip; + struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); + + clear_bam_transaction(nandc); + - nandc_set_reg(nandc, NAND_FLASH_CMD, RESET_DEVICE); - nandc_set_reg(nandc, NAND_EXEC_CMD, 1); - + nandc_set_reg(nandc, NAND_FLASH_CMD, RESET_DEVICE); + nandc_set_reg(nandc, NAND_EXEC_CMD, 1); + - write_reg_dma(nandc, NAND_FLASH_CMD, 1); - write_reg_dma(nandc, NAND_EXEC_CMD, 1); + write_reg_dma(nandc, NAND_FLASH_CMD, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); + write_reg_dma(nandc, NAND_EXEC_CMD, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); -+ + +- read_reg_dma(nandc, NAND_FLASH_STATUS, 1); + read_reg_dma(nandc, NAND_FLASH_STATUS, 1, DMA_DESC_FLAG_BAM_NEXT_SGL); -+ -+ return 0; -+} -+ + + return 0; + } + +static int prepare_bam_async_desc(struct qcom_nand_controller *nandc, + struct dma_chan *chan, + struct qcom_bam_sgl *bam_sgl, @@ -715,19 +714,18 @@ index 76a0ffc..9d941e3 100644 + } + + desc->dma_desc = dma_desc; - -- read_reg_dma(nandc, NAND_FLASH_STATUS, 1); ++ + list_add_tail(&desc->node, &nandc->desc_list); - - return 0; + - } - ++ return 0; ++ ++} ++ /* helpers to submit/free our list of dma descriptors */ -@@ -801,12 +1175,46 @@ static int submit_descs(struct qcom_nand_controller *nandc) + static int submit_descs(struct qcom_nand_controller *nandc) { - struct desc_info *desc; - dma_cookie_t cookie = 0; + struct desc_info *desc; + dma_cookie_t cookie = 0; + struct bam_transaction *bam_txn = nandc->bam_txn; + int r; + @@ -754,10 +752,10 @@ index 76a0ffc..9d941e3 100644 + if (r) + return r; + } - - list_for_each_entry(desc, &nandc->desc_list, node) - cookie = dmaengine_submit(desc->dma_desc); - + + list_for_each_entry(desc, &nandc->desc_list, node) + cookie = dmaengine_submit(desc->dma_desc); + - if (dma_sync_wait(nandc->chan, cookie) != DMA_COMPLETE) - return -ETIMEDOUT; + if (nandc->dma_bam_enabled) { @@ -770,13 +768,13 @@ index 76a0ffc..9d941e3 100644 + if (dma_sync_wait(nandc->chan, cookie) != DMA_COMPLETE) + return -ETIMEDOUT; + } - - return 0; + + return 0; } -@@ -817,7 +1225,16 @@ static void free_descs(struct qcom_nand_controller *nandc) - - list_for_each_entry_safe(desc, n, &nandc->desc_list, node) { - list_del(&desc->node); +@@ -817,7 +1225,16 @@ static void free_descs(struct qcom_nand_ + + list_for_each_entry_safe(desc, n, &nandc->desc_list, node) { + list_del(&desc->node); - dma_unmap_sg(nandc->dev, &desc->sgl, 1, desc->dir); + + if (nandc->dma_bam_enabled) @@ -788,23 +786,23 @@ index 76a0ffc..9d941e3 100644 + dma_unmap_sg(nandc->dev, &desc->sgl, 1, + desc->dir); + - kfree(desc); - } + kfree(desc); + } } -@@ -1128,6 +1545,9 @@ static int read_page_ecc(struct qcom_nand_host *host, u8 *data_buf, - struct nand_ecc_ctrl *ecc = &chip->ecc; - int i, ret; - +@@ -1128,6 +1545,9 @@ static int read_page_ecc(struct qcom_nan + struct nand_ecc_ctrl *ecc = &chip->ecc; + int i, ret; + + if (nandc->dma_bam_enabled) + config_bam_page_read(nandc); + - /* queue cmd descs for each codeword */ - for (i = 0; i < ecc->steps; i++) { - int data_size, oob_size; -@@ -1141,11 +1561,36 @@ static int read_page_ecc(struct qcom_nand_host *host, u8 *data_buf, - oob_size = host->ecc_bytes_hw + host->spare_bytes; - } - + /* queue cmd descs for each codeword */ + for (i = 0; i < ecc->steps; i++) { + int data_size, oob_size; +@@ -1141,11 +1561,36 @@ static int read_page_ecc(struct qcom_nan + oob_size = host->ecc_bytes_hw + host->spare_bytes; + } + - config_cw_read(nandc); + if (nandc->dma_bam_enabled) { + if (data_buf && oob_buf) { @@ -832,71 +830,71 @@ index 76a0ffc..9d941e3 100644 + } else { + config_cw_read(nandc); + } - - if (data_buf) - read_data_dma(nandc, FLASH_BUF_ACC, data_buf, + + if (data_buf) + read_data_dma(nandc, FLASH_BUF_ACC, data_buf, - data_size); + data_size, 0); - - /* - * when ecc is enabled, the controller doesn't read the real -@@ -1161,7 +1606,7 @@ static int read_page_ecc(struct qcom_nand_host *host, u8 *data_buf, - *oob_buf++ = 0xff; - - read_data_dma(nandc, FLASH_BUF_ACC + data_size, + + /* + * when ecc is enabled, the controller doesn't read the real +@@ -1161,7 +1606,7 @@ static int read_page_ecc(struct qcom_nan + *oob_buf++ = 0xff; + + read_data_dma(nandc, FLASH_BUF_ACC + data_size, - oob_buf, oob_size); + oob_buf, oob_size, 0); - } - - if (data_buf) -@@ -1200,10 +1645,14 @@ static int copy_last_cw(struct qcom_nand_host *host, int page) - - set_address(host, host->cw_size * (ecc->steps - 1), page); - update_rw_regs(host, 1, true); + } + + if (data_buf) +@@ -1200,10 +1645,14 @@ static int copy_last_cw(struct qcom_nand + + set_address(host, host->cw_size * (ecc->steps - 1), page); + update_rw_regs(host, 1, true); + nandc_set_reg(nandc, NAND_READ_LOCATION_0, + (0 << READ_LOCATION_OFFSET) | + (size << READ_LOCATION_SIZE) | + (1 << READ_LOCATION_LAST)); - - config_cw_read(nandc); - + + config_cw_read(nandc); + - read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, size); + read_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, size, 0); - - ret = submit_descs(nandc); - if (ret) -@@ -1226,6 +1675,7 @@ static int qcom_nandc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - data_buf = buf; - oob_buf = oob_required ? chip->oob_poi : NULL; - + + ret = submit_descs(nandc); + if (ret) +@@ -1226,6 +1675,7 @@ static int qcom_nandc_read_page(struct m + data_buf = buf; + oob_buf = oob_required ? chip->oob_poi : NULL; + + clear_bam_transaction(nandc); - ret = read_page_ecc(host, data_buf, oob_buf); - if (ret) { - dev_err(nandc->dev, "failure to read page\n"); -@@ -1245,13 +1695,19 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd, - u8 *data_buf, *oob_buf; - struct nand_ecc_ctrl *ecc = &chip->ecc; - int i, ret; + ret = read_page_ecc(host, data_buf, oob_buf); + if (ret) { + dev_err(nandc->dev, "failure to read page\n"); +@@ -1245,13 +1695,19 @@ static int qcom_nandc_read_page_raw(stru + u8 *data_buf, *oob_buf; + struct nand_ecc_ctrl *ecc = &chip->ecc; + int i, ret; + int read_location; - - data_buf = buf; - oob_buf = chip->oob_poi; - - host->use_ecc = false; + + data_buf = buf; + oob_buf = chip->oob_poi; + + host->use_ecc = false; + + clear_bam_transaction(nandc); - update_rw_regs(host, ecc->steps, true); - + update_rw_regs(host, ecc->steps, true); + + if (nandc->dma_bam_enabled) + config_bam_page_read(nandc); + - for (i = 0; i < ecc->steps; i++) { - int data_size1, data_size2, oob_size1, oob_size2; - int reg_off = FLASH_BUF_ACC; -@@ -1269,21 +1725,49 @@ static int qcom_nandc_read_page_raw(struct mtd_info *mtd, - oob_size2 = host->ecc_bytes_hw + host->spare_bytes; - } - + for (i = 0; i < ecc->steps; i++) { + int data_size1, data_size2, oob_size1, oob_size2; + int reg_off = FLASH_BUF_ACC; +@@ -1269,21 +1725,49 @@ static int qcom_nandc_read_page_raw(stru + oob_size2 = host->ecc_bytes_hw + host->spare_bytes; + } + - config_cw_read(nandc); + if (nandc->dma_bam_enabled) { + read_location = 0; @@ -927,181 +925,181 @@ index 76a0ffc..9d941e3 100644 + } else { + config_cw_read(nandc); + } - + - read_data_dma(nandc, reg_off, data_buf, data_size1); + read_data_dma(nandc, reg_off, data_buf, data_size1, 0); - reg_off += data_size1; - data_buf += data_size1; - + reg_off += data_size1; + data_buf += data_size1; + - read_data_dma(nandc, reg_off, oob_buf, oob_size1); + read_data_dma(nandc, reg_off, oob_buf, oob_size1, 0); - reg_off += oob_size1; - oob_buf += oob_size1; - + reg_off += oob_size1; + oob_buf += oob_size1; + - read_data_dma(nandc, reg_off, data_buf, data_size2); + read_data_dma(nandc, reg_off, data_buf, data_size2, 0); - reg_off += data_size2; - data_buf += data_size2; - + reg_off += data_size2; + data_buf += data_size2; + - read_data_dma(nandc, reg_off, oob_buf, oob_size2); + read_data_dma(nandc, reg_off, oob_buf, oob_size2, 0); - oob_buf += oob_size2; - } - -@@ -1306,6 +1790,7 @@ static int qcom_nandc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int ret; - - clear_read_regs(nandc); + oob_buf += oob_size2; + } + +@@ -1306,6 +1790,7 @@ static int qcom_nandc_read_oob(struct mt + int ret; + + clear_read_regs(nandc); + clear_bam_transaction(nandc); - - host->use_ecc = true; - set_address(host, 0, page); -@@ -1329,6 +1814,7 @@ static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - int i, ret; - - clear_read_regs(nandc); + + host->use_ecc = true; + set_address(host, 0, page); +@@ -1329,6 +1814,7 @@ static int qcom_nandc_write_page(struct + int i, ret; + + clear_read_regs(nandc); + clear_bam_transaction(nandc); - - data_buf = (u8 *)buf; - oob_buf = chip->oob_poi; -@@ -1350,7 +1836,8 @@ static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - - config_cw_write_pre(nandc); - + + data_buf = (u8 *)buf; + oob_buf = chip->oob_poi; +@@ -1350,7 +1836,8 @@ static int qcom_nandc_write_page(struct + + config_cw_write_pre(nandc); + - write_data_dma(nandc, FLASH_BUF_ACC, data_buf, data_size); + write_data_dma(nandc, FLASH_BUF_ACC, data_buf, data_size, + i == (ecc->steps - 1) ? DMA_DESC_FLAG_NO_EOT : 0); - - /* - * when ECC is enabled, we don't really need to write anything -@@ -1363,7 +1850,7 @@ static int qcom_nandc_write_page(struct mtd_info *mtd, struct nand_chip *chip, - oob_buf += host->bbm_size; - - write_data_dma(nandc, FLASH_BUF_ACC + data_size, + + /* + * when ECC is enabled, we don't really need to write anything +@@ -1363,7 +1850,7 @@ static int qcom_nandc_write_page(struct + oob_buf += host->bbm_size; + + write_data_dma(nandc, FLASH_BUF_ACC + data_size, - oob_buf, oob_size); + oob_buf, oob_size, 0); - } - - config_cw_write_post(nandc); -@@ -1393,6 +1880,7 @@ static int qcom_nandc_write_page_raw(struct mtd_info *mtd, - int i, ret; - - clear_read_regs(nandc); + } + + config_cw_write_post(nandc); +@@ -1393,6 +1880,7 @@ static int qcom_nandc_write_page_raw(str + int i, ret; + + clear_read_regs(nandc); + clear_bam_transaction(nandc); - - data_buf = (u8 *)buf; - oob_buf = chip->oob_poi; -@@ -1419,19 +1907,22 @@ static int qcom_nandc_write_page_raw(struct mtd_info *mtd, - - config_cw_write_pre(nandc); - + + data_buf = (u8 *)buf; + oob_buf = chip->oob_poi; +@@ -1419,19 +1907,22 @@ static int qcom_nandc_write_page_raw(str + + config_cw_write_pre(nandc); + - write_data_dma(nandc, reg_off, data_buf, data_size1); + write_data_dma(nandc, reg_off, data_buf, data_size1, + DMA_DESC_FLAG_NO_EOT); - reg_off += data_size1; - data_buf += data_size1; - + reg_off += data_size1; + data_buf += data_size1; + - write_data_dma(nandc, reg_off, oob_buf, oob_size1); + write_data_dma(nandc, reg_off, oob_buf, oob_size1, + DMA_DESC_FLAG_NO_EOT); - reg_off += oob_size1; - oob_buf += oob_size1; - + reg_off += oob_size1; + oob_buf += oob_size1; + - write_data_dma(nandc, reg_off, data_buf, data_size2); + write_data_dma(nandc, reg_off, data_buf, data_size2, + DMA_DESC_FLAG_NO_EOT); - reg_off += data_size2; - data_buf += data_size2; - + reg_off += data_size2; + data_buf += data_size2; + - write_data_dma(nandc, reg_off, oob_buf, oob_size2); + write_data_dma(nandc, reg_off, oob_buf, oob_size2, 0); - oob_buf += oob_size2; - - config_cw_write_post(nandc); -@@ -1467,6 +1958,7 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - - host->use_ecc = true; - + oob_buf += oob_size2; + + config_cw_write_post(nandc); +@@ -1467,6 +1958,7 @@ static int qcom_nandc_write_oob(struct m + + host->use_ecc = true; + + clear_bam_transaction(nandc); - ret = copy_last_cw(host, page); - if (ret) - return ret; -@@ -1486,7 +1978,7 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - - config_cw_write_pre(nandc); - write_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, + ret = copy_last_cw(host, page); + if (ret) + return ret; +@@ -1486,7 +1978,7 @@ static int qcom_nandc_write_oob(struct m + + config_cw_write_pre(nandc); + write_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, - data_size + oob_size); + data_size + oob_size, 0); - config_cw_write_post(nandc); - - ret = submit_descs(nandc); -@@ -1524,6 +2016,7 @@ static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs) - */ - host->use_ecc = false; - + config_cw_write_post(nandc); + + ret = submit_descs(nandc); +@@ -1524,6 +2016,7 @@ static int qcom_nandc_block_bad(struct m + */ + host->use_ecc = false; + + clear_bam_transaction(nandc); - ret = copy_last_cw(host, page); - if (ret) - goto err; -@@ -1554,6 +2047,7 @@ static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs) - int page, ret, status = 0; - - clear_read_regs(nandc); + ret = copy_last_cw(host, page); + if (ret) + goto err; +@@ -1554,6 +2047,7 @@ static int qcom_nandc_block_markbad(stru + int page, ret, status = 0; + + clear_read_regs(nandc); + clear_bam_transaction(nandc); - - /* - * to mark the BBM as bad, we flash the entire last codeword with 0s. -@@ -1570,7 +2064,8 @@ static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs) - update_rw_regs(host, 1, false); - - config_cw_write_pre(nandc); + + /* + * to mark the BBM as bad, we flash the entire last codeword with 0s. +@@ -1570,7 +2064,8 @@ static int qcom_nandc_block_markbad(stru + update_rw_regs(host, 1, false); + + config_cw_write_pre(nandc); - write_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, host->cw_size); + write_data_dma(nandc, FLASH_BUF_ACC, nandc->data_buffer, + host->cw_size, 0); - config_cw_write_post(nandc); - - ret = submit_descs(nandc); -@@ -1930,6 +2425,8 @@ static int qcom_nand_host_setup(struct qcom_nand_host *host) - - host->clrflashstatus = FS_READY_BSY_N; - host->clrreadstatus = 0xc0; + config_cw_write_post(nandc); + + ret = submit_descs(nandc); +@@ -1930,6 +2425,8 @@ static int qcom_nand_host_setup(struct q + + host->clrflashstatus = FS_READY_BSY_N; + host->clrreadstatus = 0xc0; + nandc->regs->erased_cw_detect_cfg_clr = CLR_ERASED_PAGE_DET; + nandc->regs->erased_cw_detect_cfg_set = SET_ERASED_PAGE_DET; - - dev_dbg(nandc->dev, - "cfg0 %x cfg1 %x ecc_buf_cfg %x ecc_bch cfg %x cw_size %d cw_data %d strength %d parity_bytes %d steps %d\n", -@@ -2008,6 +2505,12 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc) - dev_err(nandc->dev, "failed to request cmd channel\n"); - return -ENODEV; - } + + dev_dbg(nandc->dev, + "cfg0 %x cfg1 %x ecc_buf_cfg %x ecc_bch cfg %x cw_size %d cw_data %d strength %d parity_bytes %d steps %d\n", +@@ -2008,6 +2505,12 @@ static int qcom_nandc_alloc(struct qcom_ + dev_err(nandc->dev, "failed to request cmd channel\n"); + return -ENODEV; + } + + nandc->bam_txn = alloc_bam_transaction(nandc); + if (!nandc->bam_txn) { + dev_err(nandc->dev, "failed to allocate bam transaction\n"); + return -ENOMEM; + } - } - - INIT_LIST_HEAD(&nandc->desc_list); -@@ -2043,6 +2546,9 @@ static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc) - devm_kfree(nandc->dev, nandc->reg_read_buf); - } - + } + + INIT_LIST_HEAD(&nandc->desc_list); +@@ -2043,6 +2546,9 @@ static void qcom_nandc_unalloc(struct qc + devm_kfree(nandc->dev, nandc->reg_read_buf); + } + + if (nandc->bam_txn) + devm_kfree(nandc->dev, nandc->bam_txn); + - if (nandc->regs) - devm_kfree(nandc->dev, nandc->regs); - -@@ -2053,11 +2559,18 @@ static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc) + if (nandc->regs) + devm_kfree(nandc->dev, nandc->regs); + +@@ -2053,11 +2559,18 @@ static void qcom_nandc_unalloc(struct qc /* one time setup of a few nand controller registers */ static int qcom_nandc_setup(struct qcom_nand_controller *nandc) { + u32 nand_ctrl; + - /* kill onenand */ - nandc_write(nandc, SFLASHC_BURST_CFG, 0); - + /* kill onenand */ + nandc_write(nandc, SFLASHC_BURST_CFG, 0); + - /* enable ADM DMA */ - nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN); + /* enable ADM or BAM DMA */ @@ -1111,12 +1109,9 @@ index 76a0ffc..9d941e3 100644 + nand_ctrl = nandc_read(nandc, NAND_CTRL); + nandc_write(nandc, NAND_CTRL, nand_ctrl | BAM_MODE_EN); + } - - /* save the original values of these registers */ - nandc->cmd1 = nandc_read(nandc, NAND_DEV_CMD1); -diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h -new file mode 100644 -index 0000000..7e87a85 + + /* save the original values of these registers */ + nandc->cmd1 = nandc_read(nandc, NAND_DEV_CMD1); --- /dev/null +++ b/include/linux/dma/qcom_bam_dma.h @@ -0,0 +1,149 @@ @@ -1269,5 +1264,3 @@ index 0000000..7e87a85 + bam_ce->mask = 0xFFFFFFFF; +} +#endif --- -2.7.2 |