All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/9] Support for MMIO based Denali NAND controller
@ 2011-05-06 14:28 Jamie Iles
  2011-05-06 14:28 ` [RFC PATCH 1/9] nand/denali: convert to generic DMA API Jamie Iles
                   ` (8 more replies)
  0 siblings, 9 replies; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 14:28 UTC (permalink / raw)
  To: linux-mtd; +Cc: Jamie Iles, dwmw2, chuanxiao.dong

The Denali block found in the Intel Moorestown platform can also be found in
some SoC devices on a simple bus rather than PCI.  This series refactors the
PCI based driver so that it can either be registered as either a PCI device or
a platform_device.

This series also incorporates a couple of small cleanups and support for MTD
partitioning.

This is an early RFC as the silicon with the device in isn't back yet and I
don't have a Moorestown platform to test against, but I'd appreciate any
feedback.

Jamie Iles (9):
  nand/denali: convert to generic DMA API
  nand/denali: remove nearly-duplicated register definitions
  nand/denali: detect the number of banks
  nand/denali: split the generic driver and PCI layer
  nand/denali: convert to dev_() printk helpers
  nand/denali: add an mmio driver
  nand/denali: annotate pci init/exit functions with correct section
  nand/denali: allow the number of ECC bits to be set by pdata
  nand/denali: support MTD partitioning

 drivers/mtd/nand/Kconfig             |   21 ++-
 drivers/mtd/nand/Makefile            |    2 +
 drivers/mtd/nand/denali.c            |  500 ++++++++++++----------------------
 drivers/mtd/nand/denali.h            |  379 +++++---------------------
 drivers/mtd/nand/denali_mmio.c       |  145 ++++++++++
 drivers/mtd/nand/denali_pci.c        |  143 ++++++++++
 include/linux/platform_data/denali.h |   25 ++
 7 files changed, 576 insertions(+), 639 deletions(-)
 create mode 100644 drivers/mtd/nand/denali_mmio.c
 create mode 100644 drivers/mtd/nand/denali_pci.c
 create mode 100644 include/linux/platform_data/denali.h

-- 
1.7.4.4

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

* [RFC PATCH 1/9] nand/denali: convert to generic DMA API
  2011-05-06 14:28 [RFC PATCH 0/9] Support for MMIO based Denali NAND controller Jamie Iles
@ 2011-05-06 14:28 ` Jamie Iles
  2011-05-12  8:05   ` Artem Bityutskiy
  2011-05-06 14:28 ` [RFC PATCH 2/9] nand/denali: remove nearly-duplicated register definitions Jamie Iles
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 14:28 UTC (permalink / raw)
  To: linux-mtd; +Cc: Jamie Iles, dwmw2, chuanxiao.dong

Rather than using the PCI specific DMA API, convert to the generic
DMA API so that we can use the Denali NAND controller on other bus
types.

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 drivers/mtd/nand/denali.c |   82 +++++++++++++++++++++-----------------------
 drivers/mtd/nand/denali.h |    2 +-
 2 files changed, 40 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 4633f09..1cf7281 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -19,6 +19,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -192,7 +193,7 @@ static void reset_bank(struct denali_nand_info *denali)
 	irq_status = wait_for_irq(denali, irq_mask);
 
 	if (irq_status & operation_timeout[denali->flash_bank])
-		dev_err(&denali->dev->dev, "reset bank failed.\n");
+		dev_err(denali->dev, "reset bank failed.\n");
 }
 
 /* Reset the flash controller */
@@ -200,7 +201,7 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 {
 	uint32_t i;
 
-	dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n",
+	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
 		       __FILE__, __LINE__, __func__);
 
 	for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++)
@@ -216,7 +217,7 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 			cpu_relax();
 		if (ioread32(denali->flash_reg + intr_status_addresses[i]) &
 			operation_timeout[i])
-			dev_dbg(&denali->dev->dev,
+			dev_dbg(denali->dev,
 			"NAND Reset operation timed out on bank %d\n", i);
 	}
 
@@ -254,7 +255,7 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
 	uint16_t acc_clks;
 	uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt;
 
-	dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n",
+	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
 		       __FILE__, __LINE__, __func__);
 
 	en_lo = CEIL_DIV(Trp[mode], CLK_X);
@@ -291,7 +292,7 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
 		acc_clks++;
 
 	if ((data_invalid - acc_clks * CLK_X) < 2)
-		dev_warn(&denali->dev->dev, "%s, Line %d: Warning!\n",
+		dev_warn(denali->dev, "%s, Line %d: Warning!\n",
 			__FILE__, __LINE__);
 
 	addr_2_data = CEIL_DIV(Tadl[mode], CLK_X);
@@ -419,7 +420,7 @@ static void get_hynix_nand_para(struct denali_nand_info *denali,
 #endif
 		break;
 	default:
-		dev_warn(&denali->dev->dev,
+		dev_warn(denali->dev,
 			"Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
 			"Will use default parameter values instead.\n",
 			device_id);
@@ -441,7 +442,7 @@ static void find_valid_banks(struct denali_nand_info *denali)
 		index_addr_read_data(denali,
 				(uint32_t)(MODE_11 | (i << 24) | 2), &id[i]);
 
-		dev_dbg(&denali->dev->dev,
+		dev_dbg(denali->dev,
 			"Return 1st ID for bank[%d]: %x\n", i, id[i]);
 
 		if (i == 0) {
@@ -461,13 +462,13 @@ static void find_valid_banks(struct denali_nand_info *denali)
 		 * Multichip support is not enabled.
 		 */
 		if (denali->total_used_banks != 1) {
-			dev_err(&denali->dev->dev,
+			dev_err(denali->dev,
 					"Sorry, Intel CE4100 only supports "
 					"a single NAND device.\n");
 			BUG();
 		}
 	}
-	dev_dbg(&denali->dev->dev,
+	dev_dbg(denali->dev,
 		"denali->total_used_banks: %d\n", denali->total_used_banks);
 }
 
@@ -501,7 +502,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 	uint32_t id_bytes[5], addr;
 	uint8_t i, maf_id, device_id;
 
-	dev_dbg(&denali->dev->dev,
+	dev_dbg(denali->dev,
 			"%s, Line %d, Function: %s\n",
 			__FILE__, __LINE__, __func__);
 
@@ -530,7 +531,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 		get_hynix_nand_para(denali, device_id);
 	}
 
-	dev_info(&denali->dev->dev,
+	dev_info(denali->dev,
 			"Dump timing register values:"
 			"acc_clks: %d, re_2_we: %d, re_2_re: %d\n"
 			"we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n"
@@ -560,7 +561,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 static void denali_set_intr_modes(struct denali_nand_info *denali,
 					uint16_t INT_ENABLE)
 {
-	dev_dbg(&denali->dev->dev, "%s, Line %d, Function: %s\n",
+	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
 		       __FILE__, __LINE__, __func__);
 
 	if (INT_ENABLE)
@@ -800,7 +801,7 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
 			irq_status = wait_for_irq(denali, irq_mask);
 
 			if (irq_status == 0) {
-				dev_err(&denali->dev->dev,
+				dev_err(denali->dev,
 						"cmd, page, addr on timeout "
 						"(0x%x, 0x%x, 0x%x)\n",
 						cmd, denali->page, addr);
@@ -875,11 +876,11 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 		irq_status = wait_for_irq(denali, irq_mask);
 
 		if (irq_status == 0) {
-			dev_err(&denali->dev->dev, "OOB write failed\n");
+			dev_err(denali->dev, "OOB write failed\n");
 			status = -EIO;
 		}
 	} else {
-		dev_err(&denali->dev->dev, "unable to send pipeline command\n");
+		dev_err(denali->dev, "unable to send pipeline command\n");
 		status = -EIO;
 	}
 	return status;
@@ -904,7 +905,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 		irq_status = wait_for_irq(denali, irq_mask);
 
 		if (irq_status == 0)
-			dev_err(&denali->dev->dev, "page on OOB timeout %d\n",
+			dev_err(denali->dev, "page on OOB timeout %d\n",
 					denali->page);
 
 		/* We set the device back to MAIN_ACCESS here as I observed
@@ -1045,7 +1046,6 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 			const uint8_t *buf, bool raw_xfer)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	struct pci_dev *pci_dev = denali->dev;
 
 	dma_addr_t addr = denali->buf.dma_buf;
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
@@ -1071,7 +1071,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 			mtd->oobsize);
 	}
 
-	pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVICE);
+	dma_sync_single_for_device(denali->dev, addr, size, DMA_TO_DEVICE);
 
 	clear_interrupts(denali);
 	denali_enable_dma(denali, true);
@@ -1082,7 +1082,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	irq_status = wait_for_irq(denali, irq_mask);
 
 	if (irq_status == 0) {
-		dev_err(&denali->dev->dev,
+		dev_err(denali->dev,
 				"timeout on write_page (type = %d)\n",
 				raw_xfer);
 		denali->status =
@@ -1091,7 +1091,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	}
 
 	denali_enable_dma(denali, false);
-	pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE);
+	dma_sync_single_for_cpu(denali->dev, addr, size, DMA_TO_DEVICE);
 }
 
 /* NAND core entry points */
@@ -1139,7 +1139,6 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 			    uint8_t *buf, int page)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	struct pci_dev *pci_dev = denali->dev;
 
 	dma_addr_t addr = denali->buf.dma_buf;
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
@@ -1150,7 +1149,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	bool check_erased_page = false;
 
 	if (page != denali->page) {
-		dev_err(&denali->dev->dev, "IN %s: page %d is not"
+		dev_err(denali->dev, "IN %s: page %d is not"
 				" equal to denali->page %d, investigate!!",
 				__func__, page, denali->page);
 		BUG();
@@ -1159,7 +1158,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	setup_ecc_for_xfer(denali, true, false);
 
 	denali_enable_dma(denali, true);
-	pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_FROMDEVICE);
+	dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE);
 
 	clear_interrupts(denali);
 	denali_setup_dma(denali, DENALI_READ);
@@ -1167,7 +1166,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	/* wait for operation to complete */
 	irq_status = wait_for_irq(denali, irq_mask);
 
-	pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE);
+	dma_sync_single_for_cpu(denali->dev, addr, size, DMA_FROM_DEVICE);
 
 	memcpy(buf, denali->buf.buf, mtd->writesize);
 
@@ -1192,7 +1191,6 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 				uint8_t *buf, int page)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	struct pci_dev *pci_dev = denali->dev;
 
 	dma_addr_t addr = denali->buf.dma_buf;
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
@@ -1201,7 +1199,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 	uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP;
 
 	if (page != denali->page) {
-		dev_err(&denali->dev->dev, "IN %s: page %d is not"
+		dev_err(denali->dev, "IN %s: page %d is not"
 				" equal to denali->page %d, investigate!!",
 				__func__, page, denali->page);
 		BUG();
@@ -1210,7 +1208,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 	setup_ecc_for_xfer(denali, false, true);
 	denali_enable_dma(denali, true);
 
-	pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_FROMDEVICE);
+	dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE);
 
 	clear_interrupts(denali);
 	denali_setup_dma(denali, DENALI_READ);
@@ -1218,7 +1216,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 	/* wait for operation to complete */
 	irq_status = wait_for_irq(denali, irq_mask);
 
-	pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_FROMDEVICE);
+	dma_sync_single_for_cpu(denali->dev, addr, size, DMA_FROM_DEVICE);
 
 	denali_enable_dma(denali, false);
 
@@ -1330,7 +1328,7 @@ static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
 				uint8_t *ecc_code)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(&denali->dev->dev,
+	dev_err(denali->dev,
 			"denali_ecc_calculate called unexpectedly\n");
 	BUG();
 	return -EIO;
@@ -1340,7 +1338,7 @@ static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
 				uint8_t *read_ecc, uint8_t *calc_ecc)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(&denali->dev->dev,
+	dev_err(denali->dev,
 			"denali_ecc_correct called unexpectedly\n");
 	BUG();
 	return -EIO;
@@ -1349,7 +1347,7 @@ static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
 static void denali_ecc_hwctl(struct mtd_info *mtd, int mode)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(&denali->dev->dev,
+	dev_err(denali->dev,
 			"denali_ecc_hwctl called unexpectedly\n");
 	BUG();
 }
@@ -1484,24 +1482,22 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	}
 
 	/* Is 32-bit DMA supported? */
-	ret = pci_set_dma_mask(dev, DMA_BIT_MASK(32));
-
+	ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
 	if (ret) {
 		printk(KERN_ERR "Spectra: no usable DMA configuration\n");
 		goto failed_enable_dev;
 	}
-	denali->buf.dma_buf =
-		pci_map_single(dev, denali->buf.buf,
-						DENALI_BUF_SIZE,
-						PCI_DMA_BIDIRECTIONAL);
+	denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf,
+					     DENALI_BUF_SIZE,
+					     DMA_BIDIRECTIONAL);
 
-	if (pci_dma_mapping_error(dev, denali->buf.dma_buf)) {
+	if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) {
 		dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n");
 		goto failed_enable_dev;
 	}
 
 	pci_set_master(dev);
-	denali->dev = dev;
+	denali->dev = &dev->dev;
 	denali->mtd.dev.parent = &dev->dev;
 
 	ret = pci_request_regions(dev, DENALI_NAND_NAME);
@@ -1681,8 +1677,8 @@ failed_remap_reg:
 failed_req_regions:
 	pci_release_regions(dev);
 failed_dma_map:
-	pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
-							PCI_DMA_BIDIRECTIONAL);
+	dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+			 DMA_BIDIRECTIONAL);
 failed_enable_dev:
 	pci_disable_device(dev);
 failed_alloc_memery:
@@ -1704,8 +1700,8 @@ static void denali_pci_remove(struct pci_dev *dev)
 	iounmap(denali->flash_mem);
 	pci_release_regions(dev);
 	pci_disable_device(dev);
-	pci_unmap_single(dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
-							PCI_DMA_BIDIRECTIONAL);
+	dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+			 DMA_BIDIRECTIONAL);
 	pci_set_drvdata(dev, NULL);
 	kfree(denali);
 }
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index 3918bcb..9b875fd 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -732,7 +732,7 @@ struct denali_nand_info {
 	int status;
 	int platform;
 	struct nand_buf buf;
-	struct pci_dev *dev;
+	struct device *dev;
 	int total_used_banks;
 	uint32_t block;  /* stored for future use */
 	uint16_t page;
-- 
1.7.4.4

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

* [RFC PATCH 2/9] nand/denali: remove nearly-duplicated register definitions
  2011-05-06 14:28 [RFC PATCH 0/9] Support for MMIO based Denali NAND controller Jamie Iles
  2011-05-06 14:28 ` [RFC PATCH 1/9] nand/denali: convert to generic DMA API Jamie Iles
@ 2011-05-06 14:28 ` Jamie Iles
  2011-05-12  8:05   ` Artem Bityutskiy
  2011-05-06 14:28 ` [RFC PATCH 3/9] nand/denali: detect the number of banks Jamie Iles
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 14:28 UTC (permalink / raw)
  To: linux-mtd; +Cc: Jamie Iles, dwmw2, chuanxiao.dong

The controller has interrupt enable/status register pairs for each bank
(along with ECC and status registers) that differ only in address offset.
Rather than providing definitions for each register, make the address a
macro so that it scales for devices with different numbers of banks.

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 drivers/mtd/nand/denali.c |  134 +++++++----------
 drivers/mtd/nand/denali.h |  371 +++++++--------------------------------------
 2 files changed, 110 insertions(+), 395 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 1cf7281..70a439c 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -45,16 +45,16 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
 
 /* We define a macro here that combines all interrupts this driver uses into
  * a single constant value, for convenience. */
-#define DENALI_IRQ_ALL	(INTR_STATUS0__DMA_CMD_COMP | \
-			INTR_STATUS0__ECC_TRANSACTION_DONE | \
-			INTR_STATUS0__ECC_ERR | \
-			INTR_STATUS0__PROGRAM_FAIL | \
-			INTR_STATUS0__LOAD_COMP | \
-			INTR_STATUS0__PROGRAM_COMP | \
-			INTR_STATUS0__TIME_OUT | \
-			INTR_STATUS0__ERASE_FAIL | \
-			INTR_STATUS0__RST_COMP | \
-			INTR_STATUS0__ERASE_COMP)
+#define DENALI_IRQ_ALL	(INTR_STATUS__DMA_CMD_COMP | \
+			INTR_STATUS__ECC_TRANSACTION_DONE | \
+			INTR_STATUS__ECC_ERR | \
+			INTR_STATUS__PROGRAM_FAIL | \
+			INTR_STATUS__LOAD_COMP | \
+			INTR_STATUS__PROGRAM_COMP | \
+			INTR_STATUS__TIME_OUT | \
+			INTR_STATUS__ERASE_FAIL | \
+			INTR_STATUS__RST_COMP | \
+			INTR_STATUS__ERASE_COMP)
 
 /* indicates whether or not the internal value for the flash bank is
  * valid or not */
@@ -96,30 +96,6 @@ static const struct pci_device_id denali_pci_ids[] = {
 	{ /* end: all zeroes */ }
 };
 
-
-/* these are static lookup tables that give us easy access to
- * registers in the NAND controller.
- */
-static const uint32_t intr_status_addresses[4] = {INTR_STATUS0,
-						  INTR_STATUS1,
-						  INTR_STATUS2,
-						  INTR_STATUS3};
-
-static const uint32_t device_reset_banks[4] = {DEVICE_RESET__BANK0,
-							DEVICE_RESET__BANK1,
-							DEVICE_RESET__BANK2,
-							DEVICE_RESET__BANK3};
-
-static const uint32_t operation_timeout[4] = {INTR_STATUS0__TIME_OUT,
-							INTR_STATUS1__TIME_OUT,
-							INTR_STATUS2__TIME_OUT,
-							INTR_STATUS3__TIME_OUT};
-
-static const uint32_t reset_complete[4] = {INTR_STATUS0__RST_COMP,
-							INTR_STATUS1__RST_COMP,
-							INTR_STATUS2__RST_COMP,
-							INTR_STATUS3__RST_COMP};
-
 /* forward declarations */
 static void clear_interrupts(struct denali_nand_info *denali);
 static uint32_t wait_for_irq(struct denali_nand_info *denali,
@@ -181,18 +157,16 @@ static void read_status(struct denali_nand_info *denali)
 static void reset_bank(struct denali_nand_info *denali)
 {
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = reset_complete[denali->flash_bank] |
-			    operation_timeout[denali->flash_bank];
-	int bank = 0;
+	uint32_t irq_mask = INTR_STATUS__RST_COMP |
+			    INTR_STATUS__TIME_OUT;
 
 	clear_interrupts(denali);
 
-	bank = device_reset_banks[denali->flash_bank];
-	iowrite32(bank, denali->flash_reg + DEVICE_RESET);
+	iowrite32(1 << denali->flash_bank, denali->flash_reg + DEVICE_RESET);
 
 	irq_status = wait_for_irq(denali, irq_mask);
 
-	if (irq_status & operation_timeout[denali->flash_bank])
+	if (irq_status & INTR_STATUS__TIME_OUT)
 		dev_err(denali->dev, "reset bank failed.\n");
 }
 
@@ -205,25 +179,24 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 		       __FILE__, __LINE__, __func__);
 
 	for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++)
-		iowrite32(reset_complete[i] | operation_timeout[i],
-		denali->flash_reg + intr_status_addresses[i]);
+		iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
+		denali->flash_reg + INTR_STATUS(i));
 
 	for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) {
-		iowrite32(device_reset_banks[i],
-				denali->flash_reg + DEVICE_RESET);
+		iowrite32(1 << i, denali->flash_reg + DEVICE_RESET);
 		while (!(ioread32(denali->flash_reg +
-				intr_status_addresses[i]) &
-			(reset_complete[i] | operation_timeout[i])))
+				INTR_STATUS(i)) &
+			(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT)))
 			cpu_relax();
-		if (ioread32(denali->flash_reg + intr_status_addresses[i]) &
-			operation_timeout[i])
+		if (ioread32(denali->flash_reg + INTR_STATUS(i)) &
+			INTR_STATUS__TIME_OUT)
 			dev_dbg(denali->dev,
 			"NAND Reset operation timed out on bank %d\n", i);
 	}
 
 	for (i = 0; i < LLD_MAX_FLASH_BANKS; i++)
-		iowrite32(reset_complete[i] | operation_timeout[i],
-			denali->flash_reg + intr_status_addresses[i]);
+		iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
+			denali->flash_reg + INTR_STATUS(i));
 
 	return PASS;
 }
@@ -481,15 +454,15 @@ static void detect_partition_feature(struct denali_nand_info *denali)
 	 * blocks it can't touch.
 	 * */
 	if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) {
-		if ((ioread32(denali->flash_reg + PERM_SRC_ID_1) &
-			PERM_SRC_ID_1__SRCID) == SPECTRA_PARTITION_ID) {
+		if ((ioread32(denali->flash_reg + PERM_SRC_ID(1)) &
+			PERM_SRC_ID__SRCID) == SPECTRA_PARTITION_ID) {
 			denali->fwblks =
-			    ((ioread32(denali->flash_reg + MIN_MAX_BANK_1) &
-			      MIN_MAX_BANK_1__MIN_VALUE) *
+			    ((ioread32(denali->flash_reg + MIN_MAX_BANK(1)) &
+			      MIN_MAX_BANK__MIN_VALUE) *
 			     denali->blksperchip)
 			    +
-			    (ioread32(denali->flash_reg + MIN_BLK_ADDR_1) &
-			    MIN_BLK_ADDR_1__VALUE);
+			    (ioread32(denali->flash_reg + MIN_BLK_ADDR(1)) &
+			    MIN_BLK_ADDR__VALUE);
 		} else
 			denali->fwblks = SPECTRA_START_BLOCK;
 	} else
@@ -581,6 +554,7 @@ static inline bool is_flash_bank_valid(int flash_bank)
 static void denali_irq_init(struct denali_nand_info *denali)
 {
 	uint32_t int_mask = 0;
+	int i;
 
 	/* Disable global interrupts */
 	denali_set_intr_modes(denali, false);
@@ -588,10 +562,8 @@ static void denali_irq_init(struct denali_nand_info *denali)
 	int_mask = DENALI_IRQ_ALL;
 
 	/* Clear all status bits */
-	iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS0);
-	iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS1);
-	iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS2);
-	iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS3);
+	for (i = 0; i < LLD_MAX_FLASH_BANKS; ++i)
+		iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS(i));
 
 	denali_irq_enable(denali, int_mask);
 }
@@ -605,10 +577,10 @@ static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali)
 static void denali_irq_enable(struct denali_nand_info *denali,
 							uint32_t int_mask)
 {
-	iowrite32(int_mask, denali->flash_reg + INTR_EN0);
-	iowrite32(int_mask, denali->flash_reg + INTR_EN1);
-	iowrite32(int_mask, denali->flash_reg + INTR_EN2);
-	iowrite32(int_mask, denali->flash_reg + INTR_EN3);
+	int i;
+
+	for (i = 0; i < LLD_MAX_FLASH_BANKS; ++i)
+		iowrite32(int_mask, denali->flash_reg + INTR_EN(i));
 }
 
 /* This function only returns when an interrupt that this driver cares about
@@ -625,7 +597,7 @@ static inline void clear_interrupt(struct denali_nand_info *denali,
 {
 	uint32_t intr_status_reg = 0;
 
-	intr_status_reg = intr_status_addresses[denali->flash_bank];
+	intr_status_reg = INTR_STATUS(denali->flash_bank);
 
 	iowrite32(irq_mask, denali->flash_reg + intr_status_reg);
 }
@@ -646,7 +618,7 @@ static uint32_t read_interrupt_status(struct denali_nand_info *denali)
 {
 	uint32_t intr_status_reg = 0;
 
-	intr_status_reg = intr_status_addresses[denali->flash_bank];
+	intr_status_reg = INTR_STATUS(denali->flash_bank);
 
 	return ioread32(denali->flash_reg + intr_status_reg);
 }
@@ -755,7 +727,7 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
 		 irq_mask = 0;
 
 	if (op == DENALI_READ)
-		irq_mask = INTR_STATUS0__LOAD_COMP;
+		irq_mask = INTR_STATUS__LOAD_COMP;
 	else if (op == DENALI_WRITE)
 		irq_mask = 0;
 	else
@@ -862,8 +834,8 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__PROGRAM_COMP |
-						INTR_STATUS0__PROGRAM_FAIL;
+	uint32_t irq_mask = INTR_STATUS__PROGRAM_COMP |
+						INTR_STATUS__PROGRAM_FAIL;
 	int status = 0;
 
 	denali->page = page;
@@ -890,7 +862,7 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	uint32_t irq_mask = INTR_STATUS0__LOAD_COMP,
+	uint32_t irq_mask = INTR_STATUS__LOAD_COMP,
 			 irq_status = 0, addr = 0x0, cmd = 0x0;
 
 	denali->page = page;
@@ -945,7 +917,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
 {
 	bool check_erased_page = false;
 
-	if (irq_status & INTR_STATUS0__ECC_ERR) {
+	if (irq_status & INTR_STATUS__ECC_ERR) {
 		/* read the ECC errors. we'll ignore them for now */
 		uint32_t err_address = 0, err_correction_info = 0;
 		uint32_t err_byte = 0, err_sector = 0, err_device = 0;
@@ -996,7 +968,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
 		 * for a while for this interrupt
 		 * */
 		while (!(read_interrupt_status(denali) &
-				INTR_STATUS0__ECC_TRANSACTION_DONE))
+				INTR_STATUS__ECC_TRANSACTION_DONE))
 			cpu_relax();
 		clear_interrupts(denali);
 		denali_set_intr_modes(denali, true);
@@ -1051,8 +1023,8 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP |
-						INTR_STATUS0__PROGRAM_FAIL;
+	uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP |
+						INTR_STATUS__PROGRAM_FAIL;
 
 	/* if it is a raw xfer, we want to disable ecc, and send
 	 * the spare area.
@@ -1086,7 +1058,7 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 				"timeout on write_page (type = %d)\n",
 				raw_xfer);
 		denali->status =
-			(irq_status & INTR_STATUS0__PROGRAM_FAIL) ?
+			(irq_status & INTR_STATUS__PROGRAM_FAIL) ?
 			NAND_STATUS_FAIL : PASS;
 	}
 
@@ -1144,8 +1116,8 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__ECC_TRANSACTION_DONE |
-			    INTR_STATUS0__ECC_ERR;
+	uint32_t irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE |
+			    INTR_STATUS__ECC_ERR;
 	bool check_erased_page = false;
 
 	if (page != denali->page) {
@@ -1196,7 +1168,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS0__DMA_CMD_COMP;
+	uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP;
 
 	if (page != denali->page) {
 		dev_err(denali->dev, "IN %s: page %d is not"
@@ -1269,10 +1241,10 @@ static void denali_erase(struct mtd_info *mtd, int page)
 	index_addr(denali, (uint32_t)cmd, 0x1);
 
 	/* wait for erase to complete or failure to occur */
-	irq_status = wait_for_irq(denali, INTR_STATUS0__ERASE_COMP |
-					INTR_STATUS0__ERASE_FAIL);
+	irq_status = wait_for_irq(denali, INTR_STATUS__ERASE_COMP |
+					INTR_STATUS__ERASE_FAIL);
 
-	denali->status = (irq_status & INTR_STATUS0__ERASE_FAIL) ?
+	denali->status = (irq_status & INTR_STATUS__ERASE_FAIL) ?
 						NAND_STATUS_FAIL : PASS;
 }
 
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index 9b875fd..638668c 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -211,185 +211,46 @@
 #define TRANSFER_MODE				0x400
 #define     TRANSFER_MODE__VALUE			0x0003
 
-#define INTR_STATUS0				0x410
-#define     INTR_STATUS0__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_STATUS0__ECC_ERR			0x0002
-#define     INTR_STATUS0__DMA_CMD_COMP			0x0004
-#define     INTR_STATUS0__TIME_OUT			0x0008
-#define     INTR_STATUS0__PROGRAM_FAIL			0x0010
-#define     INTR_STATUS0__ERASE_FAIL			0x0020
-#define     INTR_STATUS0__LOAD_COMP			0x0040
-#define     INTR_STATUS0__PROGRAM_COMP			0x0080
-#define     INTR_STATUS0__ERASE_COMP			0x0100
-#define     INTR_STATUS0__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_STATUS0__LOCKED_BLK			0x0400
-#define     INTR_STATUS0__UNSUP_CMD			0x0800
-#define     INTR_STATUS0__INT_ACT			0x1000
-#define     INTR_STATUS0__RST_COMP			0x2000
-#define     INTR_STATUS0__PIPE_CMD_ERR			0x4000
-#define     INTR_STATUS0__PAGE_XFER_INC			0x8000
-
-#define INTR_EN0					0x420
-#define     INTR_EN0__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_EN0__ECC_ERR				0x0002
-#define     INTR_EN0__DMA_CMD_COMP			0x0004
-#define     INTR_EN0__TIME_OUT				0x0008
-#define     INTR_EN0__PROGRAM_FAIL			0x0010
-#define     INTR_EN0__ERASE_FAIL			0x0020
-#define     INTR_EN0__LOAD_COMP				0x0040
-#define     INTR_EN0__PROGRAM_COMP			0x0080
-#define     INTR_EN0__ERASE_COMP			0x0100
-#define     INTR_EN0__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN0__LOCKED_BLK			0x0400
-#define     INTR_EN0__UNSUP_CMD				0x0800
-#define     INTR_EN0__INT_ACT				0x1000
-#define     INTR_EN0__RST_COMP				0x2000
-#define     INTR_EN0__PIPE_CMD_ERR			0x4000
-#define     INTR_EN0__PAGE_XFER_INC			0x8000
-
-#define PAGE_CNT0				0x430
-#define     PAGE_CNT0__VALUE				0x00ff
-
-#define ERR_PAGE_ADDR0				0x440
-#define     ERR_PAGE_ADDR0__VALUE			0xffff
-
-#define ERR_BLOCK_ADDR0				0x450
-#define     ERR_BLOCK_ADDR0__VALUE			0xffff
-
-#define INTR_STATUS1				0x460
-#define     INTR_STATUS1__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_STATUS1__ECC_ERR			0x0002
-#define     INTR_STATUS1__DMA_CMD_COMP			0x0004
-#define     INTR_STATUS1__TIME_OUT			0x0008
-#define     INTR_STATUS1__PROGRAM_FAIL			0x0010
-#define     INTR_STATUS1__ERASE_FAIL			0x0020
-#define     INTR_STATUS1__LOAD_COMP			0x0040
-#define     INTR_STATUS1__PROGRAM_COMP			0x0080
-#define     INTR_STATUS1__ERASE_COMP			0x0100
-#define     INTR_STATUS1__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_STATUS1__LOCKED_BLK			0x0400
-#define     INTR_STATUS1__UNSUP_CMD			0x0800
-#define     INTR_STATUS1__INT_ACT			0x1000
-#define     INTR_STATUS1__RST_COMP			0x2000
-#define     INTR_STATUS1__PIPE_CMD_ERR			0x4000
-#define     INTR_STATUS1__PAGE_XFER_INC			0x8000
-
-#define INTR_EN1					0x470
-#define     INTR_EN1__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_EN1__ECC_ERR				0x0002
-#define     INTR_EN1__DMA_CMD_COMP			0x0004
-#define     INTR_EN1__TIME_OUT				0x0008
-#define     INTR_EN1__PROGRAM_FAIL			0x0010
-#define     INTR_EN1__ERASE_FAIL			0x0020
-#define     INTR_EN1__LOAD_COMP				0x0040
-#define     INTR_EN1__PROGRAM_COMP			0x0080
-#define     INTR_EN1__ERASE_COMP			0x0100
-#define     INTR_EN1__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN1__LOCKED_BLK			0x0400
-#define     INTR_EN1__UNSUP_CMD				0x0800
-#define     INTR_EN1__INT_ACT				0x1000
-#define     INTR_EN1__RST_COMP				0x2000
-#define     INTR_EN1__PIPE_CMD_ERR			0x4000
-#define     INTR_EN1__PAGE_XFER_INC			0x8000
-
-#define PAGE_CNT1				0x480
-#define     PAGE_CNT1__VALUE				0x00ff
-
-#define ERR_PAGE_ADDR1				0x490
-#define     ERR_PAGE_ADDR1__VALUE			0xffff
-
-#define ERR_BLOCK_ADDR1				0x4a0
-#define     ERR_BLOCK_ADDR1__VALUE			0xffff
-
-#define INTR_STATUS2				0x4b0
-#define     INTR_STATUS2__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_STATUS2__ECC_ERR			0x0002
-#define     INTR_STATUS2__DMA_CMD_COMP			0x0004
-#define     INTR_STATUS2__TIME_OUT			0x0008
-#define     INTR_STATUS2__PROGRAM_FAIL			0x0010
-#define     INTR_STATUS2__ERASE_FAIL			0x0020
-#define     INTR_STATUS2__LOAD_COMP			0x0040
-#define     INTR_STATUS2__PROGRAM_COMP			0x0080
-#define     INTR_STATUS2__ERASE_COMP			0x0100
-#define     INTR_STATUS2__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_STATUS2__LOCKED_BLK			0x0400
-#define     INTR_STATUS2__UNSUP_CMD			0x0800
-#define     INTR_STATUS2__INT_ACT			0x1000
-#define     INTR_STATUS2__RST_COMP			0x2000
-#define     INTR_STATUS2__PIPE_CMD_ERR			0x4000
-#define     INTR_STATUS2__PAGE_XFER_INC			0x8000
-
-#define INTR_EN2					0x4c0
-#define     INTR_EN2__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_EN2__ECC_ERR				0x0002
-#define     INTR_EN2__DMA_CMD_COMP			0x0004
-#define     INTR_EN2__TIME_OUT				0x0008
-#define     INTR_EN2__PROGRAM_FAIL			0x0010
-#define     INTR_EN2__ERASE_FAIL			0x0020
-#define     INTR_EN2__LOAD_COMP				0x0040
-#define     INTR_EN2__PROGRAM_COMP			0x0080
-#define     INTR_EN2__ERASE_COMP			0x0100
-#define     INTR_EN2__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN2__LOCKED_BLK			0x0400
-#define     INTR_EN2__UNSUP_CMD				0x0800
-#define     INTR_EN2__INT_ACT				0x1000
-#define     INTR_EN2__RST_COMP				0x2000
-#define     INTR_EN2__PIPE_CMD_ERR			0x4000
-#define     INTR_EN2__PAGE_XFER_INC			0x8000
-
-#define PAGE_CNT2				0x4d0
-#define     PAGE_CNT2__VALUE				0x00ff
-
-#define ERR_PAGE_ADDR2				0x4e0
-#define     ERR_PAGE_ADDR2__VALUE			0xffff
-
-#define ERR_BLOCK_ADDR2				0x4f0
-#define     ERR_BLOCK_ADDR2__VALUE			0xffff
-
-#define INTR_STATUS3				0x500
-#define     INTR_STATUS3__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_STATUS3__ECC_ERR			0x0002
-#define     INTR_STATUS3__DMA_CMD_COMP			0x0004
-#define     INTR_STATUS3__TIME_OUT			0x0008
-#define     INTR_STATUS3__PROGRAM_FAIL			0x0010
-#define     INTR_STATUS3__ERASE_FAIL			0x0020
-#define     INTR_STATUS3__LOAD_COMP			0x0040
-#define     INTR_STATUS3__PROGRAM_COMP			0x0080
-#define     INTR_STATUS3__ERASE_COMP			0x0100
-#define     INTR_STATUS3__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_STATUS3__LOCKED_BLK			0x0400
-#define     INTR_STATUS3__UNSUP_CMD			0x0800
-#define     INTR_STATUS3__INT_ACT			0x1000
-#define     INTR_STATUS3__RST_COMP			0x2000
-#define     INTR_STATUS3__PIPE_CMD_ERR			0x4000
-#define     INTR_STATUS3__PAGE_XFER_INC			0x8000
-
-#define INTR_EN3					0x510
-#define     INTR_EN3__ECC_TRANSACTION_DONE		0x0001
-#define     INTR_EN3__ECC_ERR				0x0002
-#define     INTR_EN3__DMA_CMD_COMP			0x0004
-#define     INTR_EN3__TIME_OUT				0x0008
-#define     INTR_EN3__PROGRAM_FAIL			0x0010
-#define     INTR_EN3__ERASE_FAIL			0x0020
-#define     INTR_EN3__LOAD_COMP				0x0040
-#define     INTR_EN3__PROGRAM_COMP			0x0080
-#define     INTR_EN3__ERASE_COMP			0x0100
-#define     INTR_EN3__PIPE_CPYBCK_CMD_COMP		0x0200
-#define     INTR_EN3__LOCKED_BLK			0x0400
-#define     INTR_EN3__UNSUP_CMD				0x0800
-#define     INTR_EN3__INT_ACT				0x1000
-#define     INTR_EN3__RST_COMP				0x2000
-#define     INTR_EN3__PIPE_CMD_ERR			0x4000
-#define     INTR_EN3__PAGE_XFER_INC			0x8000
-
-#define PAGE_CNT3				0x520
-#define     PAGE_CNT3__VALUE				0x00ff
-
-#define ERR_PAGE_ADDR3				0x530
-#define     ERR_PAGE_ADDR3__VALUE			0xffff
-
-#define ERR_BLOCK_ADDR3				0x540
-#define     ERR_BLOCK_ADDR3__VALUE			0xffff
+#define INTR_STATUS(__bank)	(0x410 + ((__bank) * 0x50))
+#define INTR_EN(__bank)		(0x420 + ((__bank) * 0x50))
+
+#define     INTR_STATUS__ECC_TRANSACTION_DONE		0x0001
+#define     INTR_STATUS__ECC_ERR			0x0002
+#define     INTR_STATUS__DMA_CMD_COMP			0x0004
+#define     INTR_STATUS__TIME_OUT			0x0008
+#define     INTR_STATUS__PROGRAM_FAIL			0x0010
+#define     INTR_STATUS__ERASE_FAIL			0x0020
+#define     INTR_STATUS__LOAD_COMP			0x0040
+#define     INTR_STATUS__PROGRAM_COMP			0x0080
+#define     INTR_STATUS__ERASE_COMP			0x0100
+#define     INTR_STATUS__PIPE_CPYBCK_CMD_COMP		0x0200
+#define     INTR_STATUS__LOCKED_BLK			0x0400
+#define     INTR_STATUS__UNSUP_CMD			0x0800
+#define     INTR_STATUS__INT_ACT			0x1000
+#define     INTR_STATUS__RST_COMP			0x2000
+#define     INTR_STATUS__PIPE_CMD_ERR			0x4000
+#define     INTR_STATUS__PAGE_XFER_INC			0x8000
+
+#define     INTR_EN__ECC_TRANSACTION_DONE		0x0001
+#define     INTR_EN__ECC_ERR				0x0002
+#define     INTR_EN__DMA_CMD_COMP			0x0004
+#define     INTR_EN__TIME_OUT				0x0008
+#define     INTR_EN__PROGRAM_FAIL			0x0010
+#define     INTR_EN__ERASE_FAIL				0x0020
+#define     INTR_EN__LOAD_COMP				0x0040
+#define     INTR_EN__PROGRAM_COMP			0x0080
+#define     INTR_EN__ERASE_COMP				0x0100
+#define     INTR_EN__PIPE_CPYBCK_CMD_COMP		0x0200
+#define     INTR_EN__LOCKED_BLK				0x0400
+#define     INTR_EN__UNSUP_CMD				0x0800
+#define     INTR_EN__INT_ACT				0x1000
+#define     INTR_EN__RST_COMP				0x2000
+#define     INTR_EN__PIPE_CMD_ERR			0x4000
+#define     INTR_EN__PAGE_XFER_INC			0x8000
+
+#define PAGE_CNT(__bank)	(0x430 + ((__bank) * 0x50))
+#define ERR_PAGE_ADDR(__bank)	(0x440 + ((__bank) * 0x50))
+#define ERR_BLOCK_ADDR(__bank)	(0x450 + ((__bank) * 0x50))
 
 #define DATA_INTR				0x550
 #define     DATA_INTR__WRITE_SPACE_AV			0x0001
@@ -484,141 +345,23 @@
 #define     PTN_INTR_EN__ACCESS_ERROR_BANK3		0x0010
 #define     PTN_INTR_EN__REG_ACCESS_ERROR		0x0020
 
-#define PERM_SRC_ID_0				0x830
-#define     PERM_SRC_ID_0__SRCID			0x00ff
-#define     PERM_SRC_ID_0__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_0__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_0__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_0__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_0				0x840
-#define     MIN_BLK_ADDR_0__VALUE			0xffff
-
-#define MAX_BLK_ADDR_0				0x850
-#define     MAX_BLK_ADDR_0__VALUE			0xffff
-
-#define MIN_MAX_BANK_0				0x860
-#define     MIN_MAX_BANK_0__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_0__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_1				0x870
-#define     PERM_SRC_ID_1__SRCID			0x00ff
-#define     PERM_SRC_ID_1__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_1__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_1__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_1__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_1				0x880
-#define     MIN_BLK_ADDR_1__VALUE			0xffff
-
-#define MAX_BLK_ADDR_1				0x890
-#define     MAX_BLK_ADDR_1__VALUE			0xffff
-
-#define MIN_MAX_BANK_1				0x8a0
-#define     MIN_MAX_BANK_1__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_1__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_2				0x8b0
-#define     PERM_SRC_ID_2__SRCID			0x00ff
-#define     PERM_SRC_ID_2__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_2__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_2__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_2__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_2				0x8c0
-#define     MIN_BLK_ADDR_2__VALUE			0xffff
-
-#define MAX_BLK_ADDR_2				0x8d0
-#define     MAX_BLK_ADDR_2__VALUE			0xffff
-
-#define MIN_MAX_BANK_2				0x8e0
-#define     MIN_MAX_BANK_2__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_2__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_3				0x8f0
-#define     PERM_SRC_ID_3__SRCID			0x00ff
-#define     PERM_SRC_ID_3__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_3__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_3__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_3__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_3				0x900
-#define     MIN_BLK_ADDR_3__VALUE			0xffff
-
-#define MAX_BLK_ADDR_3				0x910
-#define     MAX_BLK_ADDR_3__VALUE			0xffff
-
-#define MIN_MAX_BANK_3				0x920
-#define     MIN_MAX_BANK_3__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_3__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_4				0x930
-#define     PERM_SRC_ID_4__SRCID			0x00ff
-#define     PERM_SRC_ID_4__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_4__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_4__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_4__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_4				0x940
-#define     MIN_BLK_ADDR_4__VALUE			0xffff
-
-#define MAX_BLK_ADDR_4				0x950
-#define     MAX_BLK_ADDR_4__VALUE			0xffff
-
-#define MIN_MAX_BANK_4				0x960
-#define     MIN_MAX_BANK_4__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_4__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_5				0x970
-#define     PERM_SRC_ID_5__SRCID			0x00ff
-#define     PERM_SRC_ID_5__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_5__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_5__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_5__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_5				0x980
-#define     MIN_BLK_ADDR_5__VALUE			0xffff
-
-#define MAX_BLK_ADDR_5				0x990
-#define     MAX_BLK_ADDR_5__VALUE			0xffff
-
-#define MIN_MAX_BANK_5				0x9a0
-#define     MIN_MAX_BANK_5__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_5__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_6				0x9b0
-#define     PERM_SRC_ID_6__SRCID			0x00ff
-#define     PERM_SRC_ID_6__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_6__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_6__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_6__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_6				0x9c0
-#define     MIN_BLK_ADDR_6__VALUE			0xffff
-
-#define MAX_BLK_ADDR_6				0x9d0
-#define     MAX_BLK_ADDR_6__VALUE			0xffff
-
-#define MIN_MAX_BANK_6				0x9e0
-#define     MIN_MAX_BANK_6__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_6__MAX_VALUE			0x000c
-
-#define PERM_SRC_ID_7				0x9f0
-#define     PERM_SRC_ID_7__SRCID			0x00ff
-#define     PERM_SRC_ID_7__DIRECT_ACCESS_ACTIVE		0x0800
-#define     PERM_SRC_ID_7__WRITE_ACTIVE			0x2000
-#define     PERM_SRC_ID_7__READ_ACTIVE			0x4000
-#define     PERM_SRC_ID_7__PARTITION_VALID		0x8000
-
-#define MIN_BLK_ADDR_7				0xa00
-#define     MIN_BLK_ADDR_7__VALUE			0xffff
-
-#define MAX_BLK_ADDR_7				0xa10
-#define     MAX_BLK_ADDR_7__VALUE			0xffff
-
-#define MIN_MAX_BANK_7				0xa20
-#define     MIN_MAX_BANK_7__MIN_VALUE			0x0003
-#define     MIN_MAX_BANK_7__MAX_VALUE			0x000c
+#define PERM_SRC_ID(__bank)	(0x830 + ((__bank) * 0x40))
+#define     PERM_SRC_ID__SRCID				0x00ff
+#define     PERM_SRC_ID__DIRECT_ACCESS_ACTIVE		0x0800
+#define     PERM_SRC_ID__WRITE_ACTIVE			0x2000
+#define     PERM_SRC_ID__READ_ACTIVE			0x4000
+#define     PERM_SRC_ID__PARTITION_VALID		0x8000
+
+#define MIN_BLK_ADDR(__bank)	(0x840 + ((__bank) * 0x40))
+#define     MIN_BLK_ADDR__VALUE				0xffff
+
+#define MAX_BLK_ADDR(__bank)	(0x850 + ((__bank) * 0x40))
+#define     MAX_BLK_ADDR__VALUE				0xffff
+
+#define MIN_MAX_BANK(__bank)	(0x860 + ((__bank) * 0x40))
+#define     MIN_MAX_BANK__MIN_VALUE			0x0003
+#define     MIN_MAX_BANK__MAX_VALUE			0x000c
+
 
 /* ffsdefs.h */
 #define CLEAR 0                 /*use this to clear a field instead of "fail"*/
-- 
1.7.4.4

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

* [RFC PATCH 3/9] nand/denali: detect the number of banks
  2011-05-06 14:28 [RFC PATCH 0/9] Support for MMIO based Denali NAND controller Jamie Iles
  2011-05-06 14:28 ` [RFC PATCH 1/9] nand/denali: convert to generic DMA API Jamie Iles
  2011-05-06 14:28 ` [RFC PATCH 2/9] nand/denali: remove nearly-duplicated register definitions Jamie Iles
@ 2011-05-06 14:28 ` Jamie Iles
  2011-05-12  8:05   ` Artem Bityutskiy
  2011-05-06 14:28 ` [RFC PATCH 4/9] nand/denali: split the generic driver and PCI layer Jamie Iles
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 14:28 UTC (permalink / raw)
  To: linux-mtd; +Cc: Jamie Iles, dwmw2, chuanxiao.dong

Not all configurations of the Denali controller support 4 banks.  The
controller can support between 1 and 16 banks.  Detect this from the
design features register.

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 drivers/mtd/nand/denali.c |   28 ++++++++++++++++++++--------
 drivers/mtd/nand/denali.h |    2 +-
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 70a439c..3af0a95 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -178,11 +178,11 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
 		       __FILE__, __LINE__, __func__);
 
-	for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++)
+	for (i = 0 ; i < denali->max_banks; i++)
 		iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
 		denali->flash_reg + INTR_STATUS(i));
 
-	for (i = 0 ; i < LLD_MAX_FLASH_BANKS; i++) {
+	for (i = 0 ; i < denali->max_banks; i++) {
 		iowrite32(1 << i, denali->flash_reg + DEVICE_RESET);
 		while (!(ioread32(denali->flash_reg +
 				INTR_STATUS(i)) &
@@ -194,7 +194,7 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 			"NAND Reset operation timed out on bank %d\n", i);
 	}
 
-	for (i = 0; i < LLD_MAX_FLASH_BANKS; i++)
+	for (i = 0; i < denali->max_banks; i++)
 		iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
 			denali->flash_reg + INTR_STATUS(i));
 
@@ -405,11 +405,11 @@ static void get_hynix_nand_para(struct denali_nand_info *denali,
  */
 static void find_valid_banks(struct denali_nand_info *denali)
 {
-	uint32_t id[LLD_MAX_FLASH_BANKS];
+	uint32_t id[denali->max_banks];
 	int i;
 
 	denali->total_used_banks = 1;
-	for (i = 0; i < LLD_MAX_FLASH_BANKS; i++) {
+	for (i = 0; i < denali->max_banks; i++) {
 		index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 0), 0x90);
 		index_addr(denali, (uint32_t)(MODE_11 | (i << 24) | 1), 0);
 		index_addr_read_data(denali,
@@ -445,6 +445,17 @@ static void find_valid_banks(struct denali_nand_info *denali)
 		"denali->total_used_banks: %d\n", denali->total_used_banks);
 }
 
+/*
+ * Use the configuration feature register to determine the maximum number of
+ * banks that the hardware supports.
+ */
+static void detect_max_banks(struct denali_nand_info *denali)
+{
+	uint32_t features = ioread32(denali->flash_reg + FEATURES);
+
+	denali->max_banks = 2 << (features & FEATURES__N_BANKS);
+}
+
 static void detect_partition_feature(struct denali_nand_info *denali)
 {
 	/* For MRST platform, denali->fwblks represent the
@@ -562,7 +573,7 @@ static void denali_irq_init(struct denali_nand_info *denali)
 	int_mask = DENALI_IRQ_ALL;
 
 	/* Clear all status bits */
-	for (i = 0; i < LLD_MAX_FLASH_BANKS; ++i)
+	for (i = 0; i < denali->max_banks; ++i)
 		iowrite32(0xFFFF, denali->flash_reg + INTR_STATUS(i));
 
 	denali_irq_enable(denali, int_mask);
@@ -579,7 +590,7 @@ static void denali_irq_enable(struct denali_nand_info *denali,
 {
 	int i;
 
-	for (i = 0; i < LLD_MAX_FLASH_BANKS; ++i)
+	for (i = 0; i < denali->max_banks; ++i)
 		iowrite32(int_mask, denali->flash_reg + INTR_EN(i));
 }
 
@@ -1345,6 +1356,7 @@ static void denali_hw_init(struct denali_nand_info *denali)
 	/* Should set value for these registers when init */
 	iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES);
 	iowrite32(1, denali->flash_reg + ECC_ENABLE);
+	detect_max_banks(denali);
 	denali_nand_timing_set(denali);
 	denali_irq_init(denali);
 }
@@ -1522,7 +1534,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	/* scan for NAND devices attached to the controller
 	 * this is the first stage in a two step process to register
 	 * with the nand subsystem */
-	if (nand_scan_ident(&denali->mtd, LLD_MAX_FLASH_BANKS, NULL)) {
+	if (nand_scan_ident(&denali->mtd, denali->max_banks, NULL)) {
 		ret = -ENXIO;
 		goto failed_req_irq;
 	}
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index 638668c..fabb9d5 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -454,7 +454,6 @@
 #define READ_WRITE_ENABLE_HIGH_COUNT    22
 
 #define ECC_SECTOR_SIZE     512
-#define LLD_MAX_FLASH_BANKS     4
 
 #define DENALI_BUF_SIZE		(NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE)
 
@@ -494,6 +493,7 @@ struct denali_nand_info {
 	uint32_t totalblks;
 	uint32_t blksperchip;
 	uint32_t bbtskipbytes;
+	uint32_t max_banks;
 };
 
 #endif /*_LLD_NAND_*/
-- 
1.7.4.4

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

* [RFC PATCH 4/9] nand/denali: split the generic driver and PCI layer
  2011-05-06 14:28 [RFC PATCH 0/9] Support for MMIO based Denali NAND controller Jamie Iles
                   ` (2 preceding siblings ...)
  2011-05-06 14:28 ` [RFC PATCH 3/9] nand/denali: detect the number of banks Jamie Iles
@ 2011-05-06 14:28 ` Jamie Iles
  2011-05-12  8:08   ` Artem Bityutskiy
  2011-05-06 14:28 ` [RFC PATCH 5/9] nand/denali: convert to dev_() printk helpers Jamie Iles
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 14:28 UTC (permalink / raw)
  To: linux-mtd; +Cc: Jamie Iles, dwmw2, chuanxiao.dong

The Denali controller can also be found in SoC devices attached to a
simple bus.  Move the PCI specific parts into denali_pci so that we can
add a denali_mmio that uses the same driver but for a platform_device
instead of a PCI based device.

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 drivers/mtd/nand/Kconfig      |   11 +++-
 drivers/mtd/nand/Makefile     |    1 +
 drivers/mtd/nand/denali.c     |  153 +++++------------------------------------
 drivers/mtd/nand/denali.h     |    4 +
 drivers/mtd/nand/denali_pci.c |  145 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 178 insertions(+), 136 deletions(-)
 create mode 100644 drivers/mtd/nand/denali_pci.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index edec457..d629b68 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -66,8 +66,15 @@ config MTD_NAND_AUTCPU12
 	  access the SmartMediaCard.
 
 config MTD_NAND_DENALI
-       depends on PCI
+        tristate "Support Denali NAND controller"
+        help
+	  Enable support for the Denali NAND controller.  This should be
+	  combined with either the PCI or platform drivers to provide device
+	  registration.
+
+config MTD_NAND_DENALI_PCI
         tristate "Support Denali NAND controller on Intel Moorestown"
+	depends on PCI && MTD_NAND_DENALI
         help
           Enable the driver for NAND flash on Intel Moorestown, using the
           Denali NAND controller core.
@@ -75,7 +82,7 @@ config MTD_NAND_DENALI
 config MTD_NAND_DENALI_SCRATCH_REG_ADDR
         hex "Denali NAND size scratch register address"
         default "0xFF108018"
-        depends on MTD_NAND_DENALI
+        depends on MTD_NAND_DENALI_PCI
         help
           Some platforms place the NAND chip size in a scratch register
           because (some versions of) the driver aren't able to automatically
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 5745d83..ed4a2d8 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_NAND_SPIA)		+= spia.o
 obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)		+= autcpu12.o
 obj-$(CONFIG_MTD_NAND_DENALI)		+= denali.o
+obj-$(CONFIG_MTD_NAND_DENALI_PCI)	+= denali_pci.o
 obj-$(CONFIG_MTD_NAND_EDB7312)		+= edb7312.o
 obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
 obj-$(CONFIG_MTD_NAND_BF5XX)		+= bf5xx_nand.o
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 3af0a95..e389c8c 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -16,14 +16,12 @@
  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
-
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/pci.h>
 #include <linux/mtd/mtd.h>
 #include <linux/module.h>
 
@@ -89,13 +87,6 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
  * format the bank into the proper bits for the controller */
 #define BANK(x) ((x) << 24)
 
-/* List of platforms this NAND controller has be integrated into */
-static const struct pci_device_id denali_pci_ids[] = {
-	{ PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
-	{ PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
-	{ /* end: all zeroes */ }
-};
-
 /* forward declarations */
 static void clear_interrupts(struct denali_nand_info *denali);
 static uint32_t wait_for_irq(struct denali_nand_info *denali,
@@ -1420,107 +1411,49 @@ void denali_drv_init(struct denali_nand_info *denali)
 	denali->irq_status = 0;
 }
 
-/* driver entry point */
-static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+int denali_init(struct denali_nand_info *denali)
 {
-	int ret = -ENODEV;
-	resource_size_t csr_base, mem_base;
-	unsigned long csr_len, mem_len;
-	struct denali_nand_info *denali;
-
-	denali = kzalloc(sizeof(*denali), GFP_KERNEL);
-	if (!denali)
-		return -ENOMEM;
-
-	ret = pci_enable_device(dev);
-	if (ret) {
-		printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
-		goto failed_alloc_memery;
-	}
+	int ret;
 
-	if (id->driver_data == INTEL_CE4100) {
+	if (denali->platform == INTEL_CE4100) {
 		/* Due to a silicon limitation, we can only support
 		 * ONFI timing mode 1 and below.
 		 */
 		if (onfi_timing_mode < -1 || onfi_timing_mode > 1) {
 			printk(KERN_ERR "Intel CE4100 only supports"
 					" ONFI timing mode 1 or below\n");
-			ret = -EINVAL;
-			goto failed_enable_dev;
-		}
-		denali->platform = INTEL_CE4100;
-		mem_base = pci_resource_start(dev, 0);
-		mem_len = pci_resource_len(dev, 1);
-		csr_base = pci_resource_start(dev, 1);
-		csr_len = pci_resource_len(dev, 1);
-	} else {
-		denali->platform = INTEL_MRST;
-		csr_base = pci_resource_start(dev, 0);
-		csr_len = pci_resource_len(dev, 0);
-		mem_base = pci_resource_start(dev, 1);
-		mem_len = pci_resource_len(dev, 1);
-		if (!mem_len) {
-			mem_base = csr_base + csr_len;
-			mem_len = csr_len;
+			return -EINVAL;
 		}
 	}
 
 	/* Is 32-bit DMA supported? */
-	ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
+	ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
 	if (ret) {
 		printk(KERN_ERR "Spectra: no usable DMA configuration\n");
-		goto failed_enable_dev;
+		return ret;
 	}
-	denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf,
+	denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf,
 					     DENALI_BUF_SIZE,
 					     DMA_BIDIRECTIONAL);
 
-	if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) {
-		dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n");
-		goto failed_enable_dev;
+	if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
+		dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
+		return -EIO;
 	}
-
-	pci_set_master(dev);
-	denali->dev = &dev->dev;
-	denali->mtd.dev.parent = &dev->dev;
-
-	ret = pci_request_regions(dev, DENALI_NAND_NAME);
-	if (ret) {
-		printk(KERN_ERR "Spectra: Unable to request memory regions\n");
-		goto failed_dma_map;
-	}
-
-	denali->flash_reg = ioremap_nocache(csr_base, csr_len);
-	if (!denali->flash_reg) {
-		printk(KERN_ERR "Spectra: Unable to remap memory region\n");
-		ret = -ENOMEM;
-		goto failed_req_regions;
-	}
-
-	denali->flash_mem = ioremap_nocache(mem_base, mem_len);
-	if (!denali->flash_mem) {
-		printk(KERN_ERR "Spectra: ioremap_nocache failed!");
-		ret = -ENOMEM;
-		goto failed_remap_reg;
-	}
-
+	denali->mtd.dev.parent = denali->dev;
 	denali_hw_init(denali);
 	denali_drv_init(denali);
 
 	/* denali_isr register is done after all the hardware
 	 * initilization is finished*/
-	if (request_irq(dev->irq, denali_isr, IRQF_SHARED,
+	if (request_irq(denali->irq, denali_isr, IRQF_SHARED,
 			DENALI_NAND_NAME, denali)) {
 		printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
-		ret = -ENODEV;
-		goto failed_remap_mem;
+		return -ENODEV;
 	}
 
 	/* now that our ISR is registered, we can enable interrupts */
 	denali_set_intr_modes(denali, true);
-
-	pci_set_drvdata(dev, denali);
-
 	denali->mtd.name = "denali-nand";
 	denali->mtd.owner = THIS_MODULE;
 	denali->mtd.priv = &denali->nand;
@@ -1646,71 +1579,23 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	ret = add_mtd_device(&denali->mtd);
 	if (ret) {
-		dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n",
+		dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
 				ret);
 		goto failed_req_irq;
 	}
 	return 0;
 
 failed_req_irq:
-	denali_irq_cleanup(dev->irq, denali);
-failed_remap_mem:
-	iounmap(denali->flash_mem);
-failed_remap_reg:
-	iounmap(denali->flash_reg);
-failed_req_regions:
-	pci_release_regions(dev);
-failed_dma_map:
-	dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
-			 DMA_BIDIRECTIONAL);
-failed_enable_dev:
-	pci_disable_device(dev);
-failed_alloc_memery:
-	kfree(denali);
+	denali_irq_cleanup(denali->irq, denali);
+
 	return ret;
 }
 
-/* driver exit point */
-static void denali_pci_remove(struct pci_dev *dev)
+void denali_remove(struct denali_nand_info *denali)
 {
-	struct denali_nand_info *denali = pci_get_drvdata(dev);
-
 	nand_release(&denali->mtd);
 	del_mtd_device(&denali->mtd);
-
-	denali_irq_cleanup(dev->irq, denali);
-
-	iounmap(denali->flash_reg);
-	iounmap(denali->flash_mem);
-	pci_release_regions(dev);
-	pci_disable_device(dev);
-	dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
+	denali_irq_cleanup(denali->irq, denali);
+	dma_unmap_single(denali->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
 			 DMA_BIDIRECTIONAL);
-	pci_set_drvdata(dev, NULL);
-	kfree(denali);
-}
-
-MODULE_DEVICE_TABLE(pci, denali_pci_ids);
-
-static struct pci_driver denali_pci_driver = {
-	.name = DENALI_NAND_NAME,
-	.id_table = denali_pci_ids,
-	.probe = denali_pci_probe,
-	.remove = denali_pci_remove,
-};
-
-static int __devinit denali_init(void)
-{
-	printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n",
-			__DATE__, __TIME__);
-	return pci_register_driver(&denali_pci_driver);
 }
-
-/* Free memory */
-static void __devexit denali_exit(void)
-{
-	pci_unregister_driver(&denali_pci_driver);
-}
-
-module_init(denali_init);
-module_exit(denali_exit);
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index fabb9d5..e5aa995 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -487,6 +487,7 @@ struct denali_nand_info {
 	uint32_t irq_status;
 	int irq_debug_array[32];
 	int idx;
+	int irq;
 
 	uint32_t devnum;	/* represent how many nands connected */
 	uint32_t fwblks; /* represent how many blocks FW used */
@@ -496,4 +497,7 @@ struct denali_nand_info {
 	uint32_t max_banks;
 };
 
+extern int denali_init(struct denali_nand_info *denali);
+extern void denali_remove(struct denali_nand_info *denali);
+
 #endif /*_LLD_NAND_*/
diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c
new file mode 100644
index 0000000..19b11af
--- /dev/null
+++ b/drivers/mtd/nand/denali_pci.c
@@ -0,0 +1,145 @@
+/*
+ * NAND Flash Controller Device Driver
+ * Copyright © 2009-2010, Intel Corporation and its suppliers.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "denali.h"
+
+#define DENALI_NAND_NAME    "denali-nand-pci"
+
+/* List of platforms this NAND controller has be integrated into */
+static DEFINE_PCI_DEVICE_TABLE(denali_pci_ids) = {
+	{ PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
+	{ PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
+	{ /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(pci, denali_pci_ids);
+
+static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int ret = -ENODEV;
+	resource_size_t csr_base, mem_base;
+	unsigned long csr_len, mem_len;
+	struct denali_nand_info *denali;
+
+	denali = kzalloc(sizeof(*denali), GFP_KERNEL);
+	if (!denali)
+		return -ENOMEM;
+
+	ret = pci_enable_device(dev);
+	if (ret) {
+		printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
+		goto failed_alloc_memery;
+	}
+
+	if (id->driver_data == INTEL_CE4100) {
+		denali->platform = INTEL_CE4100;
+		mem_base = pci_resource_start(dev, 0);
+		mem_len = pci_resource_len(dev, 1);
+		csr_base = pci_resource_start(dev, 1);
+		csr_len = pci_resource_len(dev, 1);
+	} else {
+		denali->platform = INTEL_MRST;
+		csr_base = pci_resource_start(dev, 0);
+		csr_len = pci_resource_len(dev, 0);
+		mem_base = pci_resource_start(dev, 1);
+		mem_len = pci_resource_len(dev, 1);
+		if (!mem_len) {
+			mem_base = csr_base + csr_len;
+			mem_len = csr_len;
+		}
+	}
+
+	pci_set_master(dev);
+	denali->dev = &dev->dev;
+	denali->irq = dev->irq;
+
+	ret = pci_request_regions(dev, DENALI_NAND_NAME);
+	if (ret) {
+		printk(KERN_ERR "Spectra: Unable to request memory regions\n");
+		goto failed_enable_dev;
+	}
+
+	denali->flash_reg = ioremap_nocache(csr_base, csr_len);
+	if (!denali->flash_reg) {
+		printk(KERN_ERR "Spectra: Unable to remap memory region\n");
+		ret = -ENOMEM;
+		goto failed_req_regions;
+	}
+
+	denali->flash_mem = ioremap_nocache(mem_base, mem_len);
+	if (!denali->flash_mem) {
+		printk(KERN_ERR "Spectra: ioremap_nocache failed!");
+		ret = -ENOMEM;
+		goto failed_remap_reg;
+	}
+
+	ret = denali_init(denali);
+	if (ret)
+		goto failed_remap_mem;
+
+	pci_set_drvdata(dev, denali);
+
+	return 0;
+
+failed_remap_mem:
+	iounmap(denali->flash_mem);
+failed_remap_reg:
+	iounmap(denali->flash_reg);
+failed_req_regions:
+	pci_release_regions(dev);
+failed_enable_dev:
+	pci_disable_device(dev);
+failed_alloc_memery:
+	kfree(denali);
+
+	return ret;
+}
+
+/* driver exit point */
+static void denali_pci_remove(struct pci_dev *dev)
+{
+	struct denali_nand_info *denali = pci_get_drvdata(dev);
+
+	denali_remove(denali);
+	iounmap(denali->flash_reg);
+	iounmap(denali->flash_mem);
+	pci_release_regions(dev);
+	pci_disable_device(dev);
+	pci_set_drvdata(dev, NULL);
+	kfree(denali);
+}
+
+static struct pci_driver denali_pci_driver = {
+	.name = DENALI_NAND_NAME,
+	.id_table = denali_pci_ids,
+	.probe = denali_pci_probe,
+	.remove = denali_pci_remove,
+};
+
+static int __devinit denali_init_pci(void)
+{
+	printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n",
+			__DATE__, __TIME__);
+	return pci_register_driver(&denali_pci_driver);
+}
+module_init(denali_init_pci);
+
+static void __devexit denali_exit_pci(void)
+{
+	pci_unregister_driver(&denali_pci_driver);
+}
+module_exit(denali_exit_pci);
-- 
1.7.4.4

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

* [RFC PATCH 5/9] nand/denali: convert to dev_() printk helpers
  2011-05-06 14:28 [RFC PATCH 0/9] Support for MMIO based Denali NAND controller Jamie Iles
                   ` (3 preceding siblings ...)
  2011-05-06 14:28 ` [RFC PATCH 4/9] nand/denali: split the generic driver and PCI layer Jamie Iles
@ 2011-05-06 14:28 ` Jamie Iles
  2011-05-12  8:10   ` Artem Bityutskiy
  2011-05-06 14:29 ` [RFC PATCH 6/9] nand/denali: add an mmio driver Jamie Iles
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 14:28 UTC (permalink / raw)
  To: linux-mtd; +Cc: Jamie Iles, dwmw2, chuanxiao.dong

Use the dev_() printk helpers rather than printk so the name of the
device is include.  Also remove a duplicate definition of BANK().

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 drivers/mtd/nand/denali.c     |  122 ++++++++++++++++++-----------------------
 drivers/mtd/nand/denali_pci.c |   10 +--
 2 files changed, 58 insertions(+), 74 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index e389c8c..ce6afd7 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -166,8 +166,7 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 {
 	uint32_t i;
 
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		       __FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "resetting\n");
 
 	for (i = 0 ; i < denali->max_banks; i++)
 		iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
@@ -182,7 +181,8 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 		if (ioread32(denali->flash_reg + INTR_STATUS(i)) &
 			INTR_STATUS__TIME_OUT)
 			dev_dbg(denali->dev,
-			"NAND Reset operation timed out on bank %d\n", i);
+				"NAND Reset operation timed out on bank %d\n",
+				i);
 	}
 
 	for (i = 0; i < denali->max_banks; i++)
@@ -219,8 +219,7 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
 	uint16_t acc_clks;
 	uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt;
 
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		       __FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "init timing\n");
 
 	en_lo = CEIL_DIV(Trp[mode], CLK_X);
 	en_hi = CEIL_DIV(Treh[mode], CLK_X);
@@ -256,8 +255,8 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
 		acc_clks++;
 
 	if ((data_invalid - acc_clks * CLK_X) < 2)
-		dev_warn(denali->dev, "%s, Line %d: Warning!\n",
-			__FILE__, __LINE__);
+		dev_warn(denali->dev, "%s, Line %d: Warning!\n", __FILE__,
+			 __LINE__);
 
 	addr_2_data = CEIL_DIV(Tadl[mode], CLK_X);
 	re_2_we = CEIL_DIV(Trhw[mode], CLK_X);
@@ -385,9 +384,8 @@ static void get_hynix_nand_para(struct denali_nand_info *denali,
 		break;
 	default:
 		dev_warn(denali->dev,
-			"Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
-			"Will use default parameter values instead.\n",
-			device_id);
+			 "unknown Hynix NAND (Device ID: 0x%x). Will use default parameter values instead.\n",
+			 device_id);
 	}
 }
 
@@ -406,8 +404,8 @@ static void find_valid_banks(struct denali_nand_info *denali)
 		index_addr_read_data(denali,
 				(uint32_t)(MODE_11 | (i << 24) | 2), &id[i]);
 
-		dev_dbg(denali->dev,
-			"Return 1st ID for bank[%d]: %x\n", i, id[i]);
+		dev_dbg(denali->dev, "Return 1st ID for bank[%d]: %x\n", i,
+			id[i]);
 
 		if (i == 0) {
 			if (!(id[i] & 0x0ff))
@@ -427,13 +425,12 @@ static void find_valid_banks(struct denali_nand_info *denali)
 		 */
 		if (denali->total_used_banks != 1) {
 			dev_err(denali->dev,
-					"Sorry, Intel CE4100 only supports "
-					"a single NAND device.\n");
+				"Sorry, Intel CE4100 only supports a single NAND device.\n");
 			BUG();
 		}
 	}
-	dev_dbg(denali->dev,
-		"denali->total_used_banks: %d\n", denali->total_used_banks);
+	dev_dbg(denali->dev, "denali->total_used_banks: %d\n",
+		denali->total_used_banks);
 }
 
 /*
@@ -477,9 +474,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 	uint32_t id_bytes[5], addr;
 	uint8_t i, maf_id, device_id;
 
-	dev_dbg(denali->dev,
-			"%s, Line %d, Function: %s\n",
-			__FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "set the timing\n");
 
 	/* Use read id method to get device ID and other
 	 * params. For some NAND chips, controller can't
@@ -507,18 +502,17 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 	}
 
 	dev_info(denali->dev,
-			"Dump timing register values:"
-			"acc_clks: %d, re_2_we: %d, re_2_re: %d\n"
-			"we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n"
-			"rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
-			ioread32(denali->flash_reg + ACC_CLKS),
-			ioread32(denali->flash_reg + RE_2_WE),
-			ioread32(denali->flash_reg + RE_2_RE),
-			ioread32(denali->flash_reg + WE_2_RE),
-			ioread32(denali->flash_reg + ADDR_2_DATA),
-			ioread32(denali->flash_reg + RDWR_EN_LO_CNT),
-			ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
-			ioread32(denali->flash_reg + CS_SETUP_CNT));
+		 "Dump timing register values: acc_clks: %d, re_2_we: %d, re_2_re: %d\n"
+		 "we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n"
+		 "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
+		 ioread32(denali->flash_reg + ACC_CLKS),
+		 ioread32(denali->flash_reg + RE_2_WE),
+		 ioread32(denali->flash_reg + RE_2_RE),
+		 ioread32(denali->flash_reg + WE_2_RE),
+		 ioread32(denali->flash_reg + ADDR_2_DATA),
+		 ioread32(denali->flash_reg + RDWR_EN_LO_CNT),
+		 ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
+		 ioread32(denali->flash_reg + CS_SETUP_CNT));
 
 	find_valid_banks(denali);
 
@@ -536,8 +530,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 static void denali_set_intr_modes(struct denali_nand_info *denali,
 					uint16_t INT_ENABLE)
 {
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		       __FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "set interrupt modes\n");
 
 	if (INT_ENABLE)
 		iowrite32(1, denali->flash_reg + GLOBAL_INT_ENABLE);
@@ -660,7 +653,6 @@ static irqreturn_t denali_isr(int irq, void *dev_id)
 	spin_unlock(&denali->irq_lock);
 	return result;
 }
-#define BANK(x) ((x) << 24)
 
 static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
 {
@@ -690,8 +682,9 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
 
 	if (comp_res == 0) {
 		/* timeout */
-		printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n",
-				intr_status, irq_mask);
+		dev_err(&denali->mtd.dev,
+			"timeout occurred, status = 0x%x, mask = 0x%x\n",
+			intr_status, irq_mask);
 
 		intr_status = 0;
 	}
@@ -776,9 +769,8 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
 
 			if (irq_status == 0) {
 				dev_err(denali->dev,
-						"cmd, page, addr on timeout "
-						"(0x%x, 0x%x, 0x%x)\n",
-						cmd, denali->page, addr);
+					"cmd, page, addr on timeout (0x%x, 0x%x, 0x%x)\n",
+					cmd, denali->page, addr);
 				status = FAIL;
 			} else {
 				cmd = MODE_01 | addr;
@@ -880,7 +872,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 
 		if (irq_status == 0)
 			dev_err(denali->dev, "page on OOB timeout %d\n",
-					denali->page);
+				denali->page);
 
 		/* We set the device back to MAIN_ACCESS here as I observed
 		 * instability with the controller if you do a block erase
@@ -1056,9 +1048,8 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	irq_status = wait_for_irq(denali, irq_mask);
 
 	if (irq_status == 0) {
-		dev_err(denali->dev,
-				"timeout on write_page (type = %d)\n",
-				raw_xfer);
+		dev_err(denali->dev, "timeout on write_page (type = %d)\n",
+			raw_xfer);
 		denali->status =
 			(irq_status & INTR_STATUS__PROGRAM_FAIL) ?
 			NAND_STATUS_FAIL : PASS;
@@ -1123,9 +1114,9 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	bool check_erased_page = false;
 
 	if (page != denali->page) {
-		dev_err(denali->dev, "IN %s: page %d is not"
-				" equal to denali->page %d, investigate!!",
-				__func__, page, denali->page);
+		dev_err(denali->dev,
+			"IN %s: page %d is not equal to denali->page %d, investigate!!",
+			__func__, page, denali->page);
 		BUG();
 	}
 
@@ -1173,9 +1164,8 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 	uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP;
 
 	if (page != denali->page) {
-		dev_err(denali->dev, "IN %s: page %d is not"
-				" equal to denali->page %d, investigate!!",
-				__func__, page, denali->page);
+		dev_err(denali->dev, "IN %s: page %d is not equal to denali->page %d, investigate!!",
+			__func__, page, denali->page);
 		BUG();
 	}
 
@@ -1291,8 +1281,8 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
 		/* TODO: Read OOB data */
 		break;
 	default:
-		printk(KERN_ERR ": unsupported command"
-				" received 0x%x\n", cmd);
+		dev_err(&denali->mtd.dev, "unsupported command received 0x%x\n",
+			cmd);
 		break;
 	}
 }
@@ -1302,8 +1292,7 @@ static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
 				uint8_t *ecc_code)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(denali->dev,
-			"denali_ecc_calculate called unexpectedly\n");
+	dev_err(denali->dev, "denali_ecc_calculate called unexpectedly\n");
 	BUG();
 	return -EIO;
 }
@@ -1312,8 +1301,7 @@ static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
 				uint8_t *read_ecc, uint8_t *calc_ecc)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(denali->dev,
-			"denali_ecc_correct called unexpectedly\n");
+	dev_err(denali->dev, "denali_ecc_correct called unexpectedly\n");
 	BUG();
 	return -EIO;
 }
@@ -1321,8 +1309,7 @@ static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
 static void denali_ecc_hwctl(struct mtd_info *mtd, int mode)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(denali->dev,
-			"denali_ecc_hwctl called unexpectedly\n");
+	dev_err(denali->dev, "denali_ecc_hwctl called unexpectedly\n");
 	BUG();
 }
 /* end NAND core entry points */
@@ -1420,8 +1407,8 @@ int denali_init(struct denali_nand_info *denali)
 		 * ONFI timing mode 1 and below.
 		 */
 		if (onfi_timing_mode < -1 || onfi_timing_mode > 1) {
-			printk(KERN_ERR "Intel CE4100 only supports"
-					" ONFI timing mode 1 or below\n");
+			dev_err(denali->dev,
+				"Intel CE4100 only supports ONFI timing mode 1 or below\n");
 			return -EINVAL;
 		}
 	}
@@ -1429,7 +1416,7 @@ int denali_init(struct denali_nand_info *denali)
 	/* Is 32-bit DMA supported? */
 	ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
 	if (ret) {
-		printk(KERN_ERR "Spectra: no usable DMA configuration\n");
+		dev_err(denali->dev, "no usable DMA configuration\n");
 		return ret;
 	}
 	denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf,
@@ -1437,7 +1424,7 @@ int denali_init(struct denali_nand_info *denali)
 					     DMA_BIDIRECTIONAL);
 
 	if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
-		dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
+		dev_err(denali->dev, "failed to map DMA buffer\n");
 		return -EIO;
 	}
 	denali->mtd.dev.parent = denali->dev;
@@ -1448,7 +1435,7 @@ int denali_init(struct denali_nand_info *denali)
 	 * initilization is finished*/
 	if (request_irq(denali->irq, denali_isr, IRQF_SHARED,
 			DENALI_NAND_NAME, denali)) {
-		printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
+		dev_err(denali->dev, "unable to allocate IRQ\n");
 		return -ENODEV;
 	}
 
@@ -1477,8 +1464,8 @@ int denali_init(struct denali_nand_info *denali)
 	 */
 	if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) {
 		ret = -ENODEV;
-		printk(KERN_ERR "Spectra: device size not supported by this "
-			"version of MTD.");
+		dev_err(denali->dev,
+			"device size not supported by this version of MTD.");
 		goto failed_req_irq;
 	}
 
@@ -1528,8 +1515,8 @@ int denali_init(struct denali_nand_info *denali)
 	} else if (denali->mtd.oobsize < (denali->bbtskipbytes +
 			ECC_8BITS * (denali->mtd.writesize /
 			ECC_SECTOR_SIZE))) {
-		printk(KERN_ERR "Your NAND chip OOB is not large enough to"
-				" contain 8bit ECC correction codes");
+		dev_err(&denali->mtd.dev,
+			"Your NAND chip OOB is not large enough to contain 8bit ECC correction codes");
 		goto failed_req_irq;
 	} else {
 		denali->nand.ecc.layout = &nand_8bit_oob;
@@ -1579,8 +1566,7 @@ int denali_init(struct denali_nand_info *denali)
 
 	ret = add_mtd_device(&denali->mtd);
 	if (ret) {
-		dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
-				ret);
+		dev_err(denali->dev, "failed to register MTD: %d\n", ret);
 		goto failed_req_irq;
 	}
 	return 0;
diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c
index 19b11af..1096d49 100644
--- a/drivers/mtd/nand/denali_pci.c
+++ b/drivers/mtd/nand/denali_pci.c
@@ -41,7 +41,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	ret = pci_enable_device(dev);
 	if (ret) {
-		printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
+		dev_err(&dev->dev, "pci_enable_device failed.\n");
 		goto failed_alloc_memery;
 	}
 
@@ -69,20 +69,20 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	ret = pci_request_regions(dev, DENALI_NAND_NAME);
 	if (ret) {
-		printk(KERN_ERR "Spectra: Unable to request memory regions\n");
+		dev_err(&dev->dev, "unable to request memory regions\n");
 		goto failed_enable_dev;
 	}
 
 	denali->flash_reg = ioremap_nocache(csr_base, csr_len);
 	if (!denali->flash_reg) {
-		printk(KERN_ERR "Spectra: Unable to remap memory region\n");
+		dev_err(&dev->dev, "unable to remap memory region\n");
 		ret = -ENOMEM;
 		goto failed_req_regions;
 	}
 
 	denali->flash_mem = ioremap_nocache(mem_base, mem_len);
 	if (!denali->flash_mem) {
-		printk(KERN_ERR "Spectra: ioremap_nocache failed!");
+		dev_err(&dev->dev, "ioremap_nocache failed!");
 		ret = -ENOMEM;
 		goto failed_remap_reg;
 	}
@@ -132,8 +132,6 @@ static struct pci_driver denali_pci_driver = {
 
 static int __devinit denali_init_pci(void)
 {
-	printk(KERN_INFO "Spectra MTD driver built on %s @ %s\n",
-			__DATE__, __TIME__);
 	return pci_register_driver(&denali_pci_driver);
 }
 module_init(denali_init_pci);
-- 
1.7.4.4

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

* [RFC PATCH 6/9] nand/denali: add an mmio driver
  2011-05-06 14:28 [RFC PATCH 0/9] Support for MMIO based Denali NAND controller Jamie Iles
                   ` (4 preceding siblings ...)
  2011-05-06 14:28 ` [RFC PATCH 5/9] nand/denali: convert to dev_() printk helpers Jamie Iles
@ 2011-05-06 14:29 ` Jamie Iles
  2011-05-06 14:29 ` [RFC PATCH 7/9] nand/denali: annotate pci init/exit functions with correct section Jamie Iles
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 14:29 UTC (permalink / raw)
  To: linux-mtd; +Cc: Jamie Iles, dwmw2, chuanxiao.dong

Add an mmio driver so that the Denali controller can be used as a
platform_device.  This is useful on SoC devices.

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 drivers/mtd/nand/Kconfig       |   10 +++-
 drivers/mtd/nand/Makefile      |    1 +
 drivers/mtd/nand/denali.h      |    1 +
 drivers/mtd/nand/denali_mmio.c |  145 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 156 insertions(+), 1 deletions(-)
 create mode 100644 drivers/mtd/nand/denali_mmio.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index d629b68..6698bd5 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -78,7 +78,15 @@ config MTD_NAND_DENALI_PCI
         help
           Enable the driver for NAND flash on Intel Moorestown, using the
           Denali NAND controller core.
- 
+
+config MTD_NAND_DENALI_MMIO
+	tristate "Support Denali NAND controller as an MMIO device"
+	depends on HAVE_CLK && MTD_NAND_DENALI
+	help
+	  Enable the driver for NAND flash on platforms using a Denali NAND
+	  controller as an MMIO device.  This uses a platform_driver and
+	  platform_device as the driver model interface.
+
 config MTD_NAND_DENALI_SCRATCH_REG_ADDR
         hex "Denali NAND size scratch register address"
         default "0xFF108018"
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index ed4a2d8..c400549 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)		+= autcpu12.o
 obj-$(CONFIG_MTD_NAND_DENALI)		+= denali.o
 obj-$(CONFIG_MTD_NAND_DENALI_PCI)	+= denali_pci.o
+obj-$(CONFIG_MTD_NAND_DENALI_MMIO)	+= denali_mmio.o
 obj-$(CONFIG_MTD_NAND_EDB7312)		+= edb7312.o
 obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
 obj-$(CONFIG_MTD_NAND_BF5XX)		+= bf5xx_nand.o
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index e5aa995..3f99b7b 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -466,6 +466,7 @@ struct nand_buf {
 
 #define INTEL_CE4100	1
 #define INTEL_MRST	2
+#define MMIO		3
 
 struct denali_nand_info {
 	struct mtd_info mtd;
diff --git a/drivers/mtd/nand/denali_mmio.c b/drivers/mtd/nand/denali_mmio.c
new file mode 100644
index 0000000..b9ef645
--- /dev/null
+++ b/drivers/mtd/nand/denali_mmio.c
@@ -0,0 +1,145 @@
+/*
+ * NAND Flash Controller Device Driver
+ *
+ * Copyright © 2011, Picochip.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "denali.h"
+
+struct denali_mmio {
+	struct denali_nand_info	denali;
+	struct clk		*clk;
+};
+
+static void __iomem *request_and_map(struct device *dev,
+				     const struct resource *res)
+{
+	void __iomem *ptr;
+
+	if (!devm_request_mem_region(dev, res->start, resource_size(res),
+				     "denali-mmio")) {
+		dev_err(dev, "unable to request %s\n", res->name);
+		return NULL;
+	}
+
+	ptr = devm_ioremap_nocache(dev, res->start, resource_size(res));
+	if (!res)
+		dev_err(dev, "ioremap_nocache of %s failed!", res->name);
+
+	return ptr;
+}
+
+static int __devinit denali_mmio_probe(struct platform_device *pdev)
+{
+	struct resource *reg, *mem;
+	struct denali_mmio *mmio;
+	struct denali_nand_info *denali;
+	int ret;
+
+	mmio = devm_kzalloc(&pdev->dev, sizeof(*mmio), GFP_KERNEL);
+	if (!mmio)
+		return -ENOMEM;
+	denali = &mmio->denali;
+
+	reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg");
+	mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
+	if (!reg || !mem) {
+		dev_err(&pdev->dev, "resources not completely defined\n");
+		return -EINVAL;
+	}
+
+	denali->platform = MMIO;
+	denali->dev = &pdev->dev;
+	denali->irq = platform_get_irq(pdev, 0);
+	if (denali->irq < 0) {
+		dev_err(&pdev->dev, "no irq defined\n");
+		return -ENXIO;
+	}
+
+	denali->flash_reg = request_and_map(&pdev->dev, reg);
+	if (!denali->flash_reg)
+		return -ENOMEM;
+
+	denali->flash_mem = request_and_map(&pdev->dev, mem);
+	if (!denali->flash_mem)
+		return -ENOMEM;
+
+	mmio->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mmio->clk)) {
+		dev_err(&pdev->dev, "no clk available\n");
+		return PTR_ERR(mmio->clk);
+	}
+
+	ret = clk_enable(mmio->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable clk\n");
+		goto out_put_clk;
+	}
+
+	ret = denali_init(denali);
+	if (ret)
+		goto out_disable_clk;
+
+	platform_set_drvdata(pdev, mmio);
+
+	return 0;
+
+out_disable_clk:
+	clk_disable(mmio->clk);
+out_put_clk:
+	clk_put(mmio->clk);
+
+	return ret;
+}
+
+static int __devexit denali_mmio_remove(struct platform_device *pdev)
+{
+	struct denali_mmio *mmio = platform_get_drvdata(pdev);
+
+	denali_remove(&mmio->denali);
+	clk_disable(mmio->clk);
+	clk_put(mmio->clk);
+
+	return 0;
+}
+
+static struct platform_driver denali_mmio_driver = {
+	.probe		= denali_mmio_probe,
+	.remove		= __devexit_p(denali_mmio_remove),
+	.driver		= {
+		.name	= "denali-nand-mmio",
+	},
+};
+
+static int __init denali_init_mmio(void)
+{
+	return platform_driver_register(&denali_mmio_driver);
+}
+module_init(denali_init_mmio);
+
+static void __exit denali_exit_mmio(void)
+{
+	platform_driver_unregister(&denali_mmio_driver);
+}
+module_exit(denali_exit_mmio);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jamie Iles");
+MODULE_DESCRIPTION("MMIO driver for Denali NAND controller");
-- 
1.7.4.4

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

* [RFC PATCH 7/9] nand/denali: annotate pci init/exit functions with correct section
  2011-05-06 14:28 [RFC PATCH 0/9] Support for MMIO based Denali NAND controller Jamie Iles
                   ` (5 preceding siblings ...)
  2011-05-06 14:29 ` [RFC PATCH 6/9] nand/denali: add an mmio driver Jamie Iles
@ 2011-05-06 14:29 ` Jamie Iles
  2011-05-06 14:29 ` [RFC PATCH 8/9] nand/denali: allow the number of ECC bits to be set by pdata Jamie Iles
  2011-05-06 14:29 ` [RFC PATCH 9/9] nand/denali: support MTD partitioning Jamie Iles
  8 siblings, 0 replies; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 14:29 UTC (permalink / raw)
  To: linux-mtd; +Cc: Jamie Iles, dwmw2, chuanxiao.dong

The module init exit functions should be annotated with __init and
__exit.

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 drivers/mtd/nand/denali_pci.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c
index 1096d49..3d9a46a 100644
--- a/drivers/mtd/nand/denali_pci.c
+++ b/drivers/mtd/nand/denali_pci.c
@@ -130,13 +130,13 @@ static struct pci_driver denali_pci_driver = {
 	.remove = denali_pci_remove,
 };
 
-static int __devinit denali_init_pci(void)
+static int __init denali_init_pci(void)
 {
 	return pci_register_driver(&denali_pci_driver);
 }
 module_init(denali_init_pci);
 
-static void __devexit denali_exit_pci(void)
+static void __exit denali_exit_pci(void)
 {
 	pci_unregister_driver(&denali_pci_driver);
 }
-- 
1.7.4.4

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

* [RFC PATCH 8/9] nand/denali: allow the number of ECC bits to be set by pdata
  2011-05-06 14:28 [RFC PATCH 0/9] Support for MMIO based Denali NAND controller Jamie Iles
                   ` (6 preceding siblings ...)
  2011-05-06 14:29 ` [RFC PATCH 7/9] nand/denali: annotate pci init/exit functions with correct section Jamie Iles
@ 2011-05-06 14:29 ` Jamie Iles
  2011-05-06 14:29 ` [RFC PATCH 9/9] nand/denali: support MTD partitioning Jamie Iles
  8 siblings, 0 replies; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 14:29 UTC (permalink / raw)
  To: linux-mtd; +Cc: Jamie Iles, dwmw2, chuanxiao.dong

Rather than having the number of ECC bits to be used set by a
preprocessor definition, allow it to be set by platform_data.  If there
is no platform_data then default to 8 bit ECC.

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 drivers/mtd/nand/denali.c            |   23 +++++++++++------------
 drivers/mtd/nand/denali.h            |    1 +
 include/linux/platform_data/denali.h |   21 +++++++++++++++++++++
 3 files changed, 33 insertions(+), 12 deletions(-)
 create mode 100644 include/linux/platform_data/denali.h

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index ce6afd7..c79009f 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/module.h>
+#include <linux/platform_data/denali.h>
 
 #include "denali.h"
 
@@ -58,8 +59,6 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
  * valid or not */
 #define CHIP_SELECT_INVALID	-1
 
-#define SUPPORT_8BITECC		1
-
 /* This macro divides two integers and rounds fractional values up
  * to the nearest integer value. */
 #define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y)))
@@ -348,11 +347,8 @@ static void get_toshiba_nand_para(struct denali_nand_info *denali)
 			ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
 		iowrite32(tmp,
 				denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
-#if SUPPORT_15BITECC
-		iowrite32(15, denali->flash_reg + ECC_CORRECTION);
-#elif SUPPORT_8BITECC
-		iowrite32(8, denali->flash_reg + ECC_CORRECTION);
-#endif
+		iowrite32(denali->nr_ecc_bits,
+			  denali->flash_reg + ECC_CORRECTION);
 	}
 }
 
@@ -376,11 +372,8 @@ static void get_hynix_nand_para(struct denali_nand_info *denali,
 		iowrite32(spare_size,
 				denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
 		iowrite32(0, denali->flash_reg + DEVICE_WIDTH);
-#if SUPPORT_15BITECC
-		iowrite32(15, denali->flash_reg + ECC_CORRECTION);
-#elif SUPPORT_8BITECC
-		iowrite32(8, denali->flash_reg + ECC_CORRECTION);
-#endif
+		iowrite32(denali->nr_ecc_bits,
+			  denali->flash_reg + ECC_CORRECTION);
 		break;
 	default:
 		dev_warn(denali->dev,
@@ -1401,6 +1394,12 @@ void denali_drv_init(struct denali_nand_info *denali)
 int denali_init(struct denali_nand_info *denali)
 {
 	int ret;
+	struct denali_nand_pdata *pdata = dev_get_platdata(denali->dev);
+
+	if (pdata && pdata->nr_ecc_bits > 8)
+		denali->nr_ecc_bits = pdata->nr_ecc_bits;
+	else
+		denali->nr_ecc_bits = 8;
 
 	if (denali->platform == INTEL_CE4100) {
 		/* Due to a silicon limitation, we can only support
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index 3f99b7b..30f8553 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -496,6 +496,7 @@ struct denali_nand_info {
 	uint32_t blksperchip;
 	uint32_t bbtskipbytes;
 	uint32_t max_banks;
+	int nr_ecc_bits;
 };
 
 extern int denali_init(struct denali_nand_info *denali);
diff --git a/include/linux/platform_data/denali.h b/include/linux/platform_data/denali.h
new file mode 100644
index 0000000..cfdb775
--- /dev/null
+++ b/include/linux/platform_data/denali.h
@@ -0,0 +1,21 @@
+/*
+ * NAND flash controller device driver platform data.
+ * Copyright © 2011, Picochip
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#ifndef __DENALI_PDATA_H__
+#define __DENALI_PDATA_H__
+
+struct denali_nand_pdata {
+	int	nr_ecc_bits;
+};
+
+#endif /* __DENALI_PDATA_H__ */
-- 
1.7.4.4

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

* [RFC PATCH 9/9] nand/denali: support MTD partitioning
  2011-05-06 14:28 [RFC PATCH 0/9] Support for MMIO based Denali NAND controller Jamie Iles
                   ` (7 preceding siblings ...)
  2011-05-06 14:29 ` [RFC PATCH 8/9] nand/denali: allow the number of ECC bits to be set by pdata Jamie Iles
@ 2011-05-06 14:29 ` Jamie Iles
  2011-05-06 14:33   ` Artem Bityutskiy
  8 siblings, 1 reply; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 14:29 UTC (permalink / raw)
  To: linux-mtd; +Cc: Jamie Iles, dwmw2, chuanxiao.dong

If CONFIG_MTD_PARTITION is enabled then take the partitions from the
platform data.

Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 drivers/mtd/nand/denali.c            |    8 ++++++++
 include/linux/platform_data/denali.h |    6 +++++-
 2 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index c79009f..ae954de 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -23,6 +23,7 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
 #include <linux/module.h>
 #include <linux/platform_data/denali.h>
 
@@ -1563,7 +1564,14 @@ int denali_init(struct denali_nand_info *denali)
 		goto failed_req_irq;
 	}
 
+#ifdef CONFIG_MTD_PARTITIONS
+	if (pdata && pdata->parts) {
+		ret = add_mtd_partitions(&denali->mtd, pdata->parts,
+					 pdata->nr_parts);
+	} else
+#endif /* CONFIG_MTD_PARTITIONS */
 	ret = add_mtd_device(&denali->mtd);
+
 	if (ret) {
 		dev_err(denali->dev, "failed to register MTD: %d\n", ret);
 		goto failed_req_irq;
diff --git a/include/linux/platform_data/denali.h b/include/linux/platform_data/denali.h
index cfdb775..e9e415b 100644
--- a/include/linux/platform_data/denali.h
+++ b/include/linux/platform_data/denali.h
@@ -14,8 +14,12 @@
 #ifndef __DENALI_PDATA_H__
 #define __DENALI_PDATA_H__
 
+struct mtd_partition;
+
 struct denali_nand_pdata {
-	int	nr_ecc_bits;
+	int				nr_ecc_bits;
+	const struct mtd_partition	*parts;
+	unsigned int			nr_parts;
 };
 
 #endif /* __DENALI_PDATA_H__ */
-- 
1.7.4.4

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

* Re: [RFC PATCH 9/9] nand/denali: support MTD partitioning
  2011-05-06 14:29 ` [RFC PATCH 9/9] nand/denali: support MTD partitioning Jamie Iles
@ 2011-05-06 14:33   ` Artem Bityutskiy
       [not found]     ` <BANLkTi=9u5bH3eoCasxMhO05Qvh0cJxyqQ@mail.gmail.com>
  0 siblings, 1 reply; 19+ messages in thread
From: Artem Bityutskiy @ 2011-05-06 14:33 UTC (permalink / raw)
  To: Jamie Iles; +Cc: dwmw2, linux-mtd, chuanxiao.dong

On Fri, 2011-05-06 at 15:29 +0100, Jamie Iles wrote:
> If CONFIG_MTD_PARTITION is enabled then take the partitions from the
> platform data.
> 
> Cc: David Woodhouse <dwmw2@infradead.org>
> Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> ---
>  drivers/mtd/nand/denali.c            |    8 ++++++++
>  include/linux/platform_data/denali.h |    6 +++++-
>  2 files changed, 13 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
> index c79009f..ae954de 100644
> --- a/drivers/mtd/nand/denali.c
> +++ b/drivers/mtd/nand/denali.c
> @@ -23,6 +23,7 @@
>  #include <linux/mutex.h>
>  #include <linux/slab.h>
>  #include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
>  #include <linux/module.h>
>  #include <linux/platform_data/denali.h>
>  
> @@ -1563,7 +1564,14 @@ int denali_init(struct denali_nand_info *denali)
>  		goto failed_req_irq;
>  	}
>  
> +#ifdef CONFIG_MTD_PARTITIONS
> +	if (pdata && pdata->parts) {
> +		ret = add_mtd_partitions(&denali->mtd, pdata->parts,
> +					 pdata->nr_parts);
> +	} else
> +#endif /* CONFIG_MTD_PARTITIONS */
>  	ret = add_mtd_device(&denali->mtd);
> +

Oops:
http://www.linux-mtd.infradead.org/doc/general.html#L_partitions_ban

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [RFC PATCH 9/9] nand/denali: support MTD partitioning
       [not found]       ` <1304707397.7222.100.camel@localhost>
@ 2011-05-06 19:33         ` Jamie Iles
  0 siblings, 0 replies; 19+ messages in thread
From: Jamie Iles @ 2011-05-06 19:33 UTC (permalink / raw)
  To: Artem Bityutskiy; +Cc: Jamie Iles, linux-mtd

On Fri, May 06, 2011 at 09:43:17PM +0300, Artem Bityutskiy wrote:
> On Fri, 2011-05-06 at 16:18 +0100, Jamie Iles wrote:
> > On 6 May 2011 15:33, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> > > On Fri, 2011-05-06 at 15:29 +0100, Jamie Iles wrote:
> > >> If CONFIG_MTD_PARTITION is enabled then take the partitions from the
> > >> platform data.
> > >>
> > >> Cc: David Woodhouse <dwmw2@infradead.org>
> > >> Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
> > >> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> > >> ---
> > >>  drivers/mtd/nand/denali.c            |    8 ++++++++
> > >>  include/linux/platform_data/denali.h |    6 +++++-
> > >>  2 files changed, 13 insertions(+), 1 deletions(-)
> > >>
> > >> diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
> > >> index c79009f..ae954de 100644
> > >> --- a/drivers/mtd/nand/denali.c
> > >> +++ b/drivers/mtd/nand/denali.c
> > >> @@ -23,6 +23,7 @@
> > >>  #include <linux/mutex.h>
> > >>  #include <linux/slab.h>
> > >>  #include <linux/mtd/mtd.h>
> > >> +#include <linux/mtd/partitions.h>
> > >>  #include <linux/module.h>
> > >>  #include <linux/platform_data/denali.h>
> > >>
> > >> @@ -1563,7 +1564,14 @@ int denali_init(struct denali_nand_info *denali)
> > >>               goto failed_req_irq;
> > >>       }
> > >>
> > >> +#ifdef CONFIG_MTD_PARTITIONS
> > >> +     if (pdata && pdata->parts) {
> > >> +             ret = add_mtd_partitions(&denali->mtd, pdata->parts,
> > >> +                                      pdata->nr_parts);
> > >> +     } else
> > >> +#endif /* CONFIG_MTD_PARTITIONS */
> > >>       ret = add_mtd_device(&denali->mtd);
> > >> +
> > >
> > > Oops:
> > > http://www.linux-mtd.infradead.org/doc/general.html#L_partitions_ban
> > 
> > Oops indeed. Thanks for pointing that out.  Just for my clarification:
> > making the denali config select MTD_PARTITIONS for this patch then
> > removing the preprocessor garbage and always calling
> > add_mtd_partitions would *not* be ok?
> 
> No :-) That's the whole point of the ban - no one wants to clean up the
> crap and everyone wants to just get patches in ASAP.

OK, I just wanted to make sure that I'd read it properly.

> So I suggest you to separate this patch, and make the rest to go in
> independently, and then solve the partitions issue separately, if you
> have time/will/etc.

Will do.  I will try and have a look at a proper global fix soon too.

> Please, do not remove the mailing list from CC.

Sorry, finger trouble!

Jamie

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

* Re: [RFC PATCH 1/9] nand/denali: convert to generic DMA API
  2011-05-06 14:28 ` [RFC PATCH 1/9] nand/denali: convert to generic DMA API Jamie Iles
@ 2011-05-12  8:05   ` Artem Bityutskiy
  0 siblings, 0 replies; 19+ messages in thread
From: Artem Bityutskiy @ 2011-05-12  8:05 UTC (permalink / raw)
  To: Jamie Iles; +Cc: dwmw2, linux-mtd, chuanxiao.dong

On Fri, 2011-05-06 at 15:28 +0100, Jamie Iles wrote:
> Rather than using the PCI specific DMA API, convert to the generic
> DMA API so that we can use the Denali NAND controller on other bus
> types.
> 
> Cc: David Woodhouse <dwmw2@infradead.org>
> Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>

Pushed this one to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [RFC PATCH 2/9] nand/denali: remove nearly-duplicated register definitions
  2011-05-06 14:28 ` [RFC PATCH 2/9] nand/denali: remove nearly-duplicated register definitions Jamie Iles
@ 2011-05-12  8:05   ` Artem Bityutskiy
  0 siblings, 0 replies; 19+ messages in thread
From: Artem Bityutskiy @ 2011-05-12  8:05 UTC (permalink / raw)
  To: Jamie Iles; +Cc: dwmw2, linux-mtd, chuanxiao.dong

On Fri, 2011-05-06 at 15:28 +0100, Jamie Iles wrote:
> The controller has interrupt enable/status register pairs for each bank
> (along with ECC and status registers) that differ only in address offset.
> Rather than providing definitions for each register, make the address a
> macro so that it scales for devices with different numbers of banks.
> 
> Cc: David Woodhouse <dwmw2@infradead.org>
> Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>

Pushed this one to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [RFC PATCH 3/9] nand/denali: detect the number of banks
  2011-05-06 14:28 ` [RFC PATCH 3/9] nand/denali: detect the number of banks Jamie Iles
@ 2011-05-12  8:05   ` Artem Bityutskiy
  0 siblings, 0 replies; 19+ messages in thread
From: Artem Bityutskiy @ 2011-05-12  8:05 UTC (permalink / raw)
  To: Jamie Iles; +Cc: dwmw2, linux-mtd, chuanxiao.dong

On Fri, 2011-05-06 at 15:28 +0100, Jamie Iles wrote:
> Not all configurations of the Denali controller support 4 banks.  The
> controller can support between 1 and 16 banks.  Detect this from the
> design features register.
> 
> Cc: David Woodhouse <dwmw2@infradead.org>
> Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>

Pushed this one to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [RFC PATCH 4/9] nand/denali: split the generic driver and PCI layer
  2011-05-06 14:28 ` [RFC PATCH 4/9] nand/denali: split the generic driver and PCI layer Jamie Iles
@ 2011-05-12  8:08   ` Artem Bityutskiy
  2011-05-12  8:15     ` David Woodhouse
  0 siblings, 1 reply; 19+ messages in thread
From: Artem Bityutskiy @ 2011-05-12  8:08 UTC (permalink / raw)
  To: Jamie Iles; +Cc: dwmw2, linux-mtd, chuanxiao.dong

On Fri, 2011-05-06 at 15:28 +0100, Jamie Iles wrote:
> The Denali controller can also be found in SoC devices attached to a
> simple bus.  Move the PCI specific parts into denali_pci so that we can
> add a denali_mmio that uses the same driver but for a platform_device
> instead of a PCI based device.
> 
> Cc: David Woodhouse <dwmw2@infradead.org>
> Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> ---
>  drivers/mtd/nand/Kconfig      |   11 +++-
>  drivers/mtd/nand/Makefile     |    1 +
>  drivers/mtd/nand/denali.c     |  153 +++++------------------------------------
>  drivers/mtd/nand/denali.h     |    4 +
>  drivers/mtd/nand/denali_pci.c |  145 ++++++++++++++++++++++++++++++++++++++
>  5 files changed, 178 insertions(+), 136 deletions(-)
>  create mode 100644 drivers/mtd/nand/denali_pci.c
> 
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index edec457..d629b68 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -66,8 +66,15 @@ config MTD_NAND_AUTCPU12
>  	  access the SmartMediaCard.
>  
>  config MTD_NAND_DENALI
> -       depends on PCI
> +        tristate "Support Denali NAND controller"
> +        help
> +	  Enable support for the Denali NAND controller.  This should be
> +	  combined with either the PCI or platform drivers to provide device
> +	  registration.
> +
> +config MTD_NAND_DENALI_PCI
>          tristate "Support Denali NAND controller on Intel Moorestown"
> +	depends on PCI && MTD_NAND_DENALI
>          help
>            Enable the driver for NAND flash on Intel Moorestown, using the
>            Denali NAND controller core.
> @@ -75,7 +82,7 @@ config MTD_NAND_DENALI
>  config MTD_NAND_DENALI_SCRATCH_REG_ADDR
>          hex "Denali NAND size scratch register address"
>          default "0xFF108018"
> -        depends on MTD_NAND_DENALI
> +        depends on MTD_NAND_DENALI_PCI
>          help

I do not know for sure, but I bet there is a way to avoid adding another
config option. In general - the Linux kernel is overloaded with config
options and we try to avoid adding new ones.

Can this be done the following way? - you check if there is a PCI bus,
if no - try mmio. If yes, try to discover the device in PCI.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [RFC PATCH 5/9] nand/denali: convert to dev_() printk helpers
  2011-05-06 14:28 ` [RFC PATCH 5/9] nand/denali: convert to dev_() printk helpers Jamie Iles
@ 2011-05-12  8:10   ` Artem Bityutskiy
  0 siblings, 0 replies; 19+ messages in thread
From: Artem Bityutskiy @ 2011-05-12  8:10 UTC (permalink / raw)
  To: Jamie Iles; +Cc: dwmw2, linux-mtd, chuanxiao.dong

On Fri, 2011-05-06 at 15:28 +0100, Jamie Iles wrote:
> Use the dev_() printk helpers rather than printk so the name of the
> device is include.  Also remove a duplicate definition of BANK().
> 
> Cc: David Woodhouse <dwmw2@infradead.org>
> Cc: Chuanxiao Dong <chuanxiao.dong@intel.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>

This patch looks ok to me, but it depends on the previous one so I could
not apply it. I do not look at other patches as I presume they are all
dependent.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [RFC PATCH 4/9] nand/denali: split the generic driver and PCI layer
  2011-05-12  8:08   ` Artem Bityutskiy
@ 2011-05-12  8:15     ` David Woodhouse
  2011-05-12  8:31       ` Jamie Iles
  0 siblings, 1 reply; 19+ messages in thread
From: David Woodhouse @ 2011-05-12  8:15 UTC (permalink / raw)
  To: dedekind1; +Cc: Jamie Iles, linux-mtd, chuanxiao.dong

On Thu, 2011-05-12 at 11:08 +0300, Artem Bityutskiy wrote:
> 
> I do not know for sure, but I bet there is a way to avoid adding
> another
> config option. In general - the Linux kernel is overloaded with config
> options and we try to avoid adding new ones.
> 
> Can this be done the following way? - you check if there is a PCI bus,
> if no - try mmio. If yes, try to discover the device in PCI.

Better still, support *only* device-tree. The Intel board should have
been doing that instead of its stupid fake-pci thing anyway, and using
device properties instead of that stupid hack with putting information
at an MMIO address.

Let the Moorestown *platform* code register the device-tree at startup,
if the NAND code is present, and don't worry about that crap in the
generic driver.

-- 
dwmw2

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

* Re: [RFC PATCH 4/9] nand/denali: split the generic driver and PCI layer
  2011-05-12  8:15     ` David Woodhouse
@ 2011-05-12  8:31       ` Jamie Iles
  0 siblings, 0 replies; 19+ messages in thread
From: Jamie Iles @ 2011-05-12  8:31 UTC (permalink / raw)
  To: David Woodhouse; +Cc: Jamie Iles, chuanxiao.dong, linux-mtd, dedekind1

On Thu, May 12, 2011 at 09:15:48AM +0100, David Woodhouse wrote:
> On Thu, 2011-05-12 at 11:08 +0300, Artem Bityutskiy wrote:
> > 
> > I do not know for sure, but I bet there is a way to avoid adding
> > another
> > config option. In general - the Linux kernel is overloaded with config
> > options and we try to avoid adding new ones.
> > 
> > Can this be done the following way? - you check if there is a PCI bus,
> > if no - try mmio. If yes, try to discover the device in PCI.
> 
> Better still, support *only* device-tree. The Intel board should have
> been doing that instead of its stupid fake-pci thing anyway, and using
> device properties instead of that stupid hack with putting information
> at an MMIO address.

We don't _yet_ have device tree support on ARM, so that's why I used a 
platform_device.  There are patches circulating at the moment so I guess 
it won't be long though.

The other problem is that x86 doesn't support the clk API and that's 
something we need for our ARM system hence the dependency on HAVE_CLK 
for the MMIO driver.  But these could be stubbed out for X86.

Jamie

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

end of thread, other threads:[~2011-05-12  8:31 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-06 14:28 [RFC PATCH 0/9] Support for MMIO based Denali NAND controller Jamie Iles
2011-05-06 14:28 ` [RFC PATCH 1/9] nand/denali: convert to generic DMA API Jamie Iles
2011-05-12  8:05   ` Artem Bityutskiy
2011-05-06 14:28 ` [RFC PATCH 2/9] nand/denali: remove nearly-duplicated register definitions Jamie Iles
2011-05-12  8:05   ` Artem Bityutskiy
2011-05-06 14:28 ` [RFC PATCH 3/9] nand/denali: detect the number of banks Jamie Iles
2011-05-12  8:05   ` Artem Bityutskiy
2011-05-06 14:28 ` [RFC PATCH 4/9] nand/denali: split the generic driver and PCI layer Jamie Iles
2011-05-12  8:08   ` Artem Bityutskiy
2011-05-12  8:15     ` David Woodhouse
2011-05-12  8:31       ` Jamie Iles
2011-05-06 14:28 ` [RFC PATCH 5/9] nand/denali: convert to dev_() printk helpers Jamie Iles
2011-05-12  8:10   ` Artem Bityutskiy
2011-05-06 14:29 ` [RFC PATCH 6/9] nand/denali: add an mmio driver Jamie Iles
2011-05-06 14:29 ` [RFC PATCH 7/9] nand/denali: annotate pci init/exit functions with correct section Jamie Iles
2011-05-06 14:29 ` [RFC PATCH 8/9] nand/denali: allow the number of ECC bits to be set by pdata Jamie Iles
2011-05-06 14:29 ` [RFC PATCH 9/9] nand/denali: support MTD partitioning Jamie Iles
2011-05-06 14:33   ` Artem Bityutskiy
     [not found]     ` <BANLkTi=9u5bH3eoCasxMhO05Qvh0cJxyqQ@mail.gmail.com>
     [not found]       ` <1304707397.7222.100.camel@localhost>
2011-05-06 19:33         ` Jamie Iles

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.