From e9aa671f69acb87db4835e4f0b41f5fa16d16562 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 16 Sep 2015 09:05:31 +0200 Subject: [PATCH] mtd: nand: sunxi: improve ->cmd_ctrl() function Try to pack address and command cycles into a single NAND controller command to avoid polling the status register for each single change on the NAND bus. Signed-off-by: Boris Brezillon --- drivers/mtd/nand/sunxi_nand.c | 52 +++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index e4d487cf2ebd..ab572dd5ad3c 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -238,6 +238,10 @@ struct sunxi_nand_chip { u32 timing_cfg; u32 timing_ctl; int selected; + int addr_cycles; + u32 addr[2]; + int cmd_cycles; + u8 cmd[2]; int nsels; struct sunxi_nand_chip_sel sels[0]; }; @@ -525,17 +529,49 @@ static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, writel(tmp, nfc->regs + NFC_REG_CTL); } - if (dat == NAND_CMD_NONE) - return; + if (dat == NAND_CMD_NONE && (ctrl & NAND_NCE) && + !(ctrl & (NAND_CLE | NAND_ALE))) { + u32 cmd = 0; - if (ctrl & NAND_CLE) { - writel(NFC_SEND_CMD1 | dat, nfc->regs + NFC_REG_CMD); - } else { - writel(dat, nfc->regs + NFC_REG_ADDR_LOW); - writel(NFC_SEND_ADR, nfc->regs + NFC_REG_CMD); + if (!sunxi_nand->addr_cycles && !sunxi_nand->cmd_cycles) + return; + + if (sunxi_nand->cmd_cycles--) + cmd |= NFC_SEND_CMD1 | sunxi_nand->cmd[0]; + + if (sunxi_nand->cmd_cycles--) { + cmd |= NFC_SEND_CMD2; + writel(sunxi_nand->cmd[1], + nfc->regs + NFC_REG_RCMD_SET); + } + + sunxi_nand->cmd_cycles = 0; + + if (sunxi_nand->addr_cycles) { + cmd |= NFC_SEND_ADR | + NFC_ADR_NUM(sunxi_nand->addr_cycles); + writel(sunxi_nand->addr[0], + nfc->regs + NFC_REG_ADDR_LOW); + } + + if (sunxi_nand->addr_cycles > 4) + writel(sunxi_nand->addr[1], + nfc->regs + NFC_REG_ADDR_HIGH); + + writel(cmd, nfc->regs + NFC_REG_CMD); + sunxi_nand->addr[0] = 0; + sunxi_nand->addr[1] = 0; + sunxi_nand->addr_cycles = 0; + sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); } - sunxi_nfc_wait_int(nfc, NFC_CMD_INT_FLAG, 0); + if (ctrl & NAND_CLE) { + sunxi_nand->cmd[sunxi_nand->cmd_cycles++] = dat; + } else if (ctrl & NAND_ALE) { + sunxi_nand->addr[sunxi_nand->addr_cycles / 4] |= + dat << ((sunxi_nand->addr_cycles % 4) * 8); + sunxi_nand->addr_cycles++; + } } /* These seed values have been extracted from Allwinner's BSP */ -- 2.30.2