aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/atmel_nand.c84
1 files changed, 62 insertions, 22 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 459acf01fefe..e321c564ff05 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -97,7 +97,9 @@ struct atmel_nfc {
97 bool write_by_sram; 97 bool write_by_sram;
98 98
99 bool is_initialized; 99 bool is_initialized;
100 struct completion comp_nfc; 100 struct completion comp_ready;
101 struct completion comp_cmd_done;
102 struct completion comp_xfer_done;
101 103
102 /* Point to the sram bank which include readed data via NFC */ 104 /* Point to the sram bank which include readed data via NFC */
103 void __iomem *data_in_sram; 105 void __iomem *data_in_sram;
@@ -1596,44 +1598,80 @@ static irqreturn_t hsmc_interrupt(int irq, void *dev_id)
1596{ 1598{
1597 struct atmel_nand_host *host = dev_id; 1599 struct atmel_nand_host *host = dev_id;
1598 u32 status, mask, pending; 1600 u32 status, mask, pending;
1599 irqreturn_t ret = IRQ_HANDLED; 1601 irqreturn_t ret = IRQ_NONE;
1600 1602
1601 status = nfc_read_status(host); 1603 status = nfc_read_status(host);
1602 mask = nfc_readl(host->nfc->hsmc_regs, IMR); 1604 mask = nfc_readl(host->nfc->hsmc_regs, IMR);
1603 pending = status & mask; 1605 pending = status & mask;
1604 1606
1605 if (pending & NFC_SR_XFR_DONE) { 1607 if (pending & NFC_SR_XFR_DONE) {
1606 complete(&host->nfc->comp_nfc); 1608 complete(&host->nfc->comp_xfer_done);
1607 nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE); 1609 nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE);
1608 } else if (pending & NFC_SR_RB_EDGE) { 1610 ret = IRQ_HANDLED;
1609 complete(&host->nfc->comp_nfc); 1611 }
1612 if (pending & NFC_SR_RB_EDGE) {
1613 complete(&host->nfc->comp_ready);
1610 nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE); 1614 nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE);
1611 } else if (pending & NFC_SR_CMD_DONE) { 1615 ret = IRQ_HANDLED;
1612 complete(&host->nfc->comp_nfc); 1616 }
1617 if (pending & NFC_SR_CMD_DONE) {
1618 complete(&host->nfc->comp_cmd_done);
1613 nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_CMD_DONE); 1619 nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_CMD_DONE);
1614 } else { 1620 ret = IRQ_HANDLED;
1615 ret = IRQ_NONE;
1616 } 1621 }
1617 1622
1618 return ret; 1623 return ret;
1619} 1624}
1620 1625
1621/* NFC(Nand Flash Controller) related functions */ 1626/* NFC(Nand Flash Controller) related functions */
1622static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag) 1627static void nfc_prepare_interrupt(struct atmel_nand_host *host, u32 flag)
1623{ 1628{
1624 unsigned long timeout; 1629 if (flag & NFC_SR_XFR_DONE)
1625 init_completion(&host->nfc->comp_nfc); 1630 init_completion(&host->nfc->comp_xfer_done);
1631
1632 if (flag & NFC_SR_RB_EDGE)
1633 init_completion(&host->nfc->comp_ready);
1634
1635 if (flag & NFC_SR_CMD_DONE)
1636 init_completion(&host->nfc->comp_cmd_done);
1626 1637
1627 /* Enable interrupt that need to wait for */ 1638 /* Enable interrupt that need to wait for */
1628 nfc_writel(host->nfc->hsmc_regs, IER, flag); 1639 nfc_writel(host->nfc->hsmc_regs, IER, flag);
1640}
1629 1641
1630 timeout = wait_for_completion_timeout(&host->nfc->comp_nfc, 1642static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
1631 msecs_to_jiffies(NFC_TIME_OUT_MS)); 1643{
1632 if (timeout) 1644 int i, index = 0;
1633 return 0; 1645 struct completion *comp[3]; /* Support 3 interrupt completion */
1646
1647 if (flag & NFC_SR_XFR_DONE)
1648 comp[index++] = &host->nfc->comp_xfer_done;
1649
1650 if (flag & NFC_SR_RB_EDGE)
1651 comp[index++] = &host->nfc->comp_ready;
1634 1652
1635 /* Time out to wait for the interrupt */ 1653 if (flag & NFC_SR_CMD_DONE)
1654 comp[index++] = &host->nfc->comp_cmd_done;
1655
1656 if (index == 0) {
1657 dev_err(host->dev, "Unkown interrupt flag: 0x%08x\n", flag);
1658 return -EINVAL;
1659 }
1660
1661 for (i = 0; i < index; i++) {
1662 if (wait_for_completion_timeout(comp[i],
1663 msecs_to_jiffies(NFC_TIME_OUT_MS)))
1664 continue; /* wait for next completion */
1665 else
1666 goto err_timeout;
1667 }
1668
1669 return 0;
1670
1671err_timeout:
1636 dev_err(host->dev, "Time out to wait for interrupt: 0x%08x\n", flag); 1672 dev_err(host->dev, "Time out to wait for interrupt: 0x%08x\n", flag);
1673 /* Disable the interrupt as it is not handled by interrupt handler */
1674 nfc_writel(host->nfc->hsmc_regs, IDR, flag);
1637 return -ETIMEDOUT; 1675 return -ETIMEDOUT;
1638} 1676}
1639 1677
@@ -1641,6 +1679,9 @@ static int nfc_send_command(struct atmel_nand_host *host,
1641 unsigned int cmd, unsigned int addr, unsigned char cycle0) 1679 unsigned int cmd, unsigned int addr, unsigned char cycle0)
1642{ 1680{
1643 unsigned long timeout; 1681 unsigned long timeout;
1682 u32 flag = NFC_SR_CMD_DONE;
1683 flag |= cmd & NFCADDR_CMD_DATAEN ? NFC_SR_XFR_DONE : 0;
1684
1644 dev_dbg(host->dev, 1685 dev_dbg(host->dev,
1645 "nfc_cmd: 0x%08x, addr1234: 0x%08x, cycle0: 0x%02x\n", 1686 "nfc_cmd: 0x%08x, addr1234: 0x%08x, cycle0: 0x%02x\n",
1646 cmd, addr, cycle0); 1687 cmd, addr, cycle0);
@@ -1654,9 +1695,11 @@ static int nfc_send_command(struct atmel_nand_host *host,
1654 return -ETIMEDOUT; 1695 return -ETIMEDOUT;
1655 } 1696 }
1656 } 1697 }
1698
1699 nfc_prepare_interrupt(host, flag);
1657 nfc_writel(host->nfc->hsmc_regs, CYCLE0, cycle0); 1700 nfc_writel(host->nfc->hsmc_regs, CYCLE0, cycle0);
1658 nfc_cmd_addr1234_writel(cmd, addr, host->nfc->base_cmd_regs); 1701 nfc_cmd_addr1234_writel(cmd, addr, host->nfc->base_cmd_regs);
1659 return nfc_wait_interrupt(host, NFC_SR_CMD_DONE); 1702 return nfc_wait_interrupt(host, flag);
1660} 1703}
1661 1704
1662static int nfc_device_ready(struct mtd_info *mtd) 1705static int nfc_device_ready(struct mtd_info *mtd)
@@ -1822,10 +1865,6 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
1822 nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr; 1865 nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr;
1823 nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0); 1866 nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0);
1824 1867
1825 if (dataen == NFCADDR_CMD_DATAEN)
1826 if (nfc_wait_interrupt(host, NFC_SR_XFR_DONE))
1827 dev_err(host->dev, "something wrong, No XFR_DONE interrupt comes.\n");
1828
1829 /* 1868 /*
1830 * Program and erase have their own busy handlers status, sequential 1869 * Program and erase have their own busy handlers status, sequential
1831 * in, and deplete1 need no delay. 1870 * in, and deplete1 need no delay.
@@ -1850,6 +1889,7 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
1850 } 1889 }
1851 /* fall through */ 1890 /* fall through */
1852 default: 1891 default:
1892 nfc_prepare_interrupt(host, NFC_SR_RB_EDGE);
1853 nfc_wait_interrupt(host, NFC_SR_RB_EDGE); 1893 nfc_wait_interrupt(host, NFC_SR_RB_EDGE);
1854 } 1894 }
1855} 1895}