Re: [PATCH v3 15/20] mtd: nand: qcom: support for command descriptor formation

2017-08-09 Thread Abhishek Sahu

On 2017-08-05 21:49, Abhishek Sahu wrote:

1. Add the function for command descriptor preparation which will
   be used only by BAM DMA and it will form the DMA descriptors
   containing command elements
2. DMA_PREP_CMD flag should be used for forming command DMA
   descriptors

Signed-off-by: Abhishek Sahu 


 This patch has build dependency on
 http://www.spinics.net/lists/dmaengine/msg13665.html


---
 drivers/mtd/nand/qcom_nandc.c | 108 
+++---

 1 file changed, 92 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c 
b/drivers/mtd/nand/qcom_nandc.c

index 9c12404..16463ac 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -196,6 +196,14 @@
  ((size) << READ_LOCATION_SIZE) |\
  ((is_last) << READ_LOCATION_LAST))

+/* Returns the NAND register physical address */
+#define nandc_reg_phys(chip, offset) ((chip)->base_phys + (offset))
+
+/* Returns the dma address for reg read buffer */
+#define reg_buf_dma_addr(chip, vaddr) \
+   ((chip)->reg_read_dma + \
+   ((uint8_t *)(vaddr) - (uint8_t *)(chip)->reg_read_buf))
+
 /* Returns the actual register address for NAND_FLASH_DEV_* */
 #define nandc_dev_addr(nandc, reg) ((nandc)->props->flash_dev_offset + 
(reg))


@@ -313,7 +321,8 @@ struct nandc_regs {
  * controller
  * @dev:   parent device
  * @base:  MMIO base
- * @base_dma:  physical base address of controller registers
+ * @base_phys: physical base address of controller registers
+ * @base_dma:  dma base address of controller registers
  * @core_clk:  controller clock
  * @aon_clk:   another controller clock
  *
@@ -346,6 +355,7 @@ struct qcom_nand_controller {
struct device *dev;

void __iomem *base;
+   phys_addr_t base_phys;
dma_addr_t base_dma;

struct clk *core_clk;
@@ -747,6 +757,66 @@ static int prepare_bam_async_desc(struct
qcom_nand_controller *nandc,
 }

 /*
+ * 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)
+{
+   int bam_ce_size;
+   int i, ret;
+   struct bam_cmd_element *bam_ce_buffer;
+   struct bam_transaction *bam_txn = nandc->bam_txn;
+
+   bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos];
+
+   /* fill the command desc */
+   for (i = 0; i < size; i++) {
+   if (read)
+   bam_prep_ce(&bam_ce_buffer[i],
+   nandc_reg_phys(nandc, reg_off + 4 * i),
+   BAM_READ_COMMAND,
+   reg_buf_dma_addr(nandc,
+(__le32 *)vaddr + i));
+   else
+   bam_prep_ce_le32(&bam_ce_buffer[i],
+nandc_reg_phys(nandc, reg_off + 4 * i),
+BAM_WRITE_COMMAND,
+*((__le32 *)vaddr + i));
+   }
+
+   bam_txn->bam_ce_pos += size;
+
+   /* use the separate sgl after this command */
+   if (flags & NAND_BAM_NEXT_SGL) {
+   bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start];
+   bam_ce_size = (bam_txn->bam_ce_pos -
+   bam_txn->bam_ce_start) *
+   sizeof(struct bam_cmd_element);
+   sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos],
+  bam_ce_buffer, bam_ce_size);
+   bam_txn->cmd_sgl_pos++;
+   bam_txn->bam_ce_start = bam_txn->bam_ce_pos;
+
+   if (flags & NAND_BAM_NWD) {
+   ret = prepare_bam_async_desc(nandc, nandc->cmd_chan,
+DMA_PREP_FENCE |
+DMA_PREP_CMD);
+   if (ret)
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
+/*
  * Prepares the data descriptor for BAM DMA which will be used for 
NAND

  * data reads and writes.
  */
@@ -863,19 +933,22 @@ static int read_reg_dma(struct
qcom_nand_controller *nandc, int first,
 {
bool flow_control = false;
   

[PATCH v3 15/20] mtd: nand: qcom: support for command descriptor formation

2017-08-05 Thread Abhishek Sahu
1. Add the function for command descriptor preparation which will
   be used only by BAM DMA and it will form the DMA descriptors
   containing command elements
2. DMA_PREP_CMD flag should be used for forming command DMA
   descriptors

Signed-off-by: Abhishek Sahu 
---
 drivers/mtd/nand/qcom_nandc.c | 108 +++---
 1 file changed, 92 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 9c12404..16463ac 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -196,6 +196,14 @@
  ((size) << READ_LOCATION_SIZE) |  \
  ((is_last) << READ_LOCATION_LAST))
 
+/* Returns the NAND register physical address */
+#define nandc_reg_phys(chip, offset) ((chip)->base_phys + (offset))
+
+/* Returns the dma address for reg read buffer */
+#define reg_buf_dma_addr(chip, vaddr) \
+   ((chip)->reg_read_dma + \
+   ((uint8_t *)(vaddr) - (uint8_t *)(chip)->reg_read_buf))
+
 /* Returns the actual register address for NAND_FLASH_DEV_* */
 #define nandc_dev_addr(nandc, reg) ((nandc)->props->flash_dev_offset + (reg))
 
@@ -313,7 +321,8 @@ struct nandc_regs {
  * controller
  * @dev:   parent device
  * @base:  MMIO base
- * @base_dma:  physical base address of controller registers
+ * @base_phys: physical base address of controller registers
+ * @base_dma:  dma base address of controller registers
  * @core_clk:  controller clock
  * @aon_clk:   another controller clock
  *
@@ -346,6 +355,7 @@ struct qcom_nand_controller {
struct device *dev;
 
void __iomem *base;
+   phys_addr_t base_phys;
dma_addr_t base_dma;
 
struct clk *core_clk;
@@ -747,6 +757,66 @@ static int prepare_bam_async_desc(struct 
qcom_nand_controller *nandc,
 }
 
 /*
+ * 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)
+{
+   int bam_ce_size;
+   int i, ret;
+   struct bam_cmd_element *bam_ce_buffer;
+   struct bam_transaction *bam_txn = nandc->bam_txn;
+
+   bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos];
+
+   /* fill the command desc */
+   for (i = 0; i < size; i++) {
+   if (read)
+   bam_prep_ce(&bam_ce_buffer[i],
+   nandc_reg_phys(nandc, reg_off + 4 * i),
+   BAM_READ_COMMAND,
+   reg_buf_dma_addr(nandc,
+(__le32 *)vaddr + i));
+   else
+   bam_prep_ce_le32(&bam_ce_buffer[i],
+nandc_reg_phys(nandc, reg_off + 4 * i),
+BAM_WRITE_COMMAND,
+*((__le32 *)vaddr + i));
+   }
+
+   bam_txn->bam_ce_pos += size;
+
+   /* use the separate sgl after this command */
+   if (flags & NAND_BAM_NEXT_SGL) {
+   bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start];
+   bam_ce_size = (bam_txn->bam_ce_pos -
+   bam_txn->bam_ce_start) *
+   sizeof(struct bam_cmd_element);
+   sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos],
+  bam_ce_buffer, bam_ce_size);
+   bam_txn->cmd_sgl_pos++;
+   bam_txn->bam_ce_start = bam_txn->bam_ce_pos;
+
+   if (flags & NAND_BAM_NWD) {
+   ret = prepare_bam_async_desc(nandc, nandc->cmd_chan,
+DMA_PREP_FENCE |
+DMA_PREP_CMD);
+   if (ret)
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
+/*
  * Prepares the data descriptor for BAM DMA which will be used for NAND
  * data reads and writes.
  */
@@ -863,19 +933,22 @@ static int read_reg_dma(struct qcom_nand_controller 
*nandc, int first,
 {
bool flow_control = false;
void *vaddr;
-   int size;
 
-   if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
-   flow_control = true;
+