提交 ba7cc09c 编写于 作者: L Linus Torvalds

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

* git://git.infradead.org/mtd-2.6: (21 commits)
  [MTD] [CHIPS] Remove MTD_OBSOLETE_CHIPS (jedec, amd_flash, sharp)
  [MTD] Delete allegedly obsolete "bank_size" field of mtd_info.
  [MTD] Remove unnecessary user space check from mtd.h.
  [MTD] [MAPS] Remove flash maps for no longer supported 405LP boards
  [MTD] [MAPS] Fix missing printk() parameter in physmap_of.c MTD driver
  [MTD] [NAND] platform NAND driver: add driver
  [MTD] [NAND] platform NAND driver: update header
  [JFFS2] Simplify and clean up jffs2_add_tn_to_tree() some more.
  [JFFS2] Remove another bogus optimisation in jffs2_add_tn_to_tree()
  [JFFS2] Remove broken insert_point optimisation in jffs2_add_tn_to_tree()
  [JFFS2] Remember to calculate overlap on nodes which replace older nodes
  [JFFS2] Don't advance c->wbuf_ofs to next eraseblock after wbuf flush
  [MTD] [NAND] at91_nand.c: CMDLINE_PARTS support
  [MTD] [NAND] Tidy up handling of page number in nand_block_bad()
  [MTD] block2mtd_paramline[] mustn't be __initdata
  [MTD] [NAND] Support multiple chips in CAFÉ driver
  [MTD] [NAND] Rename cafe.c to cafe_nand.c and remove the multi-obj magic
  [MTD] [NAND] Use rslib for CAFÉ ECC
  [RSLIB] Support non-canonical GF representations
  [JFFS2] Remove dead file histo_mips.h
  ...
......@@ -2648,6 +2648,12 @@ M: corbet@lwn.net
L: video4linux-list@redhat.com
S: Maintained
ONENAND FLASH DRIVER
P: Kyungmin Park
M: kyungmin.park@samsung.com
L: linux-mtd@lists.infradead.org
S: Maintained
ONSTREAM SCSI TAPE DRIVER
P: Willem Riede
M: osst@riede.org
......
# drivers/mtd/chips/Kconfig
# $Id: Kconfig,v 1.18 2005/11/07 11:14:22 gleixner Exp $
menu "RAM/ROM/Flash chip drivers"
depends on MTD!=n
......@@ -231,45 +230,6 @@ config MTD_ABSENT
the system regardless of media presence. Device nodes created
with this driver will return -ENODEV upon access.
config MTD_OBSOLETE_CHIPS
bool "Older (theoretically obsoleted now) drivers for non-CFI chips"
help
This option does not enable any code directly, but will allow you to
select some other chip drivers which are now considered obsolete,
because the generic CONFIG_JEDECPROBE code above should now detect
the chips which are supported by these drivers, and allow the generic
CFI-compatible drivers to drive the chips. Say 'N' here unless you have
already tried the CONFIG_JEDECPROBE method and reported its failure
to the MTD mailing list at <linux-mtd@lists.infradead.org>
config MTD_AMDSTD
tristate "AMD compatible flash chip support (non-CFI)"
depends on MTD_OBSOLETE_CHIPS && BROKEN
help
This option enables support for flash chips using AMD-compatible
commands, including some which are not CFI-compatible and hence
cannot be used with the CONFIG_MTD_CFI_AMDSTD option.
It also works on AMD compatible chips that do conform to CFI.
config MTD_SHARP
tristate "pre-CFI Sharp chip support"
depends on MTD_OBSOLETE_CHIPS
help
This option enables support for flash chips using Sharp-compatible
commands, including some which are not CFI-compatible and hence
cannot be used with the CONFIG_MTD_CFI_INTELxxx options.
config MTD_JEDEC
tristate "JEDEC device support"
depends on MTD_OBSOLETE_CHIPS && BROKEN
help
Enable older JEDEC flash interface devices for self
programming flash. It is commonly used in older AMD chips. It is
only called JEDEC because the JEDEC association
<http://www.jedec.org/> distributes the identification codes for the
chips.
config MTD_XIP
bool "XIP aware MTD support"
depends on !SMP && (MTD_CFI_INTELEXT || MTD_CFI_AMDSTD) && EXPERIMENTAL && ARCH_MTD_XIP
......
#
# linux/drivers/chips/Makefile
#
# $Id: Makefile.common,v 1.5 2005/11/07 11:14:22 gleixner Exp $
obj-$(CONFIG_MTD) += chipreg.o
obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o
obj-$(CONFIG_MTD_CFI) += cfi_probe.o
obj-$(CONFIG_MTD_CFI_UTIL) += cfi_util.o
obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o
obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o
obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o
obj-$(CONFIG_MTD_GEN_PROBE) += gen_probe.o
obj-$(CONFIG_MTD_JEDEC) += jedec.o
obj-$(CONFIG_MTD_JEDECPROBE) += jedec_probe.o
obj-$(CONFIG_MTD_RAM) += map_ram.o
obj-$(CONFIG_MTD_ROM) += map_rom.o
obj-$(CONFIG_MTD_SHARP) += sharp.o
obj-$(CONFIG_MTD_ABSENT) += map_absent.o
此差异已折叠。
此差异已折叠。
/*
* MTD chip driver for pre-CFI Sharp flash chips
*
* Copyright 2000,2001 David A. Schleef <ds@schleef.org>
* 2000,2001 Lineo, Inc.
*
* $Id: sharp.c,v 1.17 2005/11/29 14:28:28 gleixner Exp $
*
* Devices supported:
* LH28F016SCT Symmetrical block flash memory, 2Mx8
* LH28F008SCT Symmetrical block flash memory, 1Mx8
*
* Documentation:
* http://www.sharpmeg.com/datasheets/memic/flashcmp/
* http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf
* 016sctl9.pdf
*
* Limitations:
* This driver only supports 4x1 arrangement of chips.
* Not tested on anything but PowerPC.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/cfi.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
#define CMD_RESET 0xffffffff
#define CMD_READ_ID 0x90909090
#define CMD_READ_STATUS 0x70707070
#define CMD_CLEAR_STATUS 0x50505050
#define CMD_BLOCK_ERASE_1 0x20202020
#define CMD_BLOCK_ERASE_2 0xd0d0d0d0
#define CMD_BYTE_WRITE 0x40404040
#define CMD_SUSPEND 0xb0b0b0b0
#define CMD_RESUME 0xd0d0d0d0
#define CMD_SET_BLOCK_LOCK_1 0x60606060
#define CMD_SET_BLOCK_LOCK_2 0x01010101
#define CMD_SET_MASTER_LOCK_1 0x60606060
#define CMD_SET_MASTER_LOCK_2 0xf1f1f1f1
#define CMD_CLEAR_BLOCK_LOCKS_1 0x60606060
#define CMD_CLEAR_BLOCK_LOCKS_2 0xd0d0d0d0
#define SR_READY 0x80808080 // 1 = ready
#define SR_ERASE_SUSPEND 0x40404040 // 1 = block erase suspended
#define SR_ERROR_ERASE 0x20202020 // 1 = error in block erase or clear lock bits
#define SR_ERROR_WRITE 0x10101010 // 1 = error in byte write or set lock bit
#define SR_VPP 0x08080808 // 1 = Vpp is low
#define SR_WRITE_SUSPEND 0x04040404 // 1 = byte write suspended
#define SR_PROTECT 0x02020202 // 1 = lock bit set
#define SR_RESERVED 0x01010101
#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT)
/* Configuration options */
#undef AUTOUNLOCK /* automatically unlocks blocks before erasing */
static struct mtd_info *sharp_probe(struct map_info *);
static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd);
static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, const u_char *buf);
static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr);
static void sharp_sync(struct mtd_info *mtd);
static int sharp_suspend(struct mtd_info *mtd);
static void sharp_resume(struct mtd_info *mtd);
static void sharp_destroy(struct mtd_info *mtd);
static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
unsigned long adr, __u32 datum);
static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr);
#ifdef AUTOUNLOCK
static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr);
#endif
struct sharp_info{
struct flchip *chip;
int bogus;
int chipshift;
int numchips;
struct flchip chips[1];
};
static void sharp_destroy(struct mtd_info *mtd);
static struct mtd_chip_driver sharp_chipdrv = {
.probe = sharp_probe,
.destroy = sharp_destroy,
.name = "sharp",
.module = THIS_MODULE
};
static struct mtd_info *sharp_probe(struct map_info *map)
{
struct mtd_info *mtd = NULL;
struct sharp_info *sharp = NULL;
int width;
mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
if(!mtd)
return NULL;
sharp = kzalloc(sizeof(*sharp), GFP_KERNEL);
if(!sharp) {
kfree(mtd);
return NULL;
}
width = sharp_probe_map(map,mtd);
if(!width){
kfree(mtd);
kfree(sharp);
return NULL;
}
mtd->priv = map;
mtd->type = MTD_NORFLASH;
mtd->erase = sharp_erase;
mtd->read = sharp_read;
mtd->write = sharp_write;
mtd->sync = sharp_sync;
mtd->suspend = sharp_suspend;
mtd->resume = sharp_resume;
mtd->flags = MTD_CAP_NORFLASH;
mtd->writesize = 1;
mtd->name = map->name;
sharp->chipshift = 23;
sharp->numchips = 1;
sharp->chips[0].start = 0;
sharp->chips[0].state = FL_READY;
sharp->chips[0].mutex = &sharp->chips[0]._spinlock;
sharp->chips[0].word_write_time = 0;
init_waitqueue_head(&sharp->chips[0].wq);
spin_lock_init(&sharp->chips[0]._spinlock);
map->fldrv = &sharp_chipdrv;
map->fldrv_priv = sharp;
__module_get(THIS_MODULE);
return mtd;
}
static inline void sharp_send_cmd(struct map_info *map, unsigned long cmd, unsigned long adr)
{
map_word map_cmd;
map_cmd.x[0] = cmd;
map_write(map, map_cmd, adr);
}
static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd)
{
map_word tmp, read0, read4;
unsigned long base = 0;
int width = 4;
tmp = map_read(map, base+0);
sharp_send_cmd(map, CMD_READ_ID, base+0);
read0 = map_read(map, base+0);
read4 = map_read(map, base+4);
if(read0.x[0] == 0x89898989){
printk("Looks like sharp flash\n");
switch(read4.x[0]){
case 0xaaaaaaaa:
case 0xa0a0a0a0:
/* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/
/* a0 - LH28F016SCT-Z4 2Mx8, 32 64k blocks*/
mtd->erasesize = 0x10000 * width;
mtd->size = 0x200000 * width;
return width;
case 0xa6a6a6a6:
/* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/
/* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/
mtd->erasesize = 0x10000 * width;
mtd->size = 0x100000 * width;
return width;
#if 0
case 0x00000000: /* unknown */
/* XX - LH28F004SCT 512kx8, 8 64k blocks*/
mtd->erasesize = 0x10000 * width;
mtd->size = 0x80000 * width;
return width;
#endif
default:
printk("Sort-of looks like sharp flash, 0x%08lx 0x%08lx\n",
read0.x[0], read4.x[0]);
}
}else if((map_read(map, base+0).x[0] == CMD_READ_ID)){
/* RAM, probably */
printk("Looks like RAM\n");
map_write(map, tmp, base+0);
}else{
printk("Doesn't look like sharp flash, 0x%08lx 0x%08lx\n",
read0.x[0], read4.x[0]);
}
return 0;
}
/* This function returns with the chip->mutex lock held. */
static int sharp_wait(struct map_info *map, struct flchip *chip)
{
int i;
map_word status;
unsigned long timeo = jiffies + HZ;
DECLARE_WAITQUEUE(wait, current);
int adr = 0;
retry:
spin_lock_bh(chip->mutex);
switch(chip->state){
case FL_READY:
sharp_send_cmd(map, CMD_READ_STATUS, adr);
chip->state = FL_STATUS;
case FL_STATUS:
for(i=0;i<100;i++){
status = map_read(map, adr);
if((status.x[0] & SR_READY)==SR_READY)
break;
udelay(1);
}
break;
default:
printk("Waiting for chip\n");
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex);
schedule();
remove_wait_queue(&chip->wq, &wait);
if(signal_pending(current))
return -EINTR;
timeo = jiffies + HZ;
goto retry;
}
sharp_send_cmd(map, CMD_RESET, adr);
chip->state = FL_READY;
return 0;
}
static void sharp_release(struct flchip *chip)
{
wake_up(&chip->wq);
spin_unlock_bh(chip->mutex);
}
static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
struct map_info *map = mtd->priv;
struct sharp_info *sharp = map->fldrv_priv;
int chipnum;
int ret = 0;
int ofs = 0;
chipnum = (from >> sharp->chipshift);
ofs = from & ((1 << sharp->chipshift)-1);
*retlen = 0;
while(len){
unsigned long thislen;
if(chipnum>=sharp->numchips)
break;
thislen = len;
if(ofs+thislen >= (1<<sharp->chipshift))
thislen = (1<<sharp->chipshift) - ofs;
ret = sharp_wait(map,&sharp->chips[chipnum]);
if(ret<0)
break;
map_copy_from(map,buf,ofs,thislen);
sharp_release(&sharp->chips[chipnum]);
*retlen += thislen;
len -= thislen;
buf += thislen;
ofs = 0;
chipnum++;
}
return ret;
}
static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
struct map_info *map = mtd->priv;
struct sharp_info *sharp = map->fldrv_priv;
int ret = 0;
int i,j;
int chipnum;
unsigned long ofs;
union { u32 l; unsigned char uc[4]; } tbuf;
*retlen = 0;
while(len){
tbuf.l = 0xffffffff;
chipnum = to >> sharp->chipshift;
ofs = to & ((1<<sharp->chipshift)-1);
j=0;
for(i=ofs&3;i<4 && len;i++){
tbuf.uc[i] = *buf;
buf++;
to++;
len--;
j++;
}
sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l);
if(ret<0)
return ret;
(*retlen)+=j;
}
return 0;
}
static int sharp_write_oneword(struct map_info *map, struct flchip *chip,
unsigned long adr, __u32 datum)
{
int ret;
int timeo;
int try;
int i;
map_word data, status;
status.x[0] = 0;
ret = sharp_wait(map,chip);
for(try=0;try<10;try++){
sharp_send_cmd(map, CMD_BYTE_WRITE, adr);
/* cpu_to_le32 -> hack to fix the writel be->le conversion */
data.x[0] = cpu_to_le32(datum);
map_write(map, data, adr);
chip->state = FL_WRITING;
timeo = jiffies + (HZ/2);
sharp_send_cmd(map, CMD_READ_STATUS, adr);
for(i=0;i<100;i++){
status = map_read(map, adr);
if((status.x[0] & SR_READY) == SR_READY)
break;
}
if(i==100){
printk("sharp: timed out writing\n");
}
if(!(status.x[0] & SR_ERRORS))
break;
printk("sharp: error writing byte at addr=%08lx status=%08lx\n", adr, status.x[0]);
sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
}
sharp_send_cmd(map, CMD_RESET, adr);
chip->state = FL_READY;
wake_up(&chip->wq);
spin_unlock_bh(chip->mutex);
return 0;
}
static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct map_info *map = mtd->priv;
struct sharp_info *sharp = map->fldrv_priv;
unsigned long adr,len;
int chipnum, ret=0;
//printk("sharp_erase()\n");
if(instr->addr & (mtd->erasesize - 1))
return -EINVAL;
if(instr->len & (mtd->erasesize - 1))
return -EINVAL;
if(instr->len + instr->addr > mtd->size)
return -EINVAL;
chipnum = instr->addr >> sharp->chipshift;
adr = instr->addr & ((1<<sharp->chipshift)-1);
len = instr->len;
while(len){
ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr);
if(ret)return ret;
adr += mtd->erasesize;
len -= mtd->erasesize;
if(adr >> sharp->chipshift){
adr = 0;
chipnum++;
if(chipnum>=sharp->numchips)
break;
}
}
instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
return 0;
}
static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
int ret;
unsigned long timeo;
map_word status;
DECLARE_WAITQUEUE(wait, current);
sharp_send_cmd(map, CMD_READ_STATUS, adr);
status = map_read(map, adr);
timeo = jiffies + HZ;
while(time_before(jiffies, timeo)){
sharp_send_cmd(map, CMD_READ_STATUS, adr);
status = map_read(map, adr);
if((status.x[0] & SR_READY)==SR_READY){
ret = 0;
goto out;
}
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
//spin_unlock_bh(chip->mutex);
schedule_timeout(1);
schedule();
remove_wait_queue(&chip->wq, &wait);
//spin_lock_bh(chip->mutex);
if (signal_pending(current)){
ret = -EINTR;
goto out;
}
}
ret = -ETIME;
out:
return ret;
}
static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
int ret;
//int timeo;
map_word status;
//int i;
//printk("sharp_erase_oneblock()\n");
#ifdef AUTOUNLOCK
/* This seems like a good place to do an unlock */
sharp_unlock_oneblock(map,chip,adr);
#endif
sharp_send_cmd(map, CMD_BLOCK_ERASE_1, adr);
sharp_send_cmd(map, CMD_BLOCK_ERASE_2, adr);
chip->state = FL_ERASING;
ret = sharp_do_wait_for_ready(map,chip,adr);
if(ret<0)return ret;
sharp_send_cmd(map, CMD_READ_STATUS, adr);
status = map_read(map, adr);
if(!(status.x[0] & SR_ERRORS)){
sharp_send_cmd(map, CMD_RESET, adr);
chip->state = FL_READY;
//spin_unlock_bh(chip->mutex);
return 0;
}
printk("sharp: error erasing block at addr=%08lx status=%08lx\n", adr, status.x[0]);
sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
//spin_unlock_bh(chip->mutex);
return -EIO;
}
#ifdef AUTOUNLOCK
static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
int i;
map_word status;
sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_1, adr);
sharp_send_cmd(map, CMD_CLEAR_BLOCK_LOCKS_2, adr);
udelay(100);
status = map_read(map, adr);
printk("status=%08lx\n", status.x[0]);
for(i=0;i<1000;i++){
//sharp_send_cmd(map, CMD_READ_STATUS, adr);
status = map_read(map, adr);
if((status.x[0] & SR_READY) == SR_READY)
break;
udelay(100);
}
if(i==1000){
printk("sharp: timed out unlocking block\n");
}
if(!(status.x[0] & SR_ERRORS)){
sharp_send_cmd(map, CMD_RESET, adr);
chip->state = FL_READY;
return;
}
printk("sharp: error unlocking block at addr=%08lx status=%08lx\n", adr, status.x[0]);
sharp_send_cmd(map, CMD_CLEAR_STATUS, adr);
}
#endif
static void sharp_sync(struct mtd_info *mtd)
{
//printk("sharp_sync()\n");
}
static int sharp_suspend(struct mtd_info *mtd)
{
printk("sharp_suspend()\n");
return -EINVAL;
}
static void sharp_resume(struct mtd_info *mtd)
{
printk("sharp_resume()\n");
}
static void sharp_destroy(struct mtd_info *mtd)
{
printk("sharp_destroy()\n");
}
static int __init sharp_probe_init(void)
{
printk("MTD Sharp chip driver <ds@lineo.com>\n");
register_mtd_chip_driver(&sharp_chipdrv);
return 0;
}
static void __exit sharp_probe_exit(void)
{
unregister_mtd_chip_driver(&sharp_chipdrv);
}
module_init(sharp_probe_init);
module_exit(sharp_probe_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Schleef <ds@schleef.org>");
MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");
......@@ -373,7 +373,7 @@ static inline void kill_final_newline(char *str)
#ifndef MODULE
static int block2mtd_init_called = 0;
static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
#endif
......
......@@ -358,22 +358,6 @@ config MTD_CFI_FLAGADM
Mapping for the Flaga digital module. If you don't have one, ignore
this setting.
config MTD_BEECH
tristate "CFI Flash device mapped on IBM 405LP Beech"
depends on MTD_CFI && BEECH
help
This enables access routines for the flash chips on the IBM
405LP Beech board. If you have one of these boards and would like
to use the flash chips on it, say 'Y'.
config MTD_ARCTIC
tristate "CFI Flash device mapped on IBM 405LP Arctic"
depends on MTD_CFI && ARCTIC2
help
This enables access routines for the flash chips on the IBM 405LP
Arctic board. If you have one of these boards and would like to
use the flash chips on it, say 'Y'.
config MTD_WALNUT
tristate "Flash device mapped on IBM 405GP Walnut"
depends on MTD_JEDECPROBE && WALNUT
......
......@@ -58,8 +58,6 @@ obj-$(CONFIG_MTD_NETtel) += nettel.o
obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o
obj-$(CONFIG_MTD_EBONY) += ebony.o
obj-$(CONFIG_MTD_OCOTEA) += ocotea.o
obj-$(CONFIG_MTD_BEECH) += beech-mtd.o
obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o
obj-$(CONFIG_MTD_WALNUT) += walnut.o
obj-$(CONFIG_MTD_H720X) += h720x-flash.o
obj-$(CONFIG_MTD_SBC8240) += sbc8240.o
......
/*
* $Id: arctic-mtd.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $
*
* drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for
* IBM 405LP Arctic boards.
*
* 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
*
* Copyright (C) 2002, International Business Machines Corporation
* All Rights Reserved.
*
* Bishop Brock
* IBM Research, Austin Center for Low-Power Computing
* bcbrock@us.ibm.com
* March 2002
*
* modified for Arctic by,
* David Gibson
* IBM OzLabs, Canberra, Australia
* <arctic@gibson.dropbear.id.au>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/ibm4xx.h>
/*
* 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB)
* 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB)
* 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP)
* 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB)
*/
#define FFS1_SIZE 0x01000000 /* 16MiB */
#define KERNEL_SIZE 0x00500000 /* 5.12MiB */
#define FFS2_SIZE 0x00a60000 /* 10.624MiB */
#define FIRMWARE_SIZE 0x000a0000 /* 640KiB */
#define NAME "Arctic Linux Flash"
#define PADDR SUBZERO_BOOTFLASH_PADDR
#define BUSWIDTH 2
#define SIZE SUBZERO_BOOTFLASH_SIZE
#define PARTITIONS 4
/* Flash memories on these boards are memory resources, accessed big-endian. */
{
/* do nothing for now */
}
static struct map_info arctic_mtd_map = {
.name = NAME,
.size = SIZE,
.bankwidth = BUSWIDTH,
.phys = PADDR,
};
static struct mtd_info *arctic_mtd;
static struct mtd_partition arctic_partitions[PARTITIONS] = {
{ .name = "Filesystem",
.size = FFS1_SIZE,
.offset = 0,},
{ .name = "Kernel",
.size = KERNEL_SIZE,
.offset = FFS1_SIZE,},
{ .name = "Filesystem",
.size = FFS2_SIZE,
.offset = FFS1_SIZE + KERNEL_SIZE,},
{ .name = "Firmware",
.size = FIRMWARE_SIZE,
.offset = SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,},
};
static int __init
init_arctic_mtd(void)
{
int err;
printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
arctic_mtd_map.virt = ioremap(PADDR, SIZE);
if (!arctic_mtd_map.virt) {
printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
return -EIO;
}
simple_map_init(&arctic_mtd_map);
printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map);
if (!arctic_mtd) {
iounmap(arctic_mtd_map.virt);
return -ENXIO;
}
arctic_mtd->owner = THIS_MODULE;
err = add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS);
if (err) {
printk("%s: add_mtd_partitions failed\n", NAME);
iounmap(arctic_mtd_map.virt);
}
return err;
}
static void __exit
cleanup_arctic_mtd(void)
{
if (arctic_mtd) {
del_mtd_partitions(arctic_mtd);
map_destroy(arctic_mtd);
iounmap((void *) arctic_mtd_map.virt);
}
}
module_init(init_arctic_mtd);
module_exit(cleanup_arctic_mtd);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Gibson <arctic@gibson.dropbear.id.au>");
MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Arctic boards");
/*
* $Id: beech-mtd.c,v 1.11 2005/11/07 11:14:26 gleixner Exp $
*
* drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for
* IBM 405LP Beech boards.
*
* 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
*
* Copyright (C) 2002, International Business Machines Corporation
* All Rights Reserved.
*
* Bishop Brock
* IBM Research, Austin Center for Low-Power Computing
* bcbrock@us.ibm.com
* March 2002
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/ibm4xx.h>
#define NAME "Beech Linux Flash"
#define PADDR BEECH_BIGFLASH_PADDR
#define SIZE BEECH_BIGFLASH_SIZE
#define BUSWIDTH 1
/* Flash memories on these boards are memory resources, accessed big-endian. */
static struct map_info beech_mtd_map = {
.name = NAME,
.size = SIZE,
.bankwidth = BUSWIDTH,
.phys = PADDR
};
static struct mtd_info *beech_mtd;
static struct mtd_partition beech_partitions[2] = {
{
.name = "Linux Kernel",
.size = BEECH_KERNEL_SIZE,
.offset = BEECH_KERNEL_OFFSET
}, {
.name = "Free Area",
.size = BEECH_FREE_AREA_SIZE,
.offset = BEECH_FREE_AREA_OFFSET
}
};
static int __init
init_beech_mtd(void)
{
int err;
printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
beech_mtd_map.virt = ioremap(PADDR, SIZE);
if (!beech_mtd_map.virt) {
printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
return -EIO;
}
simple_map_init(&beech_mtd_map);
printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map);
if (!beech_mtd) {
iounmap(beech_mtd_map.virt);
return -ENXIO;
}
beech_mtd->owner = THIS_MODULE;
err = add_mtd_partitions(beech_mtd, beech_partitions, 2);
if (err) {
printk("%s: add_mtd_partitions failed\n", NAME);
iounmap(beech_mtd_map.virt);
}
return err;
}
static void __exit
cleanup_beech_mtd(void)
{
if (beech_mtd) {
del_mtd_partitions(beech_mtd);
map_destroy(beech_mtd);
iounmap((void *) beech_mtd_map.virt);
}
}
module_init(init_beech_mtd);
module_exit(cleanup_beech_mtd);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bishop Brock <bcbrock@us.ibm.com>");
MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Beech boards");
......@@ -186,7 +186,7 @@ static int __devinit of_physmap_probe(struct of_device *dev, const struct of_dev
else {
if (strcmp(of_probe, "ROM"))
dev_dbg(&dev->dev, "map_probe: don't know probe type "
"'%s', mapping as rom\n");
"'%s', mapping as rom\n", of_probe);
info->mtd = do_map_probe("mtd_rom", &info->map);
}
if (info->mtd == NULL) {
......
......@@ -347,7 +347,6 @@ int add_mtd_partitions(struct mtd_info *master,
slave->mtd.subpage_sft = master->subpage_sft;
slave->mtd.name = parts[i].name;
slave->mtd.bank_size = master->bank_size;
slave->mtd.owner = master->owner;
slave->mtd.read = part_read;
......
......@@ -232,11 +232,13 @@ config MTD_NAND_BASLER_EXCITE
will be named "excite_nandflash.ko".
config MTD_NAND_CAFE
tristate "NAND support for OLPC CAFÉ chip"
depends on PCI
help
Use NAND flash attached to the CAFÉ chip designed for the $100
laptop.
tristate "NAND support for OLPC CAFÉ chip"
depends on PCI
select REED_SOLOMON
select REED_SOLOMON_DEC16
help
Use NAND flash attached to the CAFÉ chip designed for the $100
laptop.
config MTD_NAND_CS553X
tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
......@@ -270,4 +272,13 @@ config MTD_NAND_NANDSIM
The simulator may simulate various NAND flash chips for the
MTD nand layer.
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
via platform_data.
endif # MTD_NAND
......@@ -26,6 +26,6 @@ obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
nand-objs := nand_base.o nand_bbt.o
cafe_nand-objs := cafe.o cafe_ecc.o
......@@ -82,6 +82,10 @@ static void at91_nand_disable(struct at91_nand_host *host)
at91_set_gpio_value(host->board->enable_pin, 1);
}
#ifdef CONFIG_MTD_PARTITIONS
const char *part_probes[] = { "cmdlinepart", NULL };
#endif
/*
* Probe for the NAND device.
*/
......@@ -151,6 +155,12 @@ static int __init at91_nand_probe(struct platform_device *pdev)
#ifdef CONFIG_MTD_PARTITIONS
if (host->board->partition_info)
partitions = host->board->partition_info(mtd->size, &num_partitions);
#ifdef CONFIG_MTD_CMDLINE_PARTS
else {
mtd->name = "at91_nand";
num_partitions = parse_mtd_partitions(mtd, part_probes, &partitions, 0);
}
#endif
if ((!partitions) || (num_partitions == 0)) {
printk(KERN_ERR "at91_nand: No parititions defined, or unsupported device.\n");
......
此差异已折叠。
......@@ -303,28 +303,27 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
struct nand_chip *chip = mtd->priv;
u16 bad;
page = (int)(ofs >> chip->page_shift) & chip->pagemask;
if (getchip) {
page = (int)(ofs >> chip->page_shift);
chipnr = (int)(ofs >> chip->chip_shift);
nand_get_device(chip, mtd, FL_READING);
/* Select the NAND device */
chip->select_chip(mtd, chipnr);
} else
page = (int)(ofs >> chip->page_shift);
}
if (chip->options & NAND_BUSWIDTH_16) {
chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
page & chip->pagemask);
page);
bad = cpu_to_le16(chip->read_word(mtd));
if (chip->badblockpos & 0x1)
bad >>= 8;
if ((bad & 0xFF) != 0xff)
res = 1;
} else {
chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
page & chip->pagemask);
chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page);
if (chip->read_byte(mtd) != 0xff)
res = 1;
}
......
/*
* Generic NAND driver
*
* Author: Vitaly Wool <vitalywool@gmail.com>
*
* 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
* published by the Free Software Foundation.
*
*/
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
struct plat_nand_data {
struct nand_chip chip;
struct mtd_info mtd;
void __iomem *io_base;
#ifdef CONFIG_MTD_PARTITIONS
int nr_parts;
struct mtd_partition *parts;
#endif
};
/*
* Probe for the NAND device.
*/
static int __init plat_nand_probe(struct platform_device *pdev)
{
struct platform_nand_data *pdata = pdev->dev.platform_data;
struct plat_nand_data *data;
int res = 0;
/* Allocate memory for the device structure (and zero it) */
data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL);
if (!data) {
dev_err(&pdev->dev, "failed to allocate device structure.\n");
return -ENOMEM;
}
data->io_base = ioremap(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1);
if (data->io_base == NULL) {
dev_err(&pdev->dev, "ioremap failed\n");
kfree(data);
return -EIO;
}
data->chip.priv = &data;
data->mtd.priv = &data->chip;
data->mtd.owner = THIS_MODULE;
data->chip.IO_ADDR_R = data->io_base;
data->chip.IO_ADDR_W = data->io_base;
data->chip.cmd_ctrl = pdata->ctrl.cmd_ctrl;
data->chip.dev_ready = pdata->ctrl.dev_ready;
data->chip.select_chip = pdata->ctrl.select_chip;
data->chip.chip_delay = pdata->chip.chip_delay;
data->chip.options |= pdata->chip.options;
data->chip.ecc.hwctl = pdata->ctrl.hwcontrol;
data->chip.ecc.layout = pdata->chip.ecclayout;
data->chip.ecc.mode = NAND_ECC_SOFT;
platform_set_drvdata(pdev, data);
/* Scan to find existance of the device */
if (nand_scan(&data->mtd, 1)) {
res = -ENXIO;
goto out;
}
#ifdef CONFIG_MTD_PARTITIONS
if (pdata->chip.part_probe_types) {
res = parse_mtd_partitions(&data->mtd,
pdata->chip.part_probe_types,
&data->parts, 0);
if (res > 0) {
add_mtd_partitions(&data->mtd, data->parts, res);
return 0;
}
}
if (pdata->chip.partitions) {
data->parts = pdata->chip.partitions;
res = add_mtd_partitions(&data->mtd, data->parts,
pdata->chip.nr_partitions);
} else
#endif
res = add_mtd_device(&data->mtd);
if (!res)
return res;
nand_release(&data->mtd);
out:
platform_set_drvdata(pdev, NULL);
iounmap(data->io_base);
kfree(data);
return res;
}
/*
* Remove a NAND device.
*/
static int __devexit plat_nand_remove(struct platform_device *pdev)
{
struct plat_nand_data *data = platform_get_drvdata(pdev);
struct platform_nand_data *pdata = pdev->dev.platform_data;
nand_release(&data->mtd);
#ifdef CONFIG_MTD_PARTITIONS
if (data->parts && data->parts != pdata->chip.partitions)
kfree(data->parts);
#endif
iounmap(data->io_base);
kfree(data);
return 0;
}
static struct platform_driver plat_nand_driver = {
.probe = plat_nand_probe,
.remove = plat_nand_remove,
.driver = {
.name = "gen_nand",
.owner = THIS_MODULE,
},
};
static int __init plat_nand_init(void)
{
return platform_driver_register(&plat_nand_driver);
}
static void __exit plat_nand_exit(void)
{
platform_driver_unregister(&plat_nand_driver);
}
module_init(plat_nand_init);
module_exit(plat_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vitaly Wool");
MODULE_DESCRIPTION("Simple generic NAND driver");
#define BIT_DIVIDER_MIPS 1043
static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */
此差异已折叠。
......@@ -637,7 +637,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
memset(c->wbuf,0xff,c->wbuf_pagesize);
/* adjust write buffer offset, else we get a non contiguous write bug */
c->wbuf_ofs += c->wbuf_pagesize;
if (SECTOR_ADDR(c->wbuf_ofs) == SECTOR_ADDR(c->wbuf_ofs+c->wbuf_pagesize))
c->wbuf_ofs += c->wbuf_pagesize;
else
c->wbuf_ofs = 0xffffffff;
c->wbuf_len = 0;
return 0;
}
......
......@@ -9,10 +9,6 @@
#ifndef __MTD_MTD_H__
#define __MTD_MTD_H__
#ifndef __KERNEL__
#error This is a kernel header. Perhaps include mtd-user.h instead?
#endif
#include <linux/types.h>
#include <linux/module.h>
#include <linux/uio.h>
......@@ -137,9 +133,6 @@ struct mtd_info {
int numeraseregions;
struct mtd_erase_region_info *eraseregions;
/* This really shouldn't be here. It can go away in 2.5 */
u_int32_t bank_size;
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
/* This stuff for eXecute-In-Place */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册