* [PATCH 2/6] mtd: prepare place for BCMA NAND flash driver(s)
2012-09-27 11:55 [PATCH 1/6] bcma: export PLL reading function Rafał Miłecki
@ 2012-09-27 11:55 ` Rafał Miłecki
2012-09-27 11:55 ` [PATCH 3/6] mtd: bcm47xxnflash: init NAND on BCM4706 Rafał Miłecki
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Rafał Miłecki @ 2012-09-27 11:55 UTC (permalink / raw)
To: linux-mtd, Artem Bityutskiy; +Cc: Rafał Miłecki
BCMA bus can contain NAND flash memory, it's registered in system as
platform device. This adds required hooks and place for controler
specific drivers.
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
0002-mtd-prepare-place-for-BCMA-NAND-flash-driver-s.patch
Successfully built configuration "mips-bcm47xx_defconfig,mips,mips-linux-", no issues
WARNING:CONFIG_DESCRIPTION: please write a paragraph that describes the config symbol fully
#33: FILE: drivers/mtd/nand/Kconfig:492:
+config MTD_NAND_BCM47XXNFLASH
WARNING:STATIC_CONST_CHAR_ARRAY: static const char * array should probably be static const char * const
#113: FILE: drivers/mtd/nand/bcm47xxnflash/main.c:24:
+static const char *probes[] = { "bcm47xxpart", NULL };
I believe that Kconfig description is OK, and I don't anything wrong
with my probes. Other drivers define probes in the same way.
---
drivers/mtd/nand/Kconfig | 8 ++
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/bcm47xxnflash/Makefile | 3 +
drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h | 14 +++
drivers/mtd/nand/bcm47xxnflash/main.c | 108 ++++++++++++++++++++++++
5 files changed, 134 insertions(+), 0 deletions(-)
create mode 100644 drivers/mtd/nand/bcm47xxnflash/Makefile
create mode 100644 drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
create mode 100644 drivers/mtd/nand/bcm47xxnflash/main.c
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 4883139..6ba1988 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -446,6 +446,14 @@ config MTD_NAND_GPMI_NAND
block, such as SD card. So pay attention to it when you enable
the GPMI.
+config MTD_NAND_BCM47XXNFLASH
+ tristate "R/O support for NAND flash on BCMA bus"
+ depends on BCMA_NFLASH
+ help
+ BCMA bus can have various flash memories attached, they are
+ registered by bcma as platform devices. This enables driver for
+ NAND flash memories. For now only read mode is implemented.
+
config MTD_NAND_PLATFORM
tristate "Support for generic platform NAND driver"
depends on HAS_IOMEM
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 2cbd091..01f39f87c 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -53,5 +53,6 @@ obj-$(CONFIG_MTD_NAND_RICOH) += r852.o
obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/
obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o
+obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/
nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/bcm47xxnflash/Makefile b/drivers/mtd/nand/bcm47xxnflash/Makefile
new file mode 100644
index 0000000..1d0693a
--- /dev/null
+++ b/drivers/mtd/nand/bcm47xxnflash/Makefile
@@ -0,0 +1,3 @@
+bcm47xxnflash-y += main.o
+
+obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash.o
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
new file mode 100644
index 0000000..2e8864a
--- /dev/null
+++ b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
@@ -0,0 +1,14 @@
+#ifndef __BCM47XXNFLASH_H
+#define __BCM47XXNFLASH_H
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+
+struct bcm47xxnflash {
+ struct bcma_drv_cc *cc;
+
+ struct nand_chip nand_chip;
+ struct mtd_info mtd;
+};
+
+#endif /* BCM47XXNFLASH */
diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c
new file mode 100644
index 0000000..fc9139d
--- /dev/null
+++ b/drivers/mtd/nand/bcm47xxnflash/main.c
@@ -0,0 +1,108 @@
+/*
+ * BCM47XX NAND flash driver
+ *
+ * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/bcma/bcma.h>
+
+#include "bcm47xxnflash.h"
+
+MODULE_DESCRIPTION("NAND flash driver for BCMA bus");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rafał Miłecki");
+
+static const char *probes[] = { "bcm47xxpart", NULL };
+
+static int bcm47xxnflash_probe(struct platform_device *pdev)
+{
+ struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
+ struct bcm47xxnflash *b47n;
+ int err = 0;
+
+ b47n = kzalloc(sizeof(*b47n), GFP_KERNEL);
+ if (!b47n) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ b47n->nand_chip.priv = b47n;
+ b47n->mtd.owner = THIS_MODULE;
+ b47n->mtd.priv = &b47n->nand_chip; /* Required */
+ b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash);
+
+ if (0) {
+ /* TODO: init device */
+ } else {
+ pr_err("Device not supported\n");
+ err = -ENOTSUPP;
+ }
+ if (err) {
+ pr_err("Initialization failed: %d\n", err);
+ goto err_init;
+ }
+
+ err = mtd_device_parse_register(&b47n->mtd, probes, NULL, NULL, 0);
+ if (err) {
+ pr_err("Failed to register MTD device: %d\n", err);
+ goto err_dev_reg;
+ }
+
+ return 0;
+
+err_dev_reg:
+err_init:
+ kfree(b47n);
+out:
+ return err;
+}
+
+static int __devexit bcm47xxnflash_remove(struct platform_device *pdev)
+{
+ struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
+
+ if (nflash->mtd)
+ mtd_device_unregister(nflash->mtd);
+
+ return 0;
+}
+
+static struct platform_driver bcm47xxnflash_driver = {
+ .remove = __devexit_p(bcm47xxnflash_remove),
+ .driver = {
+ .name = "bcma_nflash",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init bcm47xxnflash_init(void)
+{
+ int err;
+
+ /*
+ * Platform device "bcma_nflash" exists on SoCs and is registered very
+ * early, it won't be added during runtime (use platform_driver_probe).
+ */
+ err = platform_driver_probe(&bcm47xxnflash_driver, bcm47xxnflash_probe);
+ if (err)
+ pr_err("Failed to register serial flash driver: %d\n", err);
+
+ return err;
+}
+
+static void __exit bcm47xxnflash_exit(void)
+{
+ platform_driver_unregister(&bcm47xxnflash_driver);
+}
+
+module_init(bcm47xxnflash_init);
+module_exit(bcm47xxnflash_exit);
--
1.7.7
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 3/6] mtd: bcm47xxnflash: init NAND on BCM4706
2012-09-27 11:55 [PATCH 1/6] bcma: export PLL reading function Rafał Miłecki
2012-09-27 11:55 ` [PATCH 2/6] mtd: prepare place for BCMA NAND flash driver(s) Rafał Miłecki
@ 2012-09-27 11:55 ` Rafał Miłecki
2012-09-27 11:55 ` [PATCH 4/6] mtd: bcm47xxnflash: support for NAND_CMD_READID command Rafał Miłecki
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Rafał Miłecki @ 2012-09-27 11:55 UTC (permalink / raw)
To: linux-mtd, Artem Bityutskiy; +Cc: Rafał Miłecki
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
0003-mtd-bcm47xxnflash-init-NAND-on-BCM4706.patch
Successfully built configuration "mips-bcm47xx_defconfig,mips,mips-linux-", no issues
---
drivers/mtd/nand/bcm47xxnflash/Makefile | 1 +
drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c | 111 ++++++++++++++++++++++++++
2 files changed, 112 insertions(+), 0 deletions(-)
create mode 100644 drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
diff --git a/drivers/mtd/nand/bcm47xxnflash/Makefile b/drivers/mtd/nand/bcm47xxnflash/Makefile
index 1d0693a..4f688f9 100644
--- a/drivers/mtd/nand/bcm47xxnflash/Makefile
+++ b/drivers/mtd/nand/bcm47xxnflash/Makefile
@@ -1,3 +1,4 @@
bcm47xxnflash-y += main.o
+bcm47xxnflash- += ops_bcm4706.o
obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash.o
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
new file mode 100644
index 0000000..2f0ad1d
--- /dev/null
+++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
@@ -0,0 +1,111 @@
+/*
+ * BCM47XX NAND flash driver
+ *
+ * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/bcma/bcma.h>
+
+#include "bcm47xxnflash.h"
+
+/**************************************************
+ * Various helpers
+ **************************************************/
+
+static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
+{
+ return ((ns * 1000 * clock) / 1000000) + 1;
+}
+
+/**************************************************
+ * NAND chip ops
+ **************************************************/
+
+/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
+static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
+ int chip)
+{
+ return;
+}
+
+/**************************************************
+ * Init
+ **************************************************/
+
+int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
+{
+ int err;
+ u32 freq;
+ u16 clock;
+ u8 w0, w1, w2, w3, w4;
+
+ unsigned long chipsize; /* MiB */
+ u8 tbits, col_bits, col_size, row_bits, row_bsize;
+ u32 col_mask;
+ u32 val;
+
+ b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
+ b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
+
+ /* Enable NAND flash access */
+ bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
+ BCMA_CC_4706_FLASHSCFG_NF1);
+
+ /* Configure wait counters */
+ if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
+ freq = 100000000;
+ } else {
+ freq = bcma_chipco_pll_read(b47n->cc, 4);
+ freq = (freq * 0xFFF) >> 3;
+ freq = (freq * 25000000) >> 3;
+ }
+ clock = freq / 1000000;
+ w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
+ w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
+ w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
+ w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
+ w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
+ bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
+ (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
+
+ /* Scan NAND */
+ err = nand_scan(&b47n->mtd, 1);
+ if (err) {
+ pr_err("Could not scan NAND flash: %d\n", err);
+ goto exit;
+ }
+
+ /* Configure FLASH */
+ chipsize = b47n->nand_chip.chipsize >> 20;
+ tbits = ffs(chipsize); /* find first bit set */
+ if (!tbits || tbits != fls(chipsize)) {
+ pr_err("Invalid flash size: 0x%lX\n", chipsize);
+ err = -ENOTSUPP;
+ goto exit;
+ }
+ tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
+
+ col_bits = b47n->nand_chip.page_shift + 1;
+ col_mask = (1 << col_bits) - 1;
+ col_size = (col_bits + 7) / 8;
+
+ row_bits = tbits - col_bits + 1;
+ row_bsize = (row_bits + 7) / 8;
+
+ val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
+ bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
+
+exit:
+ if (err)
+ bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
+ ~BCMA_CC_4706_FLASHSCFG_NF1);
+ return err;
+}
--
1.7.7
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 4/6] mtd: bcm47xxnflash: support for NAND_CMD_READID command
2012-09-27 11:55 [PATCH 1/6] bcma: export PLL reading function Rafał Miłecki
2012-09-27 11:55 ` [PATCH 2/6] mtd: prepare place for BCMA NAND flash driver(s) Rafał Miłecki
2012-09-27 11:55 ` [PATCH 3/6] mtd: bcm47xxnflash: init NAND on BCM4706 Rafał Miłecki
@ 2012-09-27 11:55 ` Rafał Miłecki
2012-09-27 11:55 ` [PATCH 5/6] mtd: bcm47xxnflash: implement reading Rafał Miłecki
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Rafał Miłecki @ 2012-09-27 11:55 UTC (permalink / raw)
To: linux-mtd, Artem Bityutskiy; +Cc: Rafał Miłecki
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
0004-mtd-bcm47xxnflash-support-for-NAND_CMD_READID-comman.patch
Successfully built configuration "mips-bcm47xx_defconfig,mips,mips-linux-", no issues
WARNING:LONG_LINE: line over 80 characters
#120: FILE: drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c:106:
+ b47n->id_data[i] = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA) & 0xFF;
I avoid lines over 80 chars, but in this single case I left it to
make it easier to read the code (don't like having that code in 3 lines)
---
drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h | 5 +
drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c | 99 ++++++++++++++++++++++++
2 files changed, 104 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
index 2e8864a..cc71400 100644
--- a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
+++ b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
@@ -9,6 +9,11 @@ struct bcm47xxnflash {
struct nand_chip nand_chip;
struct mtd_info mtd;
+
+ unsigned curr_command;
+ int curr_column;
+
+ u8 id_data[8];
};
#endif /* BCM47XXNFLASH */
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
index 2f0ad1d..9ca6882 100644
--- a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
+++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
@@ -16,6 +16,10 @@
#include "bcm47xxnflash.h"
+/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
+ * shown 164 retries as maxiumum. */
+#define NFLASH_READY_RETRIES 1000
+
/**************************************************
* Various helpers
**************************************************/
@@ -25,6 +29,24 @@ static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
return ((ns * 1000 * clock) / 1000000) + 1;
}
+static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
+{
+ int i = 0;
+
+ bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, 0x80000000 | code);
+ for (i = 0; i < NFLASH_READY_RETRIES; i++) {
+ if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & 0x80000000)) {
+ i = 0;
+ break;
+ }
+ }
+ if (i) {
+ pr_err("NFLASH control command not ready!\n");
+ return -EBUSY;
+ }
+ return 0;
+}
+
/**************************************************
* NAND chip ops
**************************************************/
@@ -36,6 +58,81 @@ static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
return;
}
+/*
+ * Default nand_command and nand_command_lp don't match BCM4706 hardware layout.
+ * For example, reading chip id is performed in a non-standard way.
+ * Setting column and page is also handled differently, we use a special
+ * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
+ * standard commands would be much more complicated.
+ */
+static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
+ unsigned command, int column,
+ int page_addr)
+{
+ struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
+ struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
+ u32 ctlcode;
+ int i;
+
+ if (column != -1)
+ b47n->curr_column = column;
+
+ switch (command) {
+ case NAND_CMD_RESET:
+ pr_warn("Chip reset not implemented yet\n");
+ break;
+ case NAND_CMD_READID:
+ ctlcode = 0x40000000 | 0x01000000 | 0x00080000 | 0x00010000;
+ ctlcode |= NAND_CMD_READID;
+ if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) {
+ pr_err("READID error\n");
+ break;
+ }
+
+ /*
+ * Reading is specific, last one has to go without 0x40000000
+ * bit. We don't know how many reads NAND subsystem is going
+ * to perform, so cache everything.
+ */
+ for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {
+ ctlcode = 0x40000000 | 0x00100000;
+ if (i == ARRAY_SIZE(b47n->id_data) - 1)
+ ctlcode &= ~0x40000000;
+ if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
+ ctlcode)) {
+ pr_err("READID error\n");
+ break;
+ }
+ b47n->id_data[i] = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA) & 0xFF;
+ }
+
+ break;
+ default:
+ pr_err("Command 0x%X unsupported\n", command);
+ break;
+ }
+ b47n->curr_command = command;
+}
+
+static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
+{
+ 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_READID:
+ if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) {
+ pr_err("Requested invalid id_data: %d\n",
+ b47n->curr_column);
+ return 0;
+ }
+ return b47n->id_data[b47n->curr_column++];
+ }
+
+ pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
+ return 0;
+}
+
/**************************************************
* Init
**************************************************/
@@ -53,6 +150,8 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
u32 val;
b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
+ b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
+ b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
/* Enable NAND flash access */
--
1.7.7
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 5/6] mtd: bcm47xxnflash: implement reading
2012-09-27 11:55 [PATCH 1/6] bcma: export PLL reading function Rafał Miłecki
` (2 preceding siblings ...)
2012-09-27 11:55 ` [PATCH 4/6] mtd: bcm47xxnflash: support for NAND_CMD_READID command Rafał Miłecki
@ 2012-09-27 11:55 ` Rafał Miłecki
2012-09-27 11:55 ` [PATCH 6/6] bcm47xxnflash: enable BCM4706 driver Rafał Miłecki
2012-10-11 9:51 ` [PATCH 1/6] bcma: export PLL reading function Artem Bityutskiy
5 siblings, 0 replies; 8+ messages in thread
From: Rafał Miłecki @ 2012-09-27 11:55 UTC (permalink / raw)
To: linux-mtd, Artem Bityutskiy; +Cc: Rafał Miłecki
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
0005-mtd-bcm47xxnflash-implement-reading.patch
Successfully built configuration "mips-bcm47xx_defconfig,mips,mips-linux-", no issues
---
drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h | 1 +
drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c | 106 ++++++++++++++++++++++++
2 files changed, 107 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
index cc71400..264aec4 100644
--- a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
+++ b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
@@ -11,6 +11,7 @@ struct bcm47xxnflash {
struct mtd_info mtd;
unsigned curr_command;
+ int curr_page_addr;
int curr_column;
u8 id_data[8];
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
index 9ca6882..12a6227 100644
--- a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
+++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
@@ -20,6 +20,8 @@
* shown 164 retries as maxiumum. */
#define NFLASH_READY_RETRIES 1000
+#define NFLASH_SECTOR_SIZE 512
+
/**************************************************
* Various helpers
**************************************************/
@@ -47,6 +49,80 @@ static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
return 0;
}
+static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
+{
+ int i;
+
+ for (i = 0; i < NFLASH_READY_RETRIES; i++) {
+ if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & 0x04000000) {
+ if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) &
+ BCMA_CC_NFLASH_CTL_ERR) {
+ pr_err("Error on polling\n");
+ return -EBUSY;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ pr_err("Polling timeout!\n");
+ return -EBUSY;
+}
+
+/**************************************************
+ * R/W
+ **************************************************/
+
+static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
+ int len)
+{
+ struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
+ struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
+
+ u32 ctlcode;
+ u32 *dest = (u32 *)buf;
+ int i;
+ int toread;
+
+ 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 */
+
+ while (len) {
+ /* We can read maximum of 0x200 bytes at once */
+ toread = min(len, 0x200);
+
+ /* Set page and column */
+ bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR,
+ b47n->curr_column);
+ bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR,
+ b47n->curr_page_addr);
+
+ /* Prepare to read */
+ ctlcode = 0x40000000 | 0x00080000 | 0x00040000 | 0x00020000 |
+ 0x00010000;
+ ctlcode |= NAND_CMD_READSTART << 8;
+ if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode))
+ return;
+ if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc))
+ return;
+
+ /* Eventually read some data :) */
+ for (i = 0; i < toread; i += 4, dest++) {
+ ctlcode = 0x40000000 | 0x30000000 | 0x00100000;
+ if (i == toread - 4) /* Last read goes without that */
+ ctlcode &= ~0x40000000;
+ if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
+ ctlcode))
+ return;
+ *dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA);
+ }
+
+ b47n->curr_column += toread;
+ len -= toread;
+ }
+}
+
/**************************************************
* NAND chip ops
**************************************************/
@@ -76,6 +152,8 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
if (column != -1)
b47n->curr_column = column;
+ if (page_addr != -1)
+ b47n->curr_page_addr = page_addr;
switch (command) {
case NAND_CMD_RESET:
@@ -107,6 +185,12 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
}
break;
+ case NAND_CMD_READ0:
+ break;
+ case NAND_CMD_READOOB:
+ if (page_addr != -1)
+ b47n->curr_column += mtd->writesize;
+ break;
default:
pr_err("Command 0x%X unsupported\n", command);
break;
@@ -118,6 +202,7 @@ static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
{
struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
+ u32 tmp = 0;
switch (b47n->curr_command) {
case NAND_CMD_READID:
@@ -127,12 +212,31 @@ static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
return 0;
}
return b47n->id_data[b47n->curr_column++];
+ case NAND_CMD_READOOB:
+ bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4);
+ return tmp & 0xFF;
}
pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
return 0;
}
+static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
+ 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_READ0:
+ case NAND_CMD_READOOB:
+ bcm47xxnflash_ops_bcm4706_read(mtd, buf, len);
+ return;
+ }
+
+ pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
+}
+
/**************************************************
* Init
**************************************************/
@@ -152,6 +256,8 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
+ b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
+ b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
/* Enable NAND flash access */
--
1.7.7
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 6/6] bcm47xxnflash: enable BCM4706 driver
2012-09-27 11:55 [PATCH 1/6] bcma: export PLL reading function Rafał Miłecki
` (3 preceding siblings ...)
2012-09-27 11:55 ` [PATCH 5/6] mtd: bcm47xxnflash: implement reading Rafał Miłecki
@ 2012-09-27 11:55 ` Rafał Miłecki
2012-10-02 20:10 ` Rafał Miłecki
2012-10-11 9:51 ` [PATCH 1/6] bcma: export PLL reading function Artem Bityutskiy
5 siblings, 1 reply; 8+ messages in thread
From: Rafał Miłecki @ 2012-09-27 11:55 UTC (permalink / raw)
To: linux-mtd, Artem Bityutskiy; +Cc: Rafał Miłecki
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
0006-bcm47xxnflash-enable-BCM4706-driver.patch
Successfully built configuration "mips-bcm47xx_defconfig,mips,mips-linux-", no issues
---
drivers/mtd/nand/bcm47xxnflash/Makefile | 2 +-
drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h | 2 ++
drivers/mtd/nand/bcm47xxnflash/main.c | 4 ++--
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/bcm47xxnflash/Makefile b/drivers/mtd/nand/bcm47xxnflash/Makefile
index 4f688f9..f05b119 100644
--- a/drivers/mtd/nand/bcm47xxnflash/Makefile
+++ b/drivers/mtd/nand/bcm47xxnflash/Makefile
@@ -1,4 +1,4 @@
bcm47xxnflash-y += main.o
-bcm47xxnflash- += ops_bcm4706.o
+bcm47xxnflash-y += ops_bcm4706.o
obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash.o
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
index 264aec4..0bdb2ce 100644
--- a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
+++ b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
@@ -17,4 +17,6 @@ struct bcm47xxnflash {
u8 id_data[8];
};
+int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n);
+
#endif /* BCM47XXNFLASH */
diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c
index fc9139d..2b8b05b 100644
--- a/drivers/mtd/nand/bcm47xxnflash/main.c
+++ b/drivers/mtd/nand/bcm47xxnflash/main.c
@@ -40,8 +40,8 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
b47n->mtd.priv = &b47n->nand_chip; /* Required */
b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash);
- if (0) {
- /* TODO: init device */
+ if (b47n->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
+ err = bcm47xxnflash_ops_bcm4706_init(b47n);
} else {
pr_err("Device not supported\n");
err = -ENOTSUPP;
--
1.7.7
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 1/6] bcma: export PLL reading function
2012-09-27 11:55 [PATCH 1/6] bcma: export PLL reading function Rafał Miłecki
` (4 preceding siblings ...)
2012-09-27 11:55 ` [PATCH 6/6] bcm47xxnflash: enable BCM4706 driver Rafał Miłecki
@ 2012-10-11 9:51 ` Artem Bityutskiy
5 siblings, 0 replies; 8+ messages in thread
From: Artem Bityutskiy @ 2012-10-11 9:51 UTC (permalink / raw)
To: Rafał Miłecki; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 2488 bytes --]
On Thu, 2012-09-27 at 13:55 +0200, Rafał Miłecki wrote:
> This is required by NAND flash driver for initializing wait counters.
>
> Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
> ---
> 0001-bcma-export-PLL-reading-function.patch
> Successfully built configuration "mips-bcm47xx_defconfig,mips,mips-linux-", no issues
I think you did not enable the driver in the defconfig.
Tested the patch(es) on top of the following commits:
e3134a5 Quick fixes - applied by aiaiai
a7c1993 mtd: fsl_elbc_nand: remove unnecessary badblock_pattern
03ba2bf mtd: ofpart: Fix incorrect NULL check in parse_ofoldpart_partitions()
c525349 mtd: m25p80: add support for the windbond w25q256 chip
--------------------------------------------------------------------------------
Successfully built configuration "mips-bcm47xx_defconfig,mips,mips-linux-", results:
--- before_patching.log
+++ after_patching.log
@@ @@
+drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c: In function 'bcm47xxnflash_ops_bcm4706_init':
+drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c:253:6: warning: variable 'col_mask' set but not used [-Wunused-but-set-variable]
--------------------------------------------------------------------------------
checkpatch.pl has some complaints:
--------------------------------------------------------------------------------
checkpatch.pl results for patch "[PATCH 2/6] mtd: prepare place for BCMA NAND flash driver(s)"
WARNING:CONFIG_DESCRIPTION: please write a paragraph that describes the config symbol fully
#33: FILE: drivers/mtd/nand/Kconfig:449:
+config MTD_NAND_BCM47XXNFLASH
WARNING:STATIC_CONST_CHAR_ARRAY: static const char * array should probably be static const char * const
#113: FILE: drivers/mtd/nand/bcm47xxnflash/main.c:24:
+static const char *probes[] = { "bcm47xxpart", NULL };
total: 0 errors, 2 warnings, 145 lines checked
--------------------------------------------------------------------------------
checkpatch.pl results for patch "[PATCH 4/6] mtd: bcm47xxnflash: support for NAND_CMD_READID command"
WARNING:LONG_LINE: line over 80 characters
#120: FILE: drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c:106:
+ b47n->id_data[i] = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA) & 0xFF;
total: 0 errors, 1 warnings, 134 lines checked
--------------------------------------------------------------------------------
--
Best Regards,
Artem Bityutskiy
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread