Merge branches 'pm-domains' and 'pm-cpufreq'
[firefly-linux-kernel-4.4.55.git] / drivers / mtd / nand / bcm47xxnflash / ops_bcm4706.c
index 1ea5e77facd747be9d76674a87a26b18ce2836ef..592befc7ffa1229cb121452e20c64a78f4dec903 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <linux/bcma/bcma.h>
 
 /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
@@ -23,6 +24,8 @@
 #define NFLASH_SECTOR_SIZE             512
 
 #define NCTL_CMD0                      0x00010000
+#define NCTL_COL                       0x00020000      /* Update column with value from BCMA_CC_NFLASH_COL_ADDR */
+#define NCTL_ROW                       0x00040000      /* Update row (page) with value from BCMA_CC_NFLASH_ROW_ADDR */
 #define NCTL_CMD1W                     0x00080000
 #define NCTL_READ                      0x00100000
 #define NCTL_WRITE                     0x00200000
@@ -109,7 +112,7 @@ static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
                                b47n->curr_page_addr);
 
                /* Prepare to read */
-               ctlcode = NCTL_CSA | NCTL_CMD1W | 0x00040000 | 0x00020000 |
+               ctlcode = NCTL_CSA | NCTL_CMD1W | NCTL_ROW | NCTL_COL |
                          NCTL_CMD0;
                ctlcode |= NAND_CMD_READSTART << 8;
                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode))
@@ -167,6 +170,26 @@ static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
  * NAND chip ops
  **************************************************/
 
+static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd,
+                                              unsigned int ctrl)
+{
+       struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
+       struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
+       u32 code = 0;
+
+       if (cmd == NAND_CMD_NONE)
+               return;
+
+       if (cmd & NAND_CTRL_CLE)
+               code = cmd | NCTL_CMD0;
+
+       /* nCS is not needed for reset command */
+       if (cmd != NAND_CMD_RESET)
+               code |= NCTL_CSA;
+
+       bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, code);
+}
+
 /* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
 static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
                                                  int chip)
@@ -206,7 +229,10 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
 
        switch (command) {
        case NAND_CMD_RESET:
-               pr_warn("Chip reset not implemented yet\n");
+               nand_chip->cmd_ctrl(mtd, command, NAND_CTRL_CLE);
+
+               ndelay(100);
+               nand_wait_ready(mtd);
                break;
        case NAND_CMD_READID:
                ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0;
@@ -250,7 +276,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
        case NAND_CMD_ERASE1:
                bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
                                b47n->curr_page_addr);
-               ctlcode = 0x00040000 | NCTL_CMD1W | NCTL_CMD0 |
+               ctlcode = NCTL_ROW | NCTL_CMD1W | NCTL_CMD0 |
                          NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8);
                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
                        pr_err("ERASE1 failed\n");
@@ -265,13 +291,13 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
                                b47n->curr_page_addr);
 
                /* Prepare to write */
-               ctlcode = 0x40000000 | 0x00040000 | 0x00020000 | 0x00010000;
+               ctlcode = 0x40000000 | NCTL_ROW | NCTL_COL | NCTL_CMD0;
                ctlcode |= NAND_CMD_SEQIN;
                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
                        pr_err("SEQIN failed\n");
                break;
        case NAND_CMD_PAGEPROG:
-               if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, 0x00010000 |
+               if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_CMD0 |
                                                          NAND_CMD_PAGEPROG))
                        pr_err("PAGEPROG failed\n");
                if (bcm47xxnflash_ops_bcm4706_poll(cc))
@@ -360,6 +386,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
        u32 val;
 
        b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
+       nand_chip->cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl;
        nand_chip->dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready;
        b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
        b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;