aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/bcm47xxnflash
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/nand/bcm47xxnflash
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/nand/bcm47xxnflash')
-rw-r--r--drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c77
1 files changed, 77 insertions, 0 deletions
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