|
@@ -238,6 +238,10 @@ struct sunxi_nand_chip {
|
|
u32 timing_cfg;
|
|
u32 timing_cfg;
|
|
u32 timing_ctl;
|
|
u32 timing_ctl;
|
|
int selected;
|
|
int selected;
|
|
|
|
+ int addr_cycles;
|
|
|
|
+ u32 addr[2];
|
|
|
|
+ int cmd_cycles;
|
|
|
|
+ u8 cmd[2];
|
|
int nsels;
|
|
int nsels;
|
|
struct sunxi_nand_chip_sel sels[0];
|
|
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);
|
|
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 */
|
|
/* These seed values have been extracted from Allwinner's BSP */
|