@ -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 @@
@ -138,19 +136,19 @@ index 76a0ffc..9d941e3 100644
+ * @bam_desc_data - used for bam desc mappings
+ */
struct desc_info {
struct list_head node;
struct list_head node;
enum dma_data_direction dir;
struct scatterlist sgl;
struct dma_async_tx_descriptor *dma_desc;
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 orig_vld;
__le32 ecc_buf_cfg;
__le32 ecc_buf_cfg;
+ __le32 read_location0;
+ __le32 read_location1;
+ __le32 read_location2;
@ -171,14 +169,14 @@ 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 */
@ -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)
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;
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;
} 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;
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,24 +371,24 @@ 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,21 +399,21 @@ 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)
@ -427,11 +425,11 @@ 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_CMD1_RESTORE)
first = NAND_DEV_CMD1;
if (first == NAND_DEV_CMD_VLD_RESTORE)
first = NAND_DEV_CMD_VLD;
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);
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,
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,10 +466,10 @@ 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)
{
@ -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);
+
@ -535,7 +533,7 @@ index 76a0ffc..9d941e3 100644
}
/*
@@ -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)
{
@ -563,19 +561,19 @@ index 76a0ffc..9d941e3 100644
}
/*
@@ -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)
/*
* 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_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) |
@ -586,36 +584,36 @@ index 76a0ffc..9d941e3 100644
+ 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);
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,
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);
@ -625,29 +623,29 @@ index 76a0ffc..9d941e3 100644
+ 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);
@ -657,27 +655,28 @@ index 76a0ffc..9d941e3 100644
- 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;
+
@ -755,8 +753,8 @@ index 76a0ffc..9d941e3 100644
+ 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;
@ -771,12 +769,12 @@ index 76a0ffc..9d941e3 100644
+ return -ETIMEDOUT;
+ }
return 0;
return 0;
}
@@ -817,7 +1225,16 @@ static void free_descs(struct qcom_nand_controller *nandc)
@@ -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);
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,22 +786,22 @@ 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) {
@ -833,69 +831,69 @@ index 76a0ffc..9d941e3 100644
+ 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;
/*
* 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,
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)
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);
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;
data_buf = buf;
oob_buf = chip->oob_poi;
host->use_ecc = false;
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) {
@ -930,177 +928,177 @@ index 76a0ffc..9d941e3 100644
- 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;
}
oob_buf += oob_size2;
}
@@ -1306,6 +1790,7 @@ static int qcom_nandc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
int ret;
@@ -1306,6 +1790,7 @@ static int qcom_nandc_read_oob(struct mt
int ret;
clear_read_regs(nandc);
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;
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_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,
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);
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;
/*
* 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,
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;
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_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,
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);
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;
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,
config_cw_write_post(nandc);
@@ -1467,6 +1958,7 @@ static int qcom_nandc_write_oob(struct m
host->use_ecc = true;
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,
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,
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);
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;
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;
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_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);
/*
* 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);
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);
config_cw_write_post(nandc);
ret = submit_descs(nandc);
@@ -1930,6 +2425,8 @@ static int qcom_nand_host_setup(struct qcom_nand_host *host)
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;
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);
if (nandc->regs)
devm_kfree(nandc->dev, nandc->regs);
@@ -2053,11 +2559,18 @@ static void qcom_nandc_unalloc(struct qcom_nand_controller *nandc)
@@ -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);
@ -1112,11 +1110,8 @@ index 76a0ffc..9d941e3 100644
+ 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