On Tue, 6 Nov 2018 18:00:37 +0800
Liang Yang <liang.yang@xxxxxxxxxxx> wrote:
On 2018/11/6 17:28, Boris Brezillon wrote:
On Tue, 6 Nov 2018 17:08:00 +0800ok, i will try dma here.
Liang Yang <liang.yang@xxxxxxxxxxx> wrote:
On 2018/11/5 23:53, Boris Brezillon wrote:
On Fri, 2 Nov 2018 00:42:21 +0800Register 'NFC_REG_BUF' can holds only 4 bytes, also DRD sends only one
Jianxin Pan <jianxin.pan@xxxxxxxxxxx> wrote:
+
+static inline u8 meson_nfc_read_byte(struct mtd_info *mtd)
+{
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct meson_nfc *nfc = nand_get_controller_data(nand);
+ u32 cmd;
+
+ cmd = nfc->param.chip_select | NFC_CMD_DRD | 0;
+ writel(cmd, nfc->reg_base + NFC_REG_CMD);
+
+ meson_nfc_drain_cmd(nfc);
You probably don't want to drain the FIFO every time you read a byte on
the bus, and I guess the INPUT FIFO is at least as big as the CMD
FIFO, right? If that's the case, you should queue as much DRD cmd as
possible and only sync when the user explicitly requests it or when
the INPUT/READ FIFO is full.
nand cycle to read one byte and covers the 1st byte every time reading.
i think nfc controller is faster than nand cycle, but really it is not
high efficiency when reading so many bytes once.
Or use dma command here like read_page and read_page_raw.
Yep, that's also an alternative, though you'll have to make sure the
buffer passed through the nand_op_inst is DMA-safe, and use a bounce
buffer when that's not the case.
We should probably expose the bounce buf handling as generic helpers at
the rawnand level:
void *nand_op_get_dma_safe_input_buf(struct nand_op_instr *instr)
{
void *buf;
if (WARN_ON(instr->type != NAND_OP_DATA_IN_INSTR))
return NULL;
if (virt_addr_valid(instr->data.in) &&
!object_is_on_stack(instr->data.buf.in))
return instr->data.buf.in;
return kzalloc(instr->data.len, GFP_KERNEL);
}
void nand_op_put_dma_safe_input_buf(struct nand_op_instr *instr,
void *buf)
{
if (WARN_ON(instr->type != NAND_OP_DATA_IN_INSTR) ||
WARN_ON(!buf))
return;
if (buf == instr->data.buf.in)
return;
memcpy(instr->data.buf.in, buf, instr->data.len);
kfree(buf);
}
const void *nand_op_get_dma_safe_output_buf(struct nand_op_instr *instr)
{
void *buf;
if (WARN_ON(instr->type != NAND_OP_DATA_OUT_INSTR))
return NULL;
if (virt_addr_valid(instr->data.out) &&
!object_is_on_stack(instr->data.buf.out))
return instr->data.buf.out;
return kmemdup(instr->data.buf.out, GFP_KERNEL);
}
void nand_op_put_dma_safe_output_buf(struct nand_op_instr *instr,
void *buf)
{
if (WARN_ON(instr->type != NAND_OP_DATA_OUT_INSTR) ||
WARN_ON(!buf))
return;
if (buf != instr->data.buf.out)
kfree(buf);
}
em, i got the point. indeed, until dma is checked done, nfc will execute next command in the command queue. so i will consider it.concatenated with the command fifo, there is no other status to check
Isn't the controller engine able to wait on the data transfer to be
complete before sending the next instruction in the CMD FIFO pipe?
I'm pretty sure it's able to do that, which would make
meson_nfc_wait_dma_finish() useless, and all you'd have to do is wait
for the CMD FIFO to be empty (assuming it guarantees the last command
has been executed).
Maybe the nfc design is difference. dedicated nfc dma engine is
whether dma is done.
No, I mean that internally a "DMA-transfer" instruction probably
forces the NAND controller to wait for the DMA transfer to be finished
before dequeuing/executing the next instruction. So, it should be safe
to queue the PROG and WAIT_RB instructions and just rely on the "FIFO
empty" event to consider the operation as finished. Then, all you'll
have to do is check the status reg to determine whether the
write operation succeeded or not.
.