Commit 2acdf27b authored by David Brownell's avatar David Brownell Committed by Kevin Hilman

davinci_nand: allow board-specific config

Define and use a DaVinci-specific NAND platform_data structure,
instead of reusing generic NOR platform_data.  Improvements:

 - ALE and CLE bits are no longer hard-wired
 - ECC mode is in board-specific data, not a Kconfig option
 - Supports board-specific options like BUSWIDTH_16 and FLASH_BBT

Plus:

 - Don't force the use of MTD partitioning
 - Make that platform data be optional
 - Now pdev->id specifies chipselect (must be zero for now)
 - Add missing iounmap calls on probe failure

And corresponding updates for NAND support on the two EVM boards
that now have it.  Note that dm355 evm boards will fail cleanly
on boot now, pending 4-bit ECC support.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
parent 7ab1eee5
......@@ -16,7 +16,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/onenand_regs.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/gpio.h>
......@@ -34,21 +33,31 @@
#include <mach/emac.h>
#include <mach/i2c.h>
#include <mach/serial.h>
#include <mach/nand.h>
#include <mach/mmc.h>
#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e10000
#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000
/* NOTE: this is geared for the standard config, with a socketed
* 2 GByte Micron NAND (MT29F16G08FAA) using 128KB sectors. If you
* swap chips, maybe with a different block size, partitioning may
* need to be changed.
*/
#define NAND_BLOCK_SIZE SZ_128K
struct mtd_partition davinci_nand_partitions[] = {
{
/* UBL (a few copies) plus U-Boot */
.name = "bootloader",
.offset = 0,
.size = 0x3c0000,
.size = 15 * NAND_BLOCK_SIZE,
.mask_flags = MTD_WRITEABLE, /* force read-only */
}, {
/* U-Boot environment */
.name = "params",
.offset = MTDPART_OFS_APPEND,
.size = SZ_256K,
.size = 1 * NAND_BLOCK_SIZE,
.mask_flags = 0,
}, {
.name = "kernel",
......@@ -66,11 +75,14 @@ struct mtd_partition davinci_nand_partitions[] = {
.size = MTDPART_SIZ_FULL,
.mask_flags = 0,
}
/* two blocks with bad block table (and mirror) at the end */
};
static struct flash_platform_data davinci_nand_data = {
static struct davinci_nand_pdata davinci_nand_data = {
.parts = davinci_nand_partitions,
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
.ecc_mode = NAND_ECC_HW_SYNDROME,
.options = NAND_USE_FLASH_BBT,
};
static struct resource davinci_nand_resources[] = {
......@@ -87,7 +99,7 @@ static struct resource davinci_nand_resources[] = {
static struct platform_device davinci_nand_device = {
.name = "davinci_nand",
.id = -1,
.id = 0,
.num_resources = ARRAY_SIZE(davinci_nand_resources),
.resource = davinci_nand_resources,
......
......@@ -41,6 +41,7 @@
#include <mach/serial.h>
#include <mach/mux.h>
#include <mach/psc.h>
#include <mach/nand.h>
#include <mach/mmc.h>
#define DAVINCI_CFC_ATA_BASE 0x01C66000
......@@ -119,9 +120,10 @@ struct mtd_partition davinci_evm_nandflash_partition[] = {
}
};
static struct flash_platform_data davinci_evm_nandflash_data = {
static struct davinci_nand_pdata davinci_evm_nandflash_data = {
.parts = davinci_evm_nandflash_partition,
.nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition),
.ecc_mode = NAND_ECC_HW,
};
static struct resource davinci_evm_nandflash_resource[] = {
......
/*
* include/asm-arm/arch-davinci/nand.h
* mach-davinci/nand.h
*
* Copyright (C) 2006 Texas Instruments.
*
......@@ -30,6 +30,8 @@
#ifndef __ARCH_ARM_DAVINCI_NAND_H
#define __ARCH_ARM_DAVINCI_NAND_H
#include <linux/mtd/nand.h>
#define NRCSR_OFFSET 0x00
#define AWCCR_OFFSET 0x04
#define A1CR_OFFSET 0x10
......@@ -50,10 +52,28 @@
/* NOTE: boards don't need to use these address bits
* for ALE/CLE unless they support booting from NAND.
* They're used unless platform data overrides them.
*/
#define MASK_ALE 0x08
#define MASK_CLE 0x10
#define NAND_BUSY_FLAG 0x01
struct davinci_nand_pdata { /* platform_data */
u32 mask_ale;
u32 mask_cle;
/* board's default static partition info */
struct mtd_partition *parts;
unsigned nr_parts;
/* none == NAND_ECC_NONE (strongly *not* advised!!)
* soft == NAND_ECC_SOFT
* 1-bit == NAND_ECC_HW
* 4-bit == NAND_ECC_HW_SYNDROME (not on all chips)
*/
nand_ecc_modes_t ecc_mode;
/* e.g. NAND_BUSWIDTH_16 or NAND_USE_FLASH_BBT */
unsigned options;
};
#endif /* __ARCH_ARM_DAVINCI_NAND_H */
......@@ -446,18 +446,10 @@ config MTD_NAND_SH_FLCTL
for NAND Flash using FLCTL. This driver support SH7723.
config MTD_NAND_DAVINCI
tristate "NAND Flash device on DaVinci SoC"
tristate "Support NAND on DaVinci SoC"
depends on MTD_NAND
select MTD_PARTITIONS
help
Support for NAND flash on Texas Instruments DaVinci SoC.
config NAND_FLASH_HW_ECC
bool "1-Bit Hardware ECC on NAND Device for DaVinci"
depends on MTD_NAND_DAVINCI
help
Support the single bit Hardware ECC on NAND devices
for DaVinci. This uses three bytes of OOB data for
each 512 bytes of data.
Enable the driver for NAND flash chips on Texas Instruments
DaVinci processors.
endif # MTD_NAND
/*
* linux/drivers/mtd/nand/davinci_nand.c
*
* NAND Flash Driver
* davinci_nand.c - NAND Flash Driver for DaVinci family chips
*
* Copyright (C) 2006 Texas Instruments.
*
......@@ -36,7 +34,6 @@
* Currently makes assumptions about how the NAND device(s) are wired:
* - connected on the first chipselect, controlled by A1CR
* - single NAND chip
* - ALE and CLE wired to support boot-from-NAND
* - EM_WAIT is connected to the NAND device, not another device
*
* Modifications:
......@@ -54,6 +51,7 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <mach/cpu.h>
#include <mach/hardware.h>
#include <mach/nand.h>
#include <mach/mux.h>
......@@ -74,12 +72,6 @@ static inline int mtd_has_cmdlinepart(void) { return 1; }
static inline int mtd_has_cmdlinepart(void) { return 0; }
#endif
#ifdef CONFIG_NAND_FLASH_HW_ECC
static inline int is_hw_ecc_1bit(void) { return 1; }
#else
static inline int is_hw_ecc_1bit(void) { return 0; }
#endif
struct davinci_nand_info {
struct mtd_info mtd;
......@@ -97,6 +89,8 @@ struct davinci_nand_info {
u32 mask_cle;
};
#define NAND_CHIPSEL 0
#define to_davinci_nand(m) container_of(m, struct davinci_nand_info, mtd)
......@@ -262,7 +256,7 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
{
struct davinci_nand_info *info = to_davinci_nand(mtd);
return davinci_nand_readl(info, NANDFSR_OFFSET) & NAND_BUSY_FLAG;
return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
}
static void __init nand_dm355evm_flash_init(struct davinci_nand_info *info)
......@@ -349,7 +343,7 @@ static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info)
static int __init nand_davinci_probe(struct platform_device *pdev)
{
struct flash_platform_data *pdata = pdev->dev.platform_data;
struct davinci_nand_pdata *pdata = pdev->dev.platform_data;
struct davinci_nand_info *info;
struct resource *res1;
struct resource *res2;
......@@ -357,12 +351,11 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
void __iomem *base;
int ret;
u32 val;
nand_ecc_modes_t ecc_mode;
if (!pdata) {
dev_err(&pdev->dev, "platform_data missing\n");
ret = -ENODEV;
goto err_pdata;
}
/* only one chipselect is supported for now */
if (pdev->id != NAND_CHIPSEL)
return -ENODEV;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
......@@ -402,13 +395,21 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
info->chip.IO_ADDR_W = vaddr;
info->chip.chip_delay = 0;
info->chip.select_chip = nand_davinci_select_chip;
info->chip.options = 0;
/* options such as NAND_USE_FLASH_BBT or 16-bit widths */
info->chip.options = pdata ? pdata->options : 0;
info->ioaddr = (u32 __force) vaddr;
/* FIXME these masks should come from platform_data */
info->mask_ale = MASK_ALE;
info->mask_cle = MASK_CLE;
/* use nandboot-capable ALE/CLE masks by default */
if (pdata && pdata->mask_ale)
info->mask_ale = pdata->mask_cle;
else
info->mask_ale = MASK_ALE;
if (pdata && pdata->mask_cle)
info->mask_cle = pdata->mask_cle;
else
info->mask_cle = MASK_CLE;
/* Set address of hardware control function */
info->chip.cmd_ctrl = nand_davinci_hwcontrol;
......@@ -418,12 +419,15 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
info->chip.read_buf = nand_davinci_read_buf;
info->chip.write_buf = nand_davinci_write_buf;
/* use board-specific ECC config; else, the best available */
if (pdata)
ecc_mode = pdata->ecc_mode;
else if (cpu_is_davinci_dm355())
ecc_mode = NAND_ECC_HW_SYNDROME;
else
ecc_mode = NAND_ECC_HW;
/*
* REVISIT should probably be using runtime check using board's
* platform_data, since three ECC modes (soft, 1bit, 4bit) are
* incompatible at the binary level. If the board formatted its
* flash for a mode that's not supported by this kernel, bail!
*
* REVISIT dm355 adds an ECC mode that corrects up to 4 error
* bits, using 10 ECC bytes every 512 bytes of data. And that
* is what TI's original LSP uses... along with quite a hacked
......@@ -432,16 +436,29 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
* (in bad blocks). There was evidently a technical issue (now
* fixed?): Linux seemed to limit ECC data to 32 bytes.
*/
if (is_hw_ecc_1bit()) {
info->chip.ecc.mode = NAND_ECC_HW;
switch (ecc_mode) {
case NAND_ECC_NONE:
case NAND_ECC_SOFT:
break;
case NAND_ECC_HW:
info->chip.ecc.calculate = nand_davinci_calculate_ecc_1bit;
info->chip.ecc.correct = nand_davinci_correct_data_1bit;
info->chip.ecc.hwctl = nand_davinci_enable_hwecc_1bit;
info->chip.ecc.size = 512;
info->chip.ecc.bytes = 3;
} else {
info->chip.ecc.mode = NAND_ECC_SOFT;
break;
case NAND_ECC_HW_SYNDROME:
/* FIXME implement */
info->chip.ecc.size = 512;
info->chip.ecc.bytes = 10;
dev_warn(&pdev->dev, "4-bit ECC nyet supported\n");
/* FALL THROUGH */
default:
ret = -EINVAL;
goto err_ecc;
}
info->chip.ecc.mode = ecc_mode;
info->clk = clk_get(&pdev->dev, "AEMIFCLK");
if (IS_ERR(info->clk)) {
......@@ -497,7 +514,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
info->mtd.name = master_name;
}
if (mtd_parts_nb <= 0) {
if (mtd_parts_nb <= 0 && pdata) {
mtd_parts = pdata->parts;
mtd_parts_nb = pdata->nr_parts;
}
......@@ -510,7 +527,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
info->partitioned = true;
}
} else if (pdata->nr_parts) {
} else if (pdata && pdata->nr_parts) {
dev_warn(&pdev->dev, "ignoring %d default partitions on %s\n",
pdata->nr_parts, info->mtd.name);
}
......@@ -540,13 +557,18 @@ err_scan:
err_clk_enable:
clk_put(info->clk);
err_ecc:
err_clk:
if (base)
iounmap(base);
if (vaddr)
iounmap(vaddr);
err_ioremap:
kfree(info);
err_nomem:
err_res:
err_pdata:
return ret;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment