Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6: (49 commits)
  [MTD] [NAND] S3C2412 fix hw ecc
  [MTD] [NAND] Work around false compiler warning in CAFÉ driver
  [JFFS2] printk warning fixes
  [MTD] [MAPS] ichxrom warning fix
  [MTD] [MAPS] amd76xrom warning fix
  [MTD] [MAPS] esb2rom warning fixes
  [MTD] [MAPS] ck804xrom warning fix
  [MTD] [MAPS] netsc520 warning fix
  [MTD] [MAPS] sc520cdp warning fix
  [MTD] [ONENAND] onenand_base warning fix
  [MTD] [NAND] eXcite nand flash driver
  [MTD] Improve heuristic for detecting wrong-endian RedBoot partition table
  [MTD] Fix RedBoot partition parsing regression harder.
  [MTD] [NAND] S3C2410: Hardware ECC correction code
  [JFFS2] Use MTD_OOB_AUTO to automatically place cleanmarker on NAND
  [MTD] Clarify OOB-operation interface comments
  [MTD] remove unused ecctype,eccsize fields from struct mtd_info
  [MTD] [NOR] Intel: remove ugly PROGREGION macros
  [MTD] [NOR] STAA: use writesize instead off eccsize to represent ECC block
  [MTD] OneNAND: Invalidate bufferRAM after erase
  ...
This commit is contained in:
Linus Torvalds
2007-02-19 13:34:11 -08:00
37 changed files with 1050 additions and 470 deletions
+19 -7
View File
@@ -397,9 +397,23 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
cfi_fixup(mtd, fixup_table);
for (i=0; i< cfi->numchips; i++) {
cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
cfi->chips[i].erase_time = 1000<<cfi->cfiq->BlockEraseTimeoutTyp;
if (cfi->cfiq->WordWriteTimeoutTyp)
cfi->chips[i].word_write_time =
1<<cfi->cfiq->WordWriteTimeoutTyp;
else
cfi->chips[i].word_write_time = 50000;
if (cfi->cfiq->BufWriteTimeoutTyp)
cfi->chips[i].buffer_write_time =
1<<cfi->cfiq->BufWriteTimeoutTyp;
/* No default; if it isn't specified, we won't use it */
if (cfi->cfiq->BlockEraseTimeoutTyp)
cfi->chips[i].erase_time =
1000<<cfi->cfiq->BlockEraseTimeoutTyp;
else
cfi->chips[i].erase_time = 2000000;
cfi->chips[i].ref_point_counter = 0;
init_waitqueue_head(&(cfi->chips[i].wq));
}
@@ -546,13 +560,11 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
struct cfi_intelext_programming_regioninfo *prinfo;
prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];
mtd->writesize = cfi->interleave << prinfo->ProgRegShift;
MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid;
MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid;
mtd->flags &= ~MTD_BIT_WRITEABLE;
printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",
map->name, mtd->writesize,
MTD_PROGREGION_CTRLMODE_VALID(mtd),
MTD_PROGREGION_CTRLMODE_INVALID(mtd));
cfi->interleave * prinfo->ControlValid,
cfi->interleave * prinfo->ControlInvalid);
}
/*
+1 -1
View File
@@ -662,7 +662,7 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
* a small buffer for this.
* XXX: If the buffer size is not a multiple of 2, this will break
*/
#define ECCBUF_SIZE (mtd->eccsize)
#define ECCBUF_SIZE (mtd->writesize)
#define ECCBUF_DIV(x) ((x) & ~(ECCBUF_SIZE - 1))
#define ECCBUF_MOD(x) ((x) & (ECCBUF_SIZE - 1))
static int
-1
View File
@@ -569,7 +569,6 @@ void DoC2k_init(struct mtd_info *mtd)
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->ecctype = MTD_ECC_RS_DiskOnChip;
mtd->size = 0;
mtd->erasesize = 0;
mtd->writesize = 512;
-1
View File
@@ -348,7 +348,6 @@ void DoCMil_init(struct mtd_info *mtd)
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->ecctype = MTD_ECC_RS_DiskOnChip;
mtd->size = 0;
/* FIXME: erase size is not always 8KiB */
-1
View File
@@ -472,7 +472,6 @@ void DoCMilPlus_init(struct mtd_info *mtd)
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->ecctype = MTD_ECC_RS_DiskOnChip;
mtd->size = 0;
mtd->erasesize = 0;
+1 -1
View File
@@ -204,7 +204,7 @@ config MTD_ESB2ROM
config MTD_CK804XROM
tristate "BIOS flash chip on Nvidia CK804"
depends on X86 && MTD_JEDECPROBE
depends on X86 && MTD_JEDECPROBE && PCI
help
Support for treating the BIOS flash chip on nvidia motherboards
as an MTD device - with this you can reprogram your BIOS.
+2 -2
View File
@@ -205,8 +205,8 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
(((unsigned long)(window->virt)) + offset);
map->map.size = 0xffffffffUL - map_top + 1UL;
/* Set the name of the map to the address I am trying */
sprintf(map->map_name, "%s @%08lx",
MOD_NAME, map->map.phys);
sprintf(map->map_name, "%s @%08Lx",
MOD_NAME, (unsigned long long)map->map.phys);
/* There is no generic VPP support */
for(map->map.bankwidth = 32; map->map.bankwidth;
+3 -3
View File
@@ -207,8 +207,8 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
(((unsigned long)(window->virt)) + offset);
map->map.size = 0xffffffffUL - map_top + 1UL;
/* Set the name of the map to the address I am trying */
sprintf(map->map_name, "%s @%08lx",
MOD_NAME, map->map.phys);
sprintf(map->map_name, "%s @%08Lx",
MOD_NAME, (unsigned long long)map->map.phys);
/* There is no generic VPP support */
for(map->map.bankwidth = 32; map->map.bankwidth;
@@ -327,7 +327,7 @@ static int __init init_ck804xrom(void)
pdev = NULL;
for(id = ck804xrom_pci_tbl; id->vendor; id++) {
pdev = pci_find_device(id->vendor, id->device, NULL);
pdev = pci_get_device(id->vendor, id->device, NULL);
if (pdev)
break;
}
+2 -2
View File
@@ -289,8 +289,8 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
(((unsigned long)(window->virt)) + offset);
map->map.size = 0xffffffffUL - map_top + 1UL;
/* Set the name of the map to the address I am trying */
sprintf(map->map_name, "%s @%08lx",
MOD_NAME, map->map.phys);
sprintf(map->map_name, "%s @%08Lx",
MOD_NAME, (unsigned long long)map->map.phys);
/* Firmware hubs only use vpp when being programmed
* in a factory setting. So in-place programming
+2 -2
View File
@@ -227,8 +227,8 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev,
(((unsigned long)(window->virt)) + offset);
map->map.size = 0xffffffffUL - map_top + 1UL;
/* Set the name of the map to the address I am trying */
sprintf(map->map_name, "%s @%08lx",
MOD_NAME, map->map.phys);
sprintf(map->map_name, "%s @%08Lx",
MOD_NAME, (unsigned long long)map->map.phys);
/* Firmware hubs only use vpp when being programmed
* in a factory setting. So in-place programming
+3 -1
View File
@@ -94,7 +94,9 @@ static struct mtd_info *mymtd;
static int __init init_netsc520(void)
{
printk(KERN_NOTICE "NetSc520 flash device: 0x%lx at 0x%lx\n", netsc520_map.size, netsc520_map.phys);
printk(KERN_NOTICE "NetSc520 flash device: 0x%Lx at 0x%Lx\n",
(unsigned long long)netsc520_map.size,
(unsigned long long)netsc520_map.phys);
netsc520_map.virt = ioremap_nocache(netsc520_map.phys, netsc520_map.size);
if (!netsc520_map.virt) {
+3 -2
View File
@@ -237,8 +237,9 @@ static int __init init_sc520cdp(void)
#endif
for (i = 0; i < NUM_FLASH_BANKS; i++) {
printk(KERN_NOTICE "SC520 CDP flash device: 0x%lx at 0x%lx\n",
sc520cdp_map[i].size, sc520cdp_map[i].phys);
printk(KERN_NOTICE "SC520 CDP flash device: 0x%Lx at 0x%Lx\n",
(unsigned long long)sc520cdp_map[i].size,
(unsigned long long)sc520cdp_map[i].phys);
sc520cdp_map[i].virt = ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size);
+3 -2
View File
@@ -419,8 +419,9 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
info.erasesize = mtd->erasesize;
info.writesize = mtd->writesize;
info.oobsize = mtd->oobsize;
info.ecctype = mtd->ecctype;
info.eccsize = mtd->eccsize;
/* The below fields are obsolete */
info.ecctype = -1;
info.eccsize = 0;
if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
return -EFAULT;
break;
-4
View File
@@ -727,8 +727,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.erasesize = subdev[0]->erasesize;
concat->mtd.writesize = subdev[0]->writesize;
concat->mtd.oobsize = subdev[0]->oobsize;
concat->mtd.ecctype = subdev[0]->ecctype;
concat->mtd.eccsize = subdev[0]->eccsize;
if (subdev[0]->writev)
concat->mtd.writev = concat_writev;
if (subdev[0]->read_oob)
@@ -774,8 +772,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
if (concat->mtd.writesize != subdev[i]->writesize ||
concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
concat->mtd.oobsize != subdev[i]->oobsize ||
concat->mtd.ecctype != subdev[i]->ecctype ||
concat->mtd.eccsize != subdev[i]->eccsize ||
!concat->mtd.read_oob != !subdev[i]->read_oob ||
!concat->mtd.write_oob != !subdev[i]->write_oob) {
kfree(concat);
-2
View File
@@ -338,8 +338,6 @@ int add_mtd_partitions(struct mtd_info *master,
slave->mtd.size = parts[i].size;
slave->mtd.writesize = master->writesize;
slave->mtd.oobsize = master->oobsize;
slave->mtd.ecctype = master->ecctype;
slave->mtd.eccsize = master->eccsize;
slave->mtd.subpage_sft = master->subpage_sft;
slave->mtd.name = parts[i].name;
+9 -5
View File
@@ -126,10 +126,6 @@ config MTD_NAND_S3C2410_HWECC
incorrect ECC generation, and if using these, the default of
software ECC is preferable.
If you lay down a device with the hardware ECC, then you will
currently not be able to switch to software, as there is no
implementation for ECC method used by the S3C2410
config MTD_NAND_NDFC
tristate "NDFC NanD Flash Controller"
depends on MTD_NAND && 44x
@@ -221,9 +217,17 @@ config MTD_NAND_SHARPSL
tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
depends on MTD_NAND && ARCH_PXA
config MTD_NAND_BASLER_EXCITE
tristate "Support for NAND Flash on Basler eXcite"
depends on MTD_NAND && BASLER_EXCITE
help
This enables the driver for the NAND flash device found on the
Basler eXcite Smart Camera. If built as a module, the driver
will be named "excite_nandflash.ko".
config MTD_NAND_CAFE
tristate "NAND support for OLPC CAFÉ chip"
depends on PCI
depends on MTD_NAND && PCI
help
Use NAND flash attached to the CAFÉ chip designed for the $100
laptop.
+1
View File
@@ -24,6 +24,7 @@ obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
nand-objs := nand_base.o nand_bbt.o
cafe_nand-objs := cafe.o cafe_ecc.o
+36 -53
View File
@@ -78,8 +78,9 @@ module_param(regdebug, int, 0644);
static int checkecc = 1;
module_param(checkecc, int, 0644);
static int slowtiming = 0;
module_param(slowtiming, int, 0644);
static int numtimings;
static int timing[3];
module_param_array(timing, int, &numtimings, 0644);
/* Hrm. Why isn't this already conditional on something in the struct device? */
#define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0)
@@ -264,10 +265,10 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
ndelay(100);
if (1) {
int c = 500000;
int c;
uint32_t irqs;
while (c--) {
for (c = 500000; c != 0; c--) {
irqs = cafe_readl(cafe, NAND_IRQ);
if (irqs & doneint)
break;
@@ -529,6 +530,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
{
struct mtd_info *mtd;
struct cafe_priv *cafe;
uint32_t timing1, timing2, timing3;
uint32_t ctrl;
int err = 0;
@@ -580,31 +582,45 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
cafe->nand.block_bad = cafe_nand_block_bad;
}
if (numtimings && numtimings != 3) {
dev_warn(&cafe->pdev->dev, "%d timing register values ignored; precisely three are required\n", numtimings);
}
if (numtimings == 3) {
timing1 = timing[0];
timing2 = timing[1];
timing3 = timing[2];
cafe_dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n",
timing1, timing2, timing3);
} else {
timing1 = cafe_readl(cafe, NAND_TIMING1);
timing2 = cafe_readl(cafe, NAND_TIMING2);
timing3 = cafe_readl(cafe, NAND_TIMING3);
if (timing1 | timing2 | timing3) {
cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n", timing1, timing2, timing3);
} else {
dev_warn(&cafe->pdev->dev, "Timing registers unset; using most conservative defaults\n");
timing1 = timing2 = timing3 = 0xffffffff;
}
}
/* Start off by resetting the NAND controller completely */
cafe_writel(cafe, 1, NAND_RESET);
cafe_writel(cafe, 0, NAND_RESET);
cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
cafe_writel(cafe, timing1, NAND_TIMING1);
cafe_writel(cafe, timing2, NAND_TIMING2);
cafe_writel(cafe, timing3, NAND_TIMING3);
/* Timings from Marvell's test code (not verified or calculated by us) */
if (!slowtiming) {
cafe_writel(cafe, 0x01010a0a, NAND_TIMING1);
cafe_writel(cafe, 0x24121212, NAND_TIMING2);
cafe_writel(cafe, 0x11000000, NAND_TIMING3);
} else {
cafe_writel(cafe, 0xffffffff, NAND_TIMING1);
cafe_writel(cafe, 0xffffffff, NAND_TIMING2);
cafe_writel(cafe, 0xffffffff, NAND_TIMING3);
}
cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED,
"CAFE NAND", mtd);
if (err) {
dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
goto out_free_dma;
}
#if 1
/* Disable master reset, enable NAND clock */
ctrl = cafe_readl(cafe, GLOBAL_CTRL);
ctrl &= 0xffffeff0;
@@ -631,32 +647,8 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK));
#endif
#if 1
mtd->writesize=2048;
mtd->oobsize = 0x40;
memset(cafe->dmabuf, 0x5a, 2112);
cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1);
cafe->nand.read_byte(mtd);
cafe->nand.read_byte(mtd);
cafe->nand.read_byte(mtd);
cafe->nand.read_byte(mtd);
cafe->nand.read_byte(mtd);
#endif
#if 0
cafe->nand.cmdfunc(mtd, NAND_CMD_READ0, 0, 0);
// nand_wait_ready(mtd);
cafe->nand.read_byte(mtd);
cafe->nand.read_byte(mtd);
cafe->nand.read_byte(mtd);
cafe->nand.read_byte(mtd);
#endif
#if 0
writel(0x84600070, cafe->mmio);
udelay(10);
cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", cafe_readl(cafe, NAND_NONMEM));
#endif
/* Scan to find existance of the device */
/* Scan to find existence of the device */
if (nand_scan_ident(mtd, 1)) {
err = -ENXIO;
goto out_irq;
@@ -760,13 +752,4 @@ module_exit(cafe_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("NAND flash driver for OLPC CAFE chip");
/* Correct ECC for 2048 bytes of 0xff:
41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */
/* dwmw2's B-test board, in case of completely screwing it:
Bad eraseblock 2394 at 0x12b40000
Bad eraseblock 2627 at 0x14860000
Bad eraseblock 3349 at 0x1a2a0000
*/
MODULE_DESCRIPTION("NAND flash driver for OLPC CAFÉ chip");
+1 -1
View File
@@ -1045,7 +1045,7 @@ static unsigned short err_pos_lut[4096] = {
static unsigned short err_pos(unsigned short din)
{
BUG_ON(din > 4096);
BUG_ON(din >= ARRAY_SIZE(err_pos_lut));
return err_pos_lut[din];
}
static int chk_no_err_only(unsigned short *chk_syndrome_list, unsigned short *err_info)
+248
View File
@@ -0,0 +1,248 @@
/*
* Copyright (C) 2005 - 2007 by Basler Vision Technologies AG
* Author: Thomas Koeller <thomas.koeller.qbaslerweb.com>
* Original code by Thies Moeller <thies.moeller@baslerweb.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/rm9k-ocd.h>
#include <excite_nandflash.h>
#define EXCITE_NANDFLASH_VERSION "0.1"
/* I/O register offsets */
#define EXCITE_NANDFLASH_DATA_BYTE 0x00
#define EXCITE_NANDFLASH_STATUS_BYTE 0x0c
#define EXCITE_NANDFLASH_ADDR_BYTE 0x10
#define EXCITE_NANDFLASH_CMD_BYTE 0x14
/* prefix for debug output */
static const char module_id[] = "excite_nandflash";
/*
* partition definition
*/
static const struct mtd_partition partition_info[] = {
{
.name = "eXcite RootFS",
.offset = 0,
.size = MTDPART_SIZ_FULL
}
};
static inline const struct resource *
excite_nand_get_resource(struct platform_device *d, unsigned long flags,
const char *basename)
{
char buf[80];
if (snprintf(buf, sizeof buf, "%s_%u", basename, d->id) >= sizeof buf)
return NULL;
return platform_get_resource_byname(d, flags, buf);
}
static inline void __iomem *
excite_nand_map_regs(struct platform_device *d, const char *basename)
{
void *result = NULL;
const struct resource *const r =
excite_nand_get_resource(d, IORESOURCE_MEM, basename);
if (r)
result = ioremap_nocache(r->start, r->end + 1 - r->start);
return result;
}
/* controller and mtd information */
struct excite_nand_drvdata {
struct mtd_info board_mtd;
struct nand_chip board_chip;
void __iomem *regs;
void __iomem *tgt;
};
/* Control function */
static void excite_nand_control(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
struct excite_nand_drvdata * const d =
container_of(mtd, struct excite_nand_drvdata, board_mtd);
switch (ctrl) {
case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
d->tgt = d->regs + EXCITE_NANDFLASH_CMD_BYTE;
break;
case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
d->tgt = d->regs + EXCITE_NANDFLASH_ADDR_BYTE;
break;
case NAND_CTRL_CHANGE | NAND_NCE:
d->tgt = d->regs + EXCITE_NANDFLASH_DATA_BYTE;
break;
}
if (cmd != NAND_CMD_NONE)
__raw_writeb(cmd, d->tgt);
}
/* Return 0 if flash is busy, 1 if ready */
static int excite_nand_devready(struct mtd_info *mtd)
{
struct excite_nand_drvdata * const drvdata =
container_of(mtd, struct excite_nand_drvdata, board_mtd);
return __raw_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS_BYTE);
}
/*
* Called by device layer to remove the driver.
* The binding to the mtd and all allocated
* resources are released.
*/
static int __exit excite_nand_remove(struct device *dev)
{
struct excite_nand_drvdata * const this = dev_get_drvdata(dev);
dev_set_drvdata(dev, NULL);
if (unlikely(!this)) {
printk(KERN_ERR "%s: called %s without private data!!",
module_id, __func__);
return -EINVAL;
}
/* first thing we need to do is release our mtd
* then go through freeing the resource used
*/
nand_release(&this->board_mtd);
/* free the common resources */
iounmap(this->regs);
kfree(this);
DEBUG(MTD_DEBUG_LEVEL1, "%s: removed\n", module_id);
return 0;
}
/*
* Called by device layer when it finds a device matching
* one our driver can handle. This code checks to see if
* it can allocate all necessary resources then calls the
* nand layer to look for devices.
*/
static int __init excite_nand_probe(struct device *dev)
{
struct platform_device * const pdev = to_platform_device(dev);
struct excite_nand_drvdata *drvdata; /* private driver data */
struct nand_chip *board_chip; /* private flash chip data */
struct mtd_info *board_mtd; /* mtd info for this board */
int scan_res;
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
if (unlikely(!drvdata)) {
printk(KERN_ERR "%s: no memory for drvdata\n",
module_id);
return -ENOMEM;
}
/* bind private data into driver */
dev_set_drvdata(dev, drvdata);
/* allocate and map the resource */
drvdata->regs =
excite_nand_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS);
if (unlikely(!drvdata->regs)) {
printk(KERN_ERR "%s: cannot reserve register region\n",
module_id);
kfree(drvdata);
return -ENXIO;
}
drvdata->tgt = drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE;
/* initialise our chip */
board_chip = &drvdata->board_chip;
board_chip->IO_ADDR_R = board_chip->IO_ADDR_W =
drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE;
board_chip->cmd_ctrl = excite_nand_control;
board_chip->dev_ready = excite_nand_devready;
board_chip->chip_delay = 25;
board_chip->ecc.mode = NAND_ECC_SOFT;
/* link chip to mtd */
board_mtd = &drvdata->board_mtd;
board_mtd->priv = board_chip;
DEBUG(MTD_DEBUG_LEVEL2, "%s: device scan\n", module_id);
scan_res = nand_scan(&drvdata->board_mtd, 1);
if (likely(!scan_res)) {
DEBUG(MTD_DEBUG_LEVEL2, "%s: register partitions\n", module_id);
add_mtd_partitions(&drvdata->board_mtd, partition_info,
sizeof partition_info / sizeof partition_info[0]);
} else {
iounmap(drvdata->regs);
kfree(drvdata);
printk(KERN_ERR "%s: device scan failed\n", module_id);
return -EIO;
}
return 0;
}
static struct device_driver excite_nand_driver = {
.name = "excite_nand",
.bus = &platform_bus_type,
.probe = excite_nand_probe,
.remove = __exit_p(excite_nand_remove)
};
static int __init excite_nand_init(void)
{
pr_info("Basler eXcite nand flash driver Version "
EXCITE_NANDFLASH_VERSION "\n");
return driver_register(&excite_nand_driver);
}
static void __exit excite_nand_exit(void)
{
driver_unregister(&excite_nand_driver);
}
module_init(excite_nand_init);
module_exit(excite_nand_exit);
MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(EXCITE_NANDFLASH_VERSION)

Some files were not shown because too many files have changed in this diff Show More