* [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.