aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2012-12-03 04:22:35 -0500
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>2012-12-10 07:09:49 -0500
commitecfe57b796d4ccec7ea53783ca18a0ad48ad880b (patch)
treefcf2967b23a721aa05fe89e2723ba502ddc6ca82 /drivers/mtd
parentd8b1e34e248d89f43bab18704894d537dc0b497e (diff)
mtd: bcm47xxnflash: writing support
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/Kconfig5
-rw-r--r--drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c77
2 files changed, 79 insertions, 3 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 3314e92120c9..37ffe56e74a4 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -461,13 +461,12 @@ config MTD_NAND_GPMI_NAND
461 the GPMI. 461 the GPMI.
462 462
463config MTD_NAND_BCM47XXNFLASH 463config 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 depends on BCMA_NFLASH 465 depends on BCMA_NFLASH
466 help 466 help
467 BCMA bus can have various flash memories attached, they are 467 BCMA bus can have various flash memories attached, they are
468 registered by bcma as platform devices. This enables driver for 468 registered by bcma as platform devices. This enables driver for
469 NAND flash memories. For now only read mode for BCM4706 is 469 NAND flash memories. For now only BCM4706 is supported.
470 implemented.
471 470
472config MTD_NAND_PLATFORM 471config MTD_NAND_PLATFORM
473 tristate "Support for generic platform NAND driver" 472 tristate "Support for generic platform NAND driver"
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
index ece343ccc1b0..86c9a79b89b3 100644
--- a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
+++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
@@ -25,6 +25,7 @@
25#define NCTL_CMD0 0x00010000 25#define NCTL_CMD0 0x00010000
26#define NCTL_CMD1W 0x00080000 26#define NCTL_CMD1W 0x00080000
27#define NCTL_READ 0x00100000 27#define NCTL_READ 0x00100000
28#define NCTL_WRITE 0x00200000
28#define NCTL_SPECADDR 0x01000000 29#define NCTL_SPECADDR 0x01000000
29#define NCTL_READY 0x04000000 30#define NCTL_READY 0x04000000
30#define NCTL_ERR 0x08000000 31#define NCTL_ERR 0x08000000
@@ -132,6 +133,36 @@ static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
132 } 133 }
133} 134}
134 135
136static 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 * NAND chip ops 167 * NAND chip ops
137 **************************************************/ 168 **************************************************/
@@ -208,6 +239,36 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
208 if (page_addr != -1) 239 if (page_addr != -1)
209 b47n->curr_column += mtd->writesize; 240 b47n->curr_column += mtd->writesize;
210 break; 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 default: 272 default:
212 pr_err("Command 0x%X unsupported\n", command); 273 pr_err("Command 0x%X unsupported\n", command);
213 break; 274 break;
@@ -259,6 +320,21 @@ static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
259 pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command); 320 pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
260} 321}
261 322
323static 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 * Init 339 * Init
264 **************************************************/ 340 **************************************************/
@@ -278,6 +354,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
278 b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc; 354 b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
279 b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte; 355 b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
280 b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf; 356 b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
357 b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
281 b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH; 358 b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
282 b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */ 359 b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
283 360