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

* git://git.infradead.org/mtd-2.6: (79 commits)
  mtd: Remove obsolete <mtd/compatmac.h> include
  mtd: Update copyright notices
  jffs2: Update copyright notices
  mtd-physmap: add support users can assign the probe type in board files
  mtd: remove redwood map driver
  mxc_nand: Add v3 (i.MX51) Support
  mxc_nand: support 8bit ecc
  mxc_nand: fix correct_data function
  mxc_nand: add V1_V2 namespace to registers
  mxc_nand: factor out a check_int function
  mxc_nand: make some internally used functions overwriteable
  mxc_nand: rework get_dev_status
  mxc_nand: remove 0xe00 offset from registers
  mtd: denali: Add multi connected NAND support
  mtd: denali: Remove set_ecc_config function
  mtd: denali: Remove unuseful code in get_xx_nand_para functions
  mtd: denali: Remove device_info_tag structure
  mtd: m25p80: add support for the Winbond W25Q32 SPI flash chip
  mtd: m25p80: add support for the Intel/Numonyx {16,32,64}0S33B SPI flash chips
  mtd: m25p80: add support for the EON EN25P{32, 64} SPI flash chips
  ...

Fix up trivial conflicts in drivers/mtd/maps/{Kconfig,redwood.c} due to
redwood driver removal.
This commit is contained in:
Linus Torvalds 2010-08-10 11:49:21 -07:00
commit e8a89cebdb
107 changed files with 1909 additions and 1524 deletions

View File

@ -15,8 +15,6 @@
* partitions = mtd partition list
*/
#define NFC_PG_SIZE_256 0
#define NFC_PG_SIZE_512 1
#define NFC_PG_SIZE_OFFSET 9
#define NFC_NWIDTH_8 0
@ -30,7 +28,6 @@
struct bf5xx_nand_platform {
/* NAND chip information */
unsigned short page_size;
unsigned short data_width;
/* RD/WR strobe delay timing information, all times in SCLK cycles */

View File

@ -311,15 +311,17 @@ config SM_FTL
select MTD_BLKDEVS
select MTD_NAND_ECC
help
This enables new and very EXPERMENTAL support for SmartMedia/xD
This enables EXPERIMENTAL R/W support for SmartMedia/xD
FTL (Flash translation layer).
Write support isn't yet well tested, therefore this code IS likely to
eat your card, so please don't use it together with valuable data.
Use readonly driver (CONFIG_SSFDC) instead.
Write support is only lightly tested, therefore this driver
isn't recommended to use with valuable data (anyway if you have
valuable data, do backups regardless of software/hardware you
use, because you never know what will eat your data...)
If you only need R/O access, you can use older R/O driver
(CONFIG_SSFDC)
config MTD_OOPS
tristate "Log panic/oops to an MTD buffer"
depends on MTD
help
This enables panic and oops messages to be logged to a circular
buffer in a flash partition where it can be read back at some

View File

@ -2,7 +2,7 @@
drivers/mtd/afs.c: ARM Flash Layout/Partitioning
Copyright (C) 2000 ARM Limited
Copyright © 2000 ARM Limited
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

View File

@ -34,7 +34,6 @@
#include <linux/mtd/xip.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/compatmac.h>
#include <linux/mtd/cfi.h>
/* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */
@ -63,6 +62,8 @@ static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *);
static void cfi_intelext_sync (struct mtd_info *);
static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs,
uint64_t len);
#ifdef CONFIG_MTD_OTP
static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
@ -448,6 +449,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
mtd->sync = cfi_intelext_sync;
mtd->lock = cfi_intelext_lock;
mtd->unlock = cfi_intelext_unlock;
mtd->is_locked = cfi_intelext_is_locked;
mtd->suspend = cfi_intelext_suspend;
mtd->resume = cfi_intelext_resume;
mtd->flags = MTD_CAP_NORFLASH;
@ -717,7 +719,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
chip = &newcfi->chips[0];
for (i = 0; i < cfi->numchips; i++) {
shared[i].writing = shared[i].erasing = NULL;
spin_lock_init(&shared[i].lock);
mutex_init(&shared[i].lock);
for (j = 0; j < numparts; j++) {
*chip = cfi->chips[i];
chip->start += j << partshift;
@ -886,7 +888,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
*/
struct flchip_shared *shared = chip->priv;
struct flchip *contender;
spin_lock(&shared->lock);
mutex_lock(&shared->lock);
contender = shared->writing;
if (contender && contender != chip) {
/*
@ -899,7 +901,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
* get_chip returns success we're clear to go ahead.
*/
ret = mutex_trylock(&contender->mutex);
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
if (!ret)
goto retry;
mutex_unlock(&chip->mutex);
@ -914,7 +916,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
mutex_unlock(&contender->mutex);
return ret;
}
spin_lock(&shared->lock);
mutex_lock(&shared->lock);
/* We should not own chip if it is already
* in FL_SYNCING state. Put contender and retry. */
@ -930,7 +932,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
* on this chip. Sleep. */
if (mode == FL_ERASING && shared->erasing
&& shared->erasing->oldstate == FL_ERASING) {
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
mutex_unlock(&chip->mutex);
@ -944,7 +946,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
shared->writing = chip;
if (mode == FL_ERASING)
shared->erasing = chip;
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
}
ret = chip_ready(map, chip, adr, mode);
if (ret == -EAGAIN)
@ -959,7 +961,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
if (chip->priv) {
struct flchip_shared *shared = chip->priv;
spin_lock(&shared->lock);
mutex_lock(&shared->lock);
if (shared->writing == chip && chip->oldstate == FL_READY) {
/* We own the ability to write, but we're done */
shared->writing = shared->erasing;
@ -967,7 +969,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
/* give back ownership to who we loaned it from */
struct flchip *loaner = shared->writing;
mutex_lock(&loaner->mutex);
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
mutex_unlock(&chip->mutex);
put_chip(map, loaner, loaner->start);
mutex_lock(&chip->mutex);
@ -985,11 +987,11 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
* Don't let the switch below mess things up since
* we don't have ownership to resume anything.
*/
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
wake_up(&chip->wq);
return;
}
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
}
switch(chip->oldstate) {
@ -2139,6 +2141,13 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
return ret;
}
static int cfi_intelext_is_locked(struct mtd_info *mtd, loff_t ofs,
uint64_t len)
{
return cfi_varsize_frob(mtd, do_getlockstatus_oneblock,
ofs, len, NULL) ? 1 : 0;
}
#ifdef CONFIG_MTD_OTP
typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip,

View File

@ -33,7 +33,6 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/mtd/compatmac.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/cfi.h>
@ -417,16 +416,26 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
*/
cfi_fixup_major_minor(cfi, extp);
/*
* Valid primary extension versions are: 1.0, 1.1, 1.2, 1.3, 1.4
* see: http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_r20.pdf, page 19
* http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_100_20011201.pdf
* http://www.spansion.com/Support/Datasheets/s29ws-p_00_a12_e.pdf
*/
if (extp->MajorVersion != '1' ||
(extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
(extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '4'))) {
printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
"version %c.%c.\n", extp->MajorVersion,
extp->MinorVersion);
"version %c.%c (%#02x/%#02x).\n",
extp->MajorVersion, extp->MinorVersion,
extp->MajorVersion, extp->MinorVersion);
kfree(extp);
kfree(mtd);
return NULL;
}
printk(KERN_INFO " Amd/Fujitsu Extended Query version %c.%c.\n",
extp->MajorVersion, extp->MinorVersion);
/* Install our own private info structure */
cfi->cmdset_priv = extp;

View File

@ -33,7 +33,6 @@
#include <linux/mtd/map.h>
#include <linux/mtd/cfi.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/compatmac.h>
static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);

View File

@ -235,9 +235,9 @@ static int __xipram cfi_chip_setup(struct map_info *map,
cfi_qry_mode_off(base, map, cfi);
xip_allowed(base, map);
printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. Manufacturer ID %#08x Chip ID %#08x\n",
map->name, cfi->interleave, cfi->device_type*8, base,
map->bankwidth*8);
map->bankwidth*8, cfi->mfr, cfi->id);
return 1;
}

View File

@ -22,7 +22,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/cfi.h>
#include <linux/mtd/compatmac.h>
int __xipram cfi_qry_present(struct map_info *map, __u32 base,
struct cfi_private *cfi)

View File

@ -10,7 +10,6 @@
#include <linux/slab.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/compatmac.h>
static DEFINE_SPINLOCK(chip_drvs_lock);
static LIST_HEAD(chip_drvs_list);

View File

@ -25,7 +25,6 @@
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/compatmac.h>
static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);

View File

@ -13,7 +13,6 @@
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/compatmac.h>
static int mapram_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);

View File

@ -13,7 +13,6 @@
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/compatmac.h>
static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);

View File

@ -1,7 +1,22 @@
/*
* Read flash partition table from command line
*
* Copyright 2002 SYSGO Real-Time Solutions GmbH
* Copyright © 2002 SYSGO Real-Time Solutions GmbH
* Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The format for the command line is as follows:
*

View File

@ -31,7 +31,6 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/mtd/compatmac.h> /* for min() in older kernels */
#include <linux/mtd/mtd.h>
#include <linux/mtd/doc2000.h>

View File

@ -49,7 +49,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/doc2000.h>
#include <linux/mtd/compatmac.h>
/* Where to look for the devices? */
#ifndef CONFIG_MTD_DOCPROBE_ADDRESS

View File

@ -16,6 +16,8 @@
*/
#include <linux/init.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/interrupt.h>
@ -639,8 +641,18 @@ static const struct spi_device_id m25p_ids[] = {
{ "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
{ "at26df321", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
/* EON -- en25pxx */
{ "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
/* Intel/Numonyx -- xxxs33b */
{ "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
{ "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
{ "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) },
/* Macronix */
{ "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
{ "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
{ "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) },
{ "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) },
{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
@ -680,6 +692,16 @@ static const struct spi_device_id m25p_ids[] = {
{ "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) },
{ "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) },
{ "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) },
{ "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) },
{ "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) },
{ "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) },
{ "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) },
{ "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) },
{ "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) },
{ "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) },
{ "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) },
{ "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) },
{ "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) },
{ "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) },
@ -694,6 +716,7 @@ static const struct spi_device_id m25p_ids[] = {
{ "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
{ "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
{ "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
/* Catalyst / On Semiconductor -- non-JEDEC */
@ -723,7 +746,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
if (tmp < 0) {
DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
dev_name(&spi->dev), tmp);
return NULL;
return ERR_PTR(tmp);
}
jedec = id[0];
jedec = jedec << 8;
@ -731,14 +754,6 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
jedec = jedec << 8;
jedec |= id[2];
/*
* Some chips (like Numonyx M25P80) have JEDEC and non-JEDEC variants,
* which depend on technology process. Officially RDID command doesn't
* exist for non-JEDEC chips, but for compatibility they return ID 0.
*/
if (jedec == 0)
return NULL;
ext_jedec = id[3] << 8 | id[4];
for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
@ -749,7 +764,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
return &m25p_ids[tmp];
}
}
return NULL;
return ERR_PTR(-ENODEV);
}
@ -794,9 +809,8 @@ static int __devinit m25p_probe(struct spi_device *spi)
const struct spi_device_id *jid;
jid = jedec_probe(spi);
if (!jid) {
dev_info(&spi->dev, "non-JEDEC variant of %s\n",
id->name);
if (IS_ERR(jid)) {
return PTR_ERR(jid);
} else if (jid != id) {
/*
* JEDEC knows better, so overwrite platform ID. We
@ -826,11 +840,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
dev_set_drvdata(&spi->dev, flash);
/*
* Atmel and SST serial flash tend to power
* Atmel, SST and Intel/Numonyx serial flash tend to power
* up with the software protection bits set
*/
if (info->jedec_id >> 16 == 0x1f ||
info->jedec_id >> 16 == 0x89 ||
info->jedec_id >> 16 == 0xbf) {
write_enable(flash);
write_sr(flash, 0);

View File

@ -141,7 +141,7 @@ static int dataflash_waitready(struct spi_device *spi)
*/
static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct dataflash *priv = (struct dataflash *)mtd->priv;
struct dataflash *priv = mtd->priv;
struct spi_device *spi = priv->spi;
struct spi_transfer x = { .tx_dma = 0, };
struct spi_message msg;
@ -231,7 +231,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
struct dataflash *priv = (struct dataflash *)mtd->priv;
struct dataflash *priv = mtd->priv;
struct spi_transfer x[2] = { { .tx_dma = 0, }, };
struct spi_message msg;
unsigned int addr;
@ -304,7 +304,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t * retlen, const u_char * buf)
{
struct dataflash *priv = (struct dataflash *)mtd->priv;
struct dataflash *priv = mtd->priv;
struct spi_device *spi = priv->spi;
struct spi_transfer x[2] = { { .tx_dma = 0, }, };
struct spi_message msg;
@ -515,7 +515,7 @@ static ssize_t otp_read(struct spi_device *spi, unsigned base,
static int dataflash_read_fact_otp(struct mtd_info *mtd,
loff_t from, size_t len, size_t *retlen, u_char *buf)
{
struct dataflash *priv = (struct dataflash *)mtd->priv;
struct dataflash *priv = mtd->priv;
int status;
/* 64 bytes, from 0..63 ... start at 64 on-chip */
@ -532,7 +532,7 @@ static int dataflash_read_fact_otp(struct mtd_info *mtd,
static int dataflash_read_user_otp(struct mtd_info *mtd,
loff_t from, size_t len, size_t *retlen, u_char *buf)
{
struct dataflash *priv = (struct dataflash *)mtd->priv;
struct dataflash *priv = mtd->priv;
int status;
/* 64 bytes, from 0..63 ... start at 0 on-chip */
@ -553,7 +553,7 @@ static int dataflash_write_user_otp(struct mtd_info *mtd,
const size_t l = 4 + 64;
uint8_t *scratch;
struct spi_transfer t;
struct dataflash *priv = (struct dataflash *)mtd->priv;
struct dataflash *priv = mtd->priv;
int status;
if (len > 64)

View File

@ -14,7 +14,6 @@
#include <linux/ioport.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/mtd/compatmac.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/mtdram.h>

View File

@ -98,7 +98,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/pmc551.h>
#include <linux/mtd/compatmac.h>
static struct mtd_info *pmc551list;

View File

@ -454,7 +454,7 @@ static int __init sst25l_probe(struct spi_device *spi)
parts, nr_parts);
}
} else if (data->nr_parts) {
} else if (data && data->nr_parts) {
dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
data->nr_parts, data->name);
}

View File

@ -26,7 +26,7 @@
The initial developer of the original code is David A. Hinds
<dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
are Copyright © 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License version 2 (the "GPL"), in

View File

@ -1,11 +1,11 @@
/*
* inftlcore.c -- Linux driver for Inverse Flash Translation Layer (INFTL)
*
* (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
* Copyright © 2002, Greg Ungerer (gerg@snapgear.com)
*
* Based heavily on the nftlcore.c code which is:
* (c) 1999 Machine Vision Holdings, Inc.
* Author: David Woodhouse <dwmw2@infradead.org>
* Copyright © 1999 Machine Vision Holdings, Inc.
* Copyright © 1999 David Woodhouse <dwmw2@infradead.org>
*
* 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

View File

@ -2,11 +2,11 @@
* inftlmount.c -- INFTL mount code with extensive checks.
*
* Author: Greg Ungerer (gerg@snapgear.com)
* (C) Copyright 2002-2003, Greg Ungerer (gerg@snapgear.com)
* Copyright © 2002-2003, Greg Ungerer (gerg@snapgear.com)
*
* Based heavily on the nftlmount.c code which is:
* Author: Fabrice Bellard (fabrice.bellard@netgem.com)
* Copyright (C) 2000 Netgem S.A.
* Copyright © 2000 Netgem S.A.
*
* 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
@ -34,7 +34,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nftl.h>
#include <linux/mtd/inftl.h>
#include <linux/mtd/compatmac.h>
/*
* find_boot_record: Find the INFTL Media Header and its Spare copy which

View File

@ -98,7 +98,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum;
for (i = 0; i < numchips; i++) {
shared[i].writing = shared[i].erasing = NULL;
spin_lock_init(&shared[i].lock);
mutex_init(&shared[i].lock);
for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) {
*chip = lpddr->chips[i];
chip->start += j << lpddr->chipshift;
@ -217,7 +217,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
*/
struct flchip_shared *shared = chip->priv;
struct flchip *contender;
spin_lock(&shared->lock);
mutex_lock(&shared->lock);
contender = shared->writing;
if (contender && contender != chip) {
/*
@ -230,7 +230,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
* get_chip returns success we're clear to go ahead.
*/
ret = mutex_trylock(&contender->mutex);
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
if (!ret)
goto retry;
mutex_unlock(&chip->mutex);
@ -245,7 +245,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
mutex_unlock(&contender->mutex);
return ret;
}
spin_lock(&shared->lock);
mutex_lock(&shared->lock);
/* We should not own chip if it is already in FL_SYNCING
* state. Put contender and retry. */
@ -261,7 +261,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
Must sleep in such a case. */
if (mode == FL_ERASING && shared->erasing
&& shared->erasing->oldstate == FL_ERASING) {
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
mutex_unlock(&chip->mutex);
@ -275,7 +275,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, int mode)
shared->writing = chip;
if (mode == FL_ERASING)
shared->erasing = chip;
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
}
ret = chip_ready(map, chip, mode);
@ -348,7 +348,7 @@ static void put_chip(struct map_info *map, struct flchip *chip)
{
if (chip->priv) {
struct flchip_shared *shared = chip->priv;
spin_lock(&shared->lock);
mutex_lock(&shared->lock);
if (shared->writing == chip && chip->oldstate == FL_READY) {
/* We own the ability to write, but we're done */
shared->writing = shared->erasing;
@ -356,7 +356,7 @@ static void put_chip(struct map_info *map, struct flchip *chip)
/* give back the ownership */
struct flchip *loaner = shared->writing;
mutex_lock(&loaner->mutex);
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
mutex_unlock(&chip->mutex);
put_chip(map, loaner);
mutex_lock(&chip->mutex);
@ -374,11 +374,11 @@ static void put_chip(struct map_info *map, struct flchip *chip)
* Don't let the switch below mess things up since
* we don't have ownership to resume anything.
*/
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
wake_up(&chip->wq);
return;
}
spin_unlock(&shared->lock);
mutex_unlock(&shared->lock);
}
switch (chip->oldstate) {

View File

@ -319,14 +319,6 @@ config MTD_CFI_FLAGADM
Mapping for the Flaga digital module. If you don't have one, ignore
this setting.
config MTD_REDWOOD
tristate "CFI Flash devices mapped on IBM Redwood"
depends on MTD_CFI
help
This enables access routines for the flash chips on the IBM
Redwood board. If you have one of these boards and would like to
use the flash chips on it, say 'Y'.
config MTD_SOLUTIONENGINE
tristate "CFI Flash device mapped on Hitachi SolutionEngine"
depends on SUPERH && SOLUTION_ENGINE && MTD_CFI && MTD_REDBOOT_PARTS

View File

@ -44,7 +44,6 @@ obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
obj-$(CONFIG_MTD_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_IMPA7) += impa7.o
obj-$(CONFIG_MTD_FORTUNET) += fortunet.o
obj-$(CONFIG_MTD_REDWOOD) += redwood.o
obj-$(CONFIG_MTD_UCLINUX) += uclinux.o
obj-$(CONFIG_MTD_NETtel) += nettel.o
obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o

View File

@ -118,7 +118,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to,
*dest++ = BYTE1(data);
src += 2;
len -= 2;
}
}
if (len > 0)
*dest++ = BYTE0(flash_read16(src));
@ -185,6 +185,8 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
{
struct flash_platform_data *plat = dev->dev.platform_data;
struct ixp4xx_flash_info *info;
const char *part_type = NULL;
int nr_parts = 0;
int err = -1;
if (!plat)
@ -218,9 +220,9 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
*/
info->map.bankwidth = 2;
info->map.name = dev_name(&dev->dev);
info->map.read = ixp4xx_read16,
info->map.write = ixp4xx_probe_write16,
info->map.copy_from = ixp4xx_copy_from,
info->map.read = ixp4xx_read16;
info->map.write = ixp4xx_probe_write16;
info->map.copy_from = ixp4xx_copy_from;
info->res = request_mem_region(dev->resource->start,
resource_size(dev->resource),
@ -248,11 +250,28 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
info->mtd->owner = THIS_MODULE;
/* Use the fast version */
info->map.write = ixp4xx_write16,
info->map.write = ixp4xx_write16;
#ifdef CONFIG_MTD_PARTITIONS
nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions,
dev->resource->start);
#endif
if (nr_parts > 0) {
part_type = "dynamic";
} else {
info->partitions = plat->parts;
nr_parts = plat->nr_parts;
part_type = "static";
}
if (nr_parts == 0) {
printk(KERN_NOTICE "IXP4xx flash: no partition info "
"available, registering whole flash\n");
err = add_mtd_device(info->mtd);
} else {
printk(KERN_NOTICE "IXP4xx flash: using %s partition "
"definition\n", part_type);
err = add_mtd_partitions(info->mtd, info->partitions, nr_parts);
err = parse_mtd_partitions(info->mtd, probes, &info->partitions, dev->resource->start);
if (err > 0) {
err = add_mtd_partitions(info->mtd, info->partitions, err);
if(err)
printk(KERN_ERR "Could not parse partitions\n");
}

View File

@ -106,12 +106,12 @@ static int physmap_flash_probe(struct platform_device *dev)
for (i = 0; i < dev->num_resources; i++) {
printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
(unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1),
(unsigned long long)resource_size(&dev->resource[i]),
(unsigned long long)dev->resource[i].start);
if (!devm_request_mem_region(&dev->dev,
dev->resource[i].start,
dev->resource[i].end - dev->resource[i].start + 1,
resource_size(&dev->resource[i]),
dev_name(&dev->dev))) {
dev_err(&dev->dev, "Could not reserve memory region\n");
err = -ENOMEM;
@ -120,7 +120,7 @@ static int physmap_flash_probe(struct platform_device *dev)
info->map[i].name = dev_name(&dev->dev);
info->map[i].phys = dev->resource[i].start;
info->map[i].size = dev->resource[i].end - dev->resource[i].start + 1;
info->map[i].size = resource_size(&dev->resource[i]);
info->map[i].bankwidth = physmap_data->width;
info->map[i].set_vpp = physmap_data->set_vpp;
info->map[i].pfow_base = physmap_data->pfow_base;
@ -136,8 +136,12 @@ static int physmap_flash_probe(struct platform_device *dev)
simple_map_init(&info->map[i]);
probe_type = rom_probe_types;
for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++)
info->mtd[i] = do_map_probe(*probe_type, &info->map[i]);
if (physmap_data->probe_type == NULL) {
for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++)
info->mtd[i] = do_map_probe(*probe_type, &info->map[i]);
} else
info->mtd[i] = do_map_probe(physmap_data->probe_type, &info->map[i]);
if (info->mtd[i] == NULL) {
dev_err(&dev->dev, "map_probe failed\n");
err = -ENXIO;

View File

@ -353,7 +353,7 @@ static int __devinit of_flash_probe(struct of_device *dev,
&info->parts, 0);
if (err < 0) {
of_free_probes(part_probe_types);
return err;
goto err_out;
}
of_free_probes(part_probe_types);
@ -361,14 +361,14 @@ static int __devinit of_flash_probe(struct of_device *dev,
if (err == 0) {
err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
if (err < 0)
return err;
goto err_out;
}
#endif
if (err == 0) {
err = parse_obsolete_partitions(dev, info, dp);
if (err < 0)
return err;
goto err_out;
}
if (err > 0)

View File

@ -1,131 +0,0 @@
/*
* drivers/mtd/maps/redwood.c
*
* FLASH map for the IBM Redwood 4/5/6 boards.
*
* Author: MontaVista Software, Inc. <source@mvista.com>
*
* 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#define WINDOW_ADDR 0xffc00000
#define WINDOW_SIZE 0x00400000
#define RW_PART0_OF 0
#define RW_PART0_SZ 0x10000
#define RW_PART1_OF RW_PART0_SZ
#define RW_PART1_SZ 0x200000 - 0x10000
#define RW_PART2_OF 0x200000
#define RW_PART2_SZ 0x10000
#define RW_PART3_OF 0x210000
#define RW_PART3_SZ 0x200000 - (0x10000 + 0x20000)
#define RW_PART4_OF 0x3e0000
#define RW_PART4_SZ 0x20000
static struct mtd_partition redwood_flash_partitions[] = {
{
.name = "Redwood OpenBIOS Vital Product Data",
.offset = RW_PART0_OF,
.size = RW_PART0_SZ,
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{
.name = "Redwood kernel",
.offset = RW_PART1_OF,
.size = RW_PART1_SZ
},
{
.name = "Redwood OpenBIOS non-volatile storage",
.offset = RW_PART2_OF,
.size = RW_PART2_SZ,
.mask_flags = MTD_WRITEABLE /* force read-only */
},
{
.name = "Redwood filesystem",
.offset = RW_PART3_OF,
.size = RW_PART3_SZ
},
{
.name = "Redwood OpenBIOS",
.offset = RW_PART4_OF,
.size = RW_PART4_SZ,
.mask_flags = MTD_WRITEABLE /* force read-only */
}
};
struct map_info redwood_flash_map = {
.name = "IBM Redwood",
.size = WINDOW_SIZE,
.bankwidth = 2,
.phys = WINDOW_ADDR,
};
#define NUM_REDWOOD_FLASH_PARTITIONS ARRAY_SIZE(redwood_flash_partitions)
static struct mtd_info *redwood_mtd;
static int __init init_redwood_flash(void)
{
int err;
printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n",
WINDOW_SIZE, WINDOW_ADDR);
redwood_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
if (!redwood_flash_map.virt) {
printk("init_redwood_flash: failed to ioremap\n");
return -EIO;
}
simple_map_init(&redwood_flash_map);
redwood_mtd = do_map_probe("cfi_probe",&redwood_flash_map);
if (redwood_mtd) {
redwood_mtd->owner = THIS_MODULE;
err = add_mtd_partitions(redwood_mtd,
redwood_flash_partitions,
NUM_REDWOOD_FLASH_PARTITIONS);
if (err) {
printk("init_redwood_flash: add_mtd_partitions failed\n");
iounmap(redwood_flash_map.virt);
}
return err;
}
iounmap(redwood_flash_map.virt);
return -ENXIO;
}
static void __exit cleanup_redwood_flash(void)
{
if (redwood_mtd) {
del_mtd_partitions(redwood_mtd);
/* moved iounmap after map_destroy - armin */
map_destroy(redwood_mtd);
iounmap((void *)redwood_flash_map.virt);
}
}
module_init(init_redwood_flash);
module_exit(cleanup_redwood_flash);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("MontaVista Software <source@mvista.com>");
MODULE_DESCRIPTION("MTD map driver for the IBM Redwood reference boards");

View File

@ -1,7 +1,21 @@
/*
* (C) 2003 David Woodhouse <dwmw2@infradead.org>
* Interface to Linux block layer for MTD 'translation layers'.
*
* Interface to Linux 2.5 block layer for MTD 'translation layers'.
* Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
@ -245,6 +259,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
switch (cmd) {
case BLKFLSBUF:
ret = dev->tr->flush ? dev->tr->flush(dev) : 0;
break;
default:
ret = -ENOTTY;
}
@ -409,13 +424,14 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
BUG();
}
/* Stop new requests to arrive */
del_gendisk(old->disk);
if (old->disk_attributes)
sysfs_remove_group(&disk_to_dev(old->disk)->kobj,
old->disk_attributes);
/* Stop new requests to arrive */
del_gendisk(old->disk);
/* Stop the thread */
kthread_stop(old->thread);

View File

@ -1,8 +1,23 @@
/*
* Direct MTD block device access
*
* (C) 2000-2003 Nicolas Pitre <nico@fluxnic.net>
* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
* Copyright © 2000-2003 Nicolas Pitre <nico@fluxnic.net>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <linux/fs.h>

View File

@ -1,7 +1,22 @@
/*
* (C) 2003 David Woodhouse <dwmw2@infradead.org>
*
* Simple read-only (writable only for RAM) mtdblock driver
*
* Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <linux/init.h>

View File

@ -1,5 +1,19 @@
/*
* Character-device access to raw MTD devices.
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
@ -18,7 +32,7 @@
#include <linux/mount.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/compatmac.h>
#include <linux/mtd/map.h>
#include <asm/uaccess.h>
@ -675,6 +689,20 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
break;
}
case MEMISLOCKED:
{
struct erase_info_user einfo;
if (copy_from_user(&einfo, argp, sizeof(einfo)))
return -EFAULT;
if (!mtd->is_locked)
ret = -EOPNOTSUPP;
else
ret = mtd->is_locked(mtd, einfo.start, einfo.length);
break;
}
/* Legacy interface */
case MEMGETOOBSEL:
{
@ -950,9 +978,34 @@ static int mtd_mmap(struct file *file, struct vm_area_struct *vma)
#ifdef CONFIG_MMU
struct mtd_file_info *mfi = file->private_data;
struct mtd_info *mtd = mfi->mtd;
struct map_info *map = mtd->priv;
unsigned long start;
unsigned long off;
u32 len;
if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) {
off = vma->vm_pgoff << PAGE_SHIFT;
start = map->phys;
len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
start &= PAGE_MASK;
if ((vma->vm_end - vma->vm_start + off) > len)
return -EINVAL;
off += start;
vma->vm_pgoff = off >> PAGE_SHIFT;
vma->vm_flags |= VM_IO | VM_RESERVED;
#ifdef pgprot_noncached
if (file->f_flags & O_DSYNC || off >= __pa(high_memory))
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
#endif
if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
if (mtd->type == MTD_RAM || mtd->type == MTD_ROM)
return 0;
}
return -ENOSYS;
#else
return vma->vm_flags & VM_SHARED ? 0 : -ENOSYS;

View File

@ -1,11 +1,25 @@
/*
* MTD device concatenation layer
*
* (C) 2002 Robert Kaiser <rkaiser@sysgo.de>
* Copyright © 2002 Robert Kaiser <rkaiser@sysgo.de>
* Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org>
*
* NAND support by Christian Gan <cgan@iders.ca>
*
* This code is GPL
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <linux/kernel.h>
@ -540,10 +554,12 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
else
size = len;
err = subdev->lock(subdev, ofs, size);
if (err)
break;
if (subdev->lock) {
err = subdev->lock(subdev, ofs, size);
if (err)
break;
} else
err = -EOPNOTSUPP;
len -= size;
if (len == 0)
@ -578,10 +594,12 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
else
size = len;
err = subdev->unlock(subdev, ofs, size);
if (err)
break;
if (subdev->unlock) {
err = subdev->unlock(subdev, ofs, size);
if (err)
break;
} else
err = -EOPNOTSUPP;
len -= size;
if (len == 0)

View File

@ -2,9 +2,23 @@
* Core registration and callback routines for MTD
* drivers and users.
*
* bdi bits are:
* Copyright © 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
* Copyright © 2006 Red Hat UK Limited
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <linux/module.h>
@ -17,7 +31,6 @@
#include <linux/err.h>
#include <linux/ioctl.h>
#include <linux/init.h>
#include <linux/mtd/compatmac.h>
#include <linux/proc_fs.h>
#include <linux/idr.h>
#include <linux/backing-dev.h>

View File

@ -1,7 +1,7 @@
/*
* MTD Oops/Panic logger
*
* Copyright (C) 2007 Nokia Corporation. All rights reserved.
* Copyright © 2007 Nokia Corporation. All rights reserved.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*

View File

@ -1,12 +1,24 @@
/*
* Simple MTD partitioning layer
*
* (C) 2000 Nicolas Pitre <nico@fluxnic.net>
* Copyright © 2000 Nicolas Pitre <nico@fluxnic.net>
* Copyright © 2002 Thomas Gleixner <gleixner@linutronix.de>
* Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
*
* This code is GPL
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* 02-21-2002 Thomas Gleixner <gleixner@autronix.de>
* added support for read_oob, write_oob
*/
#include <linux/module.h>
@ -17,7 +29,6 @@
#include <linux/kmod.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/compatmac.h>
/* Our partition linked list */
static LIST_HEAD(mtd_partitions);
@ -264,6 +275,14 @@ static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
return part->master->unlock(part->master, ofs + part->offset, len);
}
static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct mtd_part *part = PART(mtd);
if ((len + ofs) > mtd->size)
return -EINVAL;
return part->master->is_locked(part->master, ofs + part->offset, len);
}
static void part_sync(struct mtd_info *mtd)
{
struct mtd_part *part = PART(mtd);
@ -402,6 +421,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
slave->mtd.lock = part_lock;
if (master->unlock)
slave->mtd.unlock = part_unlock;
if (master->is_locked)
slave->mtd.is_locked = part_is_locked;
if (master->block_isbad)
slave->mtd.block_isbad = part_block_isbad;
if (master->block_markbad)

View File

@ -1,6 +1,8 @@
/* MTD-based superblock management
*
* Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved.
* Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
*
* Written by: David Howells <dhowells@redhat.com>
* David Woodhouse <dwmw2@infradead.org>
*

View File

@ -37,7 +37,6 @@ config MTD_SM_COMMON
config MTD_NAND_MUSEUM_IDS
bool "Enable chip ids for obsolete ancient NAND devices"
depends on MTD_NAND
default n
help
Enable this option only when your board has first generation
@ -61,6 +60,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
help
Some platforms place the NAND chip size in a scratch register
because (some versions of) the driver aren't able to automatically
@ -101,13 +101,13 @@ config MTD_NAND_AMS_DELTA
config MTD_NAND_OMAP2
tristate "NAND Flash device on OMAP2 and OMAP3"
depends on ARM && MTD_NAND && (ARCH_OMAP2 || ARCH_OMAP3)
depends on ARM && (ARCH_OMAP2 || ARCH_OMAP3)
help
Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
config MTD_NAND_OMAP_PREFETCH
bool "GPMC prefetch support for NAND Flash device"
depends on MTD_NAND && MTD_NAND_OMAP2
depends on MTD_NAND_OMAP2
default y
help
The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
@ -146,7 +146,7 @@ config MTD_NAND_AU1550
config MTD_NAND_BF5XX
tristate "Blackfin on-chip NAND Flash Controller driver"
depends on (BF54x || BF52x) && MTD_NAND
depends on BF54x || BF52x
help
This enables the Blackfin on-chip NAND flash controller
@ -236,7 +236,7 @@ config MTD_NAND_S3C2410_CLKSTOP
config MTD_NAND_BCM_UMI
tristate "NAND Flash support for BCM Reference Boards"
depends on ARCH_BCMRING && MTD_NAND
depends on ARCH_BCMRING
help
This enables the NAND flash controller on the BCM UMI block.
@ -395,7 +395,7 @@ endchoice
config MTD_NAND_PXA3xx
tristate "Support for NAND flash devices on PXA3xx"
depends on MTD_NAND && (PXA3xx || ARCH_MMP)
depends on PXA3xx || ARCH_MMP
help
This enables the driver for the NAND flash device found on
PXA3xx processors
@ -409,18 +409,18 @@ config MTD_NAND_PXA3xx_BUILTIN
config MTD_NAND_CM_X270
tristate "Support for NAND Flash on CM-X270 modules"
depends on MTD_NAND && MACH_ARMCORE
depends on MACH_ARMCORE
config MTD_NAND_PASEMI
tristate "NAND support for PA Semi PWRficient"
depends on MTD_NAND && PPC_PASEMI
depends on PPC_PASEMI
help
Enables support for NAND Flash interface on PA Semi PWRficient
based boards
config MTD_NAND_TMIO
tristate "NAND Flash device on Toshiba Mobile IO Controller"
depends on MTD_NAND && MFD_TMIO
depends on MFD_TMIO
help
Support for NAND flash connected to a Toshiba Mobile IO
Controller in some PDAs, including the Sharp SL6000x.
@ -434,7 +434,6 @@ config MTD_NAND_NANDSIM
config MTD_NAND_PLATFORM
tristate "Support for generic platform NAND driver"
depends on MTD_NAND
help
This implements a generic NAND driver for on-SOC platform
devices. You will need to provide platform-specific functions
@ -442,14 +441,14 @@ config MTD_NAND_PLATFORM
config MTD_ALAUDA
tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1"
depends on MTD_NAND && USB
depends on USB
help
These two (and possibly other) Alauda-based cardreaders for
SmartMedia and xD allow raw flash access.
config MTD_NAND_ORION
tristate "NAND Flash support for Marvell Orion SoC"
depends on PLAT_ORION && MTD_NAND
depends on PLAT_ORION
help
This enables the NAND flash controller on Orion machines.
@ -458,7 +457,7 @@ config MTD_NAND_ORION
config MTD_NAND_FSL_ELBC
tristate "NAND support for Freescale eLBC controllers"
depends on MTD_NAND && PPC_OF
depends on PPC_OF
help
Various Freescale chips, including the 8313, include a NAND Flash
Controller Module with built-in hardware ECC capabilities.
@ -467,7 +466,7 @@ config MTD_NAND_FSL_ELBC
config MTD_NAND_FSL_UPM
tristate "Support for NAND on Freescale UPM"
depends on MTD_NAND && (PPC_83xx || PPC_85xx)
depends on PPC_83xx || PPC_85xx
select FSL_LBC
help
Enables support for NAND Flash chips wired onto Freescale PowerPC
@ -482,7 +481,7 @@ config MTD_NAND_MPC5121_NFC
config MTD_NAND_MXC
tristate "MXC NAND support"
depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3
depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 || ARCH_MX51
help
This enables the driver for the NAND flash controller on the
MXC processors.
@ -495,7 +494,7 @@ config MTD_NAND_NOMADIK
config MTD_NAND_SH_FLCTL
tristate "Support for NAND on Renesas SuperH FLCTL"
depends on MTD_NAND && (SUPERH || ARCH_SHMOBILE)
depends on SUPERH || ARCH_SHMOBILE
help
Several Renesas SuperH CPU has FLCTL. This option enables support
for NAND Flash using FLCTL.
@ -515,7 +514,7 @@ config MTD_NAND_TXX9NDFMC
config MTD_NAND_SOCRATES
tristate "Support for NAND on Socrates board"
depends on MTD_NAND && SOCRATES
depends on SOCRATES
help
Enables support for NAND Flash chips wired onto Socrates board.

View File

@ -364,7 +364,7 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
}
}
#ifdef CONFIG_MTD_PARTITIONS
#ifdef CONFIG_MTD_CMDLINE_PARTS
static const char *part_probes[] = { "cmdlinepart", NULL };
#endif

View File

@ -20,9 +20,6 @@
* - DMA supported in ECC_HW
* - YAFFS tested as rootfs in both ECC_HW and ECC_SW
*
* TODO:
* Enable JFFS2 over NAND as rootfs
*
* 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
@ -206,7 +203,7 @@ static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd,
if (ctrl & NAND_CLE)
bfin_write_NFC_CMD(cmd);
else
else if (ctrl & NAND_ALE)
bfin_write_NFC_ADDR(cmd);
SSYNC();
}
@ -218,9 +215,9 @@ static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd,
*/
static int bf5xx_nand_devready(struct mtd_info *mtd)
{
unsigned short val = bfin_read_NFC_IRQSTAT();
unsigned short val = bfin_read_NFC_STAT();
if ((val & NBUSYIRQ) == NBUSYIRQ)
if ((val & NBUSY) == NBUSY)
return 1;
else
return 0;
@ -317,18 +314,16 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
struct bf5xx_nand_platform *plat = info->platform;
unsigned short page_size = (plat->page_size ? 512 : 256);
struct nand_chip *chip = mtd->priv;
int ret;
ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
/* If page size is 512, correct second 256 bytes */
if (page_size == 512) {
/* If ecc size is 512, correct second 256 bytes */
if (chip->ecc.size == 512) {
dat += 256;
read_ecc += 8;
calc_ecc += 8;
read_ecc += 3;
calc_ecc += 3;
ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
}
@ -344,13 +339,12 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
const u_char *dat, u_char *ecc_code)
{
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
struct bf5xx_nand_platform *plat = info->platform;
u16 page_size = (plat->page_size ? 512 : 256);
struct nand_chip *chip = mtd->priv;
u16 ecc0, ecc1;
u32 code[2];
u8 *p;
/* first 4 bytes ECC code for 256 page size */
/* first 3 bytes ECC code for 256 page size */
ecc0 = bfin_read_NFC_ECC0();
ecc1 = bfin_read_NFC_ECC1();
@ -358,12 +352,11 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
/* first 3 bytes in ecc_code for 256 page size */
p = (u8 *) code;
memcpy(ecc_code, p, 3);
/* second 4 bytes ECC code for 512 page size */
if (page_size == 512) {
/* second 3 bytes ECC code for 512 ecc size */
if (chip->ecc.size == 512) {
ecc0 = bfin_read_NFC_ECC2();
ecc1 = bfin_read_NFC_ECC3();
code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
@ -483,8 +476,7 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
uint8_t *buf, int is_read)
{
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
struct bf5xx_nand_platform *plat = info->platform;
unsigned short page_size = (plat->page_size ? 512 : 256);
struct nand_chip *chip = mtd->priv;
unsigned short val;
dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n",
@ -498,10 +490,10 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
*/
if (is_read)
invalidate_dcache_range((unsigned int)buf,
(unsigned int)(buf + page_size));
(unsigned int)(buf + chip->ecc.size));
else
flush_dcache_range((unsigned int)buf,
(unsigned int)(buf + page_size));
(unsigned int)(buf + chip->ecc.size));
/*
* This register must be written before each page is
@ -510,6 +502,8 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
*/
bfin_write_NFC_RST(ECC_RST);
SSYNC();
while (bfin_read_NFC_RST() & ECC_RST)
cpu_relax();
disable_dma(CH_NFC);
clear_dma_irqstat(CH_NFC);
@ -520,13 +514,13 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
/* The DMAs have different size on BF52x and BF54x */
#ifdef CONFIG_BF52x
set_dma_x_count(CH_NFC, (page_size >> 1));
set_dma_x_count(CH_NFC, (chip->ecc.size >> 1));
set_dma_x_modify(CH_NFC, 2);
val = DI_EN | WDSIZE_16;
#endif
#ifdef CONFIG_BF54x
set_dma_x_count(CH_NFC, (page_size >> 2));
set_dma_x_count(CH_NFC, (chip->ecc.size >> 2));
set_dma_x_modify(CH_NFC, 4);
val = DI_EN | WDSIZE_32;
#endif
@ -548,12 +542,11 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
uint8_t *buf, int len)
{
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
struct bf5xx_nand_platform *plat = info->platform;
unsigned short page_size = (plat->page_size ? 512 : 256);
struct nand_chip *chip = mtd->priv;
dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len);
if (len == page_size)
if (len == chip->ecc.size)
bf5xx_nand_dma_rw(mtd, buf, 1);
else
bf5xx_nand_read_buf(mtd, buf, len);
@ -563,17 +556,32 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
const uint8_t *buf, int len)
{
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
struct bf5xx_nand_platform *plat = info->platform;
unsigned short page_size = (plat->page_size ? 512 : 256);
struct nand_chip *chip = mtd->priv;
dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len);
if (len == page_size)
if (len == chip->ecc.size)
bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0);
else
bf5xx_nand_write_buf(mtd, buf, len);
}
static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int page)
{
bf5xx_nand_read_buf(mtd, buf, mtd->writesize);
bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
return 0;
}
static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf)
{
bf5xx_nand_write_buf(mtd, buf, mtd->writesize);
bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
}
/*
* System initialization functions
*/
@ -627,15 +635,14 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
/* setup NFC_CTL register */
dev_info(info->device,
"page_size=%d, data_width=%d, wr_dly=%d, rd_dly=%d\n",
(plat->page_size ? 512 : 256),
"data_width=%d, wr_dly=%d, rd_dly=%d\n",
(plat->data_width ? 16 : 8),
plat->wr_dly, plat->rd_dly);
val = (plat->page_size << NFC_PG_SIZE_OFFSET) |
val = (1 << NFC_PG_SIZE_OFFSET) |
(plat->data_width << NFC_NWIDTH_OFFSET) |
(plat->rd_dly << NFC_RDDLY_OFFSET) |
(plat->rd_dly << NFC_WRDLY_OFFSET);
(plat->wr_dly << NFC_WRDLY_OFFSET);
dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val);
bfin_write_NFC_CTL(val);
@ -698,6 +705,33 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
return 0;
}
static int bf5xx_nand_scan(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
int ret;
ret = nand_scan_ident(mtd, 1);
if (ret)
return ret;
if (hardware_ecc) {
/*
* for nand with page size > 512B, think it as several sections with 512B
*/
if (likely(mtd->writesize >= 512)) {
chip->ecc.size = 512;
chip->ecc.bytes = 6;
} else {
chip->ecc.size = 256;
chip->ecc.bytes = 3;
bfin_write_NFC_CTL(bfin_read_NFC_CTL() & ~(1 << NFC_PG_SIZE_OFFSET));
SSYNC();
}
}
return nand_scan_tail(mtd);
}
/*
* bf5xx_nand_probe
*
@ -783,27 +817,20 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
chip->badblock_pattern = &bootrom_bbt;
chip->ecc.layout = &bootrom_ecclayout;
#endif
if (plat->page_size == NFC_PG_SIZE_256) {
chip->ecc.bytes = 3;
chip->ecc.size = 256;
} else if (plat->page_size == NFC_PG_SIZE_512) {
chip->ecc.bytes = 6;
chip->ecc.size = 512;
}
chip->read_buf = bf5xx_nand_dma_read_buf;
chip->write_buf = bf5xx_nand_dma_write_buf;
chip->ecc.calculate = bf5xx_nand_calculate_ecc;
chip->ecc.correct = bf5xx_nand_correct_data;
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.hwctl = bf5xx_nand_enable_hwecc;
chip->ecc.read_page_raw = bf5xx_nand_read_page_raw;
chip->ecc.write_page_raw = bf5xx_nand_write_page_raw;
} else {
chip->ecc.mode = NAND_ECC_SOFT;
}
/* scan hardware nand chip and setup mtd info data struct */
if (nand_scan(mtd, 1)) {
if (bf5xx_nand_scan(mtd)) {
err = -ENXIO;
goto out_err_nand_scan;
}

View File

@ -311,7 +311,9 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
unsigned short ecc10[8];
unsigned short *ecc16;
u32 syndrome[4];
u32 ecc_state;
unsigned num_errors, corrected;
unsigned long timeo = jiffies + msecs_to_jiffies(100);
/* All bytes 0xff? It's an erased page; ignore its ECC. */
for (i = 0; i < 10; i++) {
@ -361,6 +363,21 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
*/
davinci_nand_writel(info, NANDFCR_OFFSET,
davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13));
/*
* ECC_STATE field reads 0x3 (Error correction complete) immediately
* after setting the 4BITECC_ADD_CALC_START bit. So if you immediately
* begin trying to poll for the state, you may fall right out of your
* loop without any of the correction calculations having taken place.
* The recommendation from the hardware team is to wait till ECC_STATE
* reads less than 4, which means ECC HW has entered correction state.
*/
do {
ecc_state = (davinci_nand_readl(info,
NANDFSR_OFFSET) >> 8) & 0x0f;
cpu_relax();
} while ((ecc_state < 4) && time_before(jiffies, timeo));
for (;;) {
u32 fsr = davinci_nand_readl(info, NANDFSR_OFFSET);

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
*
*/
#include <linux/mtd/nand.h>
#include <linux/mtd/nand.h>
#define DEVICE_RESET 0x0
#define DEVICE_RESET__BANK0 0x0001
@ -29,7 +29,7 @@
#define TRANSFER_SPARE_REG__FLAG 0x0001
#define LOAD_WAIT_CNT 0x20
#define LOAD_WAIT_CNT__VALUE 0xffff
#define LOAD_WAIT_CNT__VALUE 0xffff
#define PROGRAM_WAIT_CNT 0x30
#define PROGRAM_WAIT_CNT__VALUE 0xffff
@ -83,7 +83,7 @@
#define RE_2_WE 0x120
#define RE_2_WE__VALUE 0x003f
#define ACC_CLKS 0x130
#define ACC_CLKS 0x130
#define ACC_CLKS__VALUE 0x000f
#define NUMBER_OF_PLANES 0x140
@ -140,7 +140,7 @@
#define DEVICES_CONNECTED 0x250
#define DEVICES_CONNECTED__VALUE 0x0007
#define DIE_MASK 0x260
#define DIE_MASK 0x260
#define DIE_MASK__VALUE 0x00ff
#define FIRST_BLOCK_OF_NEXT_PLANE 0x270
@ -152,7 +152,7 @@
#define RE_2_RE 0x290
#define RE_2_RE__VALUE 0x003f
#define MANUFACTURER_ID 0x300
#define MANUFACTURER_ID 0x300
#define MANUFACTURER_ID__VALUE 0x00ff
#define DEVICE_ID 0x310
@ -173,13 +173,13 @@
#define LOGICAL_PAGE_SPARE_SIZE 0x360
#define LOGICAL_PAGE_SPARE_SIZE__VALUE 0xffff
#define REVISION 0x370
#define REVISION 0x370
#define REVISION__VALUE 0xffff
#define ONFI_DEVICE_FEATURES 0x380
#define ONFI_DEVICE_FEATURES__VALUE 0x003f
#define ONFI_OPTIONAL_COMMANDS 0x390
#define ONFI_OPTIONAL_COMMANDS 0x390
#define ONFI_OPTIONAL_COMMANDS__VALUE 0x003f
#define ONFI_TIMING_MODE 0x3a0
@ -201,12 +201,12 @@
#define FEATURES 0x3f0
#define FEATURES__N_BANKS 0x0003
#define FEATURES__ECC_MAX_ERR 0x003c
#define FEATURES__DMA 0x0040
#define FEATURES__DMA 0x0040
#define FEATURES__CMD_DMA 0x0080
#define FEATURES__PARTITION 0x0100
#define FEATURES__XDMA_SIDEBAND 0x0200
#define FEATURES__GPREG 0x0400
#define FEATURES__INDEX_ADDR 0x0800
#define FEATURES__INDEX_ADDR 0x0800
#define TRANSFER_MODE 0x400
#define TRANSFER_MODE__VALUE 0x0003
@ -235,12 +235,12 @@
#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__ERASE_FAIL 0x0020
#define INTR_EN0__LOAD_COMP 0x0040
#define INTR_EN0__PROGRAM_COMP 0x0080
#define INTR_EN0__ERASE_COMP 0x0100
#define INTR_EN0__ERASE_COMP 0x0100
#define INTR_EN0__PIPE_CPYBCK_CMD_COMP 0x0200
#define INTR_EN0__LOCKED_BLK 0x0400
#define INTR_EN0__LOCKED_BLK 0x0400
#define INTR_EN0__UNSUP_CMD 0x0800
#define INTR_EN0__INT_ACT 0x1000
#define INTR_EN0__RST_COMP 0x2000
@ -253,7 +253,7 @@
#define ERR_PAGE_ADDR0 0x440
#define ERR_PAGE_ADDR0__VALUE 0xffff
#define ERR_BLOCK_ADDR0 0x450
#define ERR_BLOCK_ADDR0 0x450
#define ERR_BLOCK_ADDR0__VALUE 0xffff
#define INTR_STATUS1 0x460
@ -280,12 +280,12 @@
#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__ERASE_FAIL 0x0020
#define INTR_EN1__LOAD_COMP 0x0040
#define INTR_EN1__PROGRAM_COMP 0x0080
#define INTR_EN1__ERASE_COMP 0x0100
#define INTR_EN1__ERASE_COMP 0x0100
#define INTR_EN1__PIPE_CPYBCK_CMD_COMP 0x0200
#define INTR_EN1__LOCKED_BLK 0x0400
#define INTR_EN1__LOCKED_BLK 0x0400
#define INTR_EN1__UNSUP_CMD 0x0800
#define INTR_EN1__INT_ACT 0x1000
#define INTR_EN1__RST_COMP 0x2000
@ -298,7 +298,7 @@
#define ERR_PAGE_ADDR1 0x490
#define ERR_PAGE_ADDR1__VALUE 0xffff
#define ERR_BLOCK_ADDR1 0x4a0
#define ERR_BLOCK_ADDR1 0x4a0
#define ERR_BLOCK_ADDR1__VALUE 0xffff
#define INTR_STATUS2 0x4b0
@ -325,12 +325,12 @@
#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__ERASE_FAIL 0x0020
#define INTR_EN2__LOAD_COMP 0x0040
#define INTR_EN2__PROGRAM_COMP 0x0080
#define INTR_EN2__ERASE_COMP 0x0100
#define INTR_EN2__ERASE_COMP 0x0100
#define INTR_EN2__PIPE_CPYBCK_CMD_COMP 0x0200
#define INTR_EN2__LOCKED_BLK 0x0400
#define INTR_EN2__LOCKED_BLK 0x0400
#define INTR_EN2__UNSUP_CMD 0x0800
#define INTR_EN2__INT_ACT 0x1000
#define INTR_EN2__RST_COMP 0x2000
@ -343,7 +343,7 @@
#define ERR_PAGE_ADDR2 0x4e0
#define ERR_PAGE_ADDR2__VALUE 0xffff
#define ERR_BLOCK_ADDR2 0x4f0
#define ERR_BLOCK_ADDR2 0x4f0
#define ERR_BLOCK_ADDR2__VALUE 0xffff
#define INTR_STATUS3 0x500
@ -370,12 +370,12 @@
#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__ERASE_FAIL 0x0020
#define INTR_EN3__LOAD_COMP 0x0040
#define INTR_EN3__PROGRAM_COMP 0x0080
#define INTR_EN3__ERASE_COMP 0x0100
#define INTR_EN3__ERASE_COMP 0x0100
#define INTR_EN3__PIPE_CPYBCK_CMD_COMP 0x0200
#define INTR_EN3__LOCKED_BLK 0x0400
#define INTR_EN3__LOCKED_BLK 0x0400
#define INTR_EN3__UNSUP_CMD 0x0800
#define INTR_EN3__INT_ACT 0x1000
#define INTR_EN3__RST_COMP 0x2000
@ -388,7 +388,7 @@
#define ERR_PAGE_ADDR3 0x530
#define ERR_PAGE_ADDR3__VALUE 0xffff
#define ERR_BLOCK_ADDR3 0x540
#define ERR_BLOCK_ADDR3 0x540
#define ERR_BLOCK_ADDR3__VALUE 0xffff
#define DATA_INTR 0x550
@ -412,9 +412,9 @@
#define GPREG_3__VALUE 0xffff
#define ECC_THRESHOLD 0x600
#define ECC_THRESHOLD__VALUE 0x03ff
#define ECC_THRESHOLD__VALUE 0x03ff
#define ECC_ERROR_BLOCK_ADDRESS 0x610
#define ECC_ERROR_BLOCK_ADDRESS 0x610
#define ECC_ERROR_BLOCK_ADDRESS__VALUE 0xffff
#define ECC_ERROR_PAGE_ADDRESS 0x620
@ -466,7 +466,7 @@
#define CHNL_ACTIVE__CHANNEL3 0x0008
#define ACTIVE_SRC_ID 0x800
#define ACTIVE_SRC_ID__VALUE 0x00ff
#define ACTIVE_SRC_ID__VALUE 0x00ff
#define PTN_INTR 0x810
#define PTN_INTR__CONFIG_ERROR 0x0001
@ -485,7 +485,7 @@
#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__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
@ -502,7 +502,7 @@
#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__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
@ -519,7 +519,7 @@
#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__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
@ -536,7 +536,7 @@
#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__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
@ -553,7 +553,7 @@
#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__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
@ -570,7 +570,7 @@
#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__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
@ -587,7 +587,7 @@
#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__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
@ -604,7 +604,7 @@
#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__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
@ -620,47 +620,6 @@
#define MIN_MAX_BANK_7__MIN_VALUE 0x0003
#define MIN_MAX_BANK_7__MAX_VALUE 0x000c
/* flash.h */
struct device_info_tag {
uint16_t wDeviceMaker;
uint16_t wDeviceID;
uint8_t bDeviceParam0;
uint8_t bDeviceParam1;
uint8_t bDeviceParam2;
uint32_t wDeviceType;
uint32_t wSpectraStartBlock;
uint32_t wSpectraEndBlock;
uint32_t wTotalBlocks;
uint16_t wPagesPerBlock;
uint16_t wPageSize;
uint16_t wPageDataSize;
uint16_t wPageSpareSize;
uint16_t wNumPageSpareFlag;
uint16_t wECCBytesPerSector;
uint32_t wBlockSize;
uint32_t wBlockDataSize;
uint32_t wDataBlockNum;
uint8_t bPlaneNum;
uint16_t wDeviceMainAreaSize;
uint16_t wDeviceSpareAreaSize;
uint16_t wDevicesConnected;
uint16_t wDeviceWidth;
uint16_t wHWRevision;
uint16_t wHWFeatures;
uint16_t wONFIDevFeatures;
uint16_t wONFIOptCommands;
uint16_t wONFITimingMode;
uint16_t wONFIPgmCacheTimingMode;
uint16_t MLCDevice;
uint16_t wSpareSkipBytes;
uint8_t nBitsInPageNumber;
uint8_t nBitsInPageDataSize;
uint8_t nBitsInBlockDataSize;
};
/* ffsdefs.h */
#define CLEAR 0 /*use this to clear a field instead of "fail"*/
#define SET 1 /*use this to set a field instead of "pass"*/
@ -684,11 +643,11 @@ struct device_info_tag {
#define NAND_DBG_TRACE 3
#ifdef VERBOSE
#define nand_dbg_print(level, args...) \
do { \
if (level <= nand_debug_level) \
printk(KERN_ALERT args); \
} while (0)
#define nand_dbg_print(level, args...) \
do { \
if (level <= nand_debug_level) \
printk(KERN_ALERT args); \
} while (0)
#else
#define nand_dbg_print(level, args...)
#endif
@ -772,10 +731,9 @@ struct device_info_tag {
#define ECC_SECTOR_SIZE 512
#define LLD_MAX_FLASH_BANKS 4
#define DENALI_BUF_SIZE NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE
#define DENALI_BUF_SIZE (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE)
struct nand_buf
{
struct nand_buf {
int head;
int tail;
uint8_t buf[DENALI_BUF_SIZE];
@ -788,7 +746,6 @@ struct nand_buf
struct denali_nand_info {
struct mtd_info mtd;
struct nand_chip nand;
struct device_info_tag dev_info;
int flash_bank; /* currently selected chip */
int status;
int platform;
@ -806,11 +763,12 @@ struct denali_nand_info {
uint32_t irq_status;
int irq_debug_array[32];
int idx;
uint32_t devnum; /* represent how many nands connected */
uint32_t fwblks; /* represent how many blocks FW used */
uint32_t totalblks;
uint32_t blksperchip;
uint32_t bbtskipbytes;
};
static uint16_t NAND_Flash_Reset(struct denali_nand_info *denali);
static uint16_t NAND_Read_Device_ID(struct denali_nand_info *denali);
static void NAND_LLD_Enable_Disable_Interrupts(struct denali_nand_info *denali, uint16_t INT_ENABLE);
#endif /*_LLD_NAND_*/

View File

@ -29,7 +29,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/doc2000.h>
#include <linux/mtd/compatmac.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/inftl.h>
@ -146,6 +145,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
uint8_t parity;
uint16_t ds[4], s[5], tmp, errval[8], syn[4];
memset(syn, 0, sizeof(syn));
/* Convert the ecc bytes into words */
ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8);
ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6);
@ -169,9 +169,9 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)];
}
/* Calc s[i] = s[i] / alpha^(v + i) */
/* Calc syn[i] = s[i] / alpha^(v + i) */
for (i = 0; i < NROOTS; i++) {
if (syn[i])
if (s[i])
syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
}
/* Call the decoder library */

View File

@ -39,60 +39,96 @@
#define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35())
#define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
#define nfc_is_v3_2() cpu_is_mx51()
#define nfc_is_v3() nfc_is_v3_2()
/* Addresses for NFC registers */
#define NFC_BUF_SIZE 0xE00
#define NFC_BUF_ADDR 0xE04
#define NFC_FLASH_ADDR 0xE06
#define NFC_FLASH_CMD 0xE08
#define NFC_CONFIG 0xE0A
#define NFC_ECC_STATUS_RESULT 0xE0C
#define NFC_RSLTMAIN_AREA 0xE0E
#define NFC_RSLTSPARE_AREA 0xE10
#define NFC_WRPROT 0xE12
#define NFC_V1_UNLOCKSTART_BLKADDR 0xe14
#define NFC_V1_UNLOCKEND_BLKADDR 0xe16
#define NFC_V21_UNLOCKSTART_BLKADDR 0xe20
#define NFC_V21_UNLOCKEND_BLKADDR 0xe22
#define NFC_NF_WRPRST 0xE18
#define NFC_CONFIG1 0xE1A
#define NFC_CONFIG2 0xE1C
#define NFC_V1_V2_BUF_SIZE (host->regs + 0x00)
#define NFC_V1_V2_BUF_ADDR (host->regs + 0x04)
#define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06)
#define NFC_V1_V2_FLASH_CMD (host->regs + 0x08)
#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
#define NFC_V1_V2_WRPROT (host->regs + 0x12)
#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
#define NFC_V21_UNLOCKSTART_BLKADDR (host->regs + 0x20)
#define NFC_V21_UNLOCKEND_BLKADDR (host->regs + 0x22)
#define NFC_V1_V2_NF_WRPRST (host->regs + 0x18)
#define NFC_V1_V2_CONFIG1 (host->regs + 0x1a)
#define NFC_V1_V2_CONFIG2 (host->regs + 0x1c)
/* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
* for Command operation */
#define NFC_CMD 0x1
#define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0)
#define NFC_V1_V2_CONFIG1_SP_EN (1 << 2)
#define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3)
#define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4)
#define NFC_V1_V2_CONFIG1_BIG (1 << 5)
#define NFC_V1_V2_CONFIG1_RST (1 << 6)
#define NFC_V1_V2_CONFIG1_CE (1 << 7)
#define NFC_V1_V2_CONFIG1_ONE_CYCLE (1 << 8)
/* Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
* for Address operation */
#define NFC_ADDR 0x2
#define NFC_V1_V2_CONFIG2_INT (1 << 15)
/* Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
* for Input operation */
#define NFC_INPUT 0x4
/*
* Operation modes for the NFC. Valid for v1, v2 and v3
* type controllers.
*/
#define NFC_CMD (1 << 0)
#define NFC_ADDR (1 << 1)
#define NFC_INPUT (1 << 2)
#define NFC_OUTPUT (1 << 3)
#define NFC_ID (1 << 4)
#define NFC_STATUS (1 << 5)
/* Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register
* for Data Output operation */
#define NFC_OUTPUT 0x8
#define NFC_V3_FLASH_CMD (host->regs_axi + 0x00)
#define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04)
/* Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register
* for Read ID operation */
#define NFC_ID 0x10
#define NFC_V3_CONFIG1 (host->regs_axi + 0x34)
#define NFC_V3_CONFIG1_SP_EN (1 << 0)
#define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4)
/* Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register
* for Read Status operation */
#define NFC_STATUS 0x20
#define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38)
/* Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read
* Status operation */
#define NFC_INT 0x8000
#define NFC_V3_LAUNCH (host->regs_axi + 0x40)
#define NFC_SP_EN (1 << 2)
#define NFC_ECC_EN (1 << 3)
#define NFC_INT_MSK (1 << 4)
#define NFC_BIG (1 << 5)
#define NFC_RST (1 << 6)
#define NFC_CE (1 << 7)
#define NFC_ONE_CYCLE (1 << 8)
#define NFC_V3_WRPROT (host->regs_ip + 0x0)
#define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0)
#define NFC_V3_WRPROT_LOCK (1 << 1)
#define NFC_V3_WRPROT_UNLOCK (1 << 2)
#define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6)
#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04)
#define NFC_V3_CONFIG2 (host->regs_ip + 0x24)
#define NFC_V3_CONFIG2_PS_512 (0 << 0)
#define NFC_V3_CONFIG2_PS_2048 (1 << 0)
#define NFC_V3_CONFIG2_PS_4096 (2 << 0)
#define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2)
#define NFC_V3_CONFIG2_ECC_EN (1 << 3)
#define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4)
#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5)
#define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6)
#define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7)
#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12)
#define NFC_V3_CONFIG2_INT_MSK (1 << 15)
#define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24)
#define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16)
#define NFC_V3_CONFIG3 (host->regs_ip + 0x28)
#define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0)
#define NFC_V3_CONFIG3_FW8 (1 << 3)
#define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8)
#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12)
#define NFC_V3_CONFIG3_RBB_MODE (1 << 15)
#define NFC_V3_CONFIG3_NO_SDMA (1 << 20)
#define NFC_V3_IPC (host->regs_ip + 0x2C)
#define NFC_V3_IPC_CREQ (1 << 0)
#define NFC_V3_IPC_INT (1 << 31)
#define NFC_V3_DELAY_LINE (host->regs_ip + 0x34)
struct mxc_nand_host {
struct mtd_info mtd;
@ -102,20 +138,30 @@ struct mxc_nand_host {
void *spare0;
void *main_area0;
void *main_area1;
void __iomem *base;
void __iomem *regs;
void __iomem *regs_axi;
void __iomem *regs_ip;
int status_request;
struct clk *clk;
int clk_act;
int irq;
int eccsize;
wait_queue_head_t irq_waitq;
uint8_t *data_buf;
unsigned int buf_start;
int spare_len;
void (*preset)(struct mtd_info *);
void (*send_cmd)(struct mxc_nand_host *, uint16_t, int);
void (*send_addr)(struct mxc_nand_host *, uint16_t, int);
void (*send_page)(struct mtd_info *, unsigned int);
void (*send_read_id)(struct mxc_nand_host *);
uint16_t (*get_dev_status)(struct mxc_nand_host *);
int (*check_int)(struct mxc_nand_host *);
};
/* OOB placement block for use with hardware ecc generation */
@ -175,34 +221,52 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int check_int_v3(struct mxc_nand_host *host)
{
uint32_t tmp;
tmp = readl(NFC_V3_IPC);
if (!(tmp & NFC_V3_IPC_INT))
return 0;
tmp &= ~NFC_V3_IPC_INT;
writel(tmp, NFC_V3_IPC);
return 1;
}
static int check_int_v1_v2(struct mxc_nand_host *host)
{
uint32_t tmp;
tmp = readw(NFC_V1_V2_CONFIG2);
if (!(tmp & NFC_V1_V2_CONFIG2_INT))
return 0;
writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
return 1;
}
/* This function polls the NANDFC to wait for the basic operation to
* complete by checking the INT bit of config2 register.
*/
static void wait_op_done(struct mxc_nand_host *host, int useirq)
{
uint16_t tmp;
int max_retries = 8000;
if (useirq) {
if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
if (!host->check_int(host)) {
enable_irq(host->irq);
wait_event(host->irq_waitq,
readw(host->regs + NFC_CONFIG2) & NFC_INT);
tmp = readw(host->regs + NFC_CONFIG2);
tmp &= ~NFC_INT;
writew(tmp, host->regs + NFC_CONFIG2);
wait_event(host->irq_waitq, host->check_int(host));
}
} else {
while (max_retries-- > 0) {
if (readw(host->regs + NFC_CONFIG2) & NFC_INT) {
tmp = readw(host->regs + NFC_CONFIG2);
tmp &= ~NFC_INT;
writew(tmp, host->regs + NFC_CONFIG2);
if (host->check_int(host))
break;
}
udelay(1);
}
if (max_retries < 0)
@ -211,21 +275,33 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
}
}
static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
{
/* fill command */
writel(cmd, NFC_V3_FLASH_CMD);
/* send out command */
writel(NFC_CMD, NFC_V3_LAUNCH);
/* Wait for operation to complete */
wait_op_done(host, useirq);
}
/* This function issues the specified command to the NAND device and
* waits for completion. */
static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
{
DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
writew(cmd, host->regs + NFC_FLASH_CMD);
writew(NFC_CMD, host->regs + NFC_CONFIG2);
writew(cmd, NFC_V1_V2_FLASH_CMD);
writew(NFC_CMD, NFC_V1_V2_CONFIG2);
if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
int max_retries = 100;
/* Reset completion is indicated by NFC_CONFIG2 */
/* being set to 0 */
while (max_retries-- > 0) {
if (readw(host->regs + NFC_CONFIG2) == 0) {
if (readw(NFC_V1_V2_CONFIG2) == 0) {
break;
}
udelay(1);
@ -239,21 +315,48 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
}
}
static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast)
{
/* fill address */
writel(addr, NFC_V3_FLASH_ADDR0);
/* send out address */
writel(NFC_ADDR, NFC_V3_LAUNCH);
wait_op_done(host, 0);
}
/* This function sends an address (or partial address) to the
* NAND device. The address is used to select the source/destination for
* a NAND command. */
static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast)
static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
{
DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
writew(addr, host->regs + NFC_FLASH_ADDR);
writew(NFC_ADDR, host->regs + NFC_CONFIG2);
writew(addr, NFC_V1_V2_FLASH_ADDR);
writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
/* Wait for operation to complete */
wait_op_done(host, islast);
}
static void send_page(struct mtd_info *mtd, unsigned int ops)
static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
{
struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv;
uint32_t tmp;
tmp = readl(NFC_V3_CONFIG1);
tmp &= ~(7 << 4);
writel(tmp, NFC_V3_CONFIG1);
/* transfer data from NFC ram to nand */
writel(ops, NFC_V3_LAUNCH);
wait_op_done(host, false);
}
static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops)
{
struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv;
@ -267,24 +370,34 @@ static void send_page(struct mtd_info *mtd, unsigned int ops)
for (i = 0; i < bufs; i++) {
/* NANDFC buffer 0 is used for page read/write */
writew(i, host->regs + NFC_BUF_ADDR);
writew(i, NFC_V1_V2_BUF_ADDR);
writew(ops, host->regs + NFC_CONFIG2);
writew(ops, NFC_V1_V2_CONFIG2);
/* Wait for operation to complete */
wait_op_done(host, true);
}
}
static void send_read_id_v3(struct mxc_nand_host *host)
{
/* Read ID into main buffer */
writel(NFC_ID, NFC_V3_LAUNCH);
wait_op_done(host, true);
memcpy(host->data_buf, host->main_area0, 16);
}
/* Request the NANDFC to perform a read of the NAND device ID. */
static void send_read_id(struct mxc_nand_host *host)
static void send_read_id_v1_v2(struct mxc_nand_host *host)
{
struct nand_chip *this = &host->nand;
/* NANDFC buffer 0 is used for device ID output */
writew(0x0, host->regs + NFC_BUF_ADDR);
writew(0x0, NFC_V1_V2_BUF_ADDR);
writew(NFC_ID, host->regs + NFC_CONFIG2);
writew(NFC_ID, NFC_V1_V2_CONFIG2);
/* Wait for operation to complete */
wait_op_done(host, true);
@ -301,29 +414,36 @@ static void send_read_id(struct mxc_nand_host *host)
memcpy(host->data_buf, host->main_area0, 16);
}
/* This function requests the NANDFC to perform a read of the
* NAND device status and returns the current status. */
static uint16_t get_dev_status(struct mxc_nand_host *host)
static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
{
void __iomem *main_buf = host->main_area1;
uint32_t store;
uint16_t ret;
/* Issue status request to NAND device */
/* store the main area1 first word, later do recovery */
store = readl(main_buf);
/* NANDFC buffer 1 is used for device status to prevent
* corruption of read/write buffer on status requests. */
writew(1, host->regs + NFC_BUF_ADDR);
writew(NFC_STATUS, host->regs + NFC_CONFIG2);
/* Wait for operation to complete */
writew(NFC_STATUS, NFC_V3_LAUNCH);
wait_op_done(host, true);
return readl(NFC_V3_CONFIG1) >> 16;
}
/* This function requests the NANDFC to perform a read of the
* NAND device status and returns the current status. */
static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
{
void __iomem *main_buf = host->main_area0;
uint32_t store;
uint16_t ret;
writew(0x0, NFC_V1_V2_BUF_ADDR);
/*
* The device status is stored in main_area0. To
* prevent corruption of the buffer save the value
* and restore it afterwards.
*/
store = readl(main_buf);
writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
wait_op_done(host, true);
/* Status is placed in first word of main buffer */
/* get status, then recovery area 1 data */
ret = readw(main_buf);
writel(store, main_buf);
return ret;
@ -347,7 +467,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
*/
}
static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
struct nand_chip *nand_chip = mtd->priv;
@ -358,7 +478,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
* additional correction. 2-Bit errors cannot be corrected by
* HW ECC, so we need to return failure
*/
uint16_t ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT);
uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT);
if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
DEBUG(MTD_DEBUG_LEVEL0,
@ -369,6 +489,43 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
return 0;
}
static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv;
u32 ecc_stat, err;
int no_subpages = 1;
int ret = 0;
u8 ecc_bit_mask, err_limit;
ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
no_subpages = mtd->writesize >> 9;
if (nfc_is_v21())
ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT);
else
ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT);
do {
err = ecc_stat & ecc_bit_mask;
if (err > err_limit) {
printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
return -1;
} else {
ret += err;
}
ecc_stat >>= 4;
} while (--no_subpages);
mtd->ecc_stats.corrected += ret;
pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
return ret;
}
static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
{
@ -383,7 +540,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
/* Check for status request */
if (host->status_request)
return get_dev_status(host) & 0xFF;
return host->get_dev_status(host) & 0xFF;
ret = *(uint8_t *)(host->data_buf + host->buf_start);
host->buf_start++;
@ -519,71 +676,163 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
* we will used the saved column address to index into
* the full page.
*/
send_addr(host, 0, page_addr == -1);
host->send_addr(host, 0, page_addr == -1);
if (mtd->writesize > 512)
/* another col addr cycle for 2k page */
send_addr(host, 0, false);
host->send_addr(host, 0, false);
}
/* Write out page address, if necessary */
if (page_addr != -1) {
/* paddr_0 - p_addr_7 */
send_addr(host, (page_addr & 0xff), false);
host->send_addr(host, (page_addr & 0xff), false);
if (mtd->writesize > 512) {
if (mtd->size >= 0x10000000) {
/* paddr_8 - paddr_15 */
send_addr(host, (page_addr >> 8) & 0xff, false);
send_addr(host, (page_addr >> 16) & 0xff, true);
host->send_addr(host, (page_addr >> 8) & 0xff, false);
host->send_addr(host, (page_addr >> 16) & 0xff, true);
} else
/* paddr_8 - paddr_15 */
send_addr(host, (page_addr >> 8) & 0xff, true);
host->send_addr(host, (page_addr >> 8) & 0xff, true);
} else {
/* One more address cycle for higher density devices */
if (mtd->size >= 0x4000000) {
/* paddr_8 - paddr_15 */
send_addr(host, (page_addr >> 8) & 0xff, false);
send_addr(host, (page_addr >> 16) & 0xff, true);
host->send_addr(host, (page_addr >> 8) & 0xff, false);
host->send_addr(host, (page_addr >> 16) & 0xff, true);
} else
/* paddr_8 - paddr_15 */
send_addr(host, (page_addr >> 8) & 0xff, true);
host->send_addr(host, (page_addr >> 8) & 0xff, true);
}
}
}
static void preset(struct mtd_info *mtd)
/*
* v2 and v3 type controllers can do 4bit or 8bit ecc depending
* on how much oob the nand chip has. For 8bit ecc we need at least
* 26 bytes of oob data per 512 byte block.
*/
static int get_eccsize(struct mtd_info *mtd)
{
int oobbytes_per_512 = 0;
oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
if (oobbytes_per_512 < 26)
return 4;
else
return 8;
}
static void preset_v1_v2(struct mtd_info *mtd)
{
struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv;
uint16_t tmp;
/* enable interrupt, disable spare enable */
tmp = readw(host->regs + NFC_CONFIG1);
tmp &= ~NFC_INT_MSK;
tmp &= ~NFC_SP_EN;
tmp = readw(NFC_V1_V2_CONFIG1);
tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
tmp &= ~NFC_V1_V2_CONFIG1_SP_EN;
if (nand_chip->ecc.mode == NAND_ECC_HW) {
tmp |= NFC_ECC_EN;
tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
} else {
tmp &= ~NFC_ECC_EN;
tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN;
}
writew(tmp, host->regs + NFC_CONFIG1);
if (nfc_is_v21() && mtd->writesize) {
host->eccsize = get_eccsize(mtd);
if (host->eccsize == 4)
tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
} else {
host->eccsize = 1;
}
writew(tmp, NFC_V1_V2_CONFIG1);
/* preset operation */
/* Unlock the internal RAM Buffer */
writew(0x2, host->regs + NFC_CONFIG);
writew(0x2, NFC_V1_V2_CONFIG);
/* Blocks to be unlocked */
if (nfc_is_v21()) {
writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR);
writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR);
} else if (nfc_is_v1()) {
writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR);
} else
BUG();
/* Unlock Block Command for given address range */
writew(0x4, host->regs + NFC_WRPROT);
writew(0x4, NFC_V1_V2_WRPROT);
}
static void preset_v3(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
struct mxc_nand_host *host = chip->priv;
uint32_t config2, config3;
int i, addr_phases;
writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
/* Unlock the internal RAM Buffer */
writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
NFC_V3_WRPROT);
/* Blocks to be unlocked */
for (i = 0; i < NAND_MAX_CHIPS; i++)
writel(0x0 | (0xffff << 16),
NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
writel(0, NFC_V3_IPC);
config2 = NFC_V3_CONFIG2_ONE_CYCLE |
NFC_V3_CONFIG2_2CMD_PHASES |
NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
NFC_V3_CONFIG2_ST_CMD(0x70) |
NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
if (chip->ecc.mode == NAND_ECC_HW)
config2 |= NFC_V3_CONFIG2_ECC_EN;
addr_phases = fls(chip->pagemask) >> 3;
if (mtd->writesize == 2048) {
config2 |= NFC_V3_CONFIG2_PS_2048;
config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
} else if (mtd->writesize == 4096) {
config2 |= NFC_V3_CONFIG2_PS_4096;
config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
} else {
config2 |= NFC_V3_CONFIG2_PS_512;
config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
}
if (mtd->writesize) {
config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
host->eccsize = get_eccsize(mtd);
if (host->eccsize == 8)
config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
}
writel(config2, NFC_V3_CONFIG2);
config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
NFC_V3_CONFIG3_NO_SDMA |
NFC_V3_CONFIG3_RBB_MODE |
NFC_V3_CONFIG3_SBB(6) | /* Reset default */
NFC_V3_CONFIG3_ADD_OP(0);
if (!(chip->options & NAND_BUSWIDTH_16))
config3 |= NFC_V3_CONFIG3_FW8;
writel(config3, NFC_V3_CONFIG3);
writel(0, NFC_V3_DELAY_LINE);
}
/* Used by the upper layer to write command to NAND Flash for
@ -604,15 +853,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
/* Command pre-processing step */
switch (command) {
case NAND_CMD_RESET:
send_cmd(host, command, false);
preset(mtd);
host->preset(mtd);
host->send_cmd(host, command, false);
break;
case NAND_CMD_STATUS:
host->buf_start = 0;
host->status_request = true;
send_cmd(host, command, true);
host->send_cmd(host, command, true);
mxc_do_addr_cycle(mtd, column, page_addr);
break;
@ -625,13 +874,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
command = NAND_CMD_READ0; /* only READ0 is valid */
send_cmd(host, command, false);
host->send_cmd(host, command, false);
mxc_do_addr_cycle(mtd, column, page_addr);
if (mtd->writesize > 512)
send_cmd(host, NAND_CMD_READSTART, true);
host->send_cmd(host, NAND_CMD_READSTART, true);
send_page(mtd, NFC_OUTPUT);
host->send_page(mtd, NFC_OUTPUT);
memcpy(host->data_buf, host->main_area0, mtd->writesize);
copy_spare(mtd, true);
@ -644,28 +893,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
host->buf_start = column;
send_cmd(host, command, false);
host->send_cmd(host, command, false);
mxc_do_addr_cycle(mtd, column, page_addr);
break;
case NAND_CMD_PAGEPROG:
memcpy(host->main_area0, host->data_buf, mtd->writesize);
copy_spare(mtd, false);
send_page(mtd, NFC_INPUT);
send_cmd(host, command, true);
host->send_page(mtd, NFC_INPUT);
host->send_cmd(host, command, true);
mxc_do_addr_cycle(mtd, column, page_addr);
break;
case NAND_CMD_READID:
send_cmd(host, command, true);
host->send_cmd(host, command, true);
mxc_do_addr_cycle(mtd, column, page_addr);
send_read_id(host);
host->send_read_id(host);
host->buf_start = column;
break;
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
send_cmd(host, command, false);
host->send_cmd(host, command, false);
mxc_do_addr_cycle(mtd, column, page_addr);
break;
@ -761,22 +1010,55 @@ static int __init mxcnd_probe(struct platform_device *pdev)
}
host->main_area0 = host->base;
host->main_area1 = host->base + 0x200;
if (nfc_is_v1() || nfc_is_v21()) {
host->preset = preset_v1_v2;
host->send_cmd = send_cmd_v1_v2;
host->send_addr = send_addr_v1_v2;
host->send_page = send_page_v1_v2;
host->send_read_id = send_read_id_v1_v2;
host->get_dev_status = get_dev_status_v1_v2;
host->check_int = check_int_v1_v2;
}
if (nfc_is_v21()) {
host->regs = host->base + 0x1000;
host->regs = host->base + 0x1e00;
host->spare0 = host->base + 0x1000;
host->spare_len = 64;
oob_smallpage = &nandv2_hw_eccoob_smallpage;
oob_largepage = &nandv2_hw_eccoob_largepage;
this->ecc.bytes = 9;
} else if (nfc_is_v1()) {
host->regs = host->base;
host->regs = host->base + 0xe00;
host->spare0 = host->base + 0x800;
host->spare_len = 16;
oob_smallpage = &nandv1_hw_eccoob_smallpage;
oob_largepage = &nandv1_hw_eccoob_largepage;
this->ecc.bytes = 3;
host->eccsize = 1;
} else if (nfc_is_v3_2()) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res) {
err = -ENODEV;
goto eirq;
}
host->regs_ip = ioremap(res->start, resource_size(res));
if (!host->regs_ip) {
err = -ENOMEM;
goto eirq;
}
host->regs_axi = host->base + 0x1e00;
host->spare0 = host->base + 0x1000;
host->spare_len = 64;
host->preset = preset_v3;
host->send_cmd = send_cmd_v3;
host->send_addr = send_addr_v3;
host->send_page = send_page_v3;
host->send_read_id = send_read_id_v3;
host->check_int = check_int_v3;
host->get_dev_status = get_dev_status_v3;
oob_smallpage = &nandv2_hw_eccoob_smallpage;
oob_largepage = &nandv2_hw_eccoob_largepage;
} else
BUG();
@ -786,7 +1068,10 @@ static int __init mxcnd_probe(struct platform_device *pdev)
if (pdata->hw_ecc) {
this->ecc.calculate = mxc_nand_calculate_ecc;
this->ecc.hwctl = mxc_nand_enable_hwecc;
this->ecc.correct = mxc_nand_correct_data;
if (nfc_is_v1())
this->ecc.correct = mxc_nand_correct_data_v1;
else
this->ecc.correct = mxc_nand_correct_data_v2_v3;
this->ecc.mode = NAND_ECC_HW;
} else {
this->ecc.mode = NAND_ECC_SOFT;
@ -817,6 +1102,9 @@ static int __init mxcnd_probe(struct platform_device *pdev)
goto escan;
}
/* Call preset again, with correct writesize this time */
host->preset(mtd);
if (mtd->writesize == 2048)
this->ecc.layout = oob_largepage;
@ -848,6 +1136,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
escan:
free_irq(host->irq, host);
eirq:
if (host->regs_ip)
iounmap(host->regs_ip);
iounmap(host->base);
eres:
clk_put(host->clk);
@ -867,59 +1157,19 @@ static int __devexit mxcnd_remove(struct platform_device *pdev)
nand_release(&host->mtd);
free_irq(host->irq, host);
if (host->regs_ip)
iounmap(host->regs_ip);
iounmap(host->base);
kfree(host);
return 0;
}
#ifdef CONFIG_PM
static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
{
struct mtd_info *mtd = platform_get_drvdata(pdev);
struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv;
int ret = 0;
DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n");
ret = mtd->suspend(mtd);
/*
* nand_suspend locks the device for exclusive access, so
* the clock must already be off.
*/
BUG_ON(!ret && host->clk_act);
return ret;
}
static int mxcnd_resume(struct platform_device *pdev)
{
struct mtd_info *mtd = platform_get_drvdata(pdev);
struct nand_chip *nand_chip = mtd->priv;
struct mxc_nand_host *host = nand_chip->priv;
int ret = 0;
DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
mtd->resume(mtd);
return ret;
}
#else
# define mxcnd_suspend NULL
# define mxcnd_resume NULL
#endif /* CONFIG_PM */
static struct platform_driver mxcnd_driver = {
.driver = {
.name = DRIVER_NAME,
},
},
.remove = __devexit_p(mxcnd_remove),
.suspend = mxcnd_suspend,
.resume = mxcnd_resume,
};
static int __init mxc_nd_init(void)

View File

@ -42,7 +42,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/compatmac.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/leds.h>
@ -347,7 +346,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
struct nand_chip *chip = mtd->priv;
u16 bad;
if (chip->options & NAND_BB_LAST_PAGE)
if (chip->options & NAND_BBT_SCANLASTPAGE)
ofs += mtd->erasesize - mtd->writesize;
page = (int)(ofs >> chip->page_shift) & chip->pagemask;
@ -397,9 +396,9 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
struct nand_chip *chip = mtd->priv;
uint8_t buf[2] = { 0, 0 };
int block, ret;
int block, ret, i = 0;
if (chip->options & NAND_BB_LAST_PAGE)
if (chip->options & NAND_BBT_SCANLASTPAGE)
ofs += mtd->erasesize - mtd->writesize;
/* Get block number */
@ -411,17 +410,31 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
if (chip->options & NAND_USE_FLASH_BBT)
ret = nand_update_bbt(mtd, ofs);
else {
/* We write two bytes, so we dont have to mess with 16 bit
* access
*/
nand_get_device(chip, mtd, FL_WRITING);
ofs += mtd->oobsize;
chip->ops.len = chip->ops.ooblen = 2;
chip->ops.datbuf = NULL;
chip->ops.oobbuf = buf;
chip->ops.ooboffs = chip->badblockpos & ~0x01;
ret = nand_do_write_oob(mtd, ofs, &chip->ops);
/* Write to first two pages and to byte 1 and 6 if necessary.
* If we write to more than one location, the first error
* encountered quits the procedure. We write two bytes per
* location, so we dont have to mess with 16 bit access.
*/
do {
chip->ops.len = chip->ops.ooblen = 2;
chip->ops.datbuf = NULL;
chip->ops.oobbuf = buf;
chip->ops.ooboffs = chip->badblockpos & ~0x01;
ret = nand_do_write_oob(mtd, ofs, &chip->ops);
if (!ret && (chip->options & NAND_BBT_SCANBYTE1AND6)) {
chip->ops.ooboffs = NAND_SMALL_BADBLOCK_POS
& ~0x01;
ret = nand_do_write_oob(mtd, ofs, &chip->ops);
}
i++;
ofs += mtd->writesize;
} while (!ret && (chip->options & NAND_BBT_SCAN2NDPAGE) &&
i < 2);
nand_release_device(mtd);
}
if (!ret)
@ -2920,9 +2933,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
/* Set the bad block position */
chip->badblockpos = mtd->writesize > 512 ?
NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
chip->badblockbits = 8;
if (!(busw & NAND_BUSWIDTH_16) && (*maf_id == NAND_MFR_STMICRO ||
(*maf_id == NAND_MFR_SAMSUNG &&
mtd->writesize == 512) ||
*maf_id == NAND_MFR_AMD))
chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
else
chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
/* Get chip options, preserve non chip based options */
chip->options &= ~NAND_CHIPOPTIONS_MSK;
@ -2941,12 +2959,32 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
/*
* Bad block marker is stored in the last page of each block
* on Samsung and Hynix MLC devices
* on Samsung and Hynix MLC devices; stored in first two pages
* of each block on Micron devices with 2KiB pages and on
* SLC Samsung, Hynix, and AMD/Spansion. All others scan only
* the first page.
*/
if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
(*maf_id == NAND_MFR_SAMSUNG ||
*maf_id == NAND_MFR_HYNIX))
chip->options |= NAND_BB_LAST_PAGE;
chip->options |= NAND_BBT_SCANLASTPAGE;
else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
(*maf_id == NAND_MFR_SAMSUNG ||
*maf_id == NAND_MFR_HYNIX ||
*maf_id == NAND_MFR_AMD)) ||
(mtd->writesize == 2048 &&
*maf_id == NAND_MFR_MICRON))
chip->options |= NAND_BBT_SCAN2NDPAGE;
/*
* Numonyx/ST 2K pages, x8 bus use BOTH byte 1 and 6
*/
if (!(busw & NAND_BUSWIDTH_16) &&
*maf_id == NAND_MFR_STMICRO &&
mtd->writesize == 2048) {
chip->options |= NAND_BBT_SCANBYTE1AND6;
chip->badblockpos = 0;
}
/* Check for AND chips with 4 page planes */
if (chip->options & NAND_4PAGE_ARRAY)
@ -3306,6 +3344,11 @@ void nand_release(struct mtd_info *mtd)
kfree(chip->bbt);
if (!(chip->options & NAND_OWN_BUFFERS))
kfree(chip->buffers);
/* Free bad block descriptor memory */
if (chip->badblock_pattern && chip->badblock_pattern->options
& NAND_BBT_DYNAMICSTRUCT)
kfree(chip->badblock_pattern);
}
EXPORT_SYMBOL_GPL(nand_lock);

View File

@ -55,7 +55,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/compatmac.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/vmalloc.h>
@ -93,6 +92,28 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc
return -1;
}
/* Check both positions 1 and 6 for pattern? */
if (td->options & NAND_BBT_SCANBYTE1AND6) {
if (td->options & NAND_BBT_SCANEMPTY) {
p += td->len;
end += NAND_SMALL_BADBLOCK_POS - td->offs;
/* Check region between positions 1 and 6 */
for (i = 0; i < NAND_SMALL_BADBLOCK_POS - td->offs - td->len;
i++) {
if (*p++ != 0xff)
return -1;
}
}
else {
p += NAND_SMALL_BADBLOCK_POS - td->offs;
}
/* Compare the pattern */
for (i = 0; i < td->len; i++) {
if (p[i] != td->pattern[i])
return -1;
}
}
if (td->options & NAND_BBT_SCANEMPTY) {
p += td->len;
end += td->len;
@ -124,6 +145,13 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
if (p[td->offs + i] != td->pattern[i])
return -1;
}
/* Need to check location 1 AND 6? */
if (td->options & NAND_BBT_SCANBYTE1AND6) {
for (i = 0; i < td->len; i++) {
if (p[NAND_SMALL_BADBLOCK_POS + i] != td->pattern[i])
return -1;
}
}
return 0;
}
@ -397,12 +425,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
if (bd->options & NAND_BBT_SCANALLPAGES)
len = 1 << (this->bbt_erase_shift - this->page_shift);
else {
if (bd->options & NAND_BBT_SCAN2NDPAGE)
len = 2;
else
len = 1;
}
else if (bd->options & NAND_BBT_SCAN2NDPAGE)
len = 2;
else
len = 1;
if (!(bd->options & NAND_BBT_SCANEMPTY)) {
/* We need only read few bytes from the OOB area */
@ -432,7 +458,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
from = (loff_t)startblock << (this->bbt_erase_shift - 1);
}
if (this->options & NAND_BB_LAST_PAGE)
if (this->options & NAND_BBT_SCANLASTPAGE)
from += mtd->erasesize - (mtd->writesize * len);
for (i = startblock; i < numblocks;) {
@ -1092,30 +1118,16 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
* while scanning a device for factory marked good / bad blocks. */
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
static struct nand_bbt_descr smallpage_memorybased = {
.options = NAND_BBT_SCAN2NDPAGE,
.offs = 5,
.len = 1,
.pattern = scan_ff_pattern
};
static struct nand_bbt_descr largepage_memorybased = {
.options = 0,
.offs = 0,
.len = 2,
.pattern = scan_ff_pattern
};
static struct nand_bbt_descr smallpage_flashbased = {
.options = NAND_BBT_SCAN2NDPAGE,
.offs = 5,
.offs = NAND_SMALL_BADBLOCK_POS,
.len = 1,
.pattern = scan_ff_pattern
};
static struct nand_bbt_descr largepage_flashbased = {
.options = NAND_BBT_SCAN2NDPAGE,
.offs = 0,
.offs = NAND_LARGE_BADBLOCK_POS,
.len = 2,
.pattern = scan_ff_pattern
};
@ -1154,6 +1166,43 @@ static struct nand_bbt_descr bbt_mirror_descr = {
.pattern = mirror_pattern
};
#define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \
NAND_BBT_SCANBYTE1AND6)
/**
* nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure
* @this: NAND chip to create descriptor for
*
* This function allocates and initializes a nand_bbt_descr for BBM detection
* based on the properties of "this". The new descriptor is stored in
* this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
* passed to this function.
*
* TODO: Handle other flags, replace other static structs
* (e.g. handle NAND_BBT_FLASH for flash-based BBT,
* replace smallpage_flashbased)
*
*/
static int nand_create_default_bbt_descr(struct nand_chip *this)
{
struct nand_bbt_descr *bd;
if (this->badblock_pattern) {
printk(KERN_WARNING "BBT descr already allocated; not replacing.\n");
return -EINVAL;
}
bd = kzalloc(sizeof(*bd), GFP_KERNEL);
if (!bd) {
printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n");
return -ENOMEM;
}
bd->options = this->options & BBT_SCAN_OPTIONS;
bd->offs = this->badblockpos;
bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
bd->pattern = scan_ff_pattern;
bd->options |= NAND_BBT_DYNAMICSTRUCT;
this->badblock_pattern = bd;
return 0;
}
/**
* nand_default_bbt - [NAND Interface] Select a default bad block table for the device
* @mtd: MTD device structure
@ -1196,10 +1245,8 @@ int nand_default_bbt(struct mtd_info *mtd)
} else {
this->bbt_td = NULL;
this->bbt_md = NULL;
if (!this->badblock_pattern) {
this->badblock_pattern = (mtd->writesize > 512) ?
&largepage_memorybased : &smallpage_memorybased;
}
if (!this->badblock_pattern)
nand_create_default_bbt_descr(this);
}
return nand_scan_bbt(mtd, this->badblock_pattern);
}

View File

@ -85,6 +85,7 @@ struct nand_flash_dev nand_flash_ids[] = {
{"NAND 128MiB 3,3V 8-bit", 0xD1, 0, 128, 0, LP_OPTIONS},
{"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16},
{"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16},
{"NAND 128MiB 1,8V 16-bit", 0xAD, 0, 128, 0, LP_OPTIONS16},
/* 2 Gigabit */
{"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, LP_OPTIONS},
@ -110,6 +111,9 @@ struct nand_flash_dev nand_flash_ids[] = {
{"NAND 2GiB 1,8V 16-bit", 0xB5, 0, 2048, 0, LP_OPTIONS16},
{"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16},
/* 32 Gigabit */
{"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS16},
/*
* Renesas AND 1 Gigabit. Those chips do not support extended id and
* have a strange page/block layout ! The chosen minimum erasesize is

View File

@ -553,8 +553,8 @@ static uint64_t divide(uint64_t n, uint32_t d)
*/
static int init_nandsim(struct mtd_info *mtd)
{
struct nand_chip *chip = (struct nand_chip *)mtd->priv;
struct nandsim *ns = (struct nandsim *)(chip->priv);
struct nand_chip *chip = mtd->priv;
struct nandsim *ns = chip->priv;
int i, ret = 0;
uint64_t remains;
uint64_t next_offset;
@ -1877,7 +1877,7 @@ static void switch_state(struct nandsim *ns)
static u_char ns_nand_read_byte(struct mtd_info *mtd)
{
struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
u_char outb = 0x00;
/* Sanity and correctness checks */
@ -1950,7 +1950,7 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd)
static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
{
struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
/* Sanity and correctness checks */
if (!ns->lines.ce) {
@ -2132,7 +2132,7 @@ static uint16_t ns_nand_read_word(struct mtd_info *mtd)
static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
/* Check that chip is expecting data input */
if (!(ns->state & STATE_DATAIN_MASK)) {
@ -2159,7 +2159,7 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
/* Sanity and correctness checks */
if (!ns->lines.ce) {
@ -2352,7 +2352,7 @@ module_init(ns_init_module);
*/
static void __exit ns_cleanup_module(void)
{
struct nandsim *ns = (struct nandsim *)(((struct nand_chip *)nsmtd->priv)->priv);
struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv;
int i;
free_nandsim(ns); /* Free nandsim private resources */

View File

@ -91,7 +91,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
}
/* Scan to find existance of the device */
if (nand_scan(&data->mtd, 1)) {
if (nand_scan(&data->mtd, pdata->chip.nr_chips)) {
err = -ENXIO;
goto out;
}

View File

@ -64,8 +64,8 @@ static inline void r852_write_reg_dword(struct r852_device *dev,
/* returns pointer to our private structure */
static inline struct r852_device *r852_get_dev(struct mtd_info *mtd)
{
struct nand_chip *chip = (struct nand_chip *)mtd->priv;
return (struct r852_device *)chip->priv;
struct nand_chip *chip = mtd->priv;
return chip->priv;
}
@ -380,7 +380,7 @@ void r852_cmdctl(struct mtd_info *mtd, int dat, unsigned int ctrl)
*/
int r852_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct r852_device *dev = (struct r852_device *)chip->priv;
struct r852_device *dev = chip->priv;
unsigned long timeout;
int status;

View File

@ -24,7 +24,6 @@
#include <linux/rslib.h>
#include <linux/bitrev.h>
#include <linux/module.h>
#include <linux/mtd/compatmac.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>

View File

@ -727,15 +727,12 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
if (set == NULL)
return add_mtd_device(&mtd->mtd);
if (set->nr_partitions == 0) {
mtd->mtd.name = set->name;
nr_part = parse_mtd_partitions(&mtd->mtd, part_probes,
&part_info, 0);
} else {
if (set->nr_partitions > 0 && set->partitions != NULL) {
nr_part = set->nr_partitions;
part_info = set->partitions;
}
mtd->mtd.name = set->name;
nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0);
if (nr_part <= 0 && set->nr_partitions > 0) {
nr_part = set->nr_partitions;
part_info = set->partitions;
}
if (nr_part > 0 && part_info)

View File

@ -109,7 +109,7 @@ static struct nand_flash_dev nand_xd_flash_ids[] = {
int sm_register_device(struct mtd_info *mtd, int smartmedia)
{
struct nand_chip *chip = (struct nand_chip *)mtd->priv;
struct nand_chip *chip = mtd->priv;
int ret;
chip->options |= NAND_SKIP_BBTSCAN;

View File

@ -1,11 +1,22 @@
/* Linux driver for NAND Flash Translation Layer */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@infradead.org> */
/*
The contents of this file are distributed under the GNU General
Public License version 2. The author places no additional
restrictions of any kind on it.
* Linux driver for NAND Flash Translation Layer
*
* Copyright © 1999 Machine Vision Holdings, Inc.
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
*
* 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
*/
#define PRERELEASE

View File

@ -2,7 +2,8 @@
* NFTL mount code with extensive checks
*
* Author: Fabrice Bellard (fabrice.bellard@netgem.com)
* Copyright (C) 2000 Netgem S.A.
* Copyright © 2000 Netgem S.A.
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
*
* 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

View File

@ -1,11 +1,11 @@
/*
* Flash partitions described by the OF (or flattened) device tree
*
* Copyright (C) 2006 MontaVista Software Inc.
* Copyright © 2006 MontaVista Software Inc.
* Author: Vitaly Wool <vwool@ru.mvista.com>
*
* Revised to handle newer style flash binding by:
* Copyright (C) 2007 David Gibson, IBM Corporation.
* Copyright © 2007 David Gibson, IBM Corporation.
*
* 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

View File

@ -25,14 +25,14 @@ config MTD_ONENAND_GENERIC
config MTD_ONENAND_OMAP2
tristate "OneNAND on OMAP2/OMAP3 support"
depends on MTD_ONENAND && (ARCH_OMAP2 || ARCH_OMAP3)
depends on ARCH_OMAP2 || ARCH_OMAP3
help
Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU
via the GPMC memory controller.
config MTD_ONENAND_SAMSUNG
tristate "OneNAND on Samsung SOC controller support"
depends on MTD_ONENAND && (ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210)
depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210
help
Support for a OneNAND flash device connected to an Samsung SOC
S3C64XX/S5PC1XX controller.

View File

@ -377,8 +377,11 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
default:
block = onenand_block(this, addr);
page = (int) (addr - onenand_addr(this, block)) >> this->page_shift;
if (FLEXONENAND(this))
page = (int) (addr - onenand_addr(this, block))>>\
this->page_shift;
else
page = (int) (addr >> this->page_shift);
if (ONENAND_IS_2PLANE(this)) {
/* Make the even block number */
block &= ~1;
@ -3730,17 +3733,16 @@ int flexonenand_set_boundary(struct mtd_info *mtd, int die,
}
/**
* onenand_probe - [OneNAND Interface] Probe the OneNAND device
* onenand_chip_probe - [OneNAND Interface] The generic chip probe
* @param mtd MTD device structure
*
* OneNAND detection method:
* Compare the values from command with ones from register
*/
static int onenand_probe(struct mtd_info *mtd)
static int onenand_chip_probe(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id;
int density;
int bram_maf_id, bram_dev_id, maf_id, dev_id;
int syscfg;
/* Save system configuration 1 */
@ -3763,12 +3765,6 @@ static int onenand_probe(struct mtd_info *mtd)
/* Restore system configuration 1 */
this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
/* Workaround */
if (syscfg & ONENAND_SYS_CFG1_SYNC_WRITE) {
bram_maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
bram_dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
}
/* Check manufacturer ID */
if (onenand_check_maf(bram_maf_id))
return -ENXIO;
@ -3776,13 +3772,35 @@ static int onenand_probe(struct mtd_info *mtd)
/* Read manufacturer and device IDs from Register */
maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
/* Check OneNAND device */
if (maf_id != bram_maf_id || dev_id != bram_dev_id)
return -ENXIO;
return 0;
}
/**
* onenand_probe - [OneNAND Interface] Probe the OneNAND device
* @param mtd MTD device structure
*/
static int onenand_probe(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
int maf_id, dev_id, ver_id;
int density;
int ret;
ret = this->chip_probe(mtd);
if (ret)
return ret;
/* Read manufacturer and device IDs from Register */
maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
/* Flash device information */
onenand_print_device_info(dev_id, ver_id);
this->device_id = dev_id;
@ -3909,6 +3927,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
if (!this->unlock_all)
this->unlock_all = onenand_unlock_all;
if (!this->chip_probe)
this->chip_probe = onenand_chip_probe;
if (!this->read_bufferram)
this->read_bufferram = onenand_read_bufferram;
if (!this->write_bufferram)

View File

@ -15,7 +15,6 @@
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <linux/mtd/compatmac.h>
/**
* check_short_pattern - [GENERIC] check if a pattern is in the buffer

View File

@ -630,6 +630,12 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
return 0;
}
static int s5pc110_chip_probe(struct mtd_info *mtd)
{
/* Now just return 0 */
return 0;
}
static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state)
{
unsigned int flags = INT_ACT | LOAD_CMP;
@ -757,6 +763,7 @@ static void s3c_onenand_setup(struct mtd_info *mtd)
/* Use generic onenand functions */
onenand->cmd_map = s5pc1xx_cmd_map;
this->read_bufferram = s5pc110_read_bufferram;
this->chip_probe = s5pc110_chip_probe;
return;
} else {
BUG();
@ -781,7 +788,6 @@ static int s3c_onenand_probe(struct platform_device *pdev)
struct mtd_info *mtd;
struct resource *r;
int size, err;
unsigned long onenand_ctrl_cfg = 0;
pdata = pdev->dev.platform_data;
/* No need to check pdata. the platform data is optional */
@ -900,14 +906,6 @@ static int s3c_onenand_probe(struct platform_device *pdev)
}
onenand->phys_base = onenand->base_res->start;
onenand_ctrl_cfg = readl(onenand->dma_addr + 0x100);
if ((onenand_ctrl_cfg & ONENAND_SYS_CFG1_SYNC_WRITE) &&
onenand->dma_addr)
writel(onenand_ctrl_cfg & ~ONENAND_SYS_CFG1_SYNC_WRITE,
onenand->dma_addr + 0x100);
else
onenand_ctrl_cfg = 0;
}
if (onenand_scan(mtd, 1)) {
@ -915,10 +913,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
goto scan_failed;
}
if (onenand->type == TYPE_S5PC110) {
if (onenand_ctrl_cfg && onenand->dma_addr)
writel(onenand_ctrl_cfg, onenand->dma_addr + 0x100);
} else {
if (onenand->type != TYPE_S5PC110) {
/* S3C doesn't handle subpage write */
mtd->subpage_sft = 0;
this->subpagesize = mtd->writesize;

View File

@ -1,6 +1,24 @@
/*
* Parse RedBoot-style Flash Image System (FIS) tables and
* produce a Linux partition array to match.
*
* Copyright © 2001 Red Hat UK Limited
* Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <linux/kernel.h>

View File

@ -1,7 +1,7 @@
/*
* rfd_ftl.c -- resident flash disk (flash translation layer)
*
* Copyright (C) 2005 Sean Young <sean@mess.org>
* Copyright © 2005 Sean Young <sean@mess.org>
*
* This type of flash translation layer (FTL) is used by the Embedded BIOS
* by General Software. It is known as the Resident Flash Disk (RFD), see:

View File

@ -1,6 +1,6 @@
/*
* Linux driver for SSFDC Flash Translation Layer (Read only)
* (c) 2005 Eptar srl
* © 2005 Eptar srl
* Author: Claudio Lanconelli <lanconelli.claudio@eptar.com>
*
* Based on NTFL and MTDBLOCK_RO drivers

View File

@ -310,7 +310,7 @@ static int crosstest(void)
static int erasecrosstest(void)
{
size_t read = 0, written = 0;
int err = 0, i, ebnum, ok = 1, ebnum2;
int err = 0, i, ebnum, ebnum2;
loff_t addr0;
char *readbuf = twopages;
@ -357,8 +357,7 @@ static int erasecrosstest(void)
if (memcmp(writebuf, readbuf, pgsize)) {
printk(PRINT_PREF "verify failed!\n");
errcnt += 1;
ok = 0;
return err;
return -1;
}
printk(PRINT_PREF "erasing block %d\n", ebnum);
@ -396,10 +395,10 @@ static int erasecrosstest(void)
if (memcmp(writebuf, readbuf, pgsize)) {
printk(PRINT_PREF "verify failed!\n");
errcnt += 1;
ok = 0;
return -1;
}
if (ok && !err)
if (!err)
printk(PRINT_PREF "erasecrosstest ok\n");
return err;
}

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,11 +2,12 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Created by Arjan van de Ven <arjanv@redhat.com>
*
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
* Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
* University of Szeged, Hungary
*
* Created by Arjan van de Ven <arjan@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*
*/

View File

@ -3,6 +3,7 @@
*
* Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
* University of Szeged, Hungary
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* For licensing information, see the file 'LICENCE' in this directory.
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2007 Nokia Corporation. All rights reserved.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by Richard Purdie <rpurdie@openedhand.com>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by Arjan van de Ven <arjanv@redhat.com>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by Arjan van de Ven <arjanv@redhat.com>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -2,6 +2,7 @@
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -24,7 +24,6 @@
#ifdef __ECOS
#include "os-ecos.h"
#else
#include <linux/mtd/compatmac.h> /* For compatibility with older kernels */
#include "os-linux.h"
#endif

View File

@ -1,7 +1,8 @@
/*
* JFFS2 -- Journalling Flash File System, Version 2.
*
* Copyright (C) 2001-2003 Red Hat, Inc.
* Copyright © 2001-2007 Red Hat, Inc.
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
*
* Created by David Woodhouse <dwmw2@infradead.org>
*

View File

@ -4,12 +4,26 @@
* NAND family Bad Block Management (BBM) header file
* - Bad Block Table (BBT) implementation
*
* Copyright (c) 2005 Samsung Electronics
* Copyright © 2005 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
* Copyright (c) 2000-2005
* Copyright © 2000-2005
* Thomas Gleixner <tglx@linuxtronix.de>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __LINUX_MTD_BBM_H
#define __LINUX_MTD_BBM_H
@ -82,6 +96,12 @@ struct nand_bbt_descr {
#define NAND_BBT_SAVECONTENT 0x00002000
/* Search good / bad pattern on the first and the second page */
#define NAND_BBT_SCAN2NDPAGE 0x00004000
/* Search good / bad pattern on the last page of the eraseblock */
#define NAND_BBT_SCANLASTPAGE 0x00008000
/* Chip stores bad block marker on BOTH 1st and 6th bytes of OOB */
#define NAND_BBT_SCANBYTE1AND6 0x00100000
/* The nand_bbt_descr was created dynamicaly and must be freed */
#define NAND_BBT_DYNAMICSTRUCT 0x00200000
/* The maximum number of blocks to scan for a bbt */
#define NAND_BBT_SCAN_MAXBLOCKS 4

View File

@ -1,7 +1,19 @@
/*
* (C) 2003 David Woodhouse <dwmw2@infradead.org>
* Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org>
*
* Interface to Linux block layer for MTD 'translation layers'.
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

View File

@ -1,6 +1,20 @@
/* Common Flash Interface structures
* See http://support.intel.com/design/flash/technote/index.htm
/*
* Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> et al.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __MTD_CFI_H__

View File

@ -1,3 +1,22 @@
/*
* Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <asm/byteorder.h>
#ifndef CONFIG_MTD_CFI_ADV_OPTIONS

View File

@ -1,10 +0,0 @@
#ifndef __LINUX_MTD_COMPATMAC_H__
#define __LINUX_MTD_COMPATMAC_H__
/* Nothing to see here. We write 2.5-compatible code and this
file makes it all OK in older kernels, but it's empty in _current_
kernels. Include guard just to make GCC ignore it in future inclusions
anyway... */
#endif /* __LINUX_MTD_COMPATMAC_H__ */

View File

@ -1,9 +1,22 @@
/*
* MTD device concatenation layer definitions
*
* (C) 2002 Robert Kaiser <rkaiser@sysgo.de>
* Copyright © 2002 Robert Kaiser <rkaiser@sysgo.de>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* This code is GPL
*/
#ifndef MTD_CONCAT_H

View File

@ -1,12 +1,25 @@
/*
* Linux driver for Disk-On-Chip devices
*
* Copyright (C) 1999 Machine Vision Holdings, Inc.
* Copyright (C) 2001-2003 David Woodhouse <dwmw2@infradead.org>
* Copyright (C) 2002-2003 Greg Ungerer <gerg@snapgear.com>
* Copyright (C) 2002-2003 SnapGear Inc
* Copyright © 1999 Machine Vision Holdings, Inc.
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
* Copyright © 2002-2003 Greg Ungerer <gerg@snapgear.com>
* Copyright © 2002-2003 SnapGear Inc
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Released under GPL
*/
#ifndef __MTD_DOC2000_H__

View File

@ -1,10 +1,21 @@
/*
* struct flchip definition
* Copyright © 2000 Red Hat UK Limited
* Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
*
* Contains information about the location and state of a given flash device
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* (C) 2000 Red Hat. GPLd.
*/
#ifndef __MTD_FLASHCHIP_H__
@ -92,7 +103,7 @@ struct flchip {
/* This is used to handle contention on write/erase operations
between partitions of the same physical chip. */
struct flchip_shared {
spinlock_t lock;
struct mutex lock;
struct flchip *writing;
struct flchip *erasing;
};

View File

@ -1,6 +1,21 @@
/*
* (C) 2001, 2001 Red Hat, Inc.
* GPL'd
* Copyright © 2001 Red Hat UK Limited
* Copyright © 2001-2010 David Woodhouse <dwmw2@infradead.org>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __LINUX_MTD_GEN_PROBE_H__

View File

@ -1,3 +1,21 @@
/*
* Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org> et al.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/* Overhauled routines for dealing with different mmap regions of flash */
@ -9,7 +27,6 @@
#include <linux/string.h>
#include <linux/bug.h>
#include <linux/mtd/compatmac.h>
#include <asm/unaligned.h>
#include <asm/system.h>

View File

@ -1,7 +1,20 @@
/*
* Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
* Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Released under GPL
*/
#ifndef __MTD_MTD_H__
@ -13,7 +26,6 @@
#include <linux/notifier.h>
#include <linux/device.h>
#include <linux/mtd/compatmac.h>
#include <mtd/mtd-abi.h>
#include <asm/div64.h>
@ -216,6 +228,7 @@ struct mtd_info {
/* Chip-supported device locking */
int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
int (*is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
/* Power Management functions */
int (*suspend) (struct mtd_info *mtd);

View File

@ -1,9 +1,9 @@
/*
* linux/include/linux/mtd/nand.h
*
* Copyright (c) 2000 David Woodhouse <dwmw2@infradead.org>
* Steven J. Hill <sjhill@realitydiluted.com>
* Thomas Gleixner <tglx@linutronix.de>
* Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
* Steven J. Hill <sjhill@realitydiluted.com>
* Thomas Gleixner <tglx@linutronix.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -181,8 +181,6 @@ typedef enum {
#define NAND_NO_READRDY 0x00000100
/* Chip does not allow subpage writes */
#define NAND_NO_SUBPAGE_WRITE 0x00000200
/* Chip stores bad block marker on the last page of the eraseblock */
#define NAND_BB_LAST_PAGE 0x00000400
/* Device is one of 'new' xD cards that expose fake nand command set */
#define NAND_BROKEN_XD 0x00000400

View File

@ -1,7 +1,9 @@
/*
* drivers/mtd/nand_ecc.h
*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
* Copyright (C) 2000-2010 Steven J. Hill <sjhill@realitydiluted.com>
* David Woodhouse <dwmw2@infradead.org>
* Thomas Gleixner <tglx@linutronix.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as

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