提交 ecfe57b7 编写于 作者: R Rafał Miłecki 提交者: Artem Bityutskiy

mtd: bcm47xxnflash: writing support

Signed-off-by: NRafał Miłecki <zajec5@gmail.com>
Signed-off-by: NArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
上级 d8b1e34e
...@@ -461,13 +461,12 @@ config MTD_NAND_GPMI_NAND ...@@ -461,13 +461,12 @@ config MTD_NAND_GPMI_NAND
the GPMI. the GPMI.
config MTD_NAND_BCM47XXNFLASH config MTD_NAND_BCM47XXNFLASH
tristate "R/O support for NAND flash on BCMA bus" tristate "Support for NAND flash on BCM4706 BCMA bus"
depends on BCMA_NFLASH depends on BCMA_NFLASH
help help
BCMA bus can have various flash memories attached, they are BCMA bus can have various flash memories attached, they are
registered by bcma as platform devices. This enables driver for registered by bcma as platform devices. This enables driver for
NAND flash memories. For now only read mode for BCM4706 is NAND flash memories. For now only BCM4706 is supported.
implemented.
config MTD_NAND_PLATFORM config MTD_NAND_PLATFORM
tristate "Support for generic platform NAND driver" tristate "Support for generic platform NAND driver"
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#define NCTL_CMD0 0x00010000 #define NCTL_CMD0 0x00010000
#define NCTL_CMD1W 0x00080000 #define NCTL_CMD1W 0x00080000
#define NCTL_READ 0x00100000 #define NCTL_READ 0x00100000
#define NCTL_WRITE 0x00200000
#define NCTL_SPECADDR 0x01000000 #define NCTL_SPECADDR 0x01000000
#define NCTL_READY 0x04000000 #define NCTL_READY 0x04000000
#define NCTL_ERR 0x08000000 #define NCTL_ERR 0x08000000
...@@ -132,6 +133,36 @@ static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf, ...@@ -132,6 +133,36 @@ static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
} }
} }
static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
const uint8_t *buf, int len)
{
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
struct bcma_drv_cc *cc = b47n->cc;
u32 ctlcode;
const u32 *data = (u32 *)buf;
int i;
BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
/* Don't validate column using nand_chip->page_shift, it may be bigger
* when accessing OOB */
for (i = 0; i < len; i += 4, data++) {
bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data);
ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE;
if (i == len - 4) /* Last read goes without that */
ctlcode &= ~NCTL_CSA;
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) {
pr_err("%s ctl_cmd didn't work!\n", __func__);
return;
}
}
b47n->curr_column += len;
}
/************************************************** /**************************************************
* NAND chip ops * NAND chip ops
**************************************************/ **************************************************/
...@@ -208,6 +239,36 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd, ...@@ -208,6 +239,36 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
if (page_addr != -1) if (page_addr != -1)
b47n->curr_column += mtd->writesize; b47n->curr_column += mtd->writesize;
break; break;
case NAND_CMD_ERASE1:
bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
b47n->curr_page_addr);
ctlcode = 0x00040000 | NCTL_CMD1W | NCTL_CMD0 |
NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8);
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
pr_err("ERASE1 failed\n");
break;
case NAND_CMD_ERASE2:
break;
case NAND_CMD_SEQIN:
/* Set page and column */
bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR,
b47n->curr_column);
bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
b47n->curr_page_addr);
/* Prepare to write */
ctlcode = 0x40000000 | 0x00040000 | 0x00020000 | 0x00010000;
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 |
NAND_CMD_PAGEPROG))
pr_err("PAGEPROG failed\n");
if (bcm47xxnflash_ops_bcm4706_poll(cc))
pr_err("PAGEPROG not ready\n");
break;
default: default:
pr_err("Command 0x%X unsupported\n", command); pr_err("Command 0x%X unsupported\n", command);
break; break;
...@@ -259,6 +320,21 @@ static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd, ...@@ -259,6 +320,21 @@ static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command); pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
} }
static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd,
const uint8_t *buf, int len)
{
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
switch (b47n->curr_command) {
case NAND_CMD_SEQIN:
bcm47xxnflash_ops_bcm4706_write(mtd, buf, len);
return;
}
pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command);
}
/************************************************** /**************************************************
* Init * Init
**************************************************/ **************************************************/
...@@ -278,6 +354,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n) ...@@ -278,6 +354,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc; b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte; b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf; b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH; b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */ b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册