Re: [PATCH 1/2] mtd: rawnand: brcmnand: read/write oob during EDU transfer

2021-03-28 Thread Miquel Raynal
On Thu, 2021-03-11 at 17:09:08 UTC, Kamal Dasu wrote:
> Added support to read/write oob during EDU transfers.
> 
> Signed-off-by: Kamal Dasu 

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git 
nand/next, thanks.

Miquel


[PATCH 1/2] mtd: rawnand: brcmnand: read/write oob during EDU transfer

2021-03-11 Thread Kamal Dasu
Added support to read/write oob during EDU transfers.

Signed-off-by: Kamal Dasu 
---
 drivers/mtd/nand/raw/brcmnand/brcmnand.c | 59 +---
 1 file changed, 52 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c 
b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
index 659eaa6f0980..1c95b21aa63b 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
@@ -242,6 +242,9 @@ struct brcmnand_controller {
u32 edu_ext_addr;
u32 edu_cmd;
u32 edu_config;
+   int sas; /* spare area size, per flash cache */
+   int sector_size_1k;
+   u8  *oob;
 
/* flash_dma reg */
const u16   *flash_dma_offsets;
@@ -249,7 +252,7 @@ struct brcmnand_controller {
dma_addr_t  dma_pa;
 
int (*dma_trans)(struct brcmnand_host *host, u64 addr, u32 *buf,
-u32 len, u8 dma_cmd);
+u8 *oob, u32 len, u8 dma_cmd);
 
/* in-memory cache of the FLASH_CACHE, used only for some commands */
u8  flash_cache[FC_BYTES];
@@ -1479,6 +1482,23 @@ static irqreturn_t brcmnand_edu_irq(int irq, void *data)
edu_writel(ctrl, EDU_EXT_ADDR, ctrl->edu_ext_addr);
edu_readl(ctrl, EDU_EXT_ADDR);
 
+   if (ctrl->oob) {
+   if (ctrl->edu_cmd == EDU_CMD_READ) {
+   ctrl->oob += read_oob_from_regs(ctrl,
+   ctrl->edu_count + 1,
+   ctrl->oob, ctrl->sas,
+   ctrl->sector_size_1k);
+   } else {
+   brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
+  ctrl->edu_ext_addr);
+   brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+   ctrl->oob += write_oob_to_regs(ctrl,
+  ctrl->edu_count,
+  ctrl->oob, 
ctrl->sas,
+  
ctrl->sector_size_1k);
+   }
+   }
+
mb(); /* flush previous writes */
edu_writel(ctrl, EDU_CMD, ctrl->edu_cmd);
edu_readl(ctrl, EDU_CMD);
@@ -1850,9 +1870,10 @@ static void brcmnand_write_buf(struct nand_chip *chip, 
const uint8_t *buf,
  *  Kick EDU engine
  */
 static int brcmnand_edu_trans(struct brcmnand_host *host, u64 addr, u32 *buf,
- u32 len, u8 cmd)
+ u8 *oob, u32 len, u8 cmd)
 {
struct brcmnand_controller *ctrl = host->ctrl;
+   struct brcmnand_cfg *cfg = &host->hwcfg;
unsigned long timeo = msecs_to_jiffies(200);
int ret = 0;
int dir = (cmd == CMD_PAGE_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
@@ -1860,6 +1881,9 @@ static int brcmnand_edu_trans(struct brcmnand_host *host, 
u64 addr, u32 *buf,
unsigned int trans = len >> FC_SHIFT;
dma_addr_t pa;
 
+   dev_dbg(ctrl->dev, "EDU %s %p:%p\n", ((edu_cmd == EDU_CMD_READ) ?
+ "read" : "write"), buf, oob);
+
pa = dma_map_single(ctrl->dev, buf, len, dir);
if (dma_mapping_error(ctrl->dev, pa)) {
dev_err(ctrl->dev, "unable to map buffer for EDU DMA\n");
@@ -1871,6 +1895,8 @@ static int brcmnand_edu_trans(struct brcmnand_host *host, 
u64 addr, u32 *buf,
ctrl->edu_ext_addr = addr;
ctrl->edu_cmd = edu_cmd;
ctrl->edu_count = trans;
+   ctrl->sas = cfg->spare_area_size;
+   ctrl->oob = oob;
 
edu_writel(ctrl, EDU_DRAM_ADDR, (u32)ctrl->edu_dram_addr);
edu_readl(ctrl,  EDU_DRAM_ADDR);
@@ -1879,6 +1905,16 @@ static int brcmnand_edu_trans(struct brcmnand_host 
*host, u64 addr, u32 *buf,
edu_writel(ctrl, EDU_LENGTH, FC_BYTES);
edu_readl(ctrl, EDU_LENGTH);
 
+   if (ctrl->oob && (ctrl->edu_cmd == EDU_CMD_WRITE)) {
+   brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
+  ctrl->edu_ext_addr);
+   brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+   ctrl->oob += write_oob_to_regs(ctrl,
+  1,
+  ctrl->oob, ctrl->sas,
+  ctrl->sector_size_1k);
+   }
+
/* Start edu engine */
mb(); /* flush previous writes */
edu_writel(ctrl, EDU_CMD, ctrl->edu_cmd);
@@ -1893,6 +1929,14 @@ static int brcmnand_edu_trans(struct brcmnand_host 
*host, u64 addr, u32 *buf,