1 --- a/drivers/mtd/nand/Kconfig
2 +++ b/drivers/mtd/nand/Kconfig
3 @@ -536,4 +536,12 @@ config MTD_NAND_FSMC
4 Enables support for NAND Flash chips on the ST Microelectronics
5 Flexible Static Memory Controller (FSMC)
7 +config MTD_NAND_BCM47XX
8 + tristate "bcm47xx nand flash support"
10 + depends on BCM47XX && BCMA_NFLASH
11 + select MTD_PARTITIONS
13 + Support for bcm47xx nand flash
16 --- a/drivers/mtd/nand/Makefile
17 +++ b/drivers/mtd/nand/Makefile
18 @@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mp
19 obj-$(CONFIG_MTD_NAND_RICOH) += r852.o
20 obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
21 obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/
22 +obj-$(CONFIG_MTD_NAND_BCM47XX) += bcm47xx_nand.o
24 nand-objs := nand_base.o nand_bbt.o
26 +++ b/drivers/mtd/nand/bcm47xx_nand.c
29 + * BCMA nand flash interface
31 + * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
32 + * Copyright 2010, Broadcom Corporation
34 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
35 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
36 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
37 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
41 +#define pr_fmt(fmt) "bcm47xx_nflash: " fmt
42 +#include <linux/module.h>
43 +#include <linux/slab.h>
44 +#include <linux/ioport.h>
45 +#include <linux/sched.h>
46 +#include <linux/mtd/mtd.h>
47 +#include <linux/mtd/map.h>
48 +#include <linux/mtd/partitions.h>
49 +#include <linux/errno.h>
50 +#include <linux/delay.h>
51 +#include <linux/platform_device.h>
53 +#include <linux/cramfs_fs.h>
54 +#include <linux/romfs_fs.h>
55 +#include <linux/magic.h>
56 +#include <linux/byteorder/generic.h>
57 +#include <linux/mtd/bcm47xx_nand.h>
58 +#include <linux/mtd/nand.h>
60 +static int bcm47xx_nflash_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip);
61 +static int bcm47xx_nflash_erase(struct mtd_info *mtd, unsigned int addr, unsigned int len);
63 +/* Private Global variable */
64 +static u32 read_offset = 0;
65 +static u32 write_offset;
68 +nflash_mtd_poll(struct bcm47xx_nflash *nflash, unsigned int offset, int timeout)
70 + unsigned long now = jiffies;
74 + if (!bcma_nflash_poll(nflash->bcc)) {
78 + if (time_after(jiffies, now + timeout)) {
79 + pr_err("timeout while polling\n");
90 +bcm47xx_nflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
92 + struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
93 + struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
98 + u32 offset, blocksize, mask, off;
103 + /* Check address range */
106 + if ((from + len) > mtd->size)
109 + if ((offset & (NFL_SECTOR_SIZE - 1)) != 0) {
110 + extra = offset & (NFL_SECTOR_SIZE - 1);
115 + size = (len + (NFL_SECTOR_SIZE - 1)) & ~(NFL_SECTOR_SIZE - 1);
122 + tmpbuf = (u8 *)kmalloc(size, GFP_KERNEL);
126 + blocksize = mtd->erasesize;
127 + mask = blocksize - 1;
130 + off = offset + skip_bytes;
131 + if ((bytes = bcma_nflash_read(nflash->bcc, off, NFL_SECTOR_SIZE, ptr)) < 0) {
146 + memcpy(buf, tmpbuf+extra, *retlen);
153 +static void bcm47xx_nflash_write(struct mtd_info *mtd, u32 to, const u_char *buf, u32 len)
155 + struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
156 + struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
157 + u32 offset, blocksize, mask, off;
159 + u32 copy_len, write_len, from;
160 + u_char *write_ptr, *block;
164 + /* Check address range */
166 + pr_err("Error: Attempted to write too small data\n");
173 + if ((to + len) > mtd->size) {
174 + pr_err("Error: Attempted to write too large data\n");
181 + blocksize = mtd->erasesize;
182 + if (!(block = kmalloc(blocksize, GFP_KERNEL)))
184 + mask = blocksize - 1;
187 + from = offset & ~mask;
188 + /* Copy existing data into holding block if necessary */
189 + if (((offset & (blocksize-1)) != 0) || (len < blocksize)) {
190 + if ((ret = bcm47xx_nflash_read(mtd, from, blocksize, &read_len, block)))
192 + if (read_len != blocksize) {
198 + /* Copy input data into holding block */
199 + copy_len = min(len, blocksize - (offset & mask));
200 + memcpy(block + (offset & mask), ptr, copy_len);
203 + if ((ret = bcm47xx_nflash_erase(mtd, off, blocksize)) < 0)
205 + /* Write holding block */
207 + write_len = blocksize;
208 + if ((bytes = bcma_nflash_write(nflash->bcc, (uint)from, (uint)write_len, (u8 *) write_ptr)) != 0) {
212 + offset += copy_len;
213 + if (len < copy_len)
226 +static int bcm47xx_nflash_erase(struct mtd_info *mtd, unsigned int addr, unsigned int len)
228 + struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
229 + struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
231 + /* Check address range */
234 + if ((addr + len) > mtd->size)
237 + if (bcma_nflash_erase(nflash->bcc, addr)) {
238 + pr_err("ERASE: nflash erase error\n");
242 + if (nflash_mtd_poll(nflash, addr, 10 * HZ)) {
243 + pr_err("ERASE: nflash_mtd_poll error\n");
250 +/* This functions is used by upper layer to checks if device is ready */
251 +static int bcm47xx_nflash_dev_ready(struct mtd_info *mtd)
256 +/* Issue a nand flash command */
257 +static inline void bcm47xx_nflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
259 + bcma_cc_write32(cc, NAND_CMD_START, opcode);
260 + bcma_cc_read32(cc, NAND_CMD_START);
263 +static void bcm47xx_nflash_command(struct mtd_info *mtd, unsigned command,
264 + int column, int page_addr)
266 + struct nand_chip *nchip = (struct nand_chip *)mtd->priv;
267 + struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
268 + u32 pagesize = 1 << nchip->page_shift;
270 + /* Command pre-processing step */
272 + case NAND_CMD_RESET:
273 + bcm47xx_nflash_cmd(nflash->bcc, NCMD_FLASH_RESET);
276 + case NAND_CMD_STATUS:
277 + nflash->next_opcode = NAND_CMD_STATUS;
282 + case NAND_CMD_READ0:
283 + read_offset = page_addr * pagesize;
284 + nflash->next_opcode = 0;
287 + case NAND_CMD_READOOB:
288 + read_offset = page_addr * pagesize;
289 + nflash->next_opcode = 0;
292 + case NAND_CMD_SEQIN:
293 + write_offset = page_addr * pagesize;
294 + nflash->next_opcode = 0;
297 + case NAND_CMD_PAGEPROG:
298 + nflash->next_opcode = 0;
301 + case NAND_CMD_READID:
302 + read_offset = column;
303 + bcm47xx_nflash_cmd(nflash->bcc, NCMD_ID_RD);
304 + nflash->next_opcode = NAND_DEVID;
307 + case NAND_CMD_ERASE1:
308 + nflash->next_opcode = 0;
309 + bcm47xx_nflash_erase(mtd, page_addr*pagesize, pagesize);
312 + case NAND_CMD_ERASE2:
315 + case NAND_CMD_RNDOUT:
316 + if (column > mtd->writesize)
317 + read_offset += (column - mtd->writesize);
319 + read_offset += column;
323 + pr_err("COMMAND not supported %x\n", command);
324 + nflash->next_opcode = 0;
329 +/* This function is used by upper layer for select and
330 + * deselect of the NAND chip.
331 + * It is dummy function. */
332 +static void bcm47xx_nflash_select_chip(struct mtd_info *mtd, int chip)
336 +static u_char bcm47xx_nflash_read_byte(struct mtd_info *mtd)
338 + struct nand_chip *nchip = mtd->priv;
339 + struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
343 + if (nflash->next_opcode == 0)
346 + if (nflash->next_opcode == NAND_CMD_STATUS)
347 + return NAND_STATUS_WP;
349 + id = bcma_cc_read32(nflash->bcc, nflash->next_opcode);
351 + if (nflash->next_opcode == NAND_DEVID) {
352 + ret = (id >> (8*read_offset)) & 0xff;
359 +static uint16_t bcm47xx_nflash_read_word(struct mtd_info *mtd)
361 + loff_t from = read_offset;
365 + bcm47xx_nflash_read(mtd, from, sizeof(buf), &bytes, (u_char *)&buf);
369 +/* Write data of length len to buffer buf. The data to be
370 + * written on NAND Flash is first copied to RAMbuffer. After the Data Input
371 + * Operation by the NFC, the data is written to NAND Flash */
372 +static void bcm47xx_nflash_write_buf(struct mtd_info *mtd,
373 + const u_char *buf, int len)
375 + bcm47xx_nflash_write(mtd, write_offset, buf, len);
378 +/* Read the data buffer from the NAND Flash. To read the data from NAND
379 + * Flash first the data output cycle is initiated by the NFC, which copies
380 + * the data to RAMbuffer. This data of length len is then copied to buffer buf.
382 +static void bcm47xx_nflash_read_buf(struct mtd_info *mtd, u_char *buf, int len)
384 + loff_t from = read_offset;
387 + bcm47xx_nflash_read(mtd, from, len, &bytes, buf);
390 +/* Used by the upper layer to verify the data in NAND Flash
391 + * with the data in the buf. */
392 +static int bcm47xx_nflash_verify_buf(struct mtd_info *mtd,
393 + const u_char *buf, int len)
398 +static int bcm47xx_nflash_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
400 + struct nand_chip *nchip = mtd->priv;
401 + struct bcm47xx_nflash *nflash = (struct bcm47xx_nflash *)nchip->priv;
404 + u32 pagesize = 1 << nchip->page_shift;
405 + u32 blocksize = mtd->erasesize;
407 + if ((ofs >> 20) >= nflash->size)
409 + if ((ofs & (blocksize - 1)) != 0)
412 + for (i = 0; i < 2; i++) {
413 + off = ofs + pagesize;
414 + bcma_cc_write32(nflash->bcc, NAND_CMD_ADDR, off);
415 + bcm47xx_nflash_cmd(nflash->bcc, NCMD_SPARE_RD);
416 + if (bcma_nflash_poll(nflash->bcc) < 0)
418 + if ((bcma_cc_read32(nflash->bcc, NAND_INTFC_STATUS) & NIST_SPARE_VALID) != NIST_SPARE_VALID)
420 + if ((bcma_cc_read32(nflash->bcc, NAND_SPARE_RD0) & 0xff) != 0xff)
426 +const char *part_probes[] = { "cmdlinepart", NULL };
427 +static int bcm47xx_nflash_probe(struct platform_device *pdev)
429 + struct nand_chip *nchip;
430 + struct mtd_info *mtd;
431 + struct bcm47xx_nflash *nflash = dev_get_platdata(&pdev->dev);
434 + mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
440 + nchip = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
446 + /* Register with MTD */
448 + mtd->owner = THIS_MODULE;
449 + mtd->dev.parent = &pdev->dev;
451 + /* 50 us command delay time */
452 + nchip->chip_delay = 50;
454 + nchip->priv = nflash;
455 + nchip->dev_ready = bcm47xx_nflash_dev_ready;
456 + nchip->cmdfunc = bcm47xx_nflash_command;
457 + nchip->select_chip = bcm47xx_nflash_select_chip;
458 + nchip->read_byte = bcm47xx_nflash_read_byte;
459 + nchip->read_word = bcm47xx_nflash_read_word;
460 + nchip->write_buf = bcm47xx_nflash_write_buf;
461 + nchip->read_buf = bcm47xx_nflash_read_buf;
462 + nchip->verify_buf = bcm47xx_nflash_verify_buf;
463 + nchip->block_bad = bcm47xx_nflash_block_bad;
464 + nchip->options = NAND_SKIP_BBTSCAN;
467 + nchip->ecc.mode = NAND_ECC_NONE;
469 + /* first scan to find the device and get the page size */
470 + if (nand_scan_ident(mtd, 1, NULL)) {
471 + pr_err("nand_scan_ident failed\n");
473 + goto err_free_nchip;
475 + nflash->size = mtd->size;
476 + nflash->pagesize = 1 << nchip->page_shift;
477 + nflash->blocksize = mtd->erasesize;
480 + /* second phase scan */
481 + if (nand_scan_tail(mtd)) {
482 + pr_err("nand_scan_tail failed\n");
484 + goto err_free_nchip;
487 + mtd->name = "bcm47xx-nflash";
488 + mtd->flags |= MTD_WRITEABLE;
489 + ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, 0);
492 + pr_err("mtd_device_register failed\n");
493 + goto err_free_nchip;
506 +static int __devexit bcm47xx_nflash_remove(struct platform_device *pdev)
508 + struct bcm47xx_nflash *nflash = dev_get_platdata(&pdev->dev);
509 + struct mtd_info *mtd = nflash->mtd;
512 + /* Release resources, unregister device */
521 +static const struct platform_device_id bcm47xx_nflash_table[] = {
522 + { "bcm47xx-nflash", 0 },
525 +MODULE_DEVICE_TABLE(platform, bcm47xx_nflash_table);
527 +static struct platform_driver bcm47xx_nflash_driver = {
528 + .id_table = bcm47xx_nflash_table,
529 + .probe = bcm47xx_nflash_probe,
530 + .remove = __devexit_p(bcm47xx_nflash_remove),
532 + .name = "bcm47xx-nflash",
533 + .owner = THIS_MODULE,
537 +static int __init init_bcm47xx_nflash(void)
539 + int ret = platform_driver_register(&bcm47xx_nflash_driver);
542 + pr_err("error registering platform driver: %i\n", ret);
546 +static void __exit exit_bcm47xx_nflash(void)
548 + platform_driver_unregister(&bcm47xx_nflash_driver);
551 +module_init(init_bcm47xx_nflash);
552 +module_exit(exit_bcm47xx_nflash);
554 +MODULE_LICENSE("GPL");
555 +MODULE_DESCRIPTION("BCM47XX NAND flash driver");
557 +++ b/include/linux/mtd/bcm47xx_nand.h
560 + * Broadcom chipcommon NAND flash interface
562 + * Copyright (C) 2011-2012 Tathagata Das <tathagata@alumnux.com>
563 + * Copyright (C) 2009, Broadcom Corporation
564 + * All Rights Reserved.
566 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
567 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
568 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
569 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
573 +#ifndef LINUX_MTD_BCM47XX_NAND_H_
574 +#define LINUX_MTD_BCM47XX_NAND_H_
576 +#include <linux/mtd/mtd.h>
578 +#define NAND_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */
580 +/* nand_cmd_start commands */
582 +#define NCMD_PAGE_RD 1
583 +#define NCMD_SPARE_RD 2
584 +#define NCMD_STATUS_RD 3
585 +#define NCMD_PAGE_PROG 4
586 +#define NCMD_SPARE_PROG 5
587 +#define NCMD_COPY_BACK 6
588 +#define NCMD_ID_RD 7
589 +#define NCMD_BLOCK_ERASE 8
590 +#define NCMD_FLASH_RESET 9
591 +#define NCMD_LOCK 0xa
592 +#define NCMD_LOCK_DOWN 0xb
593 +#define NCMD_UNLOCK 0xc
594 +#define NCMD_LOCK_STATUS 0xd
596 +/* nand_acc_control */
597 +#define NAC_RD_ECC_EN 0x80000000
598 +#define NAC_WR_ECC_EN 0x40000000
599 +#define NAC_RD_ECC_BLK0_EN 0x20000000
600 +#define NAC_FAST_PGM_RDIN 0x10000000
601 +#define NAC_RD_ERASED_ECC_EN 0x08000000
602 +#define NAC_PARTIAL_PAGE_EN 0x04000000
603 +#define NAC_PAGE_HIT_EN 0x01000000
604 +#define NAC_ECC_LEVEL0 0x00f00000
605 +#define NAC_ECC_LEVEL 0x000f0000
606 +#define NAC_SPARE_SIZE0 0x00003f00
607 +#define NAC_SPARE_SIZE 0x0000003f
610 +#define NCF_CONFIG_LOCK 0x80000000
611 +#define NCF_BLOCK_SIZE_MASK 0x70000000
612 +#define NCF_BLOCK_SIZE_SHIFT 28
613 +#define NCF_DEVICE_SIZE_MASK 0x0f000000
614 +#define NCF_DEVICE_SIZE_SHIFT 24
615 +#define NCF_DEVICE_WIDTH 0x00800000
616 +#define NCF_PAGE_SIZE_MASK 0x00300000
617 +#define NCF_PAGE_SIZE_SHIFT 20
618 +#define NCF_FULL_ADDR_BYTES_MASK 0x00070000
619 +#define NCF_FULL_ADDR_BYTES_SHIFT 16
620 +#define NCF_COL_ADDR_BYTES_MASK 0x00007000
621 +#define NCF_COL_ADDR_BYTES_SHIFT 12
622 +#define NCF_BLK_ADDR_BYTES_MASK 0x00000700
623 +#define NCF_BLK_ADDR_BYTES_SHIFT 8
625 +/* nand_intfc_status */
626 +#define NIST_CTRL_READY 0x80000000
627 +#define NIST_FLASH_READY 0x40000000
628 +#define NIST_CACHE_VALID 0x20000000
629 +#define NIST_SPARE_VALID 0x10000000
630 +#define NIST_ERASED 0x08000000
631 +#define NIST_STATUS 0x000000ff
633 +#define NFL_SECTOR_SIZE 512
635 +#define NFL_TABLE_END 0xffffffff
636 +#define NFL_BOOT_SIZE 0x200000
637 +#define NFL_BOOT_OS_SIZE 0x2000000
639 +/* Nand flash MLC controller registers (corerev >= 38) */
640 +#define NAND_REVISION 0xC00
641 +#define NAND_CMD_START 0xC04
642 +#define NAND_CMD_ADDR_X 0xC08
643 +#define NAND_CMD_ADDR 0xC0C
644 +#define NAND_CMD_END_ADDR 0xC10
645 +#define NAND_CS_NAND_SELECT 0xC14
646 +#define NAND_CS_NAND_XOR 0xC18
647 +#define NAND_SPARE_RD0 0xC20
648 +#define NAND_SPARE_RD4 0xC24
649 +#define NAND_SPARE_RD8 0xC28
650 +#define NAND_SPARE_RD12 0xC2C
651 +#define NAND_SPARE_WR0 0xC30
652 +#define NAND_SPARE_WR4 0xC34
653 +#define NAND_SPARE_WR8 0xC38
654 +#define NAND_SPARE_WR12 0xC3C
655 +#define NAND_ACC_CONTROL 0xC40
656 +#define NAND_CONFIG 0xC48
657 +#define NAND_TIMING_1 0xC50
658 +#define NAND_TIMING_2 0xC54
659 +#define NAND_SEMAPHORE 0xC58
660 +#define NAND_DEVID 0xC60
661 +#define NAND_DEVID_X 0xC64
662 +#define NAND_BLOCK_LOCK_STATUS 0xC68
663 +#define NAND_INTFC_STATUS 0xC6C
664 +#define NAND_ECC_CORR_ADDR_X 0xC70
665 +#define NAND_ECC_CORR_ADDR 0xC74
666 +#define NAND_ECC_UNC_ADDR_X 0xC78
667 +#define NAND_ECC_UNC_ADDR 0xC7C
668 +#define NAND_READ_ERROR_COUNT 0xC80
669 +#define NAND_CORR_STAT_THRESHOLD 0xC84
670 +#define NAND_READ_ADDR_X 0xC90
671 +#define NAND_READ_ADDR 0xC94
672 +#define NAND_PAGE_PROGRAM_ADDR_X 0xC98
673 +#define NAND_PAGE_PROGRAM_ADDR 0xC9C
674 +#define NAND_COPY_BACK_ADDR_X 0xCA0
675 +#define NAND_COPY_BACK_ADDR 0xCA4
676 +#define NAND_BLOCK_ERASE_ADDR_X 0xCA8
677 +#define NAND_BLOCK_ERASE_ADDR 0xCAC
678 +#define NAND_INV_READ_ADDR_X 0xCB0
679 +#define NAND_INV_READ_ADDR 0xCB4
680 +#define NAND_BLK_WR_PROTECT 0xCC0
681 +#define NAND_ACC_CONTROL_CS1 0xCD0
682 +#define NAND_CONFIG_CS1 0xCD4
683 +#define NAND_TIMING_1_CS1 0xCD8
684 +#define NAND_TIMING_2_CS1 0xCDC
685 +#define NAND_SPARE_RD16 0xD30
686 +#define NAND_SPARE_RD20 0xD34
687 +#define NAND_SPARE_RD24 0xD38
688 +#define NAND_SPARE_RD28 0xD3C
689 +#define NAND_CACHE_ADDR 0xD40
690 +#define NAND_CACHE_DATA 0xD44
691 +#define NAND_CTRL_CONFIG 0xD48
692 +#define NAND_CTRL_STATUS 0xD4C
696 +struct bcm47xx_nflash {
697 + struct bcma_drv_cc *bcc;
700 + bool boot; /* This is the flash the SoC boots from */
701 + u32 blocksize; /* Block size */
702 + u32 pagesize; /* Page size */
704 + u32 size; /* Total size in bytes */
705 + u32 next_opcode; /* Next expected command from upper NAND layer */
707 + struct mtd_info *mtd;
710 +#endif /* LINUX_MTD_BCM47XX_NAND_H_ */