Commit ecfe57b796d4ccec7ea53783ca18a0ad48ad880b

Authored by Rafał Miłecki
Committed by Artem Bityutskiy
1 parent d8b1e34e24

mtd: bcm47xxnflash: writing support

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>

Showing 2 changed files with 79 additions and 3 deletions Side-by-side Diff

drivers/mtd/nand/Kconfig
... ... @@ -461,13 +461,12 @@
461 461 the GPMI.
462 462  
463 463 config MTD_NAND_BCM47XXNFLASH
464   - tristate "R/O support for NAND flash on BCMA bus"
  464 + tristate "Support for NAND flash on BCM4706 BCMA bus"
465 465 depends on BCMA_NFLASH
466 466 help
467 467 BCMA bus can have various flash memories attached, they are
468 468 registered by bcma as platform devices. This enables driver for
469   - NAND flash memories. For now only read mode for BCM4706 is
470   - implemented.
  469 + NAND flash memories. For now only BCM4706 is supported.
471 470  
472 471 config MTD_NAND_PLATFORM
473 472 tristate "Support for generic platform NAND driver"
drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
... ... @@ -25,6 +25,7 @@
25 25 #define NCTL_CMD0 0x00010000
26 26 #define NCTL_CMD1W 0x00080000
27 27 #define NCTL_READ 0x00100000
  28 +#define NCTL_WRITE 0x00200000
28 29 #define NCTL_SPECADDR 0x01000000
29 30 #define NCTL_READY 0x04000000
30 31 #define NCTL_ERR 0x08000000
... ... @@ -132,6 +133,36 @@
132 133 }
133 134 }
134 135  
  136 +static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
  137 + const uint8_t *buf, int len)
  138 +{
  139 + struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
  140 + struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
  141 + struct bcma_drv_cc *cc = b47n->cc;
  142 +
  143 + u32 ctlcode;
  144 + const u32 *data = (u32 *)buf;
  145 + int i;
  146 +
  147 + BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
  148 + /* Don't validate column using nand_chip->page_shift, it may be bigger
  149 + * when accessing OOB */
  150 +
  151 + for (i = 0; i < len; i += 4, data++) {
  152 + bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data);
  153 +
  154 + ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE;
  155 + if (i == len - 4) /* Last read goes without that */
  156 + ctlcode &= ~NCTL_CSA;
  157 + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) {
  158 + pr_err("%s ctl_cmd didn't work!\n", __func__);
  159 + return;
  160 + }
  161 + }
  162 +
  163 + b47n->curr_column += len;
  164 +}
  165 +
135 166 /**************************************************
136 167 * NAND chip ops
137 168 **************************************************/
... ... @@ -208,6 +239,36 @@
208 239 if (page_addr != -1)
209 240 b47n->curr_column += mtd->writesize;
210 241 break;
  242 + case NAND_CMD_ERASE1:
  243 + bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
  244 + b47n->curr_page_addr);
  245 + ctlcode = 0x00040000 | NCTL_CMD1W | NCTL_CMD0 |
  246 + NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8);
  247 + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
  248 + pr_err("ERASE1 failed\n");
  249 + break;
  250 + case NAND_CMD_ERASE2:
  251 + break;
  252 + case NAND_CMD_SEQIN:
  253 + /* Set page and column */
  254 + bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR,
  255 + b47n->curr_column);
  256 + bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
  257 + b47n->curr_page_addr);
  258 +
  259 + /* Prepare to write */
  260 + ctlcode = 0x40000000 | 0x00040000 | 0x00020000 | 0x00010000;
  261 + ctlcode |= NAND_CMD_SEQIN;
  262 + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
  263 + pr_err("SEQIN failed\n");
  264 + break;
  265 + case NAND_CMD_PAGEPROG:
  266 + if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, 0x00010000 |
  267 + NAND_CMD_PAGEPROG))
  268 + pr_err("PAGEPROG failed\n");
  269 + if (bcm47xxnflash_ops_bcm4706_poll(cc))
  270 + pr_err("PAGEPROG not ready\n");
  271 + break;
211 272 default:
212 273 pr_err("Command 0x%X unsupported\n", command);
213 274 break;
... ... @@ -259,6 +320,21 @@
259 320 pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
260 321 }
261 322  
  323 +static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd,
  324 + const uint8_t *buf, int len)
  325 +{
  326 + struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
  327 + struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
  328 +
  329 + switch (b47n->curr_command) {
  330 + case NAND_CMD_SEQIN:
  331 + bcm47xxnflash_ops_bcm4706_write(mtd, buf, len);
  332 + return;
  333 + }
  334 +
  335 + pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command);
  336 +}
  337 +
262 338 /**************************************************
263 339 * Init
264 340 **************************************************/
... ... @@ -278,6 +354,7 @@
278 354 b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
279 355 b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
280 356 b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
  357 + b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
281 358 b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
282 359 b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
283 360