public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH 1/6] bcma: export PLL reading function
@ 2012-09-27 11:55 Rafał Miłecki
  2012-09-27 11:55 ` [PATCH 2/6] mtd: prepare place for BCMA NAND flash driver(s) Rafał Miłecki
                   ` (5 more replies)
  0 siblings, 6 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

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
---
 drivers/bcma/driver_chipcommon_pmu.c |    3 ++-
 include/linux/bcma/bcma.h            |    1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 8b8f2f3..c7d94b47 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -13,12 +13,13 @@
 #include <linux/export.h>
 #include <linux/bcma/bcma.h>
 
-static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
+u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
 {
 	bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
 	bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
 	return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
 }
+EXPORT_SYMBOL_GPL(bcma_chipco_pll_read);
 
 void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
 {
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 1954a4e..b58fae0 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -345,6 +345,7 @@ extern void bcma_core_set_clockmode(struct bcma_device *core,
 				    enum bcma_clkmode clkmode);
 extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
 			      bool on);
+extern u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset);
 #define BCMA_DMA_TRANSLATION_MASK	0xC0000000
 #define  BCMA_DMA_TRANSLATION_NONE	0x00000000
 #define  BCMA_DMA_TRANSLATION_DMA32_CMT	0x40000000 /* Client Mode Translation for 32-bit DMA */
-- 
1.7.7

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [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 6/6] bcm47xxnflash: enable BCM4706 driver
  2012-09-27 11:55 ` [PATCH 6/6] bcm47xxnflash: enable BCM4706 driver Rafał Miłecki
@ 2012-10-02 20:10   ` Rafał Miłecki
  0 siblings, 0 replies; 8+ messages in thread
From: Rafał Miłecki @ 2012-10-02 20:10 UTC (permalink / raw)
  To: linux-mtd, Artem Bityutskiy

2012/9/27 Rafał Miłecki <zajec5@gmail.com>:
> Signed-off-by: Rafał Miłecki <zajec5@gmail.com>

Any news on that? Chance for 3.7 merge window maybe?

-- 
Rafał

^ permalink raw reply	[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

end of thread, other threads:[~2012-10-11  9:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH 4/6] mtd: bcm47xxnflash: support for NAND_CMD_READID command Rafał Miłecki
2012-09-27 11:55 ` [PATCH 5/6] mtd: bcm47xxnflash: implement reading Rafał Miłecki
2012-09-27 11:55 ` [PATCH 6/6] bcm47xxnflash: enable BCM4706 driver 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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox